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.5 KiB
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/enlocale policy; legacyzhnormalizes 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/usersGET/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,
/loginroute, 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
LocalEntityReaderandLocalMemoryTools.quick_searchagainst the legacy entity/search output shapes - explicit
MEMORY_BACKEND=localswitch for simulation entity routes and preparation; default remainszepuntil migration completes SimulationManagerentity-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.