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

# Architecture and data flow

> End-to-end path from a consumer action in a partner app to a Swapnice profile or intent.

This is the system a partner integrates with: a Cloudflare Workers Partner API, Durable Object coordination for consent and per-customer event order, D1 as the system of record, and generated SDKs on top of the OpenAPI contract.

## System context

```mermaid theme={null}
flowchart TB
    subgraph partner["Partner"]
        App["Partner app + SDK"]
        Backend["Partner backend"]
    end

    subgraph swapnice["Swapnice Partner platform"]
        API["Partner API"]
        SDKGen["TypeScript and Python SDKs"]
    end

    subgraph edge["Cloudflare"]
        GW["Gateway"]
        Auth["Auth"]
        Ingest["Ingest"]
        Consent["Consent"]
        Read["Read"]
        Catalog["Catalog"]
        DO["Durable Objects"]
        D1["D1 archive"]
        Q["Archive queue"]
    end

    App --> API
    Backend --> API
    SDKGen -.-> App
    SDKGen -.-> Backend
    API --> GW
    GW --> Auth
    GW --> Ingest
    GW --> Consent
    GW --> Read
    GW --> Catalog
    Ingest --> DO
    Consent --> DO
    Ingest --> Q
    Consent --> Q
    Q --> D1
    Read --> D1
    Backend --> App
```

The consumer Swapnice app (Firebase, wallet, NFC) is a different system. Partner traffic does not go there.

## End-to-end consumer path

The sequence below is the path a technical review should walk: user action → consent → event → archive → profile → partner product.

```mermaid theme={null}
sequenceDiagram
    participant User as Consumer
    participant App as Partner app + SDK
    participant API as Partner API
    participant DO as Consent + event DOs
    participant Q as Archive queue
    participant D1 as D1
    participant Prod as Partner product

    User->>App: Opens app, starts Swapnice connect
    App->>API: POST /v1/connection-sessions
    API-->>App: connection_url, client_token
    User->>API: Authorizes + grants purposes
    App->>API: POST /v1/consent-receipts
    API->>DO: Persist grant

    User->>App: Completes a product action
    App->>API: POST /v1/events + Idempotency-Key
    API->>DO: Consent check, FIFO sequence
    DO-->>App: 202 accepted
    DO->>Q: event_archive
    Q->>D1: Persist claim

    App->>API: GET /v1/profiles/:id?consent_purpose=...
    API->>D1: Load archived events
    API-->>App: Resolved facts, confidence, alternatives
    App->>Prod: Permissioned facts and intents
```

## 1. Consumer interaction

A user does something in the partner product: views a collection, checks out, labels a fandom, or walks a stadium flow. The SDK observes only events you registered. Nothing is sent until a consent receipt exists for that purpose.

## 2. Connect and consent

```mermaid theme={null}
sequenceDiagram
    participant Partner as Partner app
    participant Consent as Consent worker
    participant Session as ConnectionSessionObject
    participant User as User
    participant Auth as Auth worker
    participant Grant as CustomerConsentObject

    Partner->>Consent: POST /v1/connection-sessions
    Consent->>Session: create
    Session-->>Partner: session_id, connection_url
    User->>Auth: OAuth authorize PKCE
    Auth-->>Partner: authorization code / token
    Partner->>Consent: POST /v1/consent-receipts
    Consent->>Grant: grant purposes
    Grant-->>Partner: receipt_id
```

Connection sessions expire. Consent can later be revoked in part or in full. After revoke, ingest and purpose-scoped reads fail closed.

## 3. Event acceptance

```mermaid theme={null}
sequenceDiagram
    participant Partner as SDK or backend
    participant Ingest as Ingest worker
    participant Events as CustomerEventObject
    participant Consent as CustomerConsentObject
    participant Q as Archive queue

    Partner->>Ingest: POST /v1/events
    Ingest->>Events: ingest
    alt same Idempotency-Key
        Events-->>Ingest: replayed result
    else new event
        Events->>Consent: allows(purpose, receipt)
        Consent-->>Events: granted or denied
        Events->>Events: persist + sequence
        Events->>Q: event_archive
        Events-->>Ingest: 202 accepted
    end
```

Guarantees partners can rely on:

* **FIFO per app + customer.** Events for one customer go through one Durable Object.
* **Idempotent writes.** Retries do not duplicate durable effects.
* **Consent at ingest.** No receipt, no accept.
* **Fast ACK.** Partners are not blocked on archive or profile recompute.

## 4. Profile resolution

V1 resolves profiles at read time from archived D1 events. There is no separate profile-recompute Durable Object yet.

```mermaid theme={null}
sequenceDiagram
    participant Partner as Partner backend
    participant Read as Read worker
    participant Consent as CustomerConsentObject
    participant D1 as D1

    Partner->>Read: GET /v1/profiles/:id?consent_purpose=personalization
    Read->>Consent: effective purposes
    alt purpose not granted
        Read-->>Partner: 403 consent_required
    else granted
        Read->>D1: listCustomerEvents
        Read->>Read: group by attribute
        Read->>Read: winner = highest confidence, then most recent
        Read-->>Partner: facts, evidence, alternatives
    end
```

The same gate applies to `/claims` and `/intents`.

## 5. Partner product output

```mermaid theme={null}
flowchart LR
    Facts["Resolved facts"] --> PartnerUX["Partner app personalization"]
    Intents["Intent scores"] --> Recs["In-app next-step prompts"]
```

The handoff is:

1. Swapnice returns permissioned profiles and intents for **connected, consented** users.
2. The partner uses those reads inside its own product.
3. Revoked purposes fail closed on ingest and purpose-scoped reads.

## Split-worker map

Production routes through a gateway. Local development can run a single worker.

| Path prefix                                                                                | Worker  | Role                       |
| ------------------------------------------------------------------------------------------ | ------- | -------------------------- |
| `/.well-known/*`, `/oauth/*`                                                               | Auth    | Discovery, PKCE, tokens    |
| `/v1/events*`                                                                              | Ingest  | Ordered, idempotent accept |
| `/v1/connection-sessions*`, `/v1/consent-receipts*`                                        | Consent | Sessions and grants        |
| `/v1/profiles*`, `/v1/workflows*`                                                          | Read    | Synchronous intelligence   |
| `/v1/apps*`, `/v1/customers*`, `/v1/entries*`, `/v1/ontologies*`, `/v1/webhook-endpoints*` | Catalog | Configuration and catalog  |

## Persistence

| Layer                     | Holds                                                        | Not for                       |
| ------------------------- | ------------------------------------------------------------ | ----------------------------- |
| Durable Object SQLite     | Sessions, effective consent, recent event order, idempotency | Long-term analytics           |
| D1                        | Apps, tokens (hashed), customers, event archive, workflows   | Per-request locks             |
| Queue + projection worker | Write-behind archive and revocation cascades                 | Synchronous partner ACKs      |
| In-memory worker state    | Nothing durable                                              | Auth, consent, or idempotency |

## Security expectations

* OAuth 2.1 authorization code + PKCE (`S256`)
* Short-lived access tokens, hashed secrets and tokens at rest
* Exact redirect URI match
* Scoped tokens (`events:write`, `profile:read`, …)
* Revocable consent, purpose-checked ingest and reads
* Idempotency keys on mutating routes
* Correlation / request ids on errors
* No leakage of wallet, payment, or private identity fields

## Related

* [Integration and sample code](/partners/integration)
* [Data collection](/partners/data-collection)
* [Outputs](/partners/outputs)
