⬡ SPOC · ARCHITECTURE & REQUEST PATH
flowchart LR
U[Client / agent] -->|GET page| CDN[(Vercel CDN · static index, cities.json, gyst.js)]
U -->|POST /api/flow · ≤256 UUIDs| F[Vercel Function · Node, 128 MB, 5 s max · runs on AWS Lambda]
F --> D[PARSE: decode 128 bits]
D --> R{namespace?}
R -->|this city| A[accepted]
R -->|other city| W[forwarded: reply names spoc.city]
R -->|unknown| H[forwarded: hub aggregator]
D -->|bad bits| B[blocked]
A & W & H & B --> RC[SHA-256 receipt chain]
RC -->|JSON response| U
F -.->|one log line per request| L[(Vercel Runtime Logs / Observability)]
Why it can't get chatty
| rule | how |
|---|---|
| no outbound calls | a SPOC never calls another SPOC; forwarding is a field in the reply |
| no background work | no cron, queues, polling, heartbeats or LLM calls; nothing runs unless a request arrives |
| bounded work | ≤256 UUIDs and ≤32 KB per request, 128 MB, 5 s max; pure bit math (~µs per UUID) |
| cache first | pages and cities.json are static; /api/spoc is CDN-cached for a day |
| observable | each /api/flow logs {evt:"spoc.flow", spoc, n, counts, conserved, head, ms}; filter Runtime Logs on spoc.flow |
Endpoints
| host | role |
|---|---|
| spoc.austinsays.com · spoc.sonomasays.com · spoc.newyorksays.com · spoc.londonsays.com · spoc.tokyosays.com | SPOC_ENDPOINT 0x1F0 |
| says-spoc.vercel.app (any other host) | Hub Aggregator view, SPOC_AGGREGATOR 0x1F1 |