Disciplines · Audits

Oshun V1 — Audit Pass 2 (2026-05-28)

Also noted (not yet ticketed):

9sections5 minread

On this page

This is the second comprehensive gap audit after the original v1 audit landed 89 fixes (tracked as tasks #1–#89). This pass covered five dimensions in parallel — security, reliability/observability, data/performance/testing, build/deploy/compliance/ops, and code quality/docs/config — and produced the issue list below.

Findings were captured as tasks #90–#118. Status: closed (in batch 1a, 1b, and follow-ups): #90–#92, #94, #96–#97, #103–#104, #109, #118. open at end of pass: #93, #95, #98–#102, #105–#108, #110–#117.

Security#

ID Severity Finding Path
90 Medium UI demo apiKey constant was named _live and matched a real-credential pattern apps/demeter/web/src/pages/settings/IntegrationSettingsPage.tsx:372
91 Critical svc-tts /v1/admin/* routes were authenticated at USER tier; USER tokens could trigger scale + read GPU metrics apps/lilith/svc-tts/src/app.impl.ts:134, 4187+
92 Critical svc-moderation had no authentication at all/v1/admin/model/filters/batch could be POSTed unauthenticated to swap moderation filters apps/lilith/svc-moderation/src/app.ts:84
93 Critical Payment webhook handlers (Stripe, CCBill, etc.) processed without verifying provider signatures — comments said // TODO: Verify webhook signature apps/aphrodite/payment/src/routes/webhooks.ts:19, 53, 63, 73, 83
94 High svc-tts /v1/admin/autoscaling/scale read req.body as anytarget_instances not validated apps/lilith/svc-tts/src/app.impl.ts:214
95 High No rate limiting on svc-auth /v1/auth/oauth/callback or password-reset paths apps/lilith/svc-auth/src/auth-endpoints.ts:103

Reliability + Observability#

ID Severity Finding Path
96 High OAuth service fetch(token_endpoint) + fetch(userinfo_endpoint) had no AbortSignal.timeout — could hang login indefinitely apps/lilith/svc-auth/src/oauth-service.ts:226, 257
97 High Google Play receipt validation fetch had no timeout apps/lilith/svc-payment-orchestrator/src/iap/iap-routes.ts:114
98 Medium veritas/video server didn't drain in-flight requests on SIGTERM; no request-ID middleware apps/veritas/video/src/server.ts:363
99 Medium 20+ console.log calls in veritas/ingestion, social, bellona/bridge-unity main entrypoints apps/veritas/ingestion/src/main.ts:90+
100 Low svc-auth hardcodes LilithLogger config without reading LOG_LEVEL apps/lilith/svc-auth/src/server.ts:25
101 Medium veritas/video has no Prometheus /metrics endpoint (veritas/agents does) apps/veritas/video/src/server.ts
102 High lilith/bff has shutdown handler but no /health route apps/lilith/bff/src/server.ts:54
103 Medium svc-auth in-memory oauthStateTokens Map could grow unbounded under attack apps/lilith/svc-auth/src/oauth-service.ts:75

Data / Performance / Testing#

ID Severity Finding
104 High aphrodite/admin user + moderation count() paged with Number.MAX_SAFE_INTEGER
105 High 7 Prisma schemas lack a migrations/ folder (veritas, arete, nisaba, psyche, v3/tara-studio, v3/lilith-commons, v3/saraswati-stage)
106 High 5 audit-log tables (bellona, hathor, isis, sophia, yemaya) have no TTL/expires + no scheduled purge
107 Critical scripts/db-backup.sh only covers Postgres; Redis sessions + queues are not backed up
108 Critical No documented S3/MinIO backup strategy for user uploads + project files

Also noted (not yet ticketed):

  • Schema drift across 5 model names (User, Notification, Device, AuditLog, AuthUser) appearing in multiple schema.prisma files with divergent fields. Consolidation needs a contracts-team decision.
  • Missing compound indexes on (userId, status), (primaryDomain, isDefault), (primaryDomain, createdAt), (status, createdAt) on hot paths in iris, yemaya.
  • Foreign-key fields (Sophia.Document.ownerId, Bellona.Build.workerId/userId/orgId) declared as String without @relation, so cascade behavior is wrong.
  • No load tests for iris/api, lilith/svc-ai, lilith/svc-conversation, oshun/bff — only tara/api has a test/load/api-load.k6.js script.
  • No chaos tests anywhere.
  • 11 packages still ship a jest.config.* (Jest→Vitest migration partial).

Build / Deploy / CI#

ID Severity Finding
115 Medium Multiple services have a Dockerfile but no adjacent .dockerignore (yemaya/api, nyx/api, others)
116 Medium deploy.yml, iris-ci.yml, deploy-ecs.yml, security-deps-and-secrets.yml run on every push to main without a paths: filter
117 Low CI uses pnpm install --frozen-lockfile but doesn't add an explicit git diff pnpm-lock.yaml reproducibility check

Also noted:

  • V5 service Dockerfiles use floating tags (FROM node:24-slim) instead of digest pins.
  • No SBOM generation in all build workflows (only iris/psyche invoke sbom-and-sign.yml).
  • No .github/actions/ composite actions; the same pnpm + Node + cache pattern is duplicated across 130+ workflows.
  • Required status checks not documented in CONTRIBUTING.md or PR template.

Compliance / Operations#

ID Severity Finding
110 Medium 15+ runbooks under docs/runbooks/ with no index
111 High No central SLO doc — per-domain uptime % / p95 latency / error budgets undocumented
112 High No central docs for log retention windows, alert routing (Slack/PagerDuty), on-call rotation
113 Critical No PII inventory and no GDPR data-subject-request endpoint registry
114 Medium No docs/DEPRECATIONS.md listing patterns slated for removal

Code Quality#

Not individually ticketed (mostly maintenance debt):

  • 3,427 any types across production code (worst offender: svc-community-translation/app.ts with 193).
  • 1,362 @ts-ignore + 61 @ts-expect-error checked in.
  • 4,354 .skip / xit / xdescribe test-skip directives.
  • 3 very large files (oshun/bff/src/admin/state.ts at 30,824 lines — generated; svc-ai/src/providers/civitai/model-type-manager.ts at 19,667 lines — model enums; lilith/sdk/src/generated/openapi.ts at 22,434 lines — generated).
  • formatDate, slugify, hashString reimplemented across 50+ files instead of consumed from libs/shared.

Documentation#

  • 10 of 12 API services lack a libs/openapi/docs/<domain>/openapi.yaml (only yemaya + nyx have one).
  • No app-level CHANGELOG.md files.
  • No per-domain CONTRIBUTING guides for high-volume domains (iris, lilith, isis).

Configuration#

  • tsconfig targets mix ES2020, ES2022, ESNext.
  • 1,667 of 1,756 package.json files lack an engines field.
  • 11 packages still have a jest.config.* alongside the broader Vitest migration.

Methodology#

Each finding was produced by one of four parallel agents working from the repo root, with explicit "already-fixed list" context so the prior 89 closed tasks weren't re-reported. Each agent was instructed to return high-signal (80%+ confidence) findings with absolute paths, line numbers, code excerpts, specific risk, and suggested fix. The findings here are a deduplicated and prioritised compilation of the four agent reports.