ARCHITECTURE NOTE · ARC-110
One request, explicit boundaries, one correlation trail.
This note follows public HTTPS traffic through the gateway, loopback origin, static or API routing, browser verification, identity resolution, input and policy checks, persistence, audit, and the final response.
1. Entry and routing
The public gateway owns transport on the public HTTPS address and forwards eligible web traffic to the Nginx origin on 127.0.0.1:8443. Nginx terminates the local TLS 1.3 origin connection, applies response policy, serves static content, and proxies only /api/* to 127.0.0.1:8090.
Public HTTPS → gateway classification → loopback TLS origin → static file or local Control API → structured responseA separate Nginx listener on 127.0.0.1:8091 accepts only the fixed Turnstile Siteverify path from the local API and performs the outbound TLS verification request. It is not publicly reachable. The API process therefore retains its localhost-only systemd network policy.
The API and origin are not bound to additional public application ports. Static documentation never receives session database access.
2. Identity boundary
The login route validates a single-use Turnstile token and checks its hostname and action before credential verification. Privileged identities then receive a short-lived second-factor challenge. Successful authentication creates a random opaque token; only its SHA-256 digest is persisted. Authenticated routes resolve the digest to the user and assigned role on every request.
| Request class | Identity requirement | Additional check |
|---|---|---|
| Public documentation | None | Static route allowlist |
| Status and health | None | Read-only response |
| Password submission | Assigned username | Turnstile success, hostname, action, and rate window |
| Console reads | Active session | Route and role where required |
| Mutations | Active session | Origin, CSRF, role, input, and rate checks |
3. Request validation
Body-bearing routes accept JSON objects with an explicit media type and a 64 KiB maximum. Transfer encoding is rejected. Resource kinds, required fields, names, regions, action identifiers, control characters, and encoded size are validated before a database transaction or audit success event.
Unsupported HTTP methods return a structured 405 response. Unknown API paths return 404; they do not fall back to the console shell.
4. Persistence and audit
SQLite stores session digests, control records, settings, recovery cases, and audit events. Each request uses a short-lived connection. Mutation transactions use parameterized statements. Audit records contain UTC time, actor, action, resource, outcome, request ID, and a keyed source digest; they exclude credentials, session tokens, MFA values, and request bodies.
5. Response construction
API responses are compact JSON with Cache-Control: no-store, a request identifier, MIME protection, and a fixed error envelope. Session cookies use the __Host- prefix, Secure, HttpOnly, SameSite=Strict, and host-wide path without a Domain attribute.
6. Failure behavior
- Gateway unavailable
- Public web and gateway traffic fail before reaching the loopback origin.
- Origin unavailable
- The gateway cannot complete the local web handoff; the API remains unexposed.
- API unavailable
- Static documentation may remain available while readiness fails.
- Database unavailable
- Authenticated state operations fail closed; no browser fallback supplies authority.
- Validation failure
- No mutation is committed and a structured request ID is returned.
Operational