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.
3.1 KiB
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
ApiErrorhandlers for simulation/report blueprints; removed the frozen exception behavior that causedFrozenInstanceErrorwhile 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_idandowner_user_id; legacy tasks without metadata fail closed. ApiErrormust 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.pyas a source-level regression gate. - Verification: backend 67 passed, frontend Node contract tests 10 passed, Vite build PASS, Python compileall PASS,
git diff --checkPASS. npm testwas attempted but the repository has notestscript; the supportednode --test tests/*.mjscommand passed.- Reviewer status remains
VERIFICATION BLOCKEDuntil the fresh independent reviewer returns a readable schema-valid terminal verdict. deleg_289b16cealso 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.pyreran 1 passed. Reviewerdeleg_e0e7bac1was narrowed via steering and remains the active pending gate.