From b645927429af938e5f32edb4cdd68d6981c2797a Mon Sep 17 00:00:00 2001 From: zouantchaw <44246692+zouantchaw@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:58:21 -0500 Subject: [PATCH] docs(m4): add business/vendor memberships and clean planning docs --- CHANGELOG.md | 3 + .../planning/m4-core-data-actors-scenarios.md | 144 ++++++++++++------ .../M4/planning/m4-discrepencies.md | 47 ------ .../m4-roadmap-csv-schema-reconciliation.md | 30 ++-- .../M4/planning/m4-target-schema-blueprint.md | 28 ++-- 5 files changed, 135 insertions(+), 117 deletions(-) delete mode 100644 docs/MILESTONES/M4/planning/m4-discrepencies.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 77bde8c2..dd7db650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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-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.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. | diff --git a/docs/MILESTONES/M4/planning/m4-core-data-actors-scenarios.md b/docs/MILESTONES/M4/planning/m4-core-data-actors-scenarios.md index 7826edbe..8c53fb69 100644 --- a/docs/MILESTONES/M4/planning/m4-core-data-actors-scenarios.md +++ b/docs/MILESTONES/M4/planning/m4-core-data-actors-scenarios.md @@ -9,20 +9,38 @@ Owner: Technical Lead 2. `User`: human identity that signs in. 3. `TenantMembership`: user role/context inside one tenant. 4. `Business`: client account served by the tenant. -5. `Vendor`: supplier account that can fulfill staffing demand. -6. `Workforce/Staff`: worker profile used for assignment and attendance. -7. `StakeholderType`: typed category (`buyer`, `operator`, `vendor_partner`, `workforce`, `partner`). -8. `StakeholderProfile`: typed actor record inside a tenant. -9. `StakeholderLink`: relationship between stakeholder profiles. +5. `BusinessMembership`: maps users to a business with role/status (`owner`, `manager`, `approver`, `viewer`). +6. `Vendor`: supplier account that can fulfill staffing demand. +7. `VendorMembership`: maps users to a vendor with role/status (`owner`, `manager`, `scheduler`, `viewer`). +8. `Workforce/Staff`: worker profile used for assignment and attendance. +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 ```mermaid flowchart LR - T["Tenant"] --> TM["TenantMembership"] + T["Tenant"] --> TM["TenantMembership (global tenant access)"] U["User"] --> TM T --> B["Business"] T --> V["Vendor"] + U --> BM["BusinessMembership"] + BM --> B + U --> VM["VendorMembership"] + VM --> V U --> S["Workforce/Staff"] T --> SP["StakeholderProfile"] ST["StakeholderType"] --> SP @@ -40,38 +58,48 @@ Context: Actor mapping (text): 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: 4. `Wil` is `admin` in Legendary tenant. -5. `Maria` is `manager` in Legendary tenant. -6. `Ana` is `member` in Legendary tenant. -7. Business: `Google Mountain View Cafes` (client account under the tenant). -8. Vendor: `Legendary Staffing Pool A` (or an external approved vendor). -9. Workforce/Staff: `Ana` is a staff profile in workforce, linked to certifications and assignments. -10. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`. -11. StakeholderProfile: -12. `Google Procurement` = `buyer`. -13. `Legendary Ops` = `operator`. -14. `FoodBuy` = `procurement_partner`. -15. StakeholderLink: -16. `Google Procurement` `contracts_with` `Legendary Ops`. -17. `Legendary Ops` `sources_from` `Vendor`. -18. `Google Procurement` `reports_through` `FoodBuy`. +5. `Maria` is `member` in Legendary tenant. +6. `Omar` is `member` in Legendary tenant. +7. `Jose` is `member` in Legendary tenant. +8. `Ana` is `member` in Legendary tenant. +9. BusinessMembership: +10. `Maria` is `manager` in `Google Mountain View Cafes`. +11. `Omar` is `approver` in `Google Mountain View Cafes`. +12. VendorMembership: +13. `Jose` is `scheduler` in `Legendary Staffing Pool A`. +14. `Wil` is `owner` in `Legendary Staffing Pool A`. +15. Business: `Google Mountain View Cafes` (client account under the tenant). +16. Vendor: `Legendary Staffing Pool A` (or an external approved vendor). +17. Workforce/Staff: `Ana` is a staff profile in workforce, linked to certifications and assignments. +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 sequenceDiagram participant Tenant as "Tenant (Legendary)" - participant Biz as "Business (Google Cafes)" - participant Ops as "User + TenantMembership (Ops Lead)" + participant BizUser as "Business user (Maria/Omar)" + participant Ops as "Ops user (Wil)" + participant VendorUser as "Vendor user (Jose)" participant Staff as "Workforce/Staff (Barista Ana)" participant StakeRel as "StakeholderLink" - Biz->>Ops: "Create staffing request" + BizUser->>Ops: "Create staffing request" Ops->>Tenant: "Create order under tenant scope" 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" - Ops-->>Biz: "Invoice/report generated with audit trail" + Ops-->>BizUser: "Invoice/report generated with audit trail" ``` ## 4) Scenario B: Another tenant (external vendor-heavy) @@ -82,41 +110,57 @@ Context: Actor mapping (text): 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: 4. `Chris` is `admin` in Peakline tenant. -5. `Nina` is `manager` in Peakline tenant. -6. `Leo` is `member` in Peakline tenant. -7. Business: `NVIDIA Campus Dining` (client account under the tenant). -8. Vendor: `Metro Staffing LLC` (approved external vendor for this tenant). -9. Workforce/Staff: `Leo` is a workforce profile fulfilled through Metro Staffing for assignment and attendance. -10. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`. -11. StakeholderProfile: -12. `NVIDIA Procurement` = `buyer`. -13. `Peakline Ops` = `operator`. -14. `FoodBuy Regional` = `procurement_partner`. -15. StakeholderLink: -16. `NVIDIA Procurement` `contracts_with` `Peakline Ops`. -17. `Peakline Ops` `sources_from` `Metro Staffing LLC`. -18. `NVIDIA Procurement` `reports_through` `FoodBuy Regional`. +5. `Nina` is `member` in Peakline tenant. +6. `Sam` is `member` in Peakline tenant. +7. `Leo` is `member` in Peakline tenant. +8. BusinessMembership: +9. `Nina` is `manager` in `NVIDIA Campus Dining`. +10. VendorMembership: +11. `Sam` is `manager` in `Metro Staffing LLC`. +12. Business: `NVIDIA Campus Dining` (client account under the tenant). +13. Vendor: `Metro Staffing LLC` (approved external vendor for this tenant). +14. Workforce/Staff: `Leo` is a workforce profile fulfilled through Metro Staffing for assignment and attendance. +15. StakeholderType: `buyer`, `operator`, `vendor_partner`, `workforce`, `procurement_partner`. +16. StakeholderProfile: +17. `NVIDIA Procurement` = `buyer`. +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 sequenceDiagram participant Tenant as "Tenant (Peakline Events)" - participant Biz as "Business (NVIDIA Dining)" - participant Ops as "User + TenantMembership (Coordinator)" - participant Vendor as "Vendor (Metro Staffing)" + participant BizUser as "Business user (Nina)" + participant Ops as "Ops user (Chris)" + participant VendorUser as "Vendor user (Sam)" 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->>Vendor: "Dispatch required roles" - Vendor->>Staff: "Provide available workers" + Ops->>VendorUser: "Dispatch required roles" + VendorUser->>Staff: "Provide available workers" Staff-->>Ops: "Attendance and completion events" - Ops-->>Biz: "Settlement + performance reports" + Ops-->>BizUser: "Settlement + performance reports" ``` ## 5) Why this model scales 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`. -3. Legendary and non-Legendary operating models both fit the same structure. +2. Business and vendor user partitioning is explicit through membership tables, not hidden in one owner field. +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 diff --git a/docs/MILESTONES/M4/planning/m4-discrepencies.md b/docs/MILESTONES/M4/planning/m4-discrepencies.md deleted file mode 100644 index 86f8f6f6..00000000 --- a/docs/MILESTONES/M4/planning/m4-discrepencies.md +++ /dev/null @@ -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. diff --git a/docs/MILESTONES/M4/planning/m4-roadmap-csv-schema-reconciliation.md b/docs/MILESTONES/M4/planning/m4-roadmap-csv-schema-reconciliation.md index 4b1f633b..bcd8e7fc 100644 --- a/docs/MILESTONES/M4/planning/m4-roadmap-csv-schema-reconciliation.md +++ b/docs/MILESTONES/M4/planning/m4-roadmap-csv-schema-reconciliation.md @@ -71,13 +71,15 @@ What already exists and is useful: Current structural gaps for roadmap scale: 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. -3. Attendance history is not first-class (check in/out only inside `applications`). -4. No offense policy, offense event, or enforcement action tables. -5. Finance is coarse (invoice + recent payment), missing line items, payment runs, remittance artifact model. -6. Sensitive bank fields are currently modeled directly in `accounts` (`accountNumber`, `routeNumber`). -7. Many core workflow fields are JSON (`orders.assignedStaff`, `orders.shifts`, `shift.managers`, `assignment.managers`). -8. Money still uses float in critical tables. +2. No first-class business user partitioning table (`business_memberships` missing). +3. No first-class vendor user partitioning table (`vendor_memberships` missing). +4. No first-class stakeholder profile/link model for buyer/operator/partner/sector relationships. +5. Attendance history is not first-class (check in/out only inside `applications`). +6. No offense policy, offense event, or enforcement action tables. +7. Finance is coarse (invoice + recent payment), missing line items, payment runs, remittance artifact model. +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: 1. 147 Data Connect mutation operations exist. @@ -88,10 +90,12 @@ Connector boundary gap: ### 6.1 Tenant and stakeholder graph 1. `tenants` 2. `tenant_memberships` -3. `stakeholder_types` -4. `stakeholder_profiles` -5. `stakeholder_links` -6. `role_bindings` (scoped to tenant/team/hub/business/vendor/resource) +3. `business_memberships` +4. `vendor_memberships` +5. `stakeholder_types` +6. `stakeholder_profiles` +7. `stakeholder_links` +8. `role_bindings` (scoped to tenant/team/hub/business/vendor/resource) ### 6.2 Attendance and timesheet reliability 1. `attendance_events` (append-only clock-in/out/NFC/manual-corrected) @@ -124,6 +128,10 @@ Connector boundary gap: ```mermaid erDiagram 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 STAKEHOLDER_PROFILE ||--o{ STAKEHOLDER_LINK : links_to diff --git a/docs/MILESTONES/M4/planning/m4-target-schema-blueprint.md b/docs/MILESTONES/M4/planning/m4-target-schema-blueprint.md index 7c77aac3..2f81014b 100644 --- a/docs/MILESTONES/M4/planning/m4-target-schema-blueprint.md +++ b/docs/MILESTONES/M4/planning/m4-target-schema-blueprint.md @@ -25,6 +25,7 @@ Practical meaning: 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. +4. Business-side users and vendor-side users are partitioned with dedicated membership tables, not only one `userId` owner field. ```mermaid flowchart LR @@ -41,16 +42,16 @@ The stakeholder labels from the customer workshop map to schema as follows: 1. Buyer (Procurements): - 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): - 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): - Operational segments or business units executing events. - Schema anchor: `teams`, `team_hubs`, `team_hud_departments`, `roles`. 4. Approved Vendor: - 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: - Individual workers/staff and their assignments. - Schema anchor: `staffs`, `staff_roles`, `applications`, `assignments`, `certificates`, `staff_documents`. @@ -99,15 +100,19 @@ What the exports confirmed: 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) +3. `business_memberships` (new; user access to business account scope) +4. `vendor_memberships` (new; user access to vendor account scope) +5. `team_members` (membership + scope per team) +6. `roles` (new) +7. `permissions` (new) +8. `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. +2. Unique business membership: `(business_id, user_id)`. +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 Tables: @@ -121,6 +126,7 @@ Tables: Rules: 1. Every command-critical row references `tenant_id`. 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) RBAC should be introduced in phases and **not enforced everywhere immediately**. @@ -250,6 +256,10 @@ erDiagram TENANT ||--o{ TEAM : owns TEAM ||--o{ TEAM_MEMBER : has 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 VENDOR ||--o{ ORDER : fulfills