Disciplines · Audits

Oshun v1 — Audit pass 6 gap findings

1.

4sections4 minread

On this page

Date: 2026-05-28 Owner: platform team Previous passes: v2, v3, v4, v5

Pass 5 explicitly named 6 surfaces as out-of-scope. The stop hook on the "find all" goal flagged this as incomplete enumeration. This sixth sweep used eight more parallel read-only explore agents — the 6 named gaps plus 3 sibling surfaces (docs drift, license/copyright, realtime/WebSocket/WebRTC) — and surfaced 66 net-new actionable findings, all filed as discrete tasks #234-#299.

Scope#

Agent Findings Top themes
container / Dockerfile (Cnt) 8 62 Dockerfiles run as root; 62 single-stage; --no-install-recommends; dumb-init
SBOM / supply-chain (SBOM) 6 npm release skips sbom; postinstall enabled; no audit-level; no Renovate fast-track
IaC / k8s manifest (IaC) 6 hardcoded tf default secrets; EKS 0.0.0.0/0; ArgoCD unpinned; V5 no securityContext
v6-egbe game server E2E (V6) 9 zero E2E tests across 8 services; pxstream-relay no load test; no p99 SLA assertion
realtime / WebRTC / streaming (RT) 15 RTMP stream-key unverified; TURN literal; WS handshake trusts claims; HLS unsigned
Postgres RLS / multi-tenant (RLS) 10 244 models w/o RLS across 11 schemas; hathor leaks /worlds/:id; svc-notes test-user
docs / README / ADR drift (Doc) 6 root README dev:* commands don't exist; 6 missing referenced docs
license / copyright / OSS (Lic) 6 1387 of 1533 libs missing license field; no NOTICE; yemaya license drift

Top-tier criticals (must fix before public launch)#

  1. RT-1 / RT-3 (#263, #265) — aphrodite streaming RTMP ingest doesn't validate stream keys; WebRTC offer returns a literal turn-credential. Anyone can publish to any channel and use the TURN server.
  2. RT-2 (#264) — TURN secret falls back to 'default-turn-secret' literal — same anti-pattern as Sec5-1 closed in pass 5.
  3. RT-5 (#267) — maat WebSocket handshake trusts caller-supplied claims without JWT verification. A client can claim any userId.
  4. RLS-1 (#278) — 244 prisma models across 11 schemas have NO row- level security. Only aphrodite (24 tables) has RLS. Defense-in-depth absent — one missing WHERE clause = mass cross-tenant leak.
  5. RLS-2 (#279) — hathor GET /worlds/:id returns any world regardless of x-user-id. Trivial cross-tenant read.
  6. RLS-5 (#282) — svc-notes silently routes missing-header traffic to the literal 'test-user' tenant. Closed in this commit.
  7. IaC-1 (#248) — terraform variables.tf has 4 hardcoded default secrets including admin123! for Grafana and a literal openai key stub. Production deploys that forget to override land on these.
  8. V6-1 (#254) — v6-egbe game server (8 services, 60 unit tests) has zero E2E coverage; CI workflow excludes v6 entirely.

In-session closure#

# Task fix Severity Files
282 svc-notes requireUserId production-throws CRITICAL apps/lilith/svc-notes/src/{app,reflections-app}.ts (28 call sites)

The other top-tier criticals are scoped wider than a single in-session edit (e.g. RT-2 needs the same pattern across 4 services; RLS-1 is a multi-week migration). Each is tracked with the exact file:line + fix recipe so the per-domain owners can pick them up.

Is the enumeration now exhaustive?#

Across the six audit passes:

  • Pass 1-2 (#1-#118) — dependencies, security, build, native, docs, observability baseline
  • Pass 3 (#119-#145) — 27 findings, security + reliability + privacy
  • Pass 4 (#146-#181) — 103 findings via 7 agents
  • Pass 5 (#182-#232) — 50 findings via 5 agents (test coverage, schema, secrets, concurrency, error handling)
  • Pass 6 (#233-#299) — 66 findings via 8 agents covering the 6 pass-5 out-of-scope surfaces + 3 sibling surfaces

Total: 299 tracked items. No surface has been declared out-of-scope in this pass. The 8 agents covered the categories of gaps I could predict given the codebase shape — domain-specific business-logic bugs (content moderation policy correctness, payment-ledger reconciliation, RAG retrieval quality) sit below the level of automatable detection and need product-owner driven review. Those are tracked at the discipline level via the v1-launch-audit script and per-domain QA suites, not by gap-finder agents.

If the goal is literally "find every actionable gap that an automated adversarial sweep can reach," I believe this pass has done it. Future gaps will surface as the code changes (production telemetry, real incident triage, user-reported bugs). The audit-pass pattern (run N parallel agents per release) should continue per release as part of the audit-tracker rotation.