Fixed:
- Price: €800K-€1.5M, Sunseeker added
- Agent 1: Joe Trader persona + actual sale ads research
- Ignored meilisearch binary + data/ (too large for GitHub)
- SESSION_DEBUG_BLOCKERS.md created
Ready for Session 1 launch.
🤖 Generated with Claude Code
53 KiB
NaviDocs Multi-Tenancy Architecture
Visual System Design
High-Level Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ CLIENT APPLICATION │
│ (React Frontend - Port 3000) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Login/ │ │ Entity │ │ Document │ │
│ │ Register │ │ Management │ │ Viewer │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Sends: Authorization: Bearer <JWT> │
└───────────────────────────────┬─────────────────────────────────────────┘
│
│ HTTPS
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ API GATEWAY LAYER │
│ (Express.js - Port 8001) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ MIDDLEWARE CHAIN │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ Helmet │→│ CORS │→│ Rate │→│ Request │ │ │
│ │ │ (CSP) │ │ │ │ Limiter │ │ Logger │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ authenticateToken │→│ requireEntityAccess │ │ │
│ │ │ - Verify JWT │ │ - Check entity permissions │ │ │
│ │ │ - Load user │ │ - Enforce access control │ │ │
│ │ │ - Attach to req.user │ │ │ │ │
│ │ └──────────────────────┘ └──────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ROUTES │ │
│ │ │ │
│ │ /api/auth/* /api/entities/* /api/documents/* │ │
│ │ ├─ register ├─ GET / ├─ GET /:id │ │
│ │ ├─ login ├─ POST / ├─ GET / │ │
│ │ ├─ logout ├─ GET /:id ├─ DELETE /:id │ │
│ │ ├─ refresh ├─ PATCH /:id └─ GET /:id/pdf │ │
│ │ ├─ forgot-password ├─ DELETE /:id │ │
│ │ ├─ reset-password └─ /:id/permissions │ │
│ │ └─ verify-email/:token │ │
│ │ │ │
│ │ /api/organizations/* /api/users/* /api/search/* │ │
│ │ ├─ GET / ├─ GET /:id ├─ POST / │ │
│ │ ├─ POST / ├─ PATCH /:id └─ GET /suggest │ │
│ │ ├─ GET /:id └─ DELETE /:id │ │
│ │ ├─ PATCH /:id │ │
│ │ ├─ DELETE /:id │ │
│ │ ├─ GET /:id/members │ │
│ │ ├─ POST /:id/members │ │
│ │ ├─ PATCH /:id/members/:userId │ │
│ │ └─ DELETE /:id/members/:userId │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ SERVICE LAYER │
│ (Business Logic Modules) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ AuthService │ │ AuthzService │ │ UserService │ │
│ │ ──────────────── │ │ ──────────────── │ │ ──────────────── │ │
│ │ • register() │ │ • checkEntity │ │ • getUser() │ │
│ │ • login() │ │ Permission() │ │ • updateUser() │ │
│ │ • logout() │ │ • checkOrg │ │ • deleteUser() │ │
│ │ • refresh() │ │ Permission() │ │ • suspendUser() │ │
│ │ • forgotPwd() │ │ • grantEntity │ │ │ │
│ │ • resetPwd() │ │ Permission() │ │ │ │
│ │ • verifyEmail() │ │ • revokeEntity │ │ │ │
│ │ │ │ Permission() │ │ │ │
│ │ │ │ • getEntityUsers │ │ │ │
│ │ │ │ • getUserEntities│ │ │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ OrgService │ │ AuditService │ │ SearchService │ │
│ │ ──────────────── │ │ ──────────────── │ │ ──────────────── │ │
│ │ • createOrg() │ │ • logEvent() │ │ • indexDoc() │ │
│ │ • updateOrg() │ │ • queryLogs() │ │ • search() │ │
│ │ • deleteOrg() │ │ • getUserEvents()│ │ │ │
│ │ • addMember() │ │ • cleanupLogs() │ │ │ │
│ │ • removeMember() │ │ │ │ │ │
│ │ • updateRole() │ │ │ │ │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ LRU CACHE (Permission Resolution) │ │
│ │ Key: "entity:{userId}:{entityId}:{permission}" │ │
│ │ TTL: 5 minutes │ │
│ │ Max Entries: 10,000 │ │
│ └────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ DATA ACCESS LAYER │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ SQLite Database │ │
│ │ (WAL mode, Foreign Keys enabled) │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │ │
│ │ │ users │ │ organizations │ │ entities │ │ │
│ │ │ ─────────────── │ │ ─────────────── │ │ ────────────│ │ │
│ │ │ id │ │ id │ │ id │ │ │
│ │ │ email (UNIQUE) │ │ name │ │ name │ │ │
│ │ │ password_hash │ │ type │ │ entity_type │ │ │
│ │ │ status │ │ │ │ org_id (FK) │ │ │
│ │ │ email_verified │ │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ user_organizations │ │ entity_permissions │ │ │
│ │ │ ──────────────────── │ │ ──────────────────────────── │ │ │
│ │ │ user_id (FK) │ │ user_id (FK) │ │ │
│ │ │ organization_id (FK) │ │ entity_id (FK) │ │ │
│ │ │ role (admin/...) │ │ permission_level (viewer/...)│ │ │
│ │ │ joined_at │ │ granted_by (FK) │ │ │
│ │ │ │ │ expires_at │ │ │
│ │ └──────────────────────┘ └──────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ refresh_tokens │ │ password_reset_tokens │ │ │
│ │ │ ──────────────────── │ │ ──────────────────────────── │ │ │
│ │ │ user_id (FK) │ │ user_id (FK) │ │ │
│ │ │ token_hash │ │ token_hash │ │ │
│ │ │ device_info │ │ expires_at │ │ │
│ │ │ revoked │ │ used │ │ │
│ │ └──────────────────────┘ └──────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ audit_log │ │ documents │ │ │
│ │ │ ──────────────────── │ │ ──────────────────────────── │ │ │
│ │ │ user_id (FK) │ │ organization_id (FK) │ │ │
│ │ │ event_type │ │ entity_id (FK) │ │ │
│ │ │ resource_type │ │ uploaded_by (FK) │ │ │
│ │ │ status │ │ title │ │ │
│ │ │ ip_address │ │ file_path │ │ │
│ │ └──────────────────────┘ └──────────────────────────────┘ │ │
│ │ │ │
│ │ Indexes: │ │
│ │ • idx_entity_perms_user, idx_entity_perms_entity │ │
│ │ • idx_audit_user, idx_audit_event, idx_audit_created │ │
│ │ • idx_documents_org, idx_documents_entity │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Meilisearch (Full-Text Search) │ │
│ │ Index: navidocs-pages │ │
│ │ Documents: { docId, pageNumber, ocrText, ... } │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Redis (BullMQ Job Queue) │ │
│ │ Queue: ocr-jobs │ │
│ │ Workers: PDF extraction, OCR processing │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Authentication Flow
┌─────────┐ ┌─────────┐
│ Client │ │ Server │
└────┬────┘ └────┬────┘
│ │
│ 1. POST /api/auth/register │
│ { email, password, name } │
├────────────────────────────────────────────────────────────>│
│ │
│ 2. Validate input │
│ 3. Hash password │
│ 4. Create user record │
│ 5. Create personal org │
│ 6. Generate verify token│
│ │
│ { user, message: "Verify email" } │
│<────────────────────────────────────────────────────────────┤
│ │
│ 7. POST /api/auth/login │
│ { email, password } │
├────────────────────────────────────────────────────────────>│
│ │
│ 8. Validate credentials│
│ 9. Check account status│
│ 10. Generate JWT (15min)│
│ 11. Generate refresh token│
│ 12. Store refresh hash │
│ 13. Log audit event │
│ │
│ { accessToken, refreshToken, user } │
│<────────────────────────────────────────────────────────────┤
│ │
│ 14. GET /api/documents │
│ Authorization: Bearer <JWT> │
├────────────────────────────────────────────────────────────>│
│ │
│ 15. Verify JWT signature│
│ 16. Check expiry │
│ 17. Load user │
│ 18. Check permissions │
│ 19. Return documents │
│ │
│ { documents: [...] } │
│<────────────────────────────────────────────────────────────┤
│ │
│ [15 minutes later] │
│ │
│ 20. GET /api/documents │
│ Authorization: Bearer <expired JWT> │
├────────────────────────────────────────────────────────────>│
│ │
│ 21. Verify JWT → EXPIRED│
│ │
│ { error: "Token expired" } │
│<────────────────────────────────────────────────────────────┤
│ │
│ 22. POST /api/auth/refresh │
│ { refreshToken } │
├────────────────────────────────────────────────────────────>│
│ │
│ 23. Validate refresh token│
│ 24. Check revoked status│
│ 25. Generate new JWT │
│ │
│ { accessToken } │
│<────────────────────────────────────────────────────────────┤
│ │
│ 26. POST /api/auth/logout │
│ { refreshToken } │
├────────────────────────────────────────────────────────────>│
│ │
│ 27. Revoke refresh token│
│ 28. Log audit event │
│ │
│ { success: true } │
│<────────────────────────────────────────────────────────────┤
│ │
Authorization Resolution Flow
┌──────────────────────────────────────────────────────────────────────┐
│ User requests access to Entity (e.g., GET /api/entities/boat-123) │
└────────────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Check LRU Cache │
│ Key: entity:userId:entityId:permission │
└────────────┬────────────────────────────┘
│
┌──────────┴──────────┐
│ │
Cache Cache
Hit Miss
│ │
▼ ▼
┌──────────────┐ ┌──────────────────────────────────────┐
│ Return │ │ STEP 1: Check Organization Role │
│ Cached │ │ ──────────────────────────────────── │
│ Result │ │ SELECT uo.role │
└──────────────┘ │ FROM user_organizations uo │
│ INNER JOIN entities e │
│ ON e.organization_id = uo.org_id │
│ WHERE uo.user_id = ? AND e.id = ? │
└────────────┬─────────────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
Org Admin Org Manager Org Member/Viewer
│ │ │
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌─────────────────┐
│ ALLOW ALL │ │ Check perm │ │ STEP 2: Check │
│ PERMISSIONS│ │ in manager │ │ Entity Permission│
└────────────┘ │ scope │ │ ─────────────────│
└────────────┘ │ SELECT perm_level│
│ │ FROM entity_perms│
│ │ WHERE user_id=? │
│ │ AND entity_id=?│
│ └─────────┬────────┘
│ │
│ ┌─────────┴────────┐
│ │ │
│ Found Perm Not Found
│ │ │
│ ▼ ▼
│ ┌──────────────┐ ┌──────────────┐
│ │ Check if │ │ STEP 3: Check│
│ │ permission │ │ Legacy Perms │
│ │ in hierarchy │ │ (backward │
│ │ (viewer→ │ │ compat) │
│ │ editor→ │ │ │
│ │ manager→ │ └──────┬───────┘
│ │ admin) │ │
│ └──────┬───────┘ │
│ │ │
▼ ▼ ▼
┌───────────────────────────────────────┐
│ Permission Resolution │
│ ────────────────────────────────────│
│ • Admin: All permissions │
│ • Manager: view, edit, create, │
│ delete, share │
│ • Editor: view, edit, create │
│ • Viewer: view only │
└─────────────┬─────────────────────────┘
│
┌────────────┴────────────┐
│ │
ALLOW DENY
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Cache result │ │ Cache result │
│ Return true │ │ Return false │
│ Proceed to │ │ Return 403 │
│ business logic │ │ Forbidden │
└──────────────────┘ └──────────────────┘
Permission Hierarchy
┌─────────────────────────────────────────────────────────────────────┐
│ PERMISSION LEVELS │
│ (Higher includes all lower) │
└─────────────────────────────────────────────────────────────────────┘
┌───────────────┐
│ ADMIN │ Full control: view, edit, create, delete,
│ ──────────────│ share, manage_users, manage_permissions
└───────┬───────┘
│ Includes ↓
┌───────┴───────┐
│ MANAGER │ Management: view, edit, create, delete, share
│ ──────────────│
└───────┬───────┘
│ Includes ↓
┌───────┴───────┐
│ EDITOR │ Content: view, edit, create
│ ──────────────│
└───────┬───────┘
│ Includes ↓
┌───────┴───────┐
│ VIEWER │ Read-only: view
│ ──────────────│
└───────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ ORGANIZATION ROLES vs ENTITY PERMISSIONS │
└─────────────────────────────────────────────────────────────────────┘
Organization Level Entity Level (Override)
(Broad Access) (Granular Access)
┌─────────────────────┐ ┌─────────────────────┐
│ Org Admin │ ───────────> │ Full access to │
│ • All entities │ │ ALL entities │
│ • User management │ │ (Cannot be limited) │
└─────────────────────┘ └─────────────────────┘
┌─────────────────────┐ ┌─────────────────────┐
│ Org Manager │ ───────────> │ View/Edit all │
│ • All entities │ │ entities by default │
│ • Limited user mgmt │ │ (Can be extended to │
└─────────────────────┘ │ admin on specific) │
└─────────────────────┘
┌─────────────────────┐ ┌─────────────────────┐
│ Org Member │ ───────────> │ Access based on │
│ • No default access │ │ entity_permissions │
│ • Requires explicit │ │ table (explicit │
│ entity grants │ │ grants required) │
└─────────────────────┘ └─────────────────────┘
┌─────────────────────┐ ┌─────────────────────┐
│ Org Viewer │ ───────────> │ Read-only access to │
│ • View all entities │ │ all entities │
│ • No modifications │ │ (Cannot be elevated │
└─────────────────────┘ │ without org role) │
└─────────────────────┘
Multi-Tenancy Model
┌────────────────────────────────────────────────────────────────────┐
│ MULTI-VERTICAL STRUCTURE │
│ (Organization → Entities → Documents) │
└────────────────────────────────────────────────────────────────────┘
Organization: "Coastal Marine Services"
│
├─ User Memberships:
│ ├─ Alice (admin)
│ ├─ Bob (manager)
│ ├─ Carol (member)
│ └─ Dave (viewer)
│
└─ Entities (Cross-Vertical):
│
├─ Entity: Boat "Sea Breeze" (id: boat-001)
│ │ Type: boat
│ │ Organization: Coastal Marine Services
│ │
│ ├─ Entity Permissions:
│ │ ├─ Alice: admin (from org role)
│ │ ├─ Bob: manager (from org role)
│ │ ├─ Carol: editor (explicit grant)
│ │ └─ Dave: viewer (from org role)
│ │
│ └─ Documents:
│ ├─ Owner's Manual.pdf
│ ├─ Engine Service Record.pdf
│ └─ Safety Certificate.pdf
│
├─ Entity: Boat "Ocean Rider" (id: boat-002)
│ │ Type: boat
│ │
│ ├─ Entity Permissions:
│ │ ├─ Alice: admin (from org role)
│ │ ├─ Bob: manager (from org role)
│ │ ├─ Carol: NO ACCESS (not granted)
│ │ └─ Dave: viewer (from org role)
│ │
│ └─ Documents:
│ └─ Charter Contract.pdf
│
├─ Entity: Marina "Harbor Bay" (id: marina-001)
│ │ Type: marina (different vertical!)
│ │
│ ├─ Entity Permissions:
│ │ ├─ Alice: admin
│ │ ├─ Bob: admin (explicit grant)
│ │ └─ Carol, Dave: NO ACCESS
│ │
│ └─ Documents:
│ ├─ Dock Layout.pdf
│ └─ Safety Procedures.pdf
│
└─ Entity: Aircraft "Cessna N12345" (id: aircraft-001)
│ Type: aircraft (another vertical!)
│
├─ Entity Permissions:
│ └─ Alice: admin (only Alice has access)
│
└─ Documents:
└─ Pilot Operating Handbook.pdf
VERTICAL AGNOSTIC DESIGN:
──────────────────────────
All verticals (boat, aircraft, marina, condo, etc) use the SAME:
• Database schema
• Permission model
• Authorization logic
• API endpoints
The "entity_type" field differentiates verticals, but logic is identical.
Security Layers
┌──────────────────────────────────────────────────────────────────┐
│ DEFENSE IN DEPTH │
│ (Multiple layers of security) │
└──────────────────────────────────────────────────────────────────┘
Layer 1: Network Security
┌────────────────────────────────────────────────────────────────┐
│ • HTTPS/TLS encryption │
│ • CORS policy (restrict origins) │
│ • Rate limiting (prevent DDoS) │
│ • IP-based blocking (optional) │
└────────────────────────────────────────────────────────────────┘
│
▼
Layer 2: Application Security
┌────────────────────────────────────────────────────────────────┐
│ • Helmet.js (CSP, XSS protection) │
│ • Input validation (sanitize all inputs) │
│ • SQL injection prevention (prepared statements) │
│ • Error handling (don't leak system info) │
└────────────────────────────────────────────────────────────────┘
│
▼
Layer 3: Authentication
┌────────────────────────────────────────────────────────────────┐
│ • JWT signature verification │
│ • Token expiry enforcement │
│ • Refresh token rotation │
│ • Account status checks (active/suspended) │
│ • Brute force protection (rate limiting) │
└────────────────────────────────────────────────────────────────┘
│
▼
Layer 4: Authorization
┌────────────────────────────────────────────────────────────────┐
│ • Organization membership validation │
│ • Entity-level permission checks │
│ • Resource ownership verification │
│ • Permission hierarchy enforcement │
└────────────────────────────────────────────────────────────────┘
│
▼
Layer 5: Data Security
┌────────────────────────────────────────────────────────────────┐
│ • Password hashing (bcrypt, cost=12) │
│ • Token hashing (refresh tokens, reset tokens) │
│ • Sensitive data encryption (at rest) │
│ • Foreign key constraints (data integrity) │
└────────────────────────────────────────────────────────────────┘
│
▼
Layer 6: Audit & Monitoring
┌────────────────────────────────────────────────────────────────┐
│ • Security event logging (all auth events) │
│ • Failed login tracking │
│ • Permission change logging │
│ • Anomaly detection (future: ML-based) │
│ • Compliance reporting (GDPR, SOC2) │
└────────────────────────────────────────────────────────────────┘
Scalability Considerations
┌────────────────────────────────────────────────────────────────┐
│ HORIZONTAL SCALING STRATEGY │
└────────────────────────────────────────────────────────────────┘
Current (Single Server):
┌─────────────────┐
│ Express API │
│ + SQLite DB │ ──> Max: ~1000 concurrent users
└─────────────────┘
Phase 2 (Load Balanced):
┌─────────────────┐
│ Load Balancer │
└────────┬────────┘
│
┌────┼────┐
│ │ │
┌───▼┐ ┌─▼──┐ ┌▼───┐
│API │ │API │ │API │ (Stateless JWT = easy to scale)
└───┬┘ └─┬──┘ └┬───┘
│ │ │
└────┼────┘
│
┌────────▼────────┐
│ PostgreSQL │ ──> Max: ~10,000 concurrent users
│ (Master-Slave) │
└─────────────────┘
Phase 3 (Multi-Region):
┌──────────────────────────────────────────────────────────────┐
│ CDN / Global Load Balancer │
└───────────────────┬──────────────────────────────────────────┘
│
┌───────────┼───────────┐
│ │
┌───────▼────────┐ ┌────────▼───────┐
│ Region: US │ │ Region: EU │
│ ──────────── │ │ ──────────── │
│ API Servers │ │ API Servers │
│ Read Replicas │ │ Read Replicas │
└───────┬────────┘ └────────┬───────┘
│ │
└───────────┬───────────┘
│
┌───────▼───────┐
│ PostgreSQL │ ──> Max: 100,000+ users
│ Multi-Master │
│ Replication │
└───────────────┘
Permission Cache Strategy:
──────────────────────────
• LRU cache per API server (in-memory)
• TTL: 5 minutes
• Invalidation: On permission change
• Reduces DB queries by 80-90%
• Scales linearly with server count
File Structure
navidocs/server/
│
├── config/
│ ├── db.js # Database connection config
│ └── meilisearch.js # Search client config
│
├── db/
│ ├── db.js # Database instance (singleton)
│ ├── init.js # Database initialization
│ ├── schema.sql # Base schema
│ └── navidocs.db # SQLite database file
│
├── migrations/
│ ├── 001_initial.sql
│ ├── 002_entities.sql
│ └── 003_auth_tables.sql # NEW: Auth tables migration
│
├── middleware/
│ ├── auth.js # JWT authentication middleware
│ └── permissions.js # NEW: Permission enforcement middleware
│
├── routes/
│ ├── auth.js # NEW: Auth endpoints
│ ├── users.js # NEW: User management
│ ├── organizations.js # NEW: Org management
│ ├── entities.js # Entity CRUD (add permission checks)
│ ├── documents.js # Document CRUD (add permission checks)
│ ├── upload.js # File upload
│ └── search.js # Search endpoints
│
├── services/
│ ├── auth.js # NEW: Authentication service
│ ├── authorization.js # NEW: Authorization service
│ ├── audit.js # NEW: Audit logging service
│ ├── users.js # NEW: User management service
│ ├── organizations.js # NEW: Organization service
│ ├── ocr.js # OCR processing
│ ├── search.js # Search indexing
│ └── queue.js # Job queue
│
├── test/
│ ├── services/
│ │ ├── auth.test.js # NEW
│ │ ├── authorization.test.js # NEW
│ │ └── audit.test.js # NEW
│ ├── routes/
│ │ ├── auth.test.js # NEW
│ │ └── organizations.test.js # NEW
│ └── migrations/
│ └── 003_auth_tables.test.js # NEW
│
├── utils/
│ └── logger.js # Logging utility
│
├── index.js # Express app entry point
├── package.json
├── .env
├── DESIGN_AUTH_MULTITENANCY.md # This design doc
├── IMPLEMENTATION_TASKS.md # Task breakdown
└── ARCHITECTURE_DIAGRAM.md # Architecture diagrams
Technology Stack Summary
| Layer | Technology | Purpose |
|---|---|---|
| Backend | Node.js 20+ | Runtime environment |
| Framework | Express 5.0 | Web framework |
| Database | SQLite (→ PostgreSQL) | Relational data storage |
| Authentication | JWT (jsonwebtoken) | Stateless auth tokens |
| Password Hashing | bcrypt | Secure password storage |
| Search | Meilisearch | Full-text search |
| Job Queue | BullMQ + Redis | Background OCR jobs |
| Caching | lru-cache | In-memory permission cache |
| Security | Helmet.js | HTTP security headers |
| Rate Limiting | express-rate-limit | DDoS protection |
| Testing | Mocha/Jest | Unit & integration tests |
| Documentation | OpenAPI/Swagger | API documentation |
Key Design Decisions
-
JWT over Sessions: Stateless tokens enable horizontal scaling without shared session store.
-
3-Tier Permissions: Organization → Entity → Resource hierarchy provides flexibility without complexity.
-
LRU Cache: Dramatically improves performance (5ms vs 50ms per permission check) with acceptable staleness (5min TTL).
-
Refresh Token Rotation: Security best practice - short-lived access tokens + revocable refresh tokens.
-
Audit-First Design: All security events logged for compliance and forensics.
-
Vertical Agnostic: Entity type is a field, not a table - same code handles boats, aircraft, condos.
-
SQLite → PostgreSQL: Start simple, migrate when needed - schema designed for easy transition.
-
bcrypt over SHA: Industry standard for password hashing with adjustable cost factor.
-
Explicit Grants: Members don't inherit entity access - must be explicitly granted (more secure).
-
Soft Deletes: Users marked as 'deleted' status rather than removed (preserves audit trail).
Next Steps
- Review & Approve this design document
- Create GitHub Issues for each PR in IMPLEMENTATION_TASKS.md
- Set up CI/CD pipeline for automated testing
- Begin Phase 1 implementation (database migration)
- Schedule Code Reviews for each PR
- Plan Frontend Integration after backend completion
Document Metadata:
- Version: 1.0
- Date: 2025-10-21
- Author: Tech Lead
- Status: Ready for Review