Skip to content

ForeignX Drops — Architecture

Plain twin: ../business-plain/business-overview.md

Layout (USPTO-shaped backend + Angular UI)

ForeignXDrops.slnx
src/ForeignXDrops/          # ASP.NET Core 8 (Cloud Run)
  Controllers/              # Auth, Lists, Users, Metrics, Organizations, Engagement
  Services/ + Interfaces/   # X API, Sheets, KeePass, Drop orchestration, orgs, cards
  Models/ + Enums/ + Jobs/  # Domain + Quartz
  Configuration/            # AppSettings
tests/ForeignXDrops.Tests/
frontend/src/app/           # Angular (USPTO-UI-style components/services/models)
  components/               # dashboard, admin-panel, metrics, engagement-cards
  services/
  models/

Multi-tenant

  • Organization = one influencer group (slug, plan, timezone, default EngagementMode).
  • Users and drops carry OrganizationId.
  • v1 org registry: process-local (OrganizationService). Next: Organizations sheet + org-prefixed tabs / per-org spreadsheet id.
  • KeePass: plan orgs/{organizationId}/… group path (not fully wired).

Engagement modes

Stored on DropList.EngagementMode at create time:

Mode Auto like/repost Manual cards
Automatic yes no
Manual scrape only yes
Both yes yes

Cards: GET /api/engagement/{listId}/cards, POST .../actions (Like/Repost/Skip/OpenInX) using member KeePass token.

X API (Flurl + Polly)

OAuth2 PKCE, lists, members, likes, reposts, DMs, optional tweet metrics. App bearer for list create/scrape; user bearer for engagement.

Google Sheets

Users / Lists / per-list tweet tabs (existing design). Org scoping is the next persistence step.

KeePass

Bearer tokens only; Sheets hold timestamp. KPScript (+ Mono on Linux). GCS sync for Cloud Run ephemeral disk.

Scheduling

Quartz: daily list create, engagement run, metrics DMs. Cloud Run min instances ≥ 1 so the host is not scaled to zero between jobs.

Deploy

Multi-stage Dockerfile → Cloud Run. PORT env, CORS_ORIGINS, no HTTPS redirection in container.