---
id: AUTH-MBR
title: Membership Authorization Model
product_area: membership
revision: 1
status: draft
design_intent: proposed
implementation_evidence: partially-observed
source_sha:
  rhythm-v2-docs: ca10379cd33c971f26af3422dfef95e110a1e39d
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
provenance: observed
source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
scopes:
  - name: customer
    meaning: >-
      Platform customer-wide assignments contribute access to that customer’s
      workspaces; Membership owns no customer-level role administration.
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-010-give-and-take-away-roles-at-the-right-scope.md
  - name: workspace
    meaning: >-
      The application gate and workspace-level keys authorize work in the
      addressed workspace.
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
  - name: organizational unit
    meaning: >-
      Six declared keys support authority over a unit and its descendants; the
      service checks the relevant membership chain or changed units.
    provenance: observed
    source: 'services-membership:modules/memberships/services/access/scope-checks.ts'
  - name: personal record
    meaning: >-
      Self-read uses the account’s linked contact within its workspace; this is
      a relationship guard rather than a separately assignable record scope.
    provenance: observed
    source: >-
      services-membership:modules/memberships/aws/api/memberships.routes.ts:getMyMemberships
  - name: service execution
    meaning: >-
      Trusted cloud and database identities authorize partner, job and internal
      entry points without human permission assignments.
    provenance: observed
    source: >-
      services-membership:aws/api/membership.routes.ts;
      modules/commerce-participant/services/participant-handler.ts
roles:
  - id: ROLE-MBR-001
    name: Membership setup administrator
    who: A customer-defined role profile for staff maintaining association setup.
    grants:
      - membership.application.access
      - membership.structure.read
      - membership.structure.manage
      - membership.programs.read
      - membership.programs.manage
      - membership.configuration.read
      - membership.configuration.manage
      - membership.billing.read
      - membership.billing.manage
      - membership.operations.run
    provenance: inferred
    source: >-
      rhythm-v2-docs:specs/membership/ACTORS.md;
      services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS
    note: >-
      Proposed entitlement profile, not a shipped role or an observed customer
      assignment. Actual roles and effective grants remain Platform-owned:
      FND-MBR-MEM-088.
  - id: ROLE-MBR-002
    name: Membership coordinator
    who: >-
      A customer-defined role profile for staff maintaining holdings and member
      connections.
    grants:
      - membership.application.access
      - membership.members.read
      - membership.memberships.create
      - membership.memberships.suspend
      - membership.terms.create
      - membership.terms.correct
      - membership.terms.terminate
      - membership.affiliations.manage
      - membership.memberships.history
    provenance: inferred
    source: >-
      rhythm-v2-docs:specs/membership/ACTORS.md;
      services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS
    note: >-
      Proposed entitlement profile, not a shipped role or an observed customer
      assignment. Actual roles and effective grants remain Platform-owned:
      FND-MBR-MEM-088.
  - id: ROLE-MBR-003
    name: Membership analyst
    who: >-
      A customer-defined role profile for workspace-wide membership and
      reporting readers.
    grants:
      - membership.application.access
      - membership.members.read
      - membership.billing.read
      - membership.memberships.query
      - membership.membership-terms.query
      - membership.lifecycle-events.query
      - membership.term-affiliations.query
      - membership.membership-snapshot-members.query
      - membership.membership-snapshot-affiliations.query
      - membership.membership-snapshot-dimensions.query
      - membership.membership-snapshot-counts.query
    provenance: inferred
    source: >-
      rhythm-v2-docs:specs/membership/ACTORS.md;
      services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS
    note: >-
      Proposed entitlement profile, not a shipped role or an observed customer
      assignment. Actual roles and effective grants remain Platform-owned:
      FND-MBR-MEM-088.
  - id: ROLE-MBR-004
    name: Structure and configuration reader
    who: A customer-defined role profile for staff inspecting association setup.
    grants:
      - membership.application.access
      - membership.structure.read
      - membership.programs.read
      - membership.configuration.read
    provenance: inferred
    source: >-
      rhythm-v2-docs:specs/membership/ACTORS.md;
      services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS
    note: >-
      Proposed entitlement profile, not a shipped role or an observed customer
      assignment. Actual roles and effective grants remain Platform-owned:
      FND-MBR-MEM-088.
  - id: ROLE-MBR-005
    name: Unit officer
    who: >-
      A customer-defined role profile assigned to organizational units, commonly
      through appointments.
    grants:
      - membership.application.access
      - membership.members.read
      - membership.affiliations.manage
      - membership.member-contact.update
      - membership.terms.renew
      - membership.memberships.enroll
      - membership.rosters.export
    provenance: inferred
    source: >-
      rhythm-v2-docs:specs/membership/ACTORS.md;
      services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS
    note: >-
      Proposed entitlement profile, not a shipped role or an observed customer
      assignment. Actual roles and effective grants remain Platform-owned:
      FND-MBR-MEM-088.
  - id: ROLE-MBR-006
    name: Portal Member
    who: >-
      A portal membership whose Platform role must attach the declared
      Membership portal policy.
    grants:
      - membership.application.access
      - membership.self.read
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:PORTAL_MEMBER_POLICY'
    note: >-
      Policy declaration is observed; deployed role attachment is not
      established: FND-MBR-MEM-088.
permissions:
  - key: membership.affiliations.manage
    intent: Maintain dated membership connections within the evaluated unit scope.
    operations:
      - addAffiliation
      - endAffiliation
      - setPrimaryAffiliation
      - transferAffiliation
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-015-01
      - BR-CAP-MBR-MEM-015-07
      - BR-CAP-MBR-MEM-007-01
      - BR-CAP-MBR-MEM-007-02
      - BR-CAP-MBR-MEM-007-03
      - BR-CAP-MBR-MEM-007-04
      - BR-CAP-MBR-MEM-007-05
      - BR-CAP-MBR-MEM-007-06
      - BR-CAP-MBR-MEM-007-10
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.application.access
    intent: 'Open Membership in an available, licensed workspace.'
    operations:
      - getTermsTenantHealth
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-019-04
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.billing.manage
    intent: 'Administer and execute renewal templates, runs and recurring definitions.'
    operations:
      - cancelBillingRun
      - createBillingRun
      - createBillingTemplate
      - createRecurringBillingRun
      - deleteBillingTemplate
      - executeBillingRun
      - planBillingRun
      - updateBillingTemplate
      - updateRecurringBillingRun
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-013-01
      - BR-CAP-MBR-MEM-013-02
      - BR-CAP-MBR-MEM-013-03
      - BR-CAP-MBR-MEM-013-04
      - BR-CAP-MBR-MEM-013-05
      - BR-CAP-MBR-MEM-013-10
      - BR-CAP-MBR-MEM-013-11
      - BR-CAP-MBR-MEM-013-13
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.billing.read
    intent: >-
      Inspect renewal templates, runs, planned actions and recurring
      definitions.
    operations:
      - getBillingRun
      - getBillingTemplate
      - getRecurringBillingRun
      - listBillingRunActions
      - listBillingRuns
      - listBillingTemplates
      - listRecurringBillingRuns
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-019-04
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.configuration.manage
    intent: >-
      Administer membership offer configuration, application processes and area
      settings.
    operations:
      - createApplicationProcess
      - createChangePolicySet
      - createMembershipPackage
      - createMembershipType
      - createStatusReason
      - deleteApplicationProcess
      - deleteChangePolicySet
      - deleteMembershipPackage
      - deleteMembershipType
      - deleteStatusReason
      - replaceScopeSettings
      - replaceSnapshotDimensionSettings
      - updateApplicationProcess
      - updateChangePolicySet
      - updateMembershipPackage
      - updateMembershipType
      - updateStatusReason
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-018-03
      - BR-CAP-MBR-STR-018-04
      - BR-CAP-MBR-STR-018-05
      - BR-CAP-MBR-STR-018-06
      - BR-CAP-MBR-STR-018-07
      - BR-CAP-MBR-STR-012-01
      - BR-CAP-MBR-STR-012-04
      - BR-CAP-MBR-STR-012-05
      - BR-CAP-MBR-STR-012-06
      - BR-CAP-MBR-STR-012-08
      - BR-CAP-MBR-STR-013-01
      - BR-CAP-MBR-STR-013-02
      - BR-CAP-MBR-STR-013-03
      - BR-CAP-MBR-STR-013-05
      - BR-CAP-MBR-MEM-011-02
      - BR-CAP-MBR-MEM-011-03
      - BR-CAP-MBR-MEM-015-09
      - BR-CAP-MBR-MEM-019-07
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.configuration.read
    intent: >-
      Inspect membership offer configuration, application processes and area
      settings.
    operations:
      - getApplicationProcess
      - getChangePolicySet
      - getMembershipPackage
      - getMembershipType
      - getScopeSettings
      - getSnapshotDimensionSettings
      - getStatusReason
      - listApplicationProcesses
      - listChangePolicySets
      - listMembershipPackages
      - listMembershipTypes
      - listStatusReasons
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-019-04
      - BR-CAP-MBR-STR-019-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.lifecycle-events.query
    intent: >-
      Query workspace membership lifecycle records through the shared query
      layer.
    operations:
      - live membership query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.member-contact.update
    intent: >-
      Request allowed contact-field changes for a member within the evaluated
      unit scope.
    operations:
      - updateMemberContact
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-016-01
      - BR-CAP-MBR-MEM-016-02
      - BR-CAP-MBR-MEM-016-03
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.members.read
    intent: Inspect memberships and related facts within the evaluated unit scope.
    operations:
      - getApplication
      - getMembership
      - getMembershipAsOf
      - getMembershipFinancialSummary
      - getMembershipRevision
      - getTermRevision
      - listApplications
      - listMembershipHistory
      - listMembershipHistoryActors
      - listMemberships
      - listTermHistory
      - listTermHistoryActors
    surfaces:
      - api
      - console
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-015-01
      - BR-CAP-MBR-MEM-015-02
      - BR-CAP-MBR-MEM-015-03
      - BR-CAP-MBR-MEM-015-04
      - BR-CAP-MBR-MEM-015-05
      - BR-CAP-MBR-MEM-015-06
      - BR-CAP-MBR-MEM-015-11
      - BR-CAP-MBR-MEM-011-06
      - BR-CAP-MBR-MEM-016-07
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.membership-snapshot-affiliations.query
    intent: Query unit connections in published monthly reporting copies.
    operations:
      - membership snapshot query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.membership-snapshot-counts.query
    intent: Query movement and standing counts in published monthly reporting copies.
    operations:
      - membership snapshot query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.membership-snapshot-dimensions.query
    intent: Query captured characteristics in published monthly reporting copies.
    operations:
      - membership snapshot query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.membership-snapshot-members.query
    intent: Query members in published monthly reporting copies.
    operations:
      - membership snapshot query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.membership-terms.query
    intent: Query workspace membership periods through the shared query layer.
    operations:
      - live membership query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.memberships.create
    intent: Establish a membership and its initial committed period without an order.
    operations:
      - createMembership
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-001-01
      - BR-CAP-MBR-MEM-001-02
      - BR-CAP-MBR-MEM-001-03
      - BR-CAP-MBR-MEM-001-04
      - BR-CAP-MBR-MEM-001-06
      - BR-CAP-MBR-MEM-001-07
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.memberships.enroll
    intent: Request an enrolment order for a member within the evaluated unit scope.
    operations:
      - enrollMember
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-016-05
      - BR-CAP-MBR-MEM-016-06
      - BR-CAP-MBR-MEM-009-02
      - BR-CAP-MBR-MEM-009-03
      - BR-CAP-MBR-MEM-009-04
      - BR-CAP-MBR-MEM-009-11
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.memberships.history
    intent: >-
      Inspect recorded membership and term revisions with additional read
      authority.
    operations:
      - getMembershipRevision
      - getTermRevision
      - listMembershipHistory
      - listMembershipHistoryActors
      - listTermHistory
      - listTermHistoryActors
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-018-05
      - BR-CAP-MBR-MEM-018-12
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.memberships.query
    intent: Query workspace membership records through the shared query layer.
    operations:
      - live membership query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.memberships.suspend
    intent: Suspend or restore principal membership standing.
    operations:
      - restoreMembership
      - suspendMembership
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-004-01
      - BR-CAP-MBR-MEM-004-03
      - BR-CAP-MBR-MEM-004-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.operations.run
    intent: Request an immediate workspace status refresh.
    operations:
      - runStatusSweep
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-019-03
      - BR-CAP-MBR-STR-019-04
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.programs.manage
    intent: Administer membership programs and their unit requirements.
    operations:
      - createProgram
      - deleteProgram
      - replaceProgramUnitTypes
      - updateProgram
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-009-01
      - BR-CAP-MBR-STR-009-02
      - BR-CAP-MBR-STR-010-01
      - BR-CAP-MBR-STR-010-02
      - BR-CAP-MBR-STR-010-03
      - BR-CAP-MBR-STR-010-04
      - BR-CAP-MBR-STR-018-03
      - BR-CAP-MBR-STR-018-04
      - BR-CAP-MBR-STR-018-05
      - BR-CAP-MBR-STR-018-06
      - BR-CAP-MBR-STR-019-03
      - BR-CAP-MBR-STR-019-04
      - BR-CAP-MBR-STR-019-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.programs.read
    intent: Inspect membership programs and their unit requirements.
    operations:
      - getProgram
      - listPrograms
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-STR-019-04
      - BR-CAP-MBR-STR-019-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.rosters.export
    intent: Capture and retrieve a roster export within authorized scope.
    operations:
      - exportRoster
      - getRosterExport
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-017-01
      - BR-CAP-MBR-MEM-017-02
      - BR-CAP-MBR-MEM-017-03
      - BR-CAP-MBR-MEM-017-04
      - BR-CAP-MBR-MEM-017-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.self.read
    intent: >-
      Inspect the holdings associated with the signed-in member’s linked
      contact.
    operations:
      - getMyMemberships
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-017-06
      - BR-CAP-MBR-MEM-017-07
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.structure.manage
    intent: >-
      Administer association units, hierarchy, links and local financial
      context.
    operations:
      - createOrganizationalUnit
      - createOrganizationalUnitDuesProduct
      - createOrganizationalUnitRelationshipType
      - createOrganizationalUnitType
      - deactivateOrganizationalUnit
      - deactivateOrganizationalUnitType
      - deleteOrganizationalUnit
      - deleteOrganizationalUnitType
      - endOrganizationalUnitOrganization
      - linkOrganizationalUnitOrganization
      - mergeOrganizationalUnit
      - mergedUnitAffiliations
      - moveOrganizationalUnit
      - replaceOrganizationalUnit
      - replaceOrganizationalUnitDuesProduct
      - replaceOrganizationalUnitType
      - setOrganizationalUnitFinancialSettings
    surfaces:
      - api
      - console
      - internal
    guarded_by:
      - BR-CAP-MBR-STR-019-03
      - BR-CAP-MBR-STR-019-04
      - BR-CAP-MBR-STR-019-05
      - BR-CAP-MBR-STR-002-01
      - BR-CAP-MBR-STR-002-02
      - BR-CAP-MBR-STR-002-03
      - BR-CAP-MBR-STR-002-04
      - BR-CAP-MBR-STR-002-05
      - BR-CAP-MBR-STR-003-01
      - BR-CAP-MBR-STR-003-02
      - BR-CAP-MBR-STR-003-03
      - BR-CAP-MBR-STR-003-04
      - BR-CAP-MBR-STR-003-05
      - BR-CAP-MBR-STR-004-01
      - BR-CAP-MBR-STR-004-02
      - BR-CAP-MBR-STR-004-03
      - BR-CAP-MBR-STR-004-04
      - BR-CAP-MBR-STR-006-05
      - BR-CAP-MBR-STR-006-06
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.structure.read
    intent: 'Inspect association units, hierarchy, links and local financial context.'
    operations:
      - getOrganizationalUnit
      - getOrganizationalUnitFinancialSettings
      - getOrganizationalUnitType
      - listOrganizationalUnitAncestors
      - listOrganizationalUnitDescendants
      - listOrganizationalUnitDuesProducts
      - listOrganizationalUnitOrganizations
      - listOrganizationalUnitParentHistory
      - listOrganizationalUnitRelationshipTypes
      - listOrganizationalUnitTree
      - listOrganizationalUnitTypes
      - listOrganizationalUnits
      - >-
        query datasets membership.organizational_units and
        membership.organizational_unit_types
      - searchOrganizationalUnits
    surfaces:
      - api
      - console
      - internal
    guarded_by:
      - BR-CAP-MBR-STR-019-04
      - BR-CAP-MBR-STR-019-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.term-affiliations.query
    intent: Query workspace dated unit connections through the shared query layer.
    operations:
      - live membership query datasets
    surfaces:
      - api
      - internal
    guarded_by: []
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.terms.correct
    intent: Correct a committed membership period while preserving recorded values.
    operations:
      - correctTerm
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-003-01
      - BR-CAP-MBR-MEM-003-04
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.terms.create
    intent: Add a committed period without an order.
    operations:
      - createTerm
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-002-01
      - BR-CAP-MBR-MEM-002-02
      - BR-CAP-MBR-MEM-002-05
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: membership.terms.renew
    intent: Request a renewal order for a membership within the evaluated unit scope.
    operations:
      - renewMembership
    surfaces:
      - api
      - portal
    guarded_by:
      - BR-CAP-MBR-MEM-016-04
      - BR-CAP-MBR-MEM-016-06
      - BR-CAP-MBR-MEM-009-03
      - BR-CAP-MBR-MEM-009-04
      - BR-CAP-MBR-MEM-009-05
      - BR-CAP-MBR-MEM-009-11
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace or organizational unit
  - key: membership.terms.terminate
    intent: Close a committed membership period with a reason.
    operations:
      - terminateTerm
    surfaces:
      - api
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-003-01
      - BR-CAP-MBR-MEM-003-06
      - BR-CAP-MBR-MEM-003-07
    provenance: observed
    source: 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
    scope: workspace
  - key: 'none: the shared module health route'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - getApplicationsHealth
      - getMembershipsHealth
      - getSnapshotsHealth
    surfaces:
      - public
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-applications.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-memberships.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-snapshots.md
  - key: 'none: the Submissions engine invokes the decision function over IAM'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - handleSubmissionDecision
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-applications.md
  - key: 'none: Commerce invokes the participant function''s live alias over IAM'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - prepare_purchase
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md
  - key: 'none: an owner database function executable by Commerce''s claimer role'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - commerce_claim_cancellation
      - commerce_claim_change
      - commerce_commit_claims
      - commerce_release_claims
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md
  - key: 'none: Commerce invokes the participant function over IAM'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - cancel
      - enforce
      - fulfill
      - modify
      - prepare_cancellation
      - prepare_change
      - restore
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md
  - key: 'none: an in-process service call of the macroservice''s modules'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - publishBusinessEvent
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-events.md
  - key: 'none: scheduled and queue-driven functions'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - change-events dispatcher and consumer
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-events.md
  - key: membership.memberships.history and membership.members.read
    intent: >-
      Require each named permission for the declared operation or its selected
      dataset.
    operations:
      - getMembershipRevision
      - getTermRevision
      - listMembershipHistory
      - listMembershipHistoryActors
      - listTermHistory
      - listTermHistoryActors
    surfaces:
      - console
    guarded_by:
      - BR-CAP-MBR-MEM-018-05
      - BR-CAP-MBR-MEM-018-12
    declaration_kind: compound requirement
    permission_keys:
      - membership.memberships.history
      - membership.members.read
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md;
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md
  - key: 'none: an in-process call; the route is the memberships module''s'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - membershipAsOf
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md
  - key: >-
      membership.memberships.query, membership.membership-terms.query,
      membership.lifecycle-events.query, membership.term-affiliations.query
    intent: >-
      Require each named permission for the declared operation or its selected
      dataset.
    operations:
      - live membership query datasets
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: compound requirement
    permission_keys:
      - membership.memberships.query
      - membership.membership-terms.query
      - membership.lifecycle-events.query
      - membership.term-affiliations.query
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md
  - key: 'none: invoked by CRM''s change-event remote handler over IAM'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - handleCrmChangeEvents
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-memberships.md
  - key: >-
      none: called in process by the structure module's merge, whose caller
      holds membership.structure.manage
    intent: >-
      Describe an internal merge participant protected by the calling structure
      operation’s authority.
    operations:
      - mergedUnitAffiliations
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-memberships.md
    upstream_permission_keys:
      - membership.structure.manage
  - key: 'none: run by Platform''s data job engine under the job''s own authority'
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - membershipDataOperations
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-memberships.md
  - key: >-
      membership.membership-snapshot-members.query,
      membership.membership-snapshot-affiliations.query,
      membership.membership-snapshot-dimensions.query,
      membership.membership-snapshot-counts.query
    intent: >-
      Require each named permission for the declared operation or its selected
      dataset.
    operations:
      - membership snapshot query datasets
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: compound requirement
    permission_keys:
      - membership.membership-snapshot-members.query
      - membership.membership-snapshot-affiliations.query
      - membership.membership-snapshot-dimensions.query
      - membership.membership-snapshot-counts.query
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-snapshots.md
  - key: database role rhythm_table_reader; row isolation on the caller's workspace
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - membership.unit_ancestors
      - membership.unit_descendants
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-structure.md;
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-structure.md
  - key: none; called by Membership code that has already authorised its caller
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - computeTermPeriod
      - statusOf and episodesOf
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md;
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md
  - key: none; called by the configuration service
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - termRuleProblems
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md
  - key: none
    intent: >-
      Describe an entry point whose authority comes from public access, trusted
      execution or its caller rather than an assignable permission.
    operations:
      - cacheOf
      - migrationSql
      - 'sweep.boundariesOf, sweep.needsCatchUp and sweep.detectionsOf'
    surfaces:
      - internal
    guarded_by: []
    declaration_kind: no permission key
    permission_keys: []
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md;
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md;
      rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md
staff_access: >-
  Rhythm staff use Platform’s recorded customer-access grant and matching
  ordinary scoped role assignment. HQ staff status alone supplies no Membership
  authority.
staff_access_provenance: documented
staff_access_source: >-
  rhythm-v2-docs:specs/platform/security/design/decisions/ADR-PFM-SEC-009-staff-enter-customer-work-only-through-recorded-grants.md
evidence:
  - 'services-membership:aws/membership.service.ts:MEMBERSHIP_PERMISSION_SETS'
  - 'services-membership:aws/api/membership.routes.ts:membershipRegistryManifest'
  - 'services-membership:aws/api/configuration-routes.ts:configurationRoutes'
  - 'services-membership:aws/terms/terms.routes.ts:termsRoutes'
  - 'services-membership:modules/structure/aws/api/structure.routes.ts'
  - 'services-membership:modules/configuration/aws/api/configuration.routes.ts'
  - 'services-membership:modules/memberships/aws/api/memberships.routes.ts'
  - 'services-membership:modules/applications/aws/api/applications.routes.ts'
  - 'services-membership:modules/billing/aws/api/billing.routes.ts'
  - 'services-membership:modules/snapshots/aws/api/snapshots.routes.ts'
  - 'services-membership:modules/history/aws/api/history.routes.ts'
  - 'services-membership:modules/memberships/services/access/scope-checks.ts'
  - 'services-membership:modules/memberships/services/access/member-contact.ts'
  - 'services-membership:modules/memberships/services/rosters/roster-exports.ts'
  - 'services-membership:modules/memberships/queries/memberships.query.ts'
  - 'services-membership:modules/snapshots/queries/membership-snapshots.query.ts'
  - 'services-membership:docs/migrations/scope/README.md'
  - >-
    rhythm-v2-docs:specs/platform/security/design/decisions/ADR-PFM-SEC-007-authority-comes-only-from-assignments-signed-per-request-and.md
  - >-
    rhythm-v2-docs:specs/platform/security/design/decisions/ADR-PFM-SEC-009-staff-enter-customer-work-only-through-recorded-grants.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-010-give-and-take-away-roles-at-the-right-scope.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-012-define-a-customer-s-own-roles-and-policies.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-013-ship-rhythm-s-built-in-roles-and-policies-with-each-release.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-014-grant-roles-automatically-from-appointments-and-eligibility.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-015-decide-every-request-against-the-caller-s-grants.md
  - >-
    rhythm-v2-docs:specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-applications.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-billing.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-commerce-participant.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-events.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-history.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-memberships.md
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/contracts/SVC-MBR-MEM-snapshots.md
  - >-
    rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-configuration.md
  - >-
    rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-structure.md
  - >-
    rhythm-v2-docs:specs/membership/structure/design/contracts/SVC-MBR-STR-terms.md
---
# Membership Authorization Model

## Authorization Boundary

Protected Membership requests pass through Platform authentication, application access, licensing and workspace availability before the declared operation authority and record guards apply. Public module health responses expose operational health rather than customer records. Partner functions, database claims and scheduled jobs use trusted machine authority; an absence of a human permission key does not make those entry points public.

Console operations are for customer staff. Routes admitted to portal access also serve authorized console users, but a portal member receives only the powers actually granted. Unit officers and personal self-read users therefore have different boundaries. Platform owns authentication, roles, policies, assignments and the recorded entry grants for Rhythm staff. HQ status does not itself grant access to Membership customer records.

## Scopes

Customer-wide Platform assignments can contribute workspace authority. Membership evaluates the application gate and workspace-level operations in the addressed workspace. Configuration, structure, billing, direct staff term changes and status processing do not accept unit-only authority.

Officer-capable permissions declare organizational-unit scope. Grants reach the selected unit and descendants, and service checks resolve the relevant membership chain or affected units. An exact-unit-only grant type is not implemented. Reporting datasets retain workspace-level query authority and do not provide officer row filtering.

Personal self-read uses the account’s linked contact. That contact relationship is a service guard, not an arbitrary record grant. Trusted service execution is a separate boundary governed by cloud roles, registered service functions and database execution grants.

## Roles

The first five profiles in this model are proposed permission bundles for the responsibilities described by the area's actors. They are not built-in role declarations, deployed assignments or new authorization policies. Customers compose and assign their actual roles in Platform. A migration producer, scheduled worker or connected application is a machine execution identity rather than another human role.

Platform supplies shared customer roles and generates application policies by permission tier. Its role and policy contracts remain authoritative for that composition; this examination does not assert their deployed Membership entitlements. The Membership service declares one built-in portal policy with application access and personal self-read. Platform must attach it to the Portal Member role before that declaration produces access.

## Permission Catalogue

The assignable keys below come from the service catalogue and the keys named by capabilities and operations. Frontmatter records operation identifiers, surfaces and additional rule references. API access declarations establish eligible channels; they do not establish a built console or portal screen. The current console member list is a synthetic prototype with no Membership permission enforcement.

| Permission | Intent |
|---|---|
| `membership.affiliations.manage` | Maintain dated membership connections within the evaluated unit scope. |
| `membership.application.access` | Open Membership in an available, licensed workspace. |
| `membership.billing.manage` | Administer and execute renewal templates, runs and recurring definitions. |
| `membership.billing.read` | Inspect renewal templates, runs, planned actions and recurring definitions. |
| `membership.configuration.manage` | Administer membership offer configuration, application processes and area settings. |
| `membership.configuration.read` | Inspect membership offer configuration, application processes and area settings. |
| `membership.lifecycle-events.query` | Query workspace membership lifecycle records through the shared query layer. |
| `membership.member-contact.update` | Request allowed contact-field changes for a member within the evaluated unit scope. |
| `membership.members.read` | Inspect memberships and related facts within the evaluated unit scope. |
| `membership.membership-snapshot-affiliations.query` | Query unit connections in published monthly reporting copies. |
| `membership.membership-snapshot-counts.query` | Query movement and standing counts in published monthly reporting copies. |
| `membership.membership-snapshot-dimensions.query` | Query captured characteristics in published monthly reporting copies. |
| `membership.membership-snapshot-members.query` | Query members in published monthly reporting copies. |
| `membership.membership-terms.query` | Query workspace membership periods through the shared query layer. |
| `membership.memberships.create` | Establish a membership and its initial committed period without an order. |
| `membership.memberships.enroll` | Request an enrolment order for a member within the evaluated unit scope. |
| `membership.memberships.history` | Inspect recorded membership and term revisions with additional read authority. |
| `membership.memberships.query` | Query workspace membership records through the shared query layer. |
| `membership.memberships.suspend` | Suspend or restore principal membership standing. |
| `membership.operations.run` | Request an immediate workspace status refresh. |
| `membership.programs.manage` | Administer membership programs and their unit requirements. |
| `membership.programs.read` | Inspect membership programs and their unit requirements. |
| `membership.rosters.export` | Capture and retrieve a roster export within authorized scope. |
| `membership.self.read` | Inspect the holdings associated with the signed-in member’s linked contact. |
| `membership.structure.manage` | Administer association units, hierarchy, links and local financial context. |
| `membership.structure.read` | Inspect association units, hierarchy, links and local financial context. |
| `membership.term-affiliations.query` | Query workspace dated unit connections through the shared query layer. |
| `membership.terms.correct` | Correct a committed membership period while preserving recorded values. |
| `membership.terms.create` | Add a committed period without an order. |
| `membership.terms.renew` | Request a renewal order for a membership within the evaluated unit scope. |
| `membership.terms.terminate` | Close a committed membership period with a reason. |

The frontmatter also preserves exact compound and no-key declarations from the existing service contracts because conformance compares those values literally. These entries describe requirements and trust boundaries; none is an additional permission that a role can grant. A compound history declaration requires both of its keys. A dataset declaration requires the key of the selected dataset, rather than every listed dataset key.

## Role Entitlement Matrix

The columns show proposed profiles before scope, conditions, explicit denies, application availability and record guards. A dash supplies no grant. The portal column shows the declared policy's contribution, conditional on Platform attachment. No column proves a deployed role.

| Permission | Setup administrator | Coordinator | Analyst | Setup reader | Unit officer | Portal Member |
|---|---|---|---|---|---|---|
| `membership.affiliations.manage` | — | Workspace | — | — | Unit | — |
| `membership.application.access` | Workspace | Workspace | Workspace | Workspace | Workspace | Workspace |
| `membership.billing.manage` | Workspace | — | — | — | — | — |
| `membership.billing.read` | Workspace | — | Workspace | — | — | — |
| `membership.configuration.manage` | Workspace | — | — | — | — | — |
| `membership.configuration.read` | Workspace | — | — | Workspace | — | — |
| `membership.lifecycle-events.query` | — | — | Workspace | — | — | — |
| `membership.member-contact.update` | — | — | — | — | Unit | — |
| `membership.members.read` | — | Workspace | Workspace | — | Unit | — |
| `membership.membership-snapshot-affiliations.query` | — | — | Workspace | — | — | — |
| `membership.membership-snapshot-counts.query` | — | — | Workspace | — | — | — |
| `membership.membership-snapshot-dimensions.query` | — | — | Workspace | — | — | — |
| `membership.membership-snapshot-members.query` | — | — | Workspace | — | — | — |
| `membership.membership-terms.query` | — | — | Workspace | — | — | — |
| `membership.memberships.create` | — | Workspace | — | — | — | — |
| `membership.memberships.enroll` | — | — | — | — | Unit | — |
| `membership.memberships.history` | — | Workspace | — | — | — | — |
| `membership.memberships.query` | — | — | Workspace | — | — | — |
| `membership.memberships.suspend` | — | Workspace | — | — | — | — |
| `membership.operations.run` | Workspace | — | — | — | — | — |
| `membership.programs.manage` | Workspace | — | — | — | — | — |
| `membership.programs.read` | Workspace | — | — | Workspace | — | — |
| `membership.rosters.export` | — | — | — | — | Unit | — |
| `membership.self.read` | — | — | — | — | — | Own contact |
| `membership.structure.manage` | Workspace | — | — | — | — | — |
| `membership.structure.read` | Workspace | — | — | Workspace | — | — |
| `membership.term-affiliations.query` | — | — | Workspace | — | — | — |
| `membership.terms.correct` | — | Workspace | — | — | — | — |
| `membership.terms.create` | — | Workspace | — | — | — | — |
| `membership.terms.renew` | — | — | — | — | Unit | — |
| `membership.terms.terminate` | — | Workspace | — | — | — | — |

## Protected Actions

Operation permission does not finish the authorization decision. Officer contact changes use the contributing roles' field allow-lists. Officer renewals and enrolments use the scoped ordering guards and purchase preparation. Affiliation mutations check the units affected by the change. Roster generation captures authorized membership identifiers at request time, and retrieval also checks the requester or workspace-wide authority.

History has an additional permission requirement and remains a workspace-staff timeline in the examined implementation. Personal lifecycle information comes through the member's self-read. Configuration and direct staff mutations retain their own reference, state, version and lifecycle guards, recorded in the permission catalogue's rule references. No examined Membership operation establishes a second-approver requirement. Rhythm staff entry uses Platform's separately recorded customer-access mechanism.

## Guards Distinguished From Permissions

A permission is an assignable power. A guard tests the record or proposed action after that power has been evaluated. Unit reach, linked-contact ownership, contact-field allowance, request ownership, current state, valid references and versions are guards. These checks cannot supply a missing permission or override a deny. The catalogue cites the owning rules rather than creating another home for their requirements.

Membership derives scope checks from the request's evaluated grant slice and current record context. It holds no additional local access cache, but Platform's gateway decision can remain cached for sixty seconds and signed context can remain valid for thirty seconds beyond that. Appointment validity is evaluated at request time. Grant withdrawal must not be presented as an immediate cutoff, and an already captured export is not recalled automatically.

## What People See When Refused

The API distinguishes missing authority from record invisibility. A missing required key produces a forbidden response. A membership outside the caller's unit reach appears absent. A visible membership with an impermissible changed unit produces a scope refusal, and a contact-field refusal identifies the disallowed fields. Validation and state conflicts explain the rejected request; stale writes identify the version conflict.

The application boundary provides refusal codes for unavailable access or licensing through Platform. Partner adapters that are not wired can fail even after authorization succeeds; those failures are not permission refusals. The prototype member list shows loading, empty results, query errors and action notifications, but provides no Membership-driven refusal or read-only state. This model therefore describes observed API refusals without claiming a connected screen experience.
