docs(m4): add business/vendor memberships and clean planning docs
This commit is contained in:
@@ -24,3 +24,6 @@
|
|||||||
| 2026-02-24 | 0.1.19 | Added customer stakeholder-wheel mapping and future stakeholder extension model to the M4 schema blueprint. |
|
| 2026-02-24 | 0.1.19 | Added customer stakeholder-wheel mapping and future stakeholder extension model to the M4 schema blueprint. |
|
||||||
| 2026-02-25 | 0.1.20 | Added roadmap CSV schema-reconciliation document with stakeholder capability matrix and concrete schema gap analysis. |
|
| 2026-02-25 | 0.1.20 | Added roadmap CSV schema-reconciliation document with stakeholder capability matrix and concrete schema gap analysis. |
|
||||||
| 2026-02-25 | 0.1.21 | Updated target schema blueprint with roadmap-evidence section plus attendance/offense, stakeholder-network, and settlement-table coverage. |
|
| 2026-02-25 | 0.1.21 | Updated target schema blueprint with roadmap-evidence section plus attendance/offense, stakeholder-network, and settlement-table coverage. |
|
||||||
|
| 2026-02-25 | 0.1.22 | Updated core actor scenarios with explicit business and vendor user partitioning via membership tables. |
|
||||||
|
| 2026-02-25 | 0.1.23 | Updated schema blueprint and reconciliation docs to add `business_memberships` and `vendor_memberships` as first-class data actors. |
|
||||||
|
| 2026-02-25 | 0.1.24 | Removed stale `m4-discrepencies.md` document from M4 planning docs cleanup. |
|
||||||
|
|||||||
@@ -9,20 +9,38 @@ Owner: Technical Lead
|
|||||||
2. `User`: human identity that signs in.
|
2. `User`: human identity that signs in.
|
||||||
3. `TenantMembership`: user role/context inside one tenant.
|
3. `TenantMembership`: user role/context inside one tenant.
|
||||||
4. `Business`: client account served by the tenant.
|
4. `Business`: client account served by the tenant.
|
||||||
5. `Vendor`: supplier account that can fulfill staffing demand.
|
5. `BusinessMembership`: maps users to a business with role/status (`owner`, `manager`, `approver`, `viewer`).
|
||||||
6. `Workforce/Staff`: worker profile used for assignment and attendance.
|
6. `Vendor`: supplier account that can fulfill staffing demand.
|
||||||
7. `StakeholderType`: typed category (`buyer`, `operator`, `vendor_partner`, `workforce`, `partner`).
|
7. `VendorMembership`: maps users to a vendor with role/status (`owner`, `manager`, `scheduler`, `viewer`).
|
||||||
8. `StakeholderProfile`: typed actor record inside a tenant.
|
8. `Workforce/Staff`: worker profile used for assignment and attendance.
|
||||||
9. `StakeholderLink`: relationship between stakeholder profiles.
|
9. `StakeholderType`: typed category (`buyer`, `operator`, `vendor_partner`, `workforce`, `partner`, `procurement_partner`).
|
||||||
|
10. `StakeholderProfile`: typed actor record inside a tenant.
|
||||||
|
11. `StakeholderLink`: relationship between stakeholder profiles.
|
||||||
|
|
||||||
|
## 1.1 Current schema coverage (today)
|
||||||
|
Current Data Connect handles this only partially:
|
||||||
|
1. `Business.userId` supports one primary business user.
|
||||||
|
2. `Vendor.userId` supports one primary vendor user.
|
||||||
|
3. `TeamMember` can represent multiple users by team as a workaround.
|
||||||
|
|
||||||
|
This is why we need first-class membership tables:
|
||||||
|
1. `business_memberships`
|
||||||
|
2. `vendor_memberships`
|
||||||
|
|
||||||
|
Without those, client/vendor user partitioning is indirect and harder to enforce safely at scale.
|
||||||
|
|
||||||
## 2) Minimal actor map
|
## 2) Minimal actor map
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
T["Tenant"] --> TM["TenantMembership"]
|
T["Tenant"] --> TM["TenantMembership (global tenant access)"]
|
||||||
U["User"] --> TM
|
U["User"] --> TM
|
||||||
T --> B["Business"]
|
T --> B["Business"]
|
||||||
T --> V["Vendor"]
|
T --> V["Vendor"]
|
||||||
|
U --> BM["BusinessMembership"]
|
||||||
|
BM --> B
|
||||||
|
U --> VM["VendorMembership"]
|
||||||
|
VM --> V
|
||||||
U --> S["Workforce/Staff"]
|
U --> S["Workforce/Staff"]
|
||||||
T --> SP["StakeholderProfile"]
|
T --> SP["StakeholderProfile"]
|
||||||
ST["StakeholderType"] --> SP
|
ST["StakeholderType"] --> SP
|
||||||
@@ -40,38 +58,48 @@ Context:
|
|||||||
|
|
||||||
Actor mapping (text):
|
Actor mapping (text):
|
||||||
1. Tenant: `Legendary Event Staffing and Entertainment` (the company using Krow).
|
1. Tenant: `Legendary Event Staffing and Entertainment` (the company using Krow).
|
||||||
2. User: `Wil` (ops lead), `Maria` (client manager), `Ana` (worker).
|
2. User: `Wil` (ops lead), `Maria` (Google client manager), `Omar` (Google procurement approver), `Jose` (vendor scheduler), `Ana` (worker).
|
||||||
3. TenantMembership:
|
3. TenantMembership:
|
||||||
4. `Wil` is `admin` in Legendary tenant.
|
4. `Wil` is `admin` in Legendary tenant.
|
||||||
5. `Maria` is `manager` in Legendary tenant.
|
5. `Maria` is `member` in Legendary tenant.
|
||||||
6. `Ana` is `member` in Legendary tenant.
|
6. `Omar` is `member` in Legendary tenant.
|
||||||
7. Business: `Google Mountain View Cafes` (client account under the tenant).
|
7. `Jose` is `member` in Legendary tenant.
|
||||||
8. Vendor: `Legendary Staffing Pool A` (or an external approved vendor).
|
8. `Ana` is `member` in Legendary tenant.
|
||||||
9. Workforce/Staff: `Ana` is a staff profile in workforce, linked to certifications and assignments.
|
9. BusinessMembership:
|
||||||
10. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`.
|
10. `Maria` is `manager` in `Google Mountain View Cafes`.
|
||||||
11. StakeholderProfile:
|
11. `Omar` is `approver` in `Google Mountain View Cafes`.
|
||||||
12. `Google Procurement` = `buyer`.
|
12. VendorMembership:
|
||||||
13. `Legendary Ops` = `operator`.
|
13. `Jose` is `scheduler` in `Legendary Staffing Pool A`.
|
||||||
14. `FoodBuy` = `procurement_partner`.
|
14. `Wil` is `owner` in `Legendary Staffing Pool A`.
|
||||||
15. StakeholderLink:
|
15. Business: `Google Mountain View Cafes` (client account under the tenant).
|
||||||
16. `Google Procurement` `contracts_with` `Legendary Ops`.
|
16. Vendor: `Legendary Staffing Pool A` (or an external approved vendor).
|
||||||
17. `Legendary Ops` `sources_from` `Vendor`.
|
17. Workforce/Staff: `Ana` is a staff profile in workforce, linked to certifications and assignments.
|
||||||
18. `Google Procurement` `reports_through` `FoodBuy`.
|
18. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`.
|
||||||
|
19. StakeholderProfile:
|
||||||
|
20. `Google Procurement` = `buyer`.
|
||||||
|
21. `Legendary Ops` = `operator`.
|
||||||
|
22. `FoodBuy` = `procurement_partner`.
|
||||||
|
23. StakeholderLink:
|
||||||
|
24. `Google Procurement` `contracts_with` `Legendary Ops`.
|
||||||
|
25. `Legendary Ops` `sources_from` `Legendary Staffing Pool A`.
|
||||||
|
26. `Google Procurement` `reports_through` `FoodBuy`.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant Tenant as "Tenant (Legendary)"
|
participant Tenant as "Tenant (Legendary)"
|
||||||
participant Biz as "Business (Google Cafes)"
|
participant BizUser as "Business user (Maria/Omar)"
|
||||||
participant Ops as "User + TenantMembership (Ops Lead)"
|
participant Ops as "Ops user (Wil)"
|
||||||
|
participant VendorUser as "Vendor user (Jose)"
|
||||||
participant Staff as "Workforce/Staff (Barista Ana)"
|
participant Staff as "Workforce/Staff (Barista Ana)"
|
||||||
participant StakeRel as "StakeholderLink"
|
participant StakeRel as "StakeholderLink"
|
||||||
|
|
||||||
Biz->>Ops: "Create staffing request"
|
BizUser->>Ops: "Create staffing request"
|
||||||
Ops->>Tenant: "Create order under tenant scope"
|
Ops->>Tenant: "Create order under tenant scope"
|
||||||
Ops->>StakeRel: "Resolve business-to-vendor/workforce relationships"
|
Ops->>StakeRel: "Resolve business-to-vendor/workforce relationships"
|
||||||
Ops->>Staff: "Assign qualified worker"
|
Ops->>VendorUser: "Dispatch role demand"
|
||||||
|
VendorUser->>Staff: "Confirm worker assignment"
|
||||||
Staff-->>Ops: "Clock in/out and complete shift"
|
Staff-->>Ops: "Clock in/out and complete shift"
|
||||||
Ops-->>Biz: "Invoice/report generated with audit trail"
|
Ops-->>BizUser: "Invoice/report generated with audit trail"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4) Scenario B: Another tenant (external vendor-heavy)
|
## 4) Scenario B: Another tenant (external vendor-heavy)
|
||||||
@@ -82,41 +110,57 @@ Context:
|
|||||||
|
|
||||||
Actor mapping (text):
|
Actor mapping (text):
|
||||||
1. Tenant: `Peakline Events` (another staffing company using Krow).
|
1. Tenant: `Peakline Events` (another staffing company using Krow).
|
||||||
2. User: `Chris` (operations coordinator), `Nina` (client manager), `Leo` (worker).
|
2. User: `Chris` (operations coordinator), `Nina` (client manager), `Sam` (vendor manager), `Leo` (worker).
|
||||||
3. TenantMembership:
|
3. TenantMembership:
|
||||||
4. `Chris` is `admin` in Peakline tenant.
|
4. `Chris` is `admin` in Peakline tenant.
|
||||||
5. `Nina` is `manager` in Peakline tenant.
|
5. `Nina` is `member` in Peakline tenant.
|
||||||
6. `Leo` is `member` in Peakline tenant.
|
6. `Sam` is `member` in Peakline tenant.
|
||||||
7. Business: `NVIDIA Campus Dining` (client account under the tenant).
|
7. `Leo` is `member` in Peakline tenant.
|
||||||
8. Vendor: `Metro Staffing LLC` (approved external vendor for this tenant).
|
8. BusinessMembership:
|
||||||
9. Workforce/Staff: `Leo` is a workforce profile fulfilled through Metro Staffing for assignment and attendance.
|
9. `Nina` is `manager` in `NVIDIA Campus Dining`.
|
||||||
10. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`.
|
10. VendorMembership:
|
||||||
11. StakeholderProfile:
|
11. `Sam` is `manager` in `Metro Staffing LLC`.
|
||||||
12. `NVIDIA Procurement` = `buyer`.
|
12. Business: `NVIDIA Campus Dining` (client account under the tenant).
|
||||||
13. `Peakline Ops` = `operator`.
|
13. Vendor: `Metro Staffing LLC` (approved external vendor for this tenant).
|
||||||
14. `FoodBuy Regional` = `procurement_partner`.
|
14. Workforce/Staff: `Leo` is a workforce profile fulfilled through Metro Staffing for assignment and attendance.
|
||||||
15. StakeholderLink:
|
15. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`.
|
||||||
16. `NVIDIA Procurement` `contracts_with` `Peakline Ops`.
|
16. StakeholderProfile:
|
||||||
17. `Peakline Ops` `sources_from` `Metro Staffing LLC`.
|
17. `NVIDIA Procurement` = `buyer`.
|
||||||
18. `NVIDIA Procurement` `reports_through` `FoodBuy Regional`.
|
18. `Peakline Ops` = `operator`.
|
||||||
|
19. `FoodBuy Regional` = `procurement_partner`.
|
||||||
|
20. StakeholderLink:
|
||||||
|
21. `NVIDIA Procurement` `contracts_with` `Peakline Ops`.
|
||||||
|
22. `Peakline Ops` `sources_from` `Metro Staffing LLC`.
|
||||||
|
23. `NVIDIA Procurement` `reports_through` `FoodBuy Regional`.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant Tenant as "Tenant (Peakline Events)"
|
participant Tenant as "Tenant (Peakline Events)"
|
||||||
participant Biz as "Business (NVIDIA Dining)"
|
participant BizUser as "Business user (Nina)"
|
||||||
participant Ops as "User + TenantMembership (Coordinator)"
|
participant Ops as "Ops user (Chris)"
|
||||||
participant Vendor as "Vendor (Metro Staffing)"
|
participant VendorUser as "Vendor user (Sam)"
|
||||||
participant Staff as "Workforce/Staff (Vendor worker)"
|
participant Staff as "Workforce/Staff (Vendor worker)"
|
||||||
|
|
||||||
Biz->>Ops: "Request recurring event staffing"
|
BizUser->>Ops: "Request recurring event staffing"
|
||||||
Ops->>Tenant: "Create recurring order"
|
Ops->>Tenant: "Create recurring order"
|
||||||
Ops->>Vendor: "Dispatch required roles"
|
Ops->>VendorUser: "Dispatch required roles"
|
||||||
Vendor->>Staff: "Provide available workers"
|
VendorUser->>Staff: "Provide available workers"
|
||||||
Staff-->>Ops: "Attendance and completion events"
|
Staff-->>Ops: "Attendance and completion events"
|
||||||
Ops-->>Biz: "Settlement + performance reports"
|
Ops-->>BizUser: "Settlement + performance reports"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5) Why this model scales
|
## 5) Why this model scales
|
||||||
1. New stakeholders can be added through `StakeholderType` and `StakeholderProfile` without changing core order/shift tables.
|
1. New stakeholders can be added through `StakeholderType` and `StakeholderProfile` without changing core order/shift tables.
|
||||||
2. Multi-tenant isolation stays strict because all critical records resolve through `Tenant`.
|
2. Business and vendor user partitioning is explicit through membership tables, not hidden in one owner field.
|
||||||
3. Legendary and non-Legendary operating models both fit the same structure.
|
3. Multi-tenant isolation stays strict because all critical records resolve through `Tenant`.
|
||||||
|
4. Legendary and non-Legendary operating models both fit the same structure.
|
||||||
|
|
||||||
|
## 6) Industry alignment (primary references)
|
||||||
|
1. Google Cloud Identity Platform multi-tenancy:
|
||||||
|
- https://docs.cloud.google.com/identity-platform/docs/multi-tenancy
|
||||||
|
2. AWS SaaS tenant isolation fundamentals:
|
||||||
|
- https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/tenant-isolation.html
|
||||||
|
3. B2B organization-aware login flows (Auth0 Organizations):
|
||||||
|
- https://auth0.com/docs/manage-users/organizations/login-flows-for-organizations
|
||||||
|
4. Supplier-side multi-user management patterns (Coupa Supplier Portal):
|
||||||
|
- https://compass.coupa.com/en-us/products/product-documentation/supplier-resources/for-suppliers/coupa-supplier-portal/set-up-the-csp/users/manage-users
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
# M4 Planning Phase: Identified Discrepancies and Enhancements
|
|
||||||
|
|
||||||
## Feedback and Discrepancies (Based on M3 Review done by Iliana)
|
|
||||||
|
|
||||||
### Mobile Application (Client & Staff)
|
|
||||||
- **Flexible Shift Locations:** Feedback from the M3 review indicated a need for the ability to specify different locations for individual positions within an order on the mobile app. Currently, the web application handles this by requiring a separate shift for each location.
|
|
||||||
|
|
||||||
- **Order Visibility Management:** Currently, when an order is created with multiple positions, the "View Order" page displays them as separate orders. This is due to UI (prototype) cannot support multi-position views in the order. We should consider adopting the "legacy" app's approach to group these positions under a single order for better clarity.
|
|
||||||
|
|
||||||
- **Cost Center Clarification:** The purpose and functionality of the "Cost Center" field in the Hub creation process is not clear.
|
|
||||||
|
|
||||||
- **Tax Form Data Completeness:** Feedback noted that while tax forms are visible in the Staff mobile application, they appear to be missing critical information. This not clear.
|
|
||||||
|
|
||||||
### Web Dashboard
|
|
||||||
- **Role-Based Content Logic:** The current web dashboard prototype contains some logical inconsistencies regarding user roles:
|
|
||||||
- **Client Dashboard:** Currently includes Staff Availability, Staff Directory, and Staff Onboarding. Since workers (Staff) are managed by Vendors, these pages should be moved to the Vendor dashboard.
|
|
||||||
|
|
||||||
- **Vendor Dashboard:** Currently includes "Teams and Hubs." Since Hubs are client-specific locations where staff clock in/out, these management pages should be moved to the Client dashboard.
|
|
||||||
|
|
||||||
- **Admin Dashboard Filtering:** The Admin dashboard requires improved filtering capabilities. Admins should be able to select specific Clients or Vendors to filter related data, such as viewing only the orders associated with a chosen partner.
|
|
||||||
|
|
||||||
## Proposed Features and Enhancements (Post-M3 Identification)
|
|
||||||
|
|
||||||
- **Feature: Navigation to Hub Details from Coverage Screen (#321)**
|
|
||||||
- **Description:** Allow users to navigate directly to the Hub Details page by clicking on a hub within the Coverage Screen.
|
|
||||||
|
|
||||||
- **Feature: Dedicated Hub Details Screen with Order History (#320)**
|
|
||||||
- **Description:** Develop a comprehensive Hub Details view that aggregates all hub-specific data, including historical order records.
|
|
||||||
- **Benefit:** Centralizes information for better decision-making and easier access to historical data.
|
|
||||||
|
|
||||||
- **Feature: Dedicated Order Details Screen**
|
|
||||||
- **Description:** Transition from displaying all order information on the primary "View Order" page to a dedicated "Order Details" screen. This screen will support viewing multiple positions within a single order.
|
|
||||||
- **Benefit:**
|
|
||||||
- **Improved UX:** Reduces complexity by grouping associated positions together and presenting them in a structured way.
|
|
||||||
- **Performance:** Optimizes data loading by fetching detailed position information only when requested.
|
|
||||||
|
|
||||||
- **Feature: Optimized Clock-In Page (#350)**
|
|
||||||
- **Description:** Remove the calendar component from the Clock-In page. Since workers only clock in for current-day assignments, the calendar is unnecessary.
|
|
||||||
- **Benefit:** Simplifies the interface and reduces user confusion.
|
|
||||||
|
|
||||||
- **Feature: Contextual Shift Actions**
|
|
||||||
- **Description:** Restrict the Clock-In page to show only active or upcoming shifts (starting within 30 minutes). Shift-specific actions (Clock-In/Clock-Out) should be performed within the specific Shift Details page.
|
|
||||||
- **Reasoning:** This solves issues where staff cannot clock out of overnight shifts (shifts starting one day and ending the next) due to the current day-based UI.
|
|
||||||
|
|
||||||
- **Feature: Dedicated Emergency Contact Management (#356)**
|
|
||||||
- **Description:** Replace the inline form in the "View Emergency Contact" page with a dedicated "Create Emergency Contact" screen.
|
|
||||||
- **Benefit:** Standardizes the data entry process and improves UI organization within the Staff app.
|
|
||||||
@@ -71,13 +71,15 @@ What already exists and is useful:
|
|||||||
|
|
||||||
Current structural gaps for roadmap scale:
|
Current structural gaps for roadmap scale:
|
||||||
1. No tenant boundary key on core tables (`tenant_id` missing).
|
1. No tenant boundary key on core tables (`tenant_id` missing).
|
||||||
2. No first-class stakeholder profile/link model for buyer/operator/partner/sector relationships.
|
2. No first-class business user partitioning table (`business_memberships` missing).
|
||||||
3. Attendance history is not first-class (check in/out only inside `applications`).
|
3. No first-class vendor user partitioning table (`vendor_memberships` missing).
|
||||||
4. No offense policy, offense event, or enforcement action tables.
|
4. No first-class stakeholder profile/link model for buyer/operator/partner/sector relationships.
|
||||||
5. Finance is coarse (invoice + recent payment), missing line items, payment runs, remittance artifact model.
|
5. Attendance history is not first-class (check in/out only inside `applications`).
|
||||||
6. Sensitive bank fields are currently modeled directly in `accounts` (`accountNumber`, `routeNumber`).
|
6. No offense policy, offense event, or enforcement action tables.
|
||||||
7. Many core workflow fields are JSON (`orders.assignedStaff`, `orders.shifts`, `shift.managers`, `assignment.managers`).
|
7. Finance is coarse (invoice + recent payment), missing line items, payment runs, remittance artifact model.
|
||||||
8. Money still uses float in critical tables.
|
8. Sensitive bank fields are currently modeled directly in `accounts` (`accountNumber`, `routeNumber`).
|
||||||
|
9. Many core workflow fields are JSON (`orders.assignedStaff`, `orders.shifts`, `shift.managers`, `assignment.managers`).
|
||||||
|
10. Money still uses float in critical tables.
|
||||||
|
|
||||||
Connector boundary gap:
|
Connector boundary gap:
|
||||||
1. 147 Data Connect mutation operations exist.
|
1. 147 Data Connect mutation operations exist.
|
||||||
@@ -88,10 +90,12 @@ Connector boundary gap:
|
|||||||
### 6.1 Tenant and stakeholder graph
|
### 6.1 Tenant and stakeholder graph
|
||||||
1. `tenants`
|
1. `tenants`
|
||||||
2. `tenant_memberships`
|
2. `tenant_memberships`
|
||||||
3. `stakeholder_types`
|
3. `business_memberships`
|
||||||
4. `stakeholder_profiles`
|
4. `vendor_memberships`
|
||||||
5. `stakeholder_links`
|
5. `stakeholder_types`
|
||||||
6. `role_bindings` (scoped to tenant/team/hub/business/vendor/resource)
|
6. `stakeholder_profiles`
|
||||||
|
7. `stakeholder_links`
|
||||||
|
8. `role_bindings` (scoped to tenant/team/hub/business/vendor/resource)
|
||||||
|
|
||||||
### 6.2 Attendance and timesheet reliability
|
### 6.2 Attendance and timesheet reliability
|
||||||
1. `attendance_events` (append-only clock-in/out/NFC/manual-corrected)
|
1. `attendance_events` (append-only clock-in/out/NFC/manual-corrected)
|
||||||
@@ -124,6 +128,10 @@ Connector boundary gap:
|
|||||||
```mermaid
|
```mermaid
|
||||||
erDiagram
|
erDiagram
|
||||||
TENANT ||--o{ TENANT_MEMBERSHIP : has
|
TENANT ||--o{ TENANT_MEMBERSHIP : has
|
||||||
|
BUSINESS ||--o{ BUSINESS_MEMBERSHIP : has
|
||||||
|
VENDOR ||--o{ VENDOR_MEMBERSHIP : has
|
||||||
|
USER ||--o{ BUSINESS_MEMBERSHIP : belongs_to
|
||||||
|
USER ||--o{ VENDOR_MEMBERSHIP : belongs_to
|
||||||
TENANT ||--o{ STAKEHOLDER_PROFILE : has
|
TENANT ||--o{ STAKEHOLDER_PROFILE : has
|
||||||
STAKEHOLDER_PROFILE ||--o{ STAKEHOLDER_LINK : links_to
|
STAKEHOLDER_PROFILE ||--o{ STAKEHOLDER_LINK : links_to
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Practical meaning:
|
|||||||
3. Not every record starts as a full active user:
|
3. Not every record starts as a full active user:
|
||||||
- invite-first or pending onboarding records are valid,
|
- invite-first or pending onboarding records are valid,
|
||||||
- then bound to `user_id` when activation is completed.
|
- then bound to `user_id` when activation is completed.
|
||||||
|
4. Business-side users and vendor-side users are partitioned with dedicated membership tables, not only one `userId` owner field.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
@@ -41,16 +42,16 @@ The stakeholder labels from the customer workshop map to schema as follows:
|
|||||||
|
|
||||||
1. Buyer (Procurements):
|
1. Buyer (Procurements):
|
||||||
- Buyer users inside a business/client account.
|
- Buyer users inside a business/client account.
|
||||||
- Schema anchor: `users` + `tenant_memberships` + `team_members` (procurement team scope).
|
- Schema anchor: `users` + `tenant_memberships` + `business_memberships`.
|
||||||
2. Enterprises (Operator):
|
2. Enterprises (Operator):
|
||||||
- Tenant operator/admin users running staffing operations.
|
- Tenant operator/admin users running staffing operations.
|
||||||
- Schema anchor: `tenants`, `team_members`, command-side permissions.
|
- Schema anchor: `tenants`, `tenant_memberships`, `role_bindings`.
|
||||||
3. Sectors (Execution):
|
3. Sectors (Execution):
|
||||||
- Operational segments or business units executing events.
|
- Operational segments or business units executing events.
|
||||||
- Schema anchor: `teams`, `team_hubs`, `team_hud_departments`, `roles`.
|
- Schema anchor: `teams`, `team_hubs`, `team_hud_departments`, `roles`.
|
||||||
4. Approved Vendor:
|
4. Approved Vendor:
|
||||||
- Supplier companies approved to fulfill staffing demand.
|
- Supplier companies approved to fulfill staffing demand.
|
||||||
- Schema anchor: `vendors`, `workforce`, `vendor_rates`, `vendor_benefit_plans`.
|
- Schema anchor: `vendors`, `vendor_memberships`, `workforce`, `vendor_rates`, `vendor_benefit_plans`.
|
||||||
5. Workforce:
|
5. Workforce:
|
||||||
- Individual workers/staff and their assignments.
|
- Individual workers/staff and their assignments.
|
||||||
- Schema anchor: `staffs`, `staff_roles`, `applications`, `assignments`, `certificates`, `staff_documents`.
|
- Schema anchor: `staffs`, `staff_roles`, `applications`, `assignments`, `certificates`, `staff_documents`.
|
||||||
@@ -99,15 +100,19 @@ What the exports confirmed:
|
|||||||
Tables:
|
Tables:
|
||||||
1. `users` (source identity, profile, auth linkage)
|
1. `users` (source identity, profile, auth linkage)
|
||||||
2. `tenant_memberships` (new; membership + base access per tenant)
|
2. `tenant_memberships` (new; membership + base access per tenant)
|
||||||
3. `team_members` (membership + scope per team)
|
3. `business_memberships` (new; user access to business account scope)
|
||||||
4. `roles` (new)
|
4. `vendor_memberships` (new; user access to vendor account scope)
|
||||||
5. `permissions` (new)
|
5. `team_members` (membership + scope per team)
|
||||||
6. `role_bindings` (new; who has which role in which scope)
|
6. `roles` (new)
|
||||||
|
7. `permissions` (new)
|
||||||
|
8. `role_bindings` (new; who has which role in which scope)
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
1. Unique tenant membership: `(tenant_id, user_id)`.
|
1. Unique tenant membership: `(tenant_id, user_id)`.
|
||||||
2. Unique team membership: `(team_id, user_id)`.
|
2. Unique business membership: `(business_id, user_id)`.
|
||||||
3. Access checks resolve through tenant membership first, then optional team/hub scope.
|
3. Unique vendor membership: `(vendor_id, user_id)`.
|
||||||
|
4. Unique team membership: `(team_id, user_id)`.
|
||||||
|
5. Access checks resolve through tenant membership first, then business/vendor/team scope.
|
||||||
|
|
||||||
## 4.2 Organization and Tenant
|
## 4.2 Organization and Tenant
|
||||||
Tables:
|
Tables:
|
||||||
@@ -121,6 +126,7 @@ Tables:
|
|||||||
Rules:
|
Rules:
|
||||||
1. Every command-critical row references `tenant_id`.
|
1. Every command-critical row references `tenant_id`.
|
||||||
2. All list queries must include tenant predicate.
|
2. All list queries must include tenant predicate.
|
||||||
|
3. Business and vendor routes must enforce membership scope before data access.
|
||||||
|
|
||||||
## 4.8 RBAC rollout strategy (deferred enforcement)
|
## 4.8 RBAC rollout strategy (deferred enforcement)
|
||||||
RBAC should be introduced in phases and **not enforced everywhere immediately**.
|
RBAC should be introduced in phases and **not enforced everywhere immediately**.
|
||||||
@@ -250,6 +256,10 @@ erDiagram
|
|||||||
TENANT ||--o{ TEAM : owns
|
TENANT ||--o{ TEAM : owns
|
||||||
TEAM ||--o{ TEAM_MEMBER : has
|
TEAM ||--o{ TEAM_MEMBER : has
|
||||||
USER ||--o{ TEAM_MEMBER : belongs_to
|
USER ||--o{ TEAM_MEMBER : belongs_to
|
||||||
|
USER ||--o{ BUSINESS_MEMBERSHIP : belongs_to
|
||||||
|
USER ||--o{ VENDOR_MEMBERSHIP : belongs_to
|
||||||
|
BUSINESS ||--o{ BUSINESS_MEMBERSHIP : has
|
||||||
|
VENDOR ||--o{ VENDOR_MEMBERSHIP : has
|
||||||
|
|
||||||
BUSINESS ||--o{ ORDER : requests
|
BUSINESS ||--o{ ORDER : requests
|
||||||
VENDOR ||--o{ ORDER : fulfills
|
VENDOR ||--o{ ORDER : fulfills
|
||||||
|
|||||||
Reference in New Issue
Block a user