Files
graph-requirements-planner/.planning/research/SUMMARY.md
ANDREW HOSFORD 0e8978f48c Update project files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 11:59:48 -05:00

322 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Project Research Summary
**Project:** req-planner v2.0 - Multi-Tenancy & User Accounts
**Domain:** Requirements management tool with collaborative features
**Researched:** 2026-03-18
**Confidence:** HIGH
## Executive Summary
The req-planner v2.0 upgrade adds user accounts, invite-only registration, role-based access control, and project sharing to an existing FastAPI + SQLAlchemy + SQLite stack. Research shows this is a **well-documented migration pattern** with established best practices from 2026. The core architecture requires minimal new dependencies (pwdlib, email-validator) and leverages existing JWT infrastructure. The main risk is **tenant isolation failures** — forgetting to filter queries by user context is the #1 cause of data leaks in multi-tenant systems. The recommended approach uses shared-schema multi-tenancy with explicit query filtering, three-tier RBAC (owner/editor/viewer), and refresh token rotation for security.
**Critical Success Factor:** Build tenant-scoped query patterns from day one. Every query must filter by user ownership or project membership. SQLite's limitations (no Row-Level Security) require manual enforcement, making systematic testing essential. The good news: this migration is additive — existing single-user functionality remains intact during the transition, allowing incremental deployment.
**Key Recommendation:** Structure the roadmap in dependency order: (1) Authentication foundation with user accounts, (2) Tenant isolation with project ownership, (3) RBAC for sharing, (4) Polish with attribution and invites. This sequence minimizes risk by validating tenant isolation before adding sharing complexity.
## Key Findings
### Recommended Stack
The existing stack (FastAPI, SQLAlchemy 2.0, SQLite, PyJWT, Angular 17) is optimal for this use case. **Only two new dependencies required:**
**Core additions:**
- **pwdlib (Argon2)** — Password hashing, replaces deprecated passlib. FastAPI official docs recommend it as of 2026. Argon2 is GPU-resistant and OWASP-approved.
- **email-validator** — Required for Pydantic EmailStr validation. Standard for registration forms.
- **secrets (stdlib)** — Cryptographically secure invite token generation using `token_urlsafe(32)` for 256-bit randomness.
**No library needed (use patterns instead):**
- Multi-tenancy via SQLAlchemy query filters with `user_id` FK (SQLite doesn't support PostgreSQL Row-Level Security)
- RBAC via Enum + FastAPI dependency injection (three roles don't justify a library like Casbin)
- Edit attribution via `modified_by_user_id` column on existing `requirement_history` table
- Email sending via stdlib `smtplib` + FastAPI BackgroundTasks (Celery is overkill)
**Critical decision:** Stick with SQLite until 100+ concurrent users or 10GB+ database. WAL mode supports unlimited concurrent readers + 1 writer, sufficient for small team collaboration. Migration to PostgreSQL adds operational complexity — delay until necessary.
### Expected Features
**Must have for v2.0 launch (table stakes):**
- Individual user accounts with email/password authentication
- Invite-only registration with admin-generated tokens (security requirement for self-hosted)
- Per-user project ownership with workspace isolation (core multi-tenancy)
- Three-tier RBAC (owner/editor/viewer) on projects
- Edit attribution in history showing who made each change
- Project sharing UI with role assignment
- Password reset flow (expected security hygiene)
- Permission enforcement on both backend and frontend
**Should have for v2.x (competitive differentiators):**
- Activity feeds per project ("what changed since I last logged in")
- Workspace-level dashboard aggregating user's projects
- Anonymous viewer links for sharing with clients without accounts
- Granular audit trail with per-edit rollback capabilities
**Defer to v3+ (future consideration):**
- Fine-grained permission customization beyond three tiers
- Inherited permissions on requirement hierarchy (complex to implement correctly)
- Organization/team hierarchies for enterprise customers
- OAuth/SSO providers
- Real-time collaborative editing (major architectural change)
**Anti-features (commonly requested but problematic):**
- Real-time collaborative editing: Massive architectural lift, requires WebSockets and operational transforms
- Organization hierarchies: Dramatically increases permission complexity
- Social login (OAuth): Complicates self-hosted deployments
- Field-level permissions: Explosion of permission checks, confusing UX
### Architecture Approach
The recommended architecture uses **four layers:** Authentication (user identity via JWT with refresh tokens), Authorization (RBAC via junction tables), Tenant Isolation (explicit query filtering by user context), and Migration Strategy (backwards-compatible schema changes). The key pattern is **shared-schema multi-tenancy** — single database with `user_id` columns and explicit filters, rather than database-per-tenant (which performs worse on SQLite's single-writer model).
**Major components:**
1. **Authentication Layer** — Extends existing JWT system with user accounts, adds refresh tokens (15min access, 30-day refresh), invite token validation, password reset flow. Uses pwdlib for Argon2 hashing.
2. **User Context Injection** — FastAPI dependency `get_current_user()` extracts user_id from JWT, verifies user active, returns immutable `UserContext(user_id, email, is_admin)`. All routes receive current_user as dependency.
3. **Tenant-Scoped Queries** — Manual filtering pattern: `query(Project).filter((Project.owner_id == user_id) | (Project.members.any(user_id)))`. Explicit over implicit (no hidden session middleware). SQLite lacks Row-Level Security.
4. **RBAC Layer**`ProjectMember` junction table with role enum (owner/editor/viewer). Permission checks via `require_project_access(project_id, required_role)` dependency. Role hierarchy encoded: owner > editor > viewer.
5. **Migration Layer** — Add nullable `user_id` columns, seed default admin user, backfill existing data to admin, make columns NOT NULL. Dual auth during transition (old password endpoint + new email/password endpoint).
**Critical pattern:** Never trust client-provided user_id. Always extract from server-verified JWT. Never use global query filters in middleware (breaks admin operations, hard to debug). Never store refresh tokens in localStorage (XSS risk).
### Critical Pitfalls
1. **Forgetting tenant filters in queries**#1 cause of data leaks. Every SQLAlchemy query needs `.filter(user_id == current_user.id)` or project membership check. Missing a single filter exposes another user's data. **Mitigation:** Create base query functions enforcing tenant scoping, use integration tests with multiple users, code review checklist: "Does this query filter by tenant?"
2. **SQLite foreign key constraint failures during migration** — Adding `user_id` FKs to existing tables causes migration failures or silent data loss. SQLite's ALTER TABLE limitations force table recreation with CASCADE risks. **Mitigation:** Use Alembic batch mode, test migration on production data copy, have rollback plan, consider enforcing constraints at application level initially.
3. **Existing JWT tokens become invalid** — Deploying new auth invalidates all current sessions. Token payload structure changes (adding user_id) breaks old token format. **Mitigation:** Version tokens (`version: 2`), handle both formats during transition, communicate forced re-login window, consider token migration endpoint.
4. **Orphaned data without clear ownership** — Existing projects/requirements have no `owner_id`. Assigning all to admin is wrong, leaving NULL breaks constraints. **Mitigation:** Decide ownership strategy before migration (assign to admin, create shared workspace, copy to all users, or delete legacy data), document rationale, make reversible.
5. **Role explosion and privilege creep** — Starting with 3 roles (viewer/editor/owner) becomes dozens of overly-specific roles. Users accumulate permissions. **Mitigation:** Resist adding roles, use project-level assignments not feature-level, implement permission inheritance, audit roles quarterly, track role changes in audit log.
## Implications for Roadmap
Based on research, the roadmap should follow a **dependency-ordered sequence** that validates tenant isolation before adding sharing complexity. The architecture naturally divides into four milestones that can be developed incrementally with clear validation gates.
### Phase 1: Authentication Foundation
**Rationale:** User accounts are the prerequisite for all multi-tenancy features. Build the identity layer before touching data isolation.
**Delivers:** Users can register with invite tokens, login with email/password, receive JWT access + refresh tokens, and maintain sessions across browser sessions.
**Addresses (from FEATURES.md):**
- Individual user accounts with email/password authentication
- Invite-only registration (security requirement)
- Session management with refresh tokens
- Password reset flow
**Avoids (from PITFALLS.md):**
- Pitfall #3: JWT token invalidation (handle old token format gracefully)
- Pitfall #6: Invite system security weaknesses (cryptographically secure tokens, single-use, expiration)
**Implementation notes:**
- Create `users`, `invite_tokens`, `refresh_tokens` tables
- Implement pwdlib password hashing
- Add `/auth/register`, `/auth/login`, `/auth/refresh`, `/auth/logout` endpoints
- Update `get_current_user()` dependency to extract from JWT
- Seed default admin user in migration
**Research flag:** No additional research needed — well-documented pattern in FastAPI ecosystem.
### Phase 2: Tenant Isolation & Project Ownership
**Rationale:** Establish data separation before adding collaboration. Validate users can only see their own data before allowing sharing.
**Delivers:** Projects belong to specific users. Users see only projects they own. All queries filtered by user context. Existing data migrated to admin user.
**Addresses (from FEATURES.md):**
- Per-user project ownership with workspace isolation
- Basic permission enforcement (backend + frontend)
**Avoids (from PITFALLS.md):**
- Pitfall #1: Forgetting tenant filters (THE critical pitfall)
- Pitfall #4: Orphaned data without ownership
- Pitfall #10: Dependency injection scope leaks
**Implementation notes:**
- Add `owner_id` column to `projects` (nullable initially)
- Add `created_by_id`, `updated_by_id` to `requirement_nodes`
- Update all queries to filter by ownership
- Migration: Assign existing projects to admin (id=1)
- Make `owner_id` NOT NULL after backfill
- Integration tests: User A cannot access User B's projects
**Research flag:** No additional research needed — standard SQLAlchemy patterns.
### Phase 3: RBAC & Project Sharing
**Rationale:** Now that tenant isolation is validated, enable controlled sharing with role-based permissions.
**Delivers:** Project owners can invite collaborators with viewer/editor/owner roles. Permission checks enforce RBAC on all operations. UI shows user's role per project.
**Addresses (from FEATURES.md):**
- Three-tier RBAC (owner/editor/viewer)
- Project sharing UI with role assignment
- Edit attribution in history (who made each change)
**Avoids (from PITFALLS.md):**
- Pitfall #5: Role explosion (stick to 3 roles)
- Pitfall #8: Cascading deletes destroying shared data
- Pitfall #9: Missing edit attribution
**Implementation notes:**
- Create `project_members` junction table with role enum
- Add `POST /projects/{id}/members`, `GET /projects/{id}/members`, `DELETE /projects/{id}/members/{user_id}`
- Implement `require_project_access(project_id, required_role)` dependency
- Update all requirement routes to check RBAC
- Add `user_id` to `requirement_history` for attribution
- Update UI to display editor names and role badges
**Research flag:** RBAC patterns well-documented. May need phase-specific research for permission UI patterns if complex interactions emerge.
### Phase 4: Polish & User Management
**Rationale:** With core multi-tenancy working, add user-facing features that improve collaboration experience.
**Delivers:** Users can invite others to the platform. Admins can manage invites. History shows detailed edit attribution. Enhanced security with rate limiting.
**Addresses (from FEATURES.md):**
- Enhanced invite system (user-driven invites, not just admin)
- Improved edit attribution in history UI
- User profile management
- Security hardening (rate limiting, token cleanup)
**Avoids (from PITFALLS.md):**
- Pitfall #7: Frontend state management assumes single user
- Performance traps (N+1 queries, pagination)
**Implementation notes:**
- Add `POST /auth/invites` (users can invite others)
- Add `GET /auth/invites` (list sent invites)
- Integrate email sending (SMTP + BackgroundTasks)
- Add rate limiting to auth endpoints (slowapi)
- Scheduled task for token cleanup
- Update history UI with user avatars and "edited by" attribution
**Research flag:** Email integration may need focused research on SMTP providers, deliverability, and template design if building production-grade invite emails.
### Phase Ordering Rationale
**Why this order:**
1. **Authentication before isolation** — Can't isolate data without user identity
2. **Isolation before sharing** — Must prove single-user works before adding multi-user
3. **RBAC after ownership** — Roles are meaningless without established ownership model
4. **Polish last** — User-facing improvements after core functionality validated
**How this avoids pitfalls:**
- Validates tenant isolation (Pitfall #1) in Phase 2 before sharing in Phase 3
- Addresses data migration (Pitfall #4) early in Phase 2 when schema is simple
- Prevents role explosion (Pitfall #5) by defining minimal roles in Phase 3
- Frontend state management (Pitfall #7) addressed progressively across phases
**Dependency chain:**
- Phase 2 depends on Phase 1 (needs user_id from auth)
- Phase 3 depends on Phase 2 (needs project ownership to share)
- Phase 4 depends on Phase 3 (invites need roles to assign)
**Incremental deployment:**
Each phase is independently deployable. Phase 1 can launch without breaking existing single-user mode. Phase 2 migrates data but doesn't force collaboration. Phase 3 adds sharing as opt-in. Phase 4 enhances without breaking.
### Research Flags
**Phases with standard patterns (skip `/gsd:research-phase`):**
- **Phase 1 (Authentication):** FastAPI JWT auth is well-documented, official examples exist, pwdlib docs comprehensive
- **Phase 2 (Tenant Isolation):** SQLAlchemy query filtering is standard ORM practice, multi-tenancy patterns mature
- **Phase 3 (RBAC):** Three-role model is trivial, junction table pattern universal, permission checks straightforward
**Phases likely needing deeper research:**
- **Phase 4 (Email Integration):** If building production-grade invite emails, may need research on:
- SMTP provider selection (SendGrid vs Mailgun vs AWS SES)
- Email deliverability (SPF, DKIM, DMARC configuration)
- Template design and testing frameworks
- Invite link generation security (signed URLs, token rotation)
However, for MVP, stdlib `smtplib` is sufficient — defer detailed research until email features become critical path.
**Overall assessment:** This is a low-research-intensity roadmap. All core patterns are well-established. Only Phase 4 email features might warrant focused research if expanding beyond basic SMTP.
## Confidence Assessment
| Area | Confidence | Notes |
|------|------------|-------|
| Stack | **HIGH** | Recommendations verified against FastAPI official docs (2026), pwdlib is official replacement for passlib, SQLAlchemy 2.0 patterns stable. No experimental dependencies. |
| Features | **HIGH** | Feature categorization based on industry-standard collaboration tools (GitHub, Notion, Figma). Table stakes vs differentiators validated across multiple UX sources. Anti-features identified from documented failures. |
| Architecture | **HIGH** | Multi-tenancy patterns sourced from official guides, 2026 FastAPI tutorials, SQLAlchemy events documented. Dependency injection is core FastAPI feature. Refresh token rotation is OAuth 2.0 standard. |
| Pitfalls | **MEDIUM-HIGH** | Top pitfalls (#1 tenant filters, #2 SQLite migrations, #3 JWT invalidation) extensively documented across sources. Some pitfalls (#7 frontend state, #10 context scope) inferred from general patterns rather than domain-specific sources. |
**Overall confidence:** **HIGH**
The research is built on official documentation (FastAPI, SQLAlchemy, SQLite, Pydantic), authoritative 2026 guides, and multiple corroborating sources. Stack recommendations align with maintainer guidance. Architecture patterns are production-proven. Pitfalls are sourced from documented post-mortems and security analyses.
### Gaps to Address
**Minor gaps that need attention during implementation:**
1. **Email deliverability details:** Research covered email *sending* (smtplib) but not email *deliverability* (SPF/DKIM/DMARC setup). If invite emails must reach inbox (not spam), Phase 4 may need focused research on email infrastructure.
- **How to handle:** Start with simple SMTP in development, use established email service (SendGrid/Mailgun) in production, defer deliverability research until user reports spam issues.
2. **SQLite concurrency limits:** Research confirms WAL mode supports multiple readers + 1 writer, but exact concurrency threshold (when to migrate to PostgreSQL) is deployment-specific.
- **How to handle:** Monitor write contention in production (SQLITE_BUSY errors), plan PostgreSQL migration at 50+ concurrent writers or 10GB database, not earlier.
3. **Cascading delete policy:** Research identifies the risk (Pitfall #8) but ownership transfer strategy is product decision, not technical.
- **How to handle:** Decide in Phase 3 planning: transfer to co-owner, mark as archived, or require explicit reassignment before user deletion.
4. **Frontend state management details:** Research identifies risk (Pitfall #7) but Angular 17 specifics (Signals vs Services for user context) are implementation details.
- **How to handle:** Validate during Phase 2 frontend work, test user switching scenarios, follow Angular 17 best practices for auth guards.
5. **Password strength requirements:** Research recommends enforcement but exact policy (length, complexity) is security policy decision.
- **How to handle:** Implement OWASP-recommended baseline (8 chars, mixed case, numbers) in Phase 1, allow customization in Phase 4 if self-hosted users request it.
**No critical blockers identified.** All gaps are solvable during implementation without requiring additional research phases.
## Sources
### Primary (HIGH confidence)
**Official Documentation:**
- [FastAPI OAuth2 with JWT](https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/) — Official security tutorial for authentication patterns
- [pwdlib introduction](https://github.com/frankie567/pwdlib/discussions/1) — Modern password hashing, FastAPI's recommended replacement for passlib
- [Python secrets module](https://docs.python.org/3/library/secrets.html) — Secure token generation (stdlib)
- [Pydantic email validation](https://docs.pydantic.dev/latest/install/) — EmailStr documentation
- [SQLite WAL mode](https://www.sqlite.org/wal.html) — Official SQLite concurrency documentation
**2026 Technical Guides:**
- [Introduction to Multi-Tenant Design with FastAPI](https://blog.greeden.me/en/2026/03/10/introduction-to-multi-tenant-design-with-fastapi-practical-patterns-for-tenant-isolation-authorization-database-strategy-and-audit-logs/) — Comprehensive 2026 multi-tenancy patterns
- [Building a Modern User Permission Management System with FastAPI, SQLAlchemy 2.0](https://dev.to/mochafreddo/building-a-modern-user-permission-management-system-with-fastapi-sqlalchemy-and-mariadb-5fp1) — RBAC implementation guide
- [JWT in FastAPI, the Secure Way (Refresh Tokens Explained)](https://medium.com/@jagan_reddy/jwt-in-fastapi-the-secure-way-refresh-tokens-explained-f7d2d17b1d17) — Jan 2026 refresh token pattern
### Secondary (MEDIUM confidence)
**Multi-Tenancy & Architecture:**
- [MergeBoard: Multitenancy with FastAPI, SQLAlchemy and PostgreSQL](https://mergeboard.com/blog/6-multitenancy-fastapi-sqlalchemy-postgresql/) — Production patterns
- [GitHub Discussion: How to implement Multi tenancy in FastAPI](https://github.com/fastapi/fastapi/discussions/6056) — Community approaches
- [The developer's guide to SaaS multi-tenant architecture — WorkOS](https://workos.com/blog/developers-guide-saas-multi-tenant-architecture) — Tenant isolation strategies
**RBAC & Authorization:**
- [FastAPI RBAC - Full Implementation Tutorial](https://www.permit.io/blog/fastapi-rbac-full-implementation-tutorial) — Permission layer patterns
- [How to Build a Role-Based Access Control Layer](https://www.osohq.com/learn/rbac-role-based-access-control) — RBAC design principles
- [Role-Based Access Control Best Practices for 2026](https://www.techprescient.com/blogs/role-based-access-control-best-practices/) — Industry best practices
**Security & Data Isolation:**
- [Preventing Cross-Tenant Data Leakage in Multi-Tenant SaaS Systems](https://agnitestudio.com/blog/preventing-cross-tenant-leakage/) — Security patterns
- [JWT Security Best Practices: Checklist for APIs](https://curity.io/resources/learn/jwt-best-practices/) — Token security
- [6 Common Role Based Access Control (RBAC) Implementation Pitfalls](https://idenhaus.com/rbac-implementation-pitfalls/) — Documented failures
**UX & Collaboration Patterns:**
- [Guide to sharing and permissions Figma Learn](https://help.figma.com/hc/en-us/articles/1500007609322-Guide-to-sharing-and-permissions) — Collaboration UX patterns
- [User Onboarding Strategies in a B2B SaaS Application](https://auth0.com/blog/user-onboarding-strategies-b2b-saas/) — Invite-only registration patterns
- [Google Workspace Updates: "Show Editors" in Google Docs](https://workspaceupdates.googleblog.com/2021/05/view-more-context-on-google-docs-edits-with-show-editors.html) — Edit attribution patterns
### Tertiary (LOW confidence, needs validation)
**SQLite Limitations:**
- [A mere add_foreign_key can wipe out your whole Rails+SQLite production table](https://kyrylo.org/software/2025/09/27/a-mere-add-foreign-key-can-wipe-out-your-whole-rails-sqlite-production-table.html) — Migration risks (Rails-specific but conceptually applicable)
- [High Performance SQLite: Multi-tenancy](https://highperformancesqlite.com/watch/multi-tenancy) — Performance patterns (video, not peer-reviewed)
---
**Research completed:** 2026-03-18
**Ready for roadmap creation:** YES
All four research files synthesized. Recommended phase structure validated against dependencies, pitfalls, and architecture patterns. No critical blockers identified. Roadmap can proceed with high confidence.