From 5e70607ae2b630b5b17709253c0db4d3162e9650 Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Tue, 31 Mar 2026 13:17:27 -0700 Subject: [PATCH 1/3] feat(openfga): add b2b_org, project_membership, and key_contact types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add three new OpenFGA types required by the v2 member service architecture (LFXV2-1356). The stub 'member' type (unused) is replaced by the three first-class types that reflect the actual Salesforce entity model. Model version is bumped to 10.1.0 (minor addition of types). The global_org_admin relation on b2b_org provides platform-wide machine user access without a hierarchical root object; writer/auditor on project_membership and key_contact inherit from both the owning b2b_org and the parent project. Note: global_org_admin team UID and provisioning method are an open question tracked in LFXV2-1356. 🤖 Generated with [GitHub Copilot](https://github.com/features/copilot) (via OpenCode) Signed-off-by: Eric Searcy --- .../lfx-platform/templates/openfga/model.yaml | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/charts/lfx-platform/templates/openfga/model.yaml b/charts/lfx-platform/templates/openfga/model.yaml index 040c0b6..1c65622 100644 --- a/charts/lfx-platform/templates/openfga/model.yaml +++ b/charts/lfx-platform/templates/openfga/model.yaml @@ -419,10 +419,38 @@ spec: # we just use the "owner" relation in our access checks! define auditor: owner or auditor from survey - # @fgadoc:hide - # This type is used for access to membership apis, not to define someone as a project member - # eventually it needs to be expanded as we index objects - type member + # The b2b_org type represents a Salesforce Account (B2B company). The UID is + # an invertible UUID v8 encoded from the Salesforce Account SFID. + # global_org_admin is written to every b2b_org at creation time by the member + # service, providing writer (and transitively auditor) access to all org admins + # without requiring a hierarchical root object. + type b2b_org + relations + define global_org_admin: [team#member] + define owner: [user] + define writer: [user] or owner or global_org_admin + define auditor: [user, team#member] or writer + + # The project_membership type represents a Salesforce Asset record: one active + # (or expired) membership term for a b2b_org within a project. Access is derived + # from the caller's relationship to the parent b2b_org or parent project. + # writer is intentionally scoped to b2b_org only: project-level writers (LF staff) + # can audit memberships but cannot create or modify them. + type project_membership relations - define auditor: [user, team#member] + define b2b_org: [b2b_org] + define project: [project] + define writer: writer from b2b_org + define auditor: auditor from b2b_org or auditor from project + + # The key_contact type represents a Salesforce Project_Role__c record: a named + # contact role assigned to a b2b_org for a specific project membership. Write + # access is granted to b2b_org writers (owners and global org-admin team) and to + # project-level writers (LF staff managing contacts on behalf of members). + type key_contact + relations + define b2b_org: [b2b_org] + define project: [project] + define writer: writer from b2b_org or writer from project + define auditor: auditor from b2b_org or auditor from project {{- end }} From 428f3ef8a744a94b30d75b06d3afa650422d324c Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Wed, 1 Apr 2026 14:09:53 -0700 Subject: [PATCH 2/3] fix(openfga): address review comments on b2b_org model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bump version to 11.0.0 (major: type additions/deletions per guidelines) - Move global_org_admin from owner to writer on b2b_org, reserving owner for future owner-only gates (e.g. org transfer/deletion) - Add writer from project to key_contact so project-level writers (LF staff) can manage key contacts without membership write access 🤖 Generated with [GitHub Copilot](https://github.com/features/copilot) (via OpenCode) Signed-off-by: Eric Searcy --- charts/lfx-platform/templates/openfga/model.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/lfx-platform/templates/openfga/model.yaml b/charts/lfx-platform/templates/openfga/model.yaml index 1c65622..4a79d96 100644 --- a/charts/lfx-platform/templates/openfga/model.yaml +++ b/charts/lfx-platform/templates/openfga/model.yaml @@ -23,8 +23,8 @@ spec: @fgadoc:hide, @fgadoc:alias, @fgadoc:collapse tags are managed manually. */}} - version: - major: 10 - minor: 1 + major: 11 + minor: 0 patch: 0 authorizationModel: | model From c19b84564b36ff5304b320794c306324c629920c Mon Sep 17 00:00:00 2001 From: Eric Searcy Date: Mon, 13 Apr 2026 15:38:20 -0700 Subject: [PATCH 3/3] docs(openfga): add @fgadoc annotations and extend PERMISSIONS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add structural @fgadoc tags to the three new member service types: - @fgadoc:alias for human-readable display names - @fgadoc:hide on global_org_admin (machine-user relation, not directly assignable by humans) Regenerate PERMISSIONS.md via the render-permissions skill to include sections for all three new types. b2b_org renders as a prose section (direct-grant roles present but no JTBDs yet; routes not yet implemented in LFXV2-1360–1362). project_membership and key_contact render as prose-only with inheritance bullets (all access is inherited, no direct grants). 🤖 Generated with [GitHub Copilot](https://github.com/features/copilot) (via OpenCode) Signed-off-by: Eric Searcy --- PERMISSIONS.md | 38 +++++++++++++++++++ .../lfx-platform/templates/openfga/model.yaml | 4 ++ 2 files changed, 42 insertions(+) diff --git a/PERMISSIONS.md b/PERMISSIONS.md index 47466d2..e628dc2 100644 --- a/PERMISSIONS.md +++ b/PERMISSIONS.md @@ -177,3 +177,41 @@ role assignment. - ***Auditor***: inherited from Project Auditor, Committee Auditor --- + +### B2B Organization + +Access to a B2B Organization object is controlled via three directly-assignable +roles: **Owner**, **Writer**, and **Auditor**. No job-to-be-done actions are +documented for this type yet; this section will be expanded as API coverage +grows. + +#### Permission Inheritance + +- **Writer**: also granted to Owner; inherited from global org-admin team +- **Auditor**: also granted to Writer + +--- + +### Project Membership + +Access to a Project Membership object is fully inherited — there are no +directly-assignable roles on this type. Write access is scoped to B2B +Organization writers; read access is additionally available to Project auditors. + +#### Permission Inheritance + +- ***Writer***: inherited from B2B Organization Writer +- ***Auditor***: inherited from B2B Organization Auditor, Project Auditor + +--- + +### Key Contact + +Access to a Key Contact object is fully inherited — there are no +directly-assignable roles on this type. Both write and read access are +available to either the parent B2B Organization or the parent Project. + +#### Permission Inheritance + +- ***Writer***: inherited from B2B Organization Writer, Project Writer +- ***Auditor***: inherited from B2B Organization Auditor, Project Auditor diff --git a/charts/lfx-platform/templates/openfga/model.yaml b/charts/lfx-platform/templates/openfga/model.yaml index 4a79d96..60ab565 100644 --- a/charts/lfx-platform/templates/openfga/model.yaml +++ b/charts/lfx-platform/templates/openfga/model.yaml @@ -419,6 +419,7 @@ spec: # we just use the "owner" relation in our access checks! define auditor: owner or auditor from survey + # @fgadoc:alias B2B Organization # The b2b_org type represents a Salesforce Account (B2B company). The UID is # an invertible UUID v8 encoded from the Salesforce Account SFID. # global_org_admin is written to every b2b_org at creation time by the member @@ -426,11 +427,13 @@ spec: # without requiring a hierarchical root object. type b2b_org relations + # @fgadoc:hide define global_org_admin: [team#member] define owner: [user] define writer: [user] or owner or global_org_admin define auditor: [user, team#member] or writer + # @fgadoc:alias Project Membership # The project_membership type represents a Salesforce Asset record: one active # (or expired) membership term for a b2b_org within a project. Access is derived # from the caller's relationship to the parent b2b_org or parent project. @@ -443,6 +446,7 @@ spec: define writer: writer from b2b_org define auditor: auditor from b2b_org or auditor from project + # @fgadoc:alias Key Contact # The key_contact type represents a Salesforce Project_Role__c record: a named # contact role assigned to a b2b_org for a specific project membership. Write # access is granted to b2b_org writers (owners and global org-admin team) and to