Skip to content

Foreign\'s X Drops (ForeignX)

Multi-tenant mutual-engagement drops on X.

Backend .NET 8 ASP.NET Core · Flurl · Polly · Quartz · Serilog
Frontend Angular 17 (standalone components under frontend/src/app)
Storage Google Sheets + KeePass (tokens)
Deploy Google Cloud Run (Dockerfile)
Jira FX board

Solution layout

src/ForeignXDrops/     USPTO-shaped API
tests/ForeignXDrops.Tests/
frontend/src/app/      components · services · models
.github/workflows/     CI · InspectCode · Stryker · Semgrep · churn
docs/                  BOARD · business · business-plain · technical

Product shape

  • Many orgs (influencer groups), not one global sheet of members.
  • Engagement mode per drop: Automatic | Manual | Both (set at create time).
  • Manual cards when auto is down: app-engagement-cards + /api/engagement/*.

Local run

# API
cd src/ForeignXDrops
dotnet run
# http://localhost:8080/swagger

# Frontend (after full Angular workspace is generated)
cd frontend && npm install && npx ng serve

Fill src/ForeignXDrops/appsettings.json (or user secrets) with X + Sheets + KeePass paths.
Never commit google-credentials.json or .kdbx files.

Cloud Run

# Build and deploy (example)
gcloud run deploy foreignx-drops \
  --source . \
  --region us-central1 \
  --min-instances 1 \
  --set-env-vars "PORT=8080,CORS_ORIGINS=https://your-frontend"
  • min-instances=1 so Quartz jobs keep running between 10pm–midnight CST.
  • Mount or GCS-sync KeePass DB; set AppSettings:Gcs:BucketName.
  • KeePass portable + KPScript in keepass/ for the image.

CI

Workflow What
ci.yml build, test, Semgrep, gitleaks, vuln scan, churn x5
inspect.yml ReSharper InspectCode (scheduled)
mutation.yml Stryker.NET scoped

Self-hosted runners: .github/runner/ (labels self-hosted,foreignx,linux|windows,x64).

Docs

Original design

Claude design dump + prompt live in sibling repo
ForeignXDropsClaudeOriginalPromptAndClaudeDesignFiles and Downloads ForeignXClaude.zip.