Architecture¶
The platform is a submodule-based monorepo. Each submodule is an independent
repo with its own build system, CI, and history. The parent repo owns the
deploy manifests (deploy/argocd/), the cluster-wide services that live
in-tree (services/), and the GitHub Actions workflows that build every
service image.
Repository layout¶
backend/ # Python APIs — Flask today, FastAPI during Phase 2.
cashless-backend/ # Admin API + background jobs (Flask 2.0, gunicorn/eventlet)
personalaccount-api/ # Personal account (Flask 2.3, gunicorn)
core/ # Shared libraries
cashless-core/ # Shared Python utils (crypto, payments, notifications)
cashless-core-ui/ # Shared Angular library (@cashless-media/core)
models/ # SQLAlchemy 2.0 models (cashless-models v2)
frontend/ # Web frontends — all Angular 21
cashless-admin-ui/
cashless-refund-ui/
marketplace-user-ui/
personalaccount-ui/
apps/ # Mobile applications
mPOS/ # Android/Kotlin — POS terminal
user_app_android/ # Android/Java — legacy cardholder (sunset)
user_app_android_with_sdk/# Android/Kotlin + Compose — active cardholder
user_app_ios/ # iOS/Swift — cardholder
dispatch_app/ # Android/Java — dispatch workflows
fastpass_app/ # Android/Java — fastpass scanning
format_app/ # Android/Java — formatting tooling
report_app/ # Android/Java — operator reporting
sdk/
cashless-core-rs/ # Rust + UniFFI → Kotlin + Swift bindings
services/ # Services that live inside the parent repo
cashless-auth/ # FastAPI — identity / sessions
cashless-cron/ # Scheduled jobs
cashless-redis/ # In-cluster Redis
cashless-db-backup/ # MySQL backup CronJob
cashless-secrets/ # External-Secrets operator config
cashless-ingress/ # Cluster-wide GCE Ingress + ManagedCertificate
cashless-docs/ # This site
otel-collector/ # OTLP receiver
cluster-bootstrap/ # First-time cluster bootstrap
deploy/
argocd/ # ArgoCD AppProject + Application CRs
Service boundaries¶
cashless-coreandmodelsare shared Python packages consumed by backend services. Treat them as libraries — never reach into their internals from a service.cashless-core-uiis the shared Angular library consumed by all four web frontends. New shared components belong here, not in any one frontend.cashless-core-rsis the only mobile SDK. The legacy KMPcashless-sdkwas retired on 2026-05-08 (Wave 6 strangler-fig complete). Use UniFFI bindings — Kotlin for Android, Swift for iOS.cashless-backendandpersonalaccount-apiare deployed independently via Helm + ArgoCD. They do not share a runtime; cross-service calls go over HTTP, authenticated viacashless-auth.
Data layer¶
- MySQL 8.0 on Cloud SQL. Schema lives in
core/models/. Migrations run as a one-shotcashless-migrateJob on every backend rollout. - Redis is in-cluster (
cashless-redis) for cache + RQ queues. The auth-claims cache (Wave 6, G4) keys bysha256(token)with a 60s TTL. - No Postgres / Drizzle despite the global stack defaults — those are aspirational for new greenfield services.
Payments¶
The active processor set is:
| Processor | Notes |
|---|---|
| Stripe | Primary card processor + Stripe Terminal (mPOS). |
| Mercado Pago | Latin-America card + wallet. |
| Adyen | Enterprise card + APMs. |
| Direct PayPal | PayPal balance + PayPal Credit (no BrainTree wrapper). |
BrainTree was dropped during the v2 modernization. It survives only on
the legacy master / develop branches for reference.
Deploy flow¶
flowchart TD
A([Push to cashless-v2]) --> B[GitHub Actions CI]
B -->|docker build| C[GHCR image<br/>sha-<12 hex>]
C --> D[Argo CD Image Updater]
D -->|write-back image.tag| E[deploy/argocd/values/*.yaml]
E --> F[ArgoCD reconcile]
F --> G([GKE rollout])
- Push to
cashless-v2on the parent repo or any submodule. - GitHub Actions runs per-service CI (
.github/workflows/ci-*.yml) and builds a Docker image taggedsha-<12 hex>pushed to GHCR. - Argo CD Image Updater detects the new tag and writes it to
deploy/argocd/values/<service>.yaml, committing back tocashless-v2. - ArgoCD reconciles the Application and rolls out the new image into
the
cashlessnamespace on GKE. - Cluster ingress (
services/cashless-ingress) fronts every host on a single static IP with a Google ManagedCertificate.
For end-to-end deploy debugging see
OPERATIONS.md.
CI matrix¶
All Python-service CI lives in the parent monorepo at .github/workflows/:
| Workflow | Purpose |
|---|---|
python-ci.yml |
Reusable: uv install, ruff, mypy (soft-fail), pytest. |
docker-build.yml |
Reusable: buildx → GHCR with provenance + SBOM. |
helm-lint.yml |
Reusable: helm lint + helm template. |
ci-cashless-*.yml |
Per-service: chains lint → helm-lint → docker-build. |
ci-marketplace-* etc. |
Frontend CI: lint + type-check + Jest + Playwright. |
Observability¶
OpenTelemetry end-to-end:
- Browser SDK in every frontend ships traces + RUM to the collector.
- Backend services export OTLP traces + metrics.
otel-collectorreceives OTLP and fans out to Prometheus + Cloud Trace.- kube-prometheus-stack scrapes everything else.
Grafana dashboards live in services/cluster-bootstrap/grafana/ and are
provisioned at bootstrap time.