> ## Documentation Index
> Fetch the complete documentation index at: https://cona.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Flows & Trust Boundaries

> Where customer and financial data travels, which boundaries it crosses, and which third parties process it

# Data Flows & Trust Boundaries

The auditor-facing view. Same system as [System Context](/architecture/system-context),
organised by **where data goes and who can see it** rather than by component.

## Trust zones

```mermaid theme={null}
flowchart LR
    subgraph Public["Zone 0 — public internet"]
        Customer["Document recipients"]
        Providers["Marketplaces · PSPs · banks"]
    end

    subgraph Tenant["Zone 1 — authenticated tenant"]
        OrgUser["Organisation users<br/>Auth0 session, scoped to org_id"]
        WebApp["@cona/webapp"]
    end

    subgraph TokenZone["Zone 2 — token-scoped"]
        Portal["@cona/portal<br/>share token + PLZ + signed cookie"]
    end

    subgraph Privileged["Zone 3 — cross-tenant"]
        Console["@cona/console<br/>requireSuperadmin"]
    end

    subgraph Internal["Zone 4 — no inbound public access"]
        Workers["temporal-workers<br/>Fly.io, no public port"]
        DB[("Supabase Postgres")]
        Redis[("Redis")]
        Storage[("Supabase Storage")]
    end

    Customer -->|"share link"| Portal
    OrgUser -->|"Auth0"| WebApp
    Providers -->|"OAuth callbacks<br/>signed webhooks"| WebApp
    Providers -->|"polled by activities"| Workers

    WebApp --> DB
    WebApp --> Redis
    WebApp --> Storage
    Portal --> DB
    Console --> DB
    Workers --> DB
    Workers --> Redis
    Workers --> Storage

    classDef boundary fill:#f8fafc,stroke:#94a3b8,color:#334155

    classDef actor fill:#eceff4,stroke:#64748b,color:#111827
    classDef app fill:#dbe2fb,stroke:#3B56C5,color:#111827
    classDef data fill:#fde8e8,stroke:#c53b3b,color:#111827
    classDef async fill:#e3f7ea,stroke:#2f9e5c,color:#111827
    classDef external fill:#fff4dd,stroke:#c98a12,color:#111827

    class Customer,OrgUser actor
    class Providers external
    class WebApp,Portal,Console app
    class Workers async
    class DB,Redis,Storage data
    class Public,Tenant,TokenZone,Privileged,Internal boundary
```

| Zone           | Authentication                                      | Scope             |
| -------------- | --------------------------------------------------- | ----------------- |
| 1 — tenant     | Auth0 session via `proxy.ts`                        | one `org_id`      |
| 2 — token      | share token **and** postal code, then signed cookie | one document set  |
| 3 — privileged | Auth0 + `requireSuperadmin()`                       | all organisations |
| 4 — internal   | none inbound — no public port                       | —                 |

## Inbound data

```mermaid theme={null}
flowchart TB
    subgraph Sources["Sources"]
        Shop["Marketplaces<br/>orders, customers, addresses"]
        Psp["PSPs<br/>payments, payouts"]
        Bank["Banks via finAPI<br/>transactions"]
        Csv["CSV upload<br/>by the user"]
    end

    Adapter["Provider adapter<br/>fetch + transform"]
    Pipeline["Shared ingestion pipeline<br/>customers → addresses → dedupe<br/>→ documents → line items"]
    Docs[("documents · line_items<br/>entities · addresses")]
    Queue[("accounting_work_queue")]
    GL[("general_ledger")]

    Shop --> Adapter
    Psp --> Adapter
    Bank --> Adapter
    Csv --> Adapter
    Adapter --> Pipeline --> Docs --> Queue --> GL

    classDef boundary fill:#f8fafc,stroke:#94a3b8,color:#334155

    classDef external fill:#fff4dd,stroke:#c98a12,color:#111827
    classDef async fill:#e3f7ea,stroke:#2f9e5c,color:#111827
    classDef data fill:#fde8e8,stroke:#c53b3b,color:#111827
    class Shop,Psp,Bank,Csv external
    class Adapter,Pipeline async
    class Docs,Queue,GL data
    class Sources boundary
```

Personal data enters at the customer and address steps. Everything downstream is
financial.

## Outbound data

Only four paths send data out of CONA. Each is a deliberate, user-initiated or
user-configured action.

| Destination               | Carries                                  | Trigger                                 |
| ------------------------- | ---------------------------------------- | --------------------------------------- |
| **Resend / org SMTP**     | document PDFs, customer email addresses  | document delivery                       |
| **Customer portal**       | documents, scoped by share token         | delivery profile                        |
| **Google Drive / Sheets** | exported tabular data                    | user action, `api/export/google-sheets` |
| **Mirakl marketplaces**   | invoice documents (OR74)                 | auto-submit workflow                    |
| **Vercel AI Gateway**     | reconciliation context for agent scoring | copilot enabled                         |

**DATEV is not on this list.** The DATEV export generates files the user downloads; no
CONA code calls a DATEV API.

## Subprocessors

Third parties that process customer or financial data.

| Service               | Role                            | Data                                      |
| --------------------- | ------------------------------- | ----------------------------------------- |
| **Vercel**            | hosting for 3 Next.js apps      | all request traffic                       |
| **Fly.io** (`fra`)    | worker compute                  | all synced data in transit                |
| **Supabase**          | Postgres + object storage       | full dataset, documents, attachments      |
| **Temporal Cloud**    | workflow orchestration          | workflow inputs — ids and sync parameters |
| **Redis**             | cache, counters, locks          | cached reads, rate-limit counters         |
| **Auth0**             | identity                        | user identities, MFA enrolment            |
| **Resend**            | transactional email             | recipient addresses, document attachments |
| **Axiom**             | logs and metrics                | application, security, and activity logs  |
| **Sentry**            | error tracking (webapp only)    | stack traces, request context             |
| **PostHog**           | product analytics (webapp only) | usage events                              |
| **Vercel AI Gateway** | model routing                   | agent prompt context                      |
| **UploadThing**       | legacy file store, read-only    | pre-migration attachments                 |

Providers connected by a customer (Shopify, Amazon, Stripe, …) are data **sources**, not
subprocessors — CONA reads from them under the customer's own credentials.

## Personal data

| Data              | Tables                                          | Notes                             |
| ----------------- | ----------------------------------------------- | --------------------------------- |
| Customer identity | `entities`, `contacts`                          | name, customer number             |
| Contact details   | `email_addresses`, `phone_numbers`, `addresses` | delivery + invoice addresses      |
| Bank details      | `customer_ibans`, `customer_iban_evidence`      | accumulated from reconciliation   |
| Portal access     | document share tokens                           | plus postal code as second factor |
| CONA users        | `users`, `actors`                               | Auth0 subject, per-org actor rows |

Postal codes are used as the portal's second authentication factor — `verifyEntityPlz`
compares against the entity's stored address.

## Deletion and retention

| Flow                       | Mechanism                            | Queue            |
| -------------------------- | ------------------------------------ | ---------------- |
| Shopify customer redaction | `processCustomerRedactionWorkflow`   | `gdpr`           |
| Shopify shop redaction     | `processShopRedactionWorkflow`       | `gdpr`           |
| Shopify data request       | `processCustomerDataRequestWorkflow` | `gdpr`           |
| Organisation deletion      | `deleteOrganizationWorkflow`         | `org-deletion`   |
| Retention expiry           | `deleteExpiredAmazonDataWorkflow`    | `data-retention` |

The three Shopify GDPR webhooks are the mandated endpoints, verified by HMAC and sitting
outside the auth proxy. See [Ingress](/architecture/ingress-oauth-webhooks).

Organisation deletion is triggered from the [Console](/architecture/console-architecture)
and executed by a Temporal workflow.

## Tenant isolation

Isolation is by `org_id` in application queries, not by database-level row security.

<Warning>
  Three things an isolation review must account for:

  1. **`csv_import_batches` uses `organization_id`**, not `org_id`.
  2. **Four tables have no tenancy column** and are scoped only through a parent FK —
     `csv_import_records`, `document_relations`, `inventory_item_history`,
     `revenue_recognition_entries`.
  3. **Console is deliberately cross-tenant** and bypasses `@cona/core` entirely.

  See [Data Model](/architecture/data-model) and
  [Auth, Tenancy & Actors](/architecture/auth-tenancy-actors).
</Warning>

## Controls at the edge

| Control                        | Where                                              |
| ------------------------------ | -------------------------------------------------- |
| Auth0 session enforcement      | `webapp proxy.ts`                                  |
| CSP nonce per request          | `webapp proxy.ts:22`                               |
| HSTS, Permissions-Policy       | `webapp` and `console` `vercel.json`               |
| Webhook signature verification | Stripe, Shopify HMAC, Stripe App                   |
| Rate limiting                  | portal PLZ + download + Shopify entry; `atomic.ts` |
| Maintenance gate               | operational config, read on every request          |
| Dev route blocking             | 404 outside dev/staging                            |
| Privileged access logging      | `/admin`, `/dev` → Axiom security dataset          |

<Warning>
  **Portal sets no CSP, no HSTS, and no `Permissions-Policy`** — the weakest header posture of the
  three Vercel apps, on the only publicly reachable surface. Its authentication is sound; this is a
  header hardening gap. See [Portal](/architecture/portal-architecture).
</Warning>

## Notes

**Workers have no inbound public surface.** The `:8080/health` endpoint is an internal Fly
Machine check, not behind Fly Proxy.

**Secrets are not in the repository.** `NEXT_PUBLIC_AXIOM_TOKEN`, `UPLOADTHING_TOKEN`, and
`ENCRYPTION_KEY` are documented in `fly.prod.toml` as `fly secrets set` values.

**Everything runs in the EU.** Fly workers are pinned to `fra`.
