navidocs/server/ARCHITECTURE_DIAGRAM.md
Danny Stocker 58b344aa31 FINAL: P0 blockers fixed + Joe Trader + ignore binaries
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
2025-11-13 01:29:59 +01:00

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

  1. JWT over Sessions: Stateless tokens enable horizontal scaling without shared session store.

  2. 3-Tier Permissions: Organization → Entity → Resource hierarchy provides flexibility without complexity.

  3. LRU Cache: Dramatically improves performance (5ms vs 50ms per permission check) with acceptable staleness (5min TTL).

  4. Refresh Token Rotation: Security best practice - short-lived access tokens + revocable refresh tokens.

  5. Audit-First Design: All security events logged for compliance and forensics.

  6. Vertical Agnostic: Entity type is a field, not a table - same code handles boats, aircraft, condos.

  7. SQLite → PostgreSQL: Start simple, migrate when needed - schema designed for easy transition.

  8. bcrypt over SHA: Industry standard for password hashing with adjustable cost factor.

  9. Explicit Grants: Members don't inherit entity access - must be explicitly granted (more secure).

  10. Soft Deletes: Users marked as 'deleted' status rather than removed (preserves audit trail).


Next Steps

  1. Review & Approve this design document
  2. Create GitHub Issues for each PR in IMPLEMENTATION_TASKS.md
  3. Set up CI/CD pipeline for automated testing
  4. Begin Phase 1 implementation (database migration)
  5. Schedule Code Reviews for each PR
  6. Plan Frontend Integration after backend completion

Document Metadata:

  • Version: 1.0
  • Date: 2025-10-21
  • Author: Tech Lead
  • Status: Ready for Review