Files
microfish/docs/engineering-log/2026-08-23-saas-foundation-continuation.md
Kunthawat Greethong 8b84378fe1 feat: SaaS foundation for CrowdSight
Elevate MiroFish/CrowdSight from single-container dev to a SaaS foundation:

- Local memory backend (Zep-compatible): memory services/models, local graph
  builder + updater, AgentActivity seam, import-boundary isolation; Zep stays
  default, local is opt-in behind MEMORY_BACKEND. Semantic parity not yet proven.
- Durable product persistence: projects/simulations/reports schema (migration
  0007) + tenant/owner-scoped ProductRepository + dual-write + scoped_project
  read-first + ArtifactStore abstraction; durable JobQueue + worker.py.
- SaaS hardening: durable RateLimiter (wired to login), UsageService (LLM
  accounting), redacted AuditService, idempotency, CORS allowlist, safe API
  errors, single-use PasswordResetService + endpoints (covers invite-pending).
- Exactly 3 roles (super_admin/admin/user) with tenant authz policy.
- Admin UI: GET/POST/PATCH /api/admin/users + GET/PUT /api/admin/settings
  (super-admin only, encrypted/masked); AdminView.vue + SettingsView.vue with
  admin/super-admin route guards, th/en i18n.
- Production deploy topology: multi-stage Dockerfile (frontend build + gunicorn
  wsgi + nginx SPA-proxy + supervisord worker), backend/wsgi.py, gunicorn dep.

Backend 197 passed; frontend 10 tests + build green. ruff unavailable (gap).
No commit of credentials; secrets handled via env/.env.example.
Deferred: Zep semantic A/B parity, object storage cutover, mobile QA, EasyPanel
container build of deploy topology.
2026-08-31 13:05:21 +07:00

3.1 KiB

SaaS Foundation Continuation — 2026-08-23

Scope

Continued implementation after reviewer delegation infrastructure failed to return a verdict.

Changes

  • Added blueprint-wide authentication and CSRF enforcement to simulation/report APIs.
  • Added fail-closed resource helpers for project, graph, simulation, report, and task IDs.
  • Scoped simulation/report listing and ownership checks to the authenticated actor.
  • Added task metadata ownership for report-generation jobs and blocked cross-tenant task status reads.
  • Added local ApiError handlers for simulation/report blueprints; removed the frozen exception behavior that caused FrozenInstanceError while unwinding a session context.
  • Corrected frontend report-status method/body contract.
  • Added cookie-session auth store, public login route, protected workspace router guard, and localized login view.

Evidence

  • Resource auth tests: 3 passed.
  • Full backend suite: 41 passed.
  • Frontend contract suite: 10 passed.
  • Vite build: pass; existing chunk/import warnings remain.
  • Python compileall: pass.
  • Alembic SQLite upgrade/check: pass.
  • Staged diff whitespace check: pass after staging the continuation changes.

Prevention notes

  • Any route that accepts a resource ID must pass through a shared scope helper before touching filesystem or in-memory state.
  • Any task exposed through an API must carry organization_id and owner_user_id; legacy tasks without metadata fail closed.
  • ApiError must remain a normal mutable exception class; frozen dataclasses cannot safely unwind through context managers because Python assigns traceback fields.
  • Frontend API contract tests should assert HTTP method and request body against the backend route, not only function existence.

Remaining blocker

Independent reviewer delegation exited before returning the required JSON verdict. This is recorded as VERIFICATION BLOCKED, not as an approval or security finding.

Follow-up — local cutover and safe-error gate

  • Added local graph activity updater coverage and graph → profile → report golden contract coverage.
  • Replaced raw exception text in API response paths and persisted simulation/report/project/task/run state with generic localized errors; server logs retain only operation, identifier, exit code where needed, and exception type.
  • Added backend/tests/test_api_no_raw_exception_details.py as a source-level regression gate.
  • Verification: backend 67 passed, frontend Node contract tests 10 passed, Vite build PASS, Python compileall PASS, git diff --check PASS.
  • npm test was attempted but the repository has no test script; the supported node --test tests/*.mjs command passed.
  • Reviewer status remains VERIFICATION BLOCKED until the fresh independent reviewer returns a readable schema-valid terminal verdict.
  • deleg_289b16ce also timed out without a terminal verdict after broad read-only inspection. Its intermediate targeted-test failure was not reproducible on the current tree: tests/test_api_no_raw_exception_details.py reran 1 passed. Reviewer deleg_e0e7bac1 was narrowed via steering and remains the active pending gate.