docs(m4): define multi-tenant schema and phased rbac rollout

This commit is contained in:
zouantchaw
2026-02-24 15:52:04 -05:00
parent a07ee75dc9
commit f4f002b41b
2 changed files with 393 additions and 0 deletions

View File

@@ -18,3 +18,6 @@
| 2026-02-24 | 0.1.13 | Added verification architecture contract with endpoint design and workflow split for attire, government ID, and certification. |
| 2026-02-24 | 0.1.14 | Implemented core verification endpoints in dev and updated frontend/API docs with live verification route contracts. |
| 2026-02-24 | 0.1.15 | Added live Vertex Flash Lite attire verification path and third-party adapter scaffolding for government ID and certification checks. |
| 2026-02-24 | 0.1.16 | Added M4 target schema blueprint doc with first-principles modular model, constraints, and migration phases. |
| 2026-02-24 | 0.1.17 | Added full current-schema mermaid model relationship map to the M4 target schema blueprint. |
| 2026-02-24 | 0.1.18 | Updated schema blueprint with explicit multi-tenant stakeholder model and phased RBAC rollout with shadow mode before enforcement. |

View File

@@ -0,0 +1,390 @@
# M4 Target Schema Blueprint (Command-Ready)
Status: Draft for team alignment
Date: 2026-02-24
Owner: Technical Lead
## 1) Goal
Define the target database shape we want **before** command-backend implementation, so critical flows are atomic, secure, and scalable.
## 1.1 Stakeholder and tenancy model
This product should be designed as a **multi-tenant platform**.
1. Tenant:
- One staffing company account (example: Legendary Event Staffing and Entertainment).
2. Business:
- A customer/client account owned by a tenant.
3. User:
- A human identity (auth account) that can belong to one or more tenants.
4. Staff:
- A workforce profile linked to a user identity and tenant-scoped operations.
Practical meaning:
1. The same platform can serve multiple staffing companies safely.
2. Data isolation is by `tenant_id`, not only by business/vendor IDs.
3. Not every record starts as a full active user:
- invite-first or pending onboarding records are valid,
- then bound to `user_id` when activation is completed.
```mermaid
flowchart LR
U["User identity"] --> M["Tenant membership"]
M --> T["Tenant staffing company"]
T --> B["Business client"]
T --> V["Vendor partner"]
B --> O["Orders and shifts"]
V --> O
```
## 2) First-principles rules
1. Every critical write must be server-mediated and transactional.
2. Tenant boundaries must be explicit in data and queries.
3. Money and rates must use exact numeric types, not floating point.
4. Data needed for constraints should be relational, not hidden in JSON blobs.
5. Every high-risk state transition must be auditable and replayable.
## 3) Current anti-patterns we are removing
1. Direct client mutation of core entities.
2. Broad `USER`-auth CRUD without strict tenant scoping.
3. Financial values as `Float`.
4. Core workflow state embedded in generic `Any/jsonb` fields.
5. Missing uniqueness/index constraints on high-traffic paths.
## 4) Target modular schema
## 4.1 Identity and Access
Tables:
1. `users` (source identity, profile, auth linkage)
2. `tenant_memberships` (new; membership + base access per tenant)
3. `team_members` (membership + scope per team)
4. `roles` (new)
5. `permissions` (new)
6. `role_bindings` (new; who has which role in which scope)
Rules:
1. Unique tenant membership: `(tenant_id, user_id)`.
2. Unique team membership: `(team_id, user_id)`.
3. Access checks resolve through tenant membership first, then optional team/hub scope.
## 4.2 Organization and Tenant
Tables:
1. `tenants` (new canonical boundary: business/vendor ownership root)
2. `businesses`
3. `vendors`
4. `teams`
5. `team_hubs`
6. `hubs`
Rules:
1. Every command-critical row references `tenant_id`.
2. All list queries must include tenant predicate.
## 4.8 RBAC rollout strategy (deferred enforcement)
RBAC should be introduced in phases and **not enforced everywhere immediately**.
Phase A: Auth-first (now)
1. Require valid auth token.
2. Resolve tenant context.
3. Allow current work to continue while logging actor + tenant + action.
Phase B: Shadow RBAC
1. Evaluate permissions (`allow`/`deny`) in backend.
2. Log decisions but do not block most requests yet.
3. Start with warnings and dashboards for denied actions.
Phase C: Enforced RBAC on command writes
1. Enforce RBAC on `/commands/*` only.
2. Keep low-risk read flows in transition mode.
Phase D: Enforced RBAC on high-risk reads
1. Enforce tenant and role checks on sensitive read connectors.
2. Remove remaining broad user-level access.
```mermaid
flowchart LR
A["Auth only"] --> B["Shadow RBAC logging"]
B --> C["Enforce RBAC on command writes"]
C --> D["Enforce RBAC on sensitive reads"]
```
## 4.3 Scheduling and Orders
Tables:
1. `orders`
2. `order_schedule_rules` (new; replaces schedule JSON fields)
3. `shifts`
4. `shift_roles`
5. `shift_role_requirements` (optional extension for policy rules)
6. `shift_managers` (new; replaces `managers: [Any!]`)
Rules:
1. No denormalized `assignedStaff` or `shifts` JSON in `orders`.
2. Time constraints: `start_time < end_time`.
3. Capacity constraints: `assigned <= count`, `filled <= workers_needed`.
4. Canonical status names (single spelling across schema).
## 4.4 Staffing and Matching
Tables:
1. `staffs`
2. `staff_roles`
3. `workforce`
4. `applications`
5. `assignments`
Rules:
1. One active workforce relation per `(vendor_id, staff_id)`.
2. One application per `(shift_id, role_id, staff_id)` unless versioned intentionally.
3. Assignment state transitions only through command APIs.
## 4.5 Compliance and Verification
Tables:
1. `documents`
2. `staff_documents`
3. `certificates`
4. `verification_jobs`
5. `verification_reviews`
6. `verification_events`
Rules:
1. Verification is asynchronous and append-only for events.
2. Manual review is explicit and tracked.
3. Government ID and certification provider references are persisted.
## 4.6 Financial and Payout
Tables:
1. `invoices`
2. `invoice_templates`
3. `recent_payments`
4. `accounts` (refactor to tokenized provider references)
Rules:
1. Replace monetary `Float` with exact numeric (`DECIMAL(12,2)` or integer cents).
2. Do not expose raw account/routing values in query connectors.
3. Add one-primary-account constraint per owner.
## 4.7 Audit and Reliability
Tables:
1. `domain_events` (new)
2. `idempotency_keys` (already started in command API SQL)
3. `activity_logs`
Rules:
1. Every command write emits a domain event.
2. Idempotency scope: `(actor_uid, route, idempotency_key)`.
## 5) Target core model (conceptual)
```mermaid
erDiagram
TENANT ||--o{ BUSINESS : owns
TENANT ||--o{ VENDOR : owns
TENANT ||--o{ TEAM : owns
TEAM ||--o{ TEAM_MEMBER : has
USER ||--o{ TEAM_MEMBER : belongs_to
BUSINESS ||--o{ ORDER : requests
VENDOR ||--o{ ORDER : fulfills
ORDER ||--o{ ORDER_SCHEDULE_RULE : has
ORDER ||--o{ SHIFT : expands_to
SHIFT ||--o{ SHIFT_ROLE : requires
SHIFT ||--o{ SHIFT_MANAGER : has
USER ||--o{ STAFF : identity
STAFF ||--o{ STAFF_ROLE : skills
VENDOR ||--o{ WORKFORCE : contracts
STAFF ||--o{ WORKFORCE : linked
SHIFT_ROLE ||--o{ APPLICATION : receives
STAFF ||--o{ APPLICATION : applies
SHIFT_ROLE ||--o{ ASSIGNMENT : allocates
WORKFORCE ||--o{ ASSIGNMENT : executes
STAFF ||--o{ CERTIFICATE : has
STAFF ||--o{ STAFF_DOCUMENT : uploads
DOCUMENT ||--o{ STAFF_DOCUMENT : references
STAFF ||--o{ VERIFICATION_JOB : subject
VERIFICATION_JOB ||--o{ VERIFICATION_REVIEW : reviewed_by
VERIFICATION_JOB ||--o{ VERIFICATION_EVENT : logs
ORDER ||--o{ INVOICE : billed_by
INVOICE ||--o{ RECENT_PAYMENT : settles
TENANT ||--o{ ACCOUNT_TOKEN_REF : payout_method
ORDER ||--o{ DOMAIN_EVENT : emits
SHIFT ||--o{ DOMAIN_EVENT : emits
ASSIGNMENT ||--o{ DOMAIN_EVENT : emits
```
## 6) Command write boundary on this schema
```mermaid
flowchart LR
A["Frontend app"] --> B["Command API"]
B --> C["Policy + validation"]
C --> D["Single database transaction"]
D --> E["orders, shifts, shift_roles, applications, assignments"]
D --> F["domain_events + idempotency_keys"]
E --> G["Read models and reports"]
```
## 7) Minimum constraints and indexes to add before command build
## 7.1 Constraints
1. `shift_roles`: check `assigned >= 0 AND assigned <= count`.
2. `shifts`: check `start_time < end_time`.
3. `applications`: unique `(shift_id, role_id, staff_id)`.
4. `workforce`: unique active `(vendor_id, staff_id)`.
5. `team_members`: unique `(team_id, user_id)`.
6. `accounts` (or token ref table): unique primary per owner.
## 7.2 Indexes
1. `orders (tenant_id, status, date)`.
2. `shifts (order_id, date, status)`.
3. `shift_roles (shift_id, role_id, start_time)`.
4. `applications (shift_id, role_id, status, created_at)`.
5. `assignments (workforce_id, shift_id, role_id, status)`.
6. `verification_jobs (subject_id, type, status, created_at)`.
7. `invoices (business_id, vendor_id, status, due_date)`.
## 8) Data type normalization
1. Monetary: `Float -> DECIMAL(12,2)` (or integer cents).
2. Generic JSON fields in core scheduling: split into relational tables.
3. Timestamps: store UTC and enforce server-generated creation/update fields.
## 9) Security boundary in schema/connectors
1. Remove broad list queries for sensitive entities unless tenant-scoped.
2. Strip sensitive fields from connector query payloads (bank/routing).
3. Keep high-risk mutations behind command API; Data Connect remains read-first for client.
## 10) Migration phases (schema-first)
```mermaid
flowchart TD
P0["Phase 0: Safety patch
- lock sensitive fields
- enforce tenant-scoped queries
- freeze new direct write connectors"] --> P1["Phase 1: Core constraints
- add unique/check constraints
- add indexes
- normalize money types"]
P1 --> P2["Phase 2: Tenant and RBAC base tables
- add tenants and tenant_memberships
- add roles permissions role_bindings
- run RBAC in shadow mode"]
P2 --> P3["Phase 3: Scheduling normalization
- remove order JSON workflow fields
- add order_schedule_rules and shift_managers"]
P3 --> P4["Phase 4: Command rollout
- command writes on hardened schema
- emit domain events + idempotency
- enforce RBAC for command routes"]
P4 --> P5["Phase 5: Read migration + cleanup
- migrate frontend reads as needed
- enforce RBAC for sensitive reads
- retire deprecated connectors"]
```
## 11) Definition of ready for command backend
1. P0 and P1 complete in `dev`.
2. Tenant scoping verified in connector tests.
3. Sensitive field exposure removed.
4. Core transaction invariants enforced by schema constraints.
5. Command API contracts mapped to new normalized tables.
6. RBAC is in shadow mode with decision logs in place (not hard-blocking yet).
## 12) Full current model relationship map (all models)
```mermaid
flowchart LR
Account["Account"]
ActivityLog["ActivityLog"]
Application["Application"]
Assignment["Assignment"]
AttireOption["AttireOption"]
BenefitsData["BenefitsData"]
Business["Business"]
Category["Category"]
Certificate["Certificate"]
ClientFeedback["ClientFeedback"]
Conversation["Conversation"]
Course["Course"]
CustomRateCard["CustomRateCard"]
Document["Document"]
EmergencyContact["EmergencyContact"]
FaqData["FaqData"]
Hub["Hub"]
Invoice["Invoice"]
InvoiceTemplate["InvoiceTemplate"]
Level["Level"]
MemberTask["MemberTask"]
Message["Message"]
Order["Order"]
RecentPayment["RecentPayment"]
Role["Role"]
RoleCategory["RoleCategory"]
Shift["Shift"]
ShiftRole["ShiftRole"]
Staff["Staff"]
StaffAvailability["StaffAvailability"]
StaffAvailabilityStats["StaffAvailabilityStats"]
StaffCourse["StaffCourse"]
StaffDocument["StaffDocument"]
StaffRole["StaffRole"]
Task["Task"]
TaskComment["TaskComment"]
TaxForm["TaxForm"]
Team["Team"]
TeamHub["TeamHub"]
TeamHudDepartment["TeamHudDepartment"]
TeamMember["TeamMember"]
User["User"]
UserConversation["UserConversation"]
Vendor["Vendor"]
VendorBenefitPlan["VendorBenefitPlan"]
VendorRate["VendorRate"]
Workforce["Workforce"]
Application --> Shift
Application --> ShiftRole
Application --> Staff
Assignment --> ShiftRole
Assignment --> Workforce
BenefitsData --> Staff
BenefitsData --> VendorBenefitPlan
Certificate --> Staff
ClientFeedback --> Business
ClientFeedback --> Vendor
Course --> Category
Invoice --> Business
Invoice --> Order
Invoice --> Vendor
InvoiceTemplate --> Business
InvoiceTemplate --> Order
InvoiceTemplate --> Vendor
MemberTask --> Task
MemberTask --> TeamMember
Message --> User
Order --> Business
Order --> TeamHub
Order --> Vendor
RecentPayment --> Application
RecentPayment --> Invoice
Shift --> Order
ShiftRole --> Role
ShiftRole --> Shift
StaffAvailability --> Staff
StaffAvailabilityStats --> Staff
StaffDocument --> Document
StaffRole --> Role
StaffRole --> Staff
TaskComment --> TeamMember
TeamHub --> Team
TeamHudDepartment --> TeamHub
TeamMember --> Team
TeamMember --> TeamHub
TeamMember --> User
UserConversation --> Conversation
UserConversation --> User
VendorBenefitPlan --> Vendor
VendorRate --> Vendor
Workforce --> Staff
Workforce --> Vendor
```