Commit 5821a3e8 by PLN (Algolia)

docs(tasks): archive the platform session (#42 deploy, #43 scopes, #33 onboard, #45 observability)

Rich entries for the api.nech.pl platform build-out: first erable deploy +
clone3/seccomp gotcha, the realm:domain:path scope convention + central
enforcement, Shipow onboarding, and the observability stack (capture + admin
analytics + public uptime). Source material for the documentary.
parent 06353568
...@@ -255,3 +255,61 @@ memory `project_douanier_api`. Named after Le Douanier Rousseau (the customs gat ...@@ -255,3 +255,61 @@ memory `project_douanier_api`. Named after Le Douanier Rousseau (the customs gat
- **Learnings:** a hand-written zero-dep client beats generated bloat for ~11 simple multipart - **Learnings:** a hand-written zero-dep client beats generated bloat for ~11 simple multipart
routes; the snapshot-drift test keeps hexa's spec honest as routes evolve. 60/60 tests. routes; the snapshot-drift test keeps hexa's spec honest as routes evolve. 60/60 tests.
- **Deps:** unblocks #33 (onboard hexa); needs #42 deploy to be live-callable. - **Deps:** unblocks #33 (onboard hexa); needs #42 deploy to be live-callable.
## #42 — Deploy douanier:latest to erable → green /audio/v1/healthz
- **Done:** First real deploy of the CPU image to erable (pln@nech.pl). Image transferred via
`docker save | ssh erable docker load`, run loopback-only on 127.0.0.1:9780. Registered
/openapi.json + /docs as public gateway routes (nechapi 89586eb). DEPLOY.md gotchas captured
(Tidal fbe1742). Green end-to-end: healthz/openapi/docs 200, authed 401 without token.
- **Learnings:** TWO erable traps — (1) `--security-opt seccomp=unconfined` is MANDATORY:
Docker 19.03/kernel 4.9 default seccomp blocks the `clone3` syscall that python:3.12-slim's
glibc 2.36 uses for pthread_create → container boots uvicorn then SIGSEGVs (exit 139) /
"OpenBLAS pthread_create … Operation not permitted". (2) pin OPENBLAS/OMP/NUMEXPR/MKL
_NUM_THREADS=1. The _platform service sidesteps #1 by being Alpine/musl on purpose. Data
volume = ~/srv/douanier/data (no sudo for /srv; pure transient cache).
- **Deps:** unblocked #33; the keystone for the whole live API.
## #43 — Hierarchical scope convention (realm:domain:path) + central enforcement + CLI/docs
- **Done:** Convention `realm:domain:path` (realm=api|admin|future mail/data); required scope
DERIVED from the path (api:audio:analyze:emotion), subtree wildcards (*, api:*, api:audio:*),
non-wildcard=exact, api:* never grants admin:*. Canonical matcher `_platform/scopes.py` vendored
byte-identical into `armada/api/scopes.py` (drift-guarded). Audio app: per-route scope strings
replaced by ONE path-derived `require` dependency + footgun fix (missing X-Scopes → "" not "*").
CENTRAL enforcement deployed in `_auth` (derive + 403). CLI validates scopes + `check` cmd.
nechapi 104748f, Tidal 4197696. Verified: hexa api:*→200, admin admin:*→403 on audio, no-id→401.
- **Learnings:** PLN chose a top-level REALM (vs flat domain root) to future-proof for non-API
capabilities (mail, personal data). Path-derived scopes = maintenance-free access control
(add a route, its scope exists). The realm split is what lets a customer hold api:* (everything
API) while admin stays a separate sealed plane. Tenant migration caveat: the active `maps`
token has OLD-style geo:read/route — must become api:geo:* BEFORE geo joins the gateway.
- **Deps:** built on #37 platform reframe; enables clean multi-API + selling seats.
## #33 — Onboard Shipow / hexa (the MVP delivery)
- **Done:** hexa minted as tenant 3, plan pro, scope api:* (full platform access). Verified
end-to-end through https://api.nech.pl/audio/v1 with his real token: /me, /features (cache
miss→hit), /analyze/emotion. Branded onboarding PDF (clients/onboarding.html template →
chromium --print-to-pdf; rendered PDF gitignored as it carries the token). Tidal b225ba7.
- **Learnings:** platform tokens DON'T expire (the schema has no expiry — revoke-by-prefix
instead), so the old "31-day" idea didn't apply. Token plaintext is shown ONCE at mint (only
the sha256 is stored). Onboarding artifact is transitional — PLN's stance: Scalar /docs +
landing will replace the PDF; "only token distribution matters." Client SDK renamed
Douanier→NechAPI (umbrella + .audio namespace) + header X-Douanier-Cache→X-Nech-Cache so the
internal codename never reaches a consumer.
- **Deps:** was blocked by #42 (deploy) + #43 (scopes); closes the EPIC's MVP.
## #45 — Platform observability: usage analytics, security monitoring, uptime status landing
- **Done:** (1) CAPTURE — `_auth` logs EVERY attempt to usage_log (status 200/401/403 + reason +
client ip; tenant_id nullable; quota counts 200 only); migration +reason +ip +health_checks.
(2) ADMIN ANALYTICS (admin:*-gated, self-authed): /admin/usage (totals, by-tenant, top routes,
14d series) + /admin/security (rejects by reason, offender IPs, recent rejects). (3) PUBLIC
STATUS — api.nech.pl/ now renders per-API up/down + uptime% (24h/7d/30d) from a 60s background
probe → health_checks; ca-certificates added for the https probe. nechapi e489d26. Verified:
landing renders, admin endpoints return real data, hexa api:*→403 on /admin (plane sealed),
rejects logged with source IP.
- **Learnings:** before this, _auth returned early on reject and logged NOTHING — a total
security blind spot; logging the decision (not just authorized calls) is the foundation.
Probing the PUBLIC healthz URL (not loopback) measures the real edge a caller sees — and a
container can't reach the host's 127.0.0.1 anyway. nginx reload briefly fails one probe → a
small transient uptime dip that self-heals. The admin/api realm split makes /admin trivially
safe (an api:* token is auto-403'd).
- **Deps:** built on #43 (admin realm) + #45 capture; Grafana visual layer scheduled as #46.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment