Skip to content

Cloud Platform Architecture ​

Scope: This page covers the Phony Cloud technical architecture — the control-plane/data-plane split, the stack for each side, security, and API design. For the overall tech stack and OSS components, see Tech Stack. For the platform-level view, see Cloud Platform.

Implementation status

Everything on this page is target design. The Rust engine and CLI exist; the control plane, the agent's cloud protocol, and all hosted services are not built.


System Architecture ​

Phony Cloud is two systems with a deliberately narrow interface:

  • Control plane (hosted by Phony): a thin metadata service — dashboard, orchestration, job state, PII inventory, audit, compliance reports, billing. It never touches customer row data.
  • Data plane (customer infrastructure): the phony agent, a single static Rust binary that does all data work locally and makes outbound-only connections to the control plane.
┌─────────────────────────────────────────────────────────────────────────┐
│                     PHONY CLOUD ARCHITECTURE                             │
│                (thin hosted control plane + local data plane)            │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  CONTROL PLANE (hosted)                                                  │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │                                                                    │  │
│  │   Web Dashboard            Control API           Mock API          │  │
│  │   (Nuxt 3 + Vue 3 + TS)    (Go)                  Server (Go)       │  │
│  │   • Auth (Auth.js)         • /api/v1/*           • hosted,         │  │
│  │   • Billing (Stripe/       • agent gRPC            synthetic       │  │
│  │     Paddle)                  endpoint               data only      │  │
│  │   • Project / PII UI       • job scheduler                         │  │
│  │                            • webhook dispatch                      │  │
│  │                                                                    │  │
│  │   ┌────────────────────────────────────────────────────────────┐   │  │
│  │   │  PostgreSQL — jobs, schemas, column classifications,       │   │  │
│  │   │  snapshot catalog, audit log, report artifacts, billing    │   │  │
│  │   │  (METADATA ONLY — never row data, credentials, or models)  │   │  │
│  │   └────────────────────────────────────────────────────────────┘   │  │
│  └───────────────────────────────▲───────────────────────────────────┘  │
│                                  │ outbound-only gRPC/HTTPS              │
│                                  │ (agent dials out; nothing dials in)   │
│  DATA PLANE (customer infrastructure)                                    │
│  ┌───────────────────────────────┴───────────────────────────────────┐  │
│  │                    PHONY AGENT (Rust, static binary)               │  │
│  │                                                                    │  │
│  │   ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────────┐  │  │
│  │   │  Schema   │  │ Transform │  │ Snapshot  │  │   N-gram      │  │  │
│  │   │ Analyzer  │  │ Pipeline  │  │  Engine   │  │   Engine +    │  │  │
│  │   │ (FK, PII) │  │ (stream)  │  │           │  │   Trainer     │  │  │
│  │   └───────────┘  └───────────┘  └───────────┘  │  ~5M rec/sec  │  │  │
│  │                                                └───────────────┘  │  │
│  │   DB connectors: PostgreSQL, MySQL/MariaDB, SQLite                 │  │
│  │   Storage: local disk / customer S3-GCS (snapshots, models)        │  │
│  │   Also runs standalone via CLI (no cloud account needed)           │  │
│  └────────────────────────────────────────────────────────────────────┘  │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

The interface between the planes is small by design: the agent pulls job specs and pushes status, schema metadata, column classifications, and report artifacts. That is the entire protocol surface — which is what makes the privacy claim auditable.


Technology Stack ​

CONTROL PLANE (hosted, thin)          DATA PLANE (customer infra)
├── Nuxt 3 dashboard                  ├── phony agent (Rust, stable)
│   ├── Vue 3 + Composition API       │   ├── single static binary
│   ├── TypeScript                    │   │   (musl / MSVC targets)
│   ├── Tailwind CSS                  │   ├── embedded N-gram engine
│   ├── Auth.js (authentication)      │   ├── DB drivers (Postgres,
│   └── Stripe SDK (billing)          │   │   MySQL/MariaDB, SQLite)
├── Go control API                    │   ├── S3/GCS clients (BYO storage)
│   ├── job/schedule orchestration    │   └── outbound gRPC/HTTPS client
│   ├── agent gRPC endpoint           ├── licensed per organization
│   └── webhook dispatch              │   (offline license file for
├── Go Mock API server                │    air-gapped Enterprise)
│   └── embeds Rust engine (CGO)      └── distributed via curl installer,
└── PostgreSQL (metadata store)           Homebrew, Docker image

DEPLOYMENT
├── Dashboard: Vercel or Docker
├── Control API + Mock API: Docker / Kubernetes (small footprint —
│   no data workloads means no data-plane scaling problem)
├── Agent: runs on customer hosts, CI runners, or a VM next to the DB
└── Enterprise: the entire control plane ships as a self-hostable
    Docker Compose / Helm bundle (air-gap capable)

Why This Stack? ​

ComponentChoiceRationale
DashboardNuxtVue familiar, TypeScript, easy deploy
Control APIGoFast HTTP/gRPC, simple ops; carries only metadata, so it stays small
AgentRustOne binary, no runtime deps — critical for "run this inside your prod network"; maximum engine performance (5M rec/sec); memory safe next to production data
No Go in the data plane—Earlier drafts split sync workers (Go) from the engine (Rust FFI). With the data plane local-first, a single Rust binary is simpler to distribute, audit, and harden
Metadata storePostgreSQLBoring, reliable; the control plane's state is small
BillingStripe SDKAfter Delaware C-Corp incorporation (see Operations)

Billing Strategy (Phased) ​

PhaseRevenueMethodNotes
Early$0-10K MRRPaddle (MoR)No company needed, 5% + $0.50 fees
Growth$10K+ MRRStripe BillingAfter Delaware C-Corp via Stripe Atlas

Note: See Operations for full incorporation timeline.


Security Model ​

The security story has two halves that must not be conflated: customer data security (structural — it never leaves their network) and control-plane security (conventional SaaS hardening, applied to metadata).

Customer Data: Never Leaves Your Network ​

┌─────────────────────────────────────────────────────────────────┐
│                    DATA-PLANE SECURITY                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Structural guarantees (architecture, not policy):               │
│  ├── Row data is read, transformed, and written by the agent    │
│  │   inside the customer network — no cloud hop exists          │
│  ├── The agent makes OUTBOUND-only connections; no inbound      │
│  │   ports, SSH tunnels from the cloud, or VPC peering          │
│  ├── DB and storage credentials are agent-local config          │
│  │   (env vars / files / OS keychain) — never sent to the cloud │
│  ├── PII-detection samples are analyzed in-process, discarded   │
│  └── Trained models stay in customer storage; the cloud sees    │
│      only name + schema hash                                    │
│                                                                  │
│  Agent hardening:                                                │
│  ├── Static binary, reproducible builds, signed releases        │
│  │   (checksums + signature published per release)              │
│  ├── Minimal privileges: needs only DB creds you give it and    │
│  │   egress to the control plane (one documented endpoint)      │
│  ├── Egress allowlist-friendly: single hostname, gRPC/HTTPS 443 │
│  ├── No telemetry beyond the documented metadata protocol       │
│  └── Fully operable offline via CLI (cloud is optional)         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Control Plane: Conventional Hardening for Metadata ​

┌─────────────────────────────────────────────────────────────────┐
│                    CONTROL-PLANE SECURITY                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  At-rest encryption (AES-256) applies to what the cloud holds:  │
│  ├── Schema metadata + column classifications                   │
│  ├── Report artifacts (PII inventory, KVKK/GDPR packs)          │
│  ├── Job history and audit log                                  │
│  └── (There is no row data to encrypt — it is not here)         │
│                                                                  │
│  API keys & agent identity:                                      │
│  ├── API keys hashed (bcrypt) — original never stored           │
│  ├── Prefix visible for identification (pk_xxx...)              │
│  ├── Revocable per-key, scoped permissions (read/write/admin)   │
│  └── Agents authenticate with per-agent tokens, revocable       │
│      from the dashboard (kill switch for a lost host)           │
│                                                                  │
│  Access control (control plane):                                 │
│  ├── RBAC roles (see Team & Collaboration below)                │
│  ├── SSO / SAML (Business+), enforced MFA option                │
│  └── Audit log of every control-plane action                    │
│                                                                  │
│  Data residency:                                                 │
│  ├── Row data residency is MOOT — rows stay wherever the        │
│  │   customer's own infrastructure is                           │
│  ├── METADATA residency remains: EU orgs → eu.phony.cloud       │
│  │   (Frankfurt), US orgs → us.phony.cloud (Virginia)           │
│  └── Enterprise: self-hosted control plane = full residency     │
│      control, including air-gapped                              │
│                                                                  │
│  Retention (metadata):                                           │
│  ├── Job logs: 90 days                                          │
│  ├── Report artifacts: until deleted by user                    │
│  └── Audit logs: 1 year (Enterprise: configurable)              │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Enterprise: Self-Hosted Control Plane ​

Enterprise is not a different product — it is the same thin control plane, shipped as a deployable bundle (Docker Compose / Helm) and run inside the customer's network. Air-gapped installs use an offline license file and receive agent/control-plane updates as signed artifacts. Because the control plane holds only metadata, self-hosting it is operationally light.


API Design ​

Versioning Strategy ​

┌─────────────────────────────────────────────────────────────────┐
│                    API VERSIONING                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Strategy: URL Path Versioning                                   │
│                                                                  │
│  Current: /api/v1/...                                           │
│  Future:  /api/v2/...                                           │
│                                                                  │
│  Versioning Rules:                                               │
│  ├── Major version in URL (/v1, /v2)                            │
│  ├── Breaking changes require new major version                 │
│  ├── Additive changes allowed within version                    │
│  ├── Deprecation notice 6 months before removal                 │
│  └── Minimum 12 months support for each version                 │
│                                                                  │
│  The agent↔control-plane gRPC protocol is versioned              │
│  independently; agents negotiate on connect and old agents      │
│  keep working across control-plane deploys.                     │
│                                                                  │
│  Headers:                                                        │
│  ├── X-API-Version: Returns current version                     │
│  ├── X-Deprecation-Date: If endpoint deprecated                 │
│  └── X-Rate-Limit-*: Rate limiting info                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Webhook System ​

Webhooks are dispatched by the control plane from job-status metadata (payloads carry counts and durations, never data):

┌─────────────────────────────────────────────────────────────────┐
│                    PHONY CLOUD WEBHOOKS                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Available Events:                                               │
│  ├── sync.started      - Sync job began (on an agent)           │
│  ├── sync.completed    - Sync job finished successfully         │
│  ├── sync.failed       - Sync job failed                        │
│  ├── snapshot.created  - Snapshot captured (metadata recorded)  │
│  ├── model.trained     - Local model training complete          │
│  ├── report.ready      - PII inventory / compliance pack ready  │
│  └── api.deployed      - Mock API deployment complete           │
│                                                                  │
│  Webhook Payload:                                                │
│  {                                                              │
│    "event": "sync.completed",                                   │
│    "timestamp": "2026-01-15T10:30:00Z",                         │
│    "project_id": "proj_abc123",                                 │
│    "data": {                                                    │
│      "job_id": "job_xyz789",                                    │
│      "agent_id": "agt_local01",                                 │
│      "rows_processed": 150000,                                  │
│      "duration_seconds": 45                                     │
│    }                                                            │
│  }                                                              │
│                                                                  │
│  Security:                                                       │
│  ├── HMAC-SHA256 signature in X-Phony-Signature header          │
│  ├── Timestamp validation (reject >5 min old)                   │
│  ├── Retry with exponential backoff (3 attempts)                │
│  └── Webhook secret per endpoint                                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

CLI Authentication ​

The CLI and the agent share credentials; both work fully offline against local databases — cloud auth is only needed for control-plane features.

┌─────────────────────────────────────────────────────────────────┐
│                    CLI AUTHENTICATION                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Method 1: API Key (Recommended for CI/CD)                       │
│  $ export PHONY_API_KEY=pk_live_xxxxx                           │
│  $ phony sync start --project my-project                        │
│                                                                  │
│  Method 2: OAuth Device Flow (Interactive)                       │
│  $ phony login                                                  │
│  → Opens browser: phony.cloud/device                            │
│  → Enter code: ABCD-1234                                        │
│  → Authenticated! Token stored in ~/.phony/credentials          │
│                                                                  │
│  Method 3: Config File                                           │
│  # ~/.phony/config.yaml                                         │
│  api_key: pk_live_xxxxx                                         │
│  default_project: my-project                                    │
│                                                                  │
│  Token Storage:                                                  │
│  ├── Stored in ~/.phony/credentials (chmod 600)                 │
│  ├── Encrypted with OS keychain when available                  │
│  └── Environment variable takes precedence                      │
│                                                                  │
│  CLI Commands:                                                   │
│  $ phony login          # OAuth flow                            │
│  $ phony logout         # Clear credentials                     │
│  $ phony whoami         # Show current user                     │
│  $ phony agent run      # Run the agent (daemon mode)           │
│  $ phony sync start     # Start sync job (local data plane)     │
│  $ phony sync status    # Check sync status                     │
│  $ phony snapshot list  # List snapshots (from catalog)         │
│  $ phony snapshot restore <id>  # Restore snapshot              │
│  $ phony mock start     # Local mock API server (no cloud)      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

CI/CD Integration ​

Because the agent is a static binary, "CI integration" means running the data plane on the CI runner itself — the runner connects to the databases it can already reach, and reports status to the control plane.

┌─────────────────────────────────────────────────────────────────┐
│                    CI/CD NATIVE INTEGRATION                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  GitHub Actions:                                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  - name: Refresh staging data                            │    │
│  │    uses: phonycloud/sync-action@v1                        │    │
│  │    with:                                                 │    │
│  │      project: my-project                                 │    │
│  │      api-key: ${{ secrets.PHONY_API_KEY }}              │    │
│  │      subset: 1%                                          │    │
│  │      wait: true                                          │    │
│  │  # Runs the phony agent ON the runner — data flows       │    │
│  │  # runner→DB, only status flows to the control plane     │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  GitLab CI:                                                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  refresh_test_data:                                      │    │
│  │    image: phonycloud/agent:latest                         │    │
│  │    script:                                               │    │
│  │      - phony sync start --project $PROJECT --wait        │    │
│  │    variables:                                            │    │
│  │      PHONY_API_KEY: $PHONY_API_KEY                       │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Generic (any CI):                                               │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  # Install the agent binary                              │    │
│  │  curl -fsSL https://phony.cloud/install.sh | bash        │    │
│  │                                                          │    │
│  │  # Or use Docker                                         │    │
│  │  docker run phonycloud/agent sync start --project X       │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Ephemeral environments per CI run (never metered):              │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  phony env spawn --from snap_abc123 --ttl 2h             │    │
│  │  # fresh DB from an anonymized snapshot, per test run    │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Supported Platforms:                                            │
│  ├── GitHub Actions (native action)                             │
│  ├── GitLab CI (Docker image)                                   │
│  ├── Bitbucket Pipelines (Docker image)                         │
│  ├── Jenkins (CLI or Docker)                                    │
│  ├── CircleCI (Orb planned)                                     │
│  └── Azure DevOps (CLI or Docker)                               │
│                                                                  │
│  Webhook Triggers:                                               │
│  ├── On sync complete → trigger test suite                      │
│  ├── On sync fail → alert Slack/Teams                           │
│  └── On snapshot create → notify team                           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Disaster Recovery & Backup ​

The blast radius of a control-plane outage is deliberately small: the data plane keeps working (the CLI drives the agent directly), and no customer data is at risk because none is hosted.

┌─────────────────────────────────────────────────────────────────┐
│                    DISASTER RECOVERY                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Control-plane data (metadata store):                            │
│  ├── Daily automated backups                                    │
│  ├── Point-in-time recovery (7 days)                            │
│  ├── Cross-region replication (Enterprise)                      │
│  └── RTO: 4 hours, RPO: 1 hour                                  │
│                                                                  │
│  During a control-plane outage:                                  │
│  ├── Agents keep running scheduled jobs from last-known config  │
│  ├── CLI drives the agent directly (sync, snapshot, restore)    │
│  ├── Local mock server unaffected                               │
│  └── Only dashboards, scheduling changes, and reports pause     │
│                                                                  │
│  Customer data (never hosted — nothing for Phony to lose):       │
│  ├── Snapshots: in customer storage, customer bucket policy     │
│  ├── Models: in customer infra, exportable .ngram files         │
│  ├── Schemas & sync configs: JSON export/import                 │
│  └── No vendor lock-in: OSS engine uses exported models         │
│                                                                  │
│  Incident Response:                                              │
│  ├── Status page: status.phony.cloud                            │
│  ├── Incident notification via email                            │
│  ├── Post-incident reports (Enterprise)                         │
│  └── Scheduled maintenance windows (announced 48h ahead)        │
│                                                                  │
│  SLA Guarantees (control plane + hosted Mock API):               │
│  ├── Free/Starter: Best effort                                  │
│  ├── Team: 99.5% uptime                                         │
│  ├── Business: 99.9% uptime                                     │
│  └── Enterprise: self-hosted — your SLA is your ops             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Team & Collaboration Features ​

RBAC, SSO, and audit are control-plane features — they govern who can configure and trigger data-plane work, not the data itself.

┌─────────────────────────────────────────────────────────────────┐
│                    TEAM COLLABORATION                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Roles:                                                          │
│  ├── Owner     - Full access, billing, delete org               │
│  ├── Admin     - Manage members + agents, all project access    │
│  ├── Developer - Create/edit projects, run syncs                │
│  └── Viewer    - Read-only access, view logs & reports          │
│                                                                  │
│  Permissions Matrix:                                             │
│  ┌────────────────┬───────┬───────┬───────┬────────┐           │
│  │ Action         │ Owner │ Admin │ Dev   │ Viewer │           │
│  ├────────────────┼───────┼───────┼───────┼────────┤           │
│  │ View projects  │   ✓   │   ✓   │   ✓   │   ✓    │           │
│  │ Create project │   ✓   │   ✓   │   ✓   │   ✗    │           │
│  │ Run sync       │   ✓   │   ✓   │   ✓   │   ✗    │           │
│  │ Edit schema    │   ✓   │   ✓   │   ✓   │   ✗    │           │
│  │ Register agent │   ✓   │   ✓   │   ✗   │   ✗    │           │
│  │ Manage members │   ✓   │   ✓   │   ✗   │   ✗    │           │
│  │ Billing        │   ✓   │   ✗   │   ✗   │   ✗    │           │
│  │ Delete org     │   ✓   │   ✗   │   ✗   │   ✗    │           │
│  └────────────────┴───────┴───────┴───────┴────────┘           │
│                                                                  │
│  Audit Logging:                                                  │
│  ├── Who did what, when (incl. agent registrations/revocations) │
│  ├── IP address and user agent                                  │
│  ├── Searchable and exportable                                  │
│  └── Retention: 90 days (Business: 1 year)                      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Phony Cloud — Documentation & Specification