Files
microfish/docs/test-evidence/2026-08-23-saas-foundation.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.5 KiB

SaaS Foundation Batch Evidence — 2026-08-23

Branch: feat/saas-foundation Scope: locale/error foundation, identity schema/session, auth/admin API, project/graph/simulation/report/task scope, frontend login guard, report API contract, local memory schema/repository, strict LLM extraction contract Status: in progress — reviewer gate blocked by delegation owner exits; simulation/report/task scope and login foundation are now implemented, but Zep replacement and durable SaaS storage are not complete

Verified commands

Command Result
PYTHONPATH=backend uv run --project backend --python 3.11 pytest backend/tests -q 55 passed
node --test frontend/tests/i18n-contract.test.mjs frontend/tests/api-error.test.mjs frontend/tests/report-api-contract.test.mjs frontend/tests/auth-contract.test.mjs 10 passed
npm run build PASS; existing chunk-size and pendingUpload import warnings remain
python3.11 -m compileall -q backend/app backend/migrations PASS
alembic upgrade head on temporary SQLite database PASS; revisions 0001_identity, 0002_sessions applied
alembic check on temporary SQLite database PASS; no new upgrade operations
git diff --cached --check via subprocess PASS
text-artifact CJK gate PASS; binary icon excluded and visually checked as graphic-only

Delivered production surfaces

  • th/en locale policy; legacy zh normalizes to Thai
  • structured API errors and raw request-body redaction
  • SQLAlchemy identity/organization/membership/session models
  • Alembic migrations
  • Argon2 password hashing
  • HttpOnly session cookie + signed CSRF cookie/header check
  • /api/auth/login, /api/auth/me, /api/auth/logout
  • /api/admin/users GET/POST with role policy and redacted serializer
  • tenant/owner fields and scoped lookup/list for projects
  • auth + owner scope on graph project get/list/delete/reset and graph build/ontology entry points
  • blueprint-wide auth + CSRF enforcement on simulation/report APIs
  • fail-closed project/simulation/report/task scope checks for IDs in paths, query strings, and JSON bodies
  • frontend auth store, /login route, protected workspace route guard, and localized login view
  • report-status frontend client corrected to POST { task_id, simulation_id }
  • durable local memory tables (memory_graphs, memory_episodes, memory_nodes, memory_edges) and tenant-scoped SQLAlchemy repository
  • strict Pydantic LLM extraction schema, bounded prompt builder, JSON parser, and deterministic extraction-to-repository service
  • golden parity fixture for LocalEntityReader and LocalMemoryTools.quick_search against the legacy entity/search output shapes
  • explicit MEMORY_BACKEND=local switch for simulation entity routes and preparation; default remains zep until migration completes
  • SimulationManager entity-reader injection and worker-owned local-reader session lifecycle
  • explicit CORS allowlist with credential support

Known incomplete surfaces

  • Existing product resources still use filesystem/in-memory persistence; no durable simulation/report/job tables yet.
  • Legacy route handlers still return raw str(e) in some untouched modules.
  • No admin user-management UI or super-admin settings UI yet.
  • No durable worker queue or object-storage artifact layer.
  • Zep dependency/runtime remains; local memory schema/contract exists, but GraphBuilder/ProfileGenerator/ReportAgent consumers have not been switched.
  • Independent reviewer verdict is blocked: delegation owners exited before recording JSON results.