---
id: ATS-MBR-STR-019
scope: CAP-MBR-STR-019
product_area: membership
module: structure
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-MBR-STR-019-01
    title: Reading and management use separate authority
    level: api
    proves:
      - BR-CAP-MBR-STR-019-01
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Exercise structure operations with read-only and administrator callers.
    expected: Read authority permits inspection and fails mutations that administration permits.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
        operation names its permission › requires membership.structure.read of every structure read and
        membership.structure.manage of every change
      - >-
        services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process
        › serves a reader the reads
      - >-
        services-membership:tests/e2e/structure-api.e2e.spec.ts#the structure API, end to end in process
        › refuses a reader a change, 403
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts#MBR-ACC-0025 one
        structure change, seven people
      - TST-MBR-STR-103
      - TST-MBR-STR-100
      - TST-MBR-STR-084
    provenance: test
    source: >-
      services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
      operation names its permission › requires membership.structure.read of every structure read and
      membership.structure.manage of every change
    category: permission
  - id: ATS-MBR-STR-019-02
    title: Configuration authority distinguishes administrators
    level: api
    proves:
      - BR-CAP-MBR-STR-019-02
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Compare program and configuration operations for administrators and read-only staff.
    expected: Administrators can mutate; readers can inspect only.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts#MBR-ACC-0088: Who
        may read and who may change configuration: the administrator does both, read-only staff and a
        standard user only read, and a chapter officer or a portal member reaches nothing because the
        keys are workspace-level
      - TST-MBR-STR-028
    provenance: test
    source: >-
      services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts#MBR-ACC-0088: Who may
      read and who may change configuration: the administrator does both, read-only staff and a standard
      user only read, and a chapter officer or a portal member reaches nothing because the keys are
      workspace-level
    category: permission
  - id: ATS-MBR-STR-019-03
    title: Local authority does not grant setup administration
    level: api
    proves:
      - BR-CAP-MBR-STR-019-03
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Attempt the same administrative change as chapter officer, regional officer and portal member.'
    expected: Each request is rejected without workspace management authority.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts#MBR-ACC-0025 one
        structure change, seven people
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts#MBR-ACC-0088: Who
        may read and who may change configuration: the administrator does both, read-only staff and a
        standard user only read, and a chapter officer or a portal member reaches nothing because the
        keys are workspace-level
      - TST-MBR-STR-084
      - TST-MBR-STR-028
    provenance: test
    source: >-
      services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts#MBR-ACC-0025 one
      structure change, seven people
    category: permission
  - id: ATS-MBR-STR-019-04
    title: Application admission precedes operation work
    level: api
    proves:
      - BR-CAP-MBR-STR-019-04
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: 'Use a caller lacking application access, an unlicensed workspace and an unavailable workspace.'
    expected: Each context is rejected before the operation’s work begins.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        answers the tenant health route to a caller holding membership.application.access there
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        refuses a caller who holds no key in the tenant
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        refuses a caller whose tenant is not licensed for Membership, as app_unlicensed
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        refuses a disabled tenant to its own people, as TenantUnavailable
      - TST-MBR-STR-101
    provenance: test
    source: >-
      services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process › answers
      the tenant health route to a caller holding membership.application.access there
    category: permission
  - id: ATS-MBR-STR-019-05
    title: Row isolation hides foreign workspace data
    level: api
    proves:
      - BR-CAP-MBR-STR-019-05
    preconditions: >-
      An isolated Membership-licensed workspace contains the relevant records, with caller permissions
      selected for the case.
    steps: Read structure and configuration with a different workspace context.
    expected: Foreign workspace records do not appear in the result.
    negative: true
    data_needs: The FAA example records or equivalent records prepared within the isolated workspace.
    bound_to:
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › row-level security › shows another tenant none of the units
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0026.acceptance.ts#MBR-ACC-0026 another
        association's structure does not exist
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0089.acceptance.ts#MBR-ACC-0089: Two
        associations with identically named configuration never see each other: the same ids live in both
        workspaces and a cross-workspace read, update or delete answers not found
      - TST-MBR-STR-006
      - TST-MBR-STR-085
      - TST-MBR-STR-029
    provenance: test
    source: >-
      services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
      units in the database › row-level security › shows another tenant none of the units
    category: boundary
  - id: ATS-MBR-STR-019-06
    title: Console authority needs a verified service mapping
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-019-07
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: >-
      Compare every console setup permission with the service’s published setup keys and the mappings
      used by an administration caller.
    expected: >-
      The comparison identifies unmapped keys; it cannot declare the two vocabularies equivalent without
      a verified translation.
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - 'react-console:lib/authz/permissions.ts:82'
  - id: ATS-MBR-STR-019-07
    title: Reader access preserves the workspace boundary
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-005-11
      - BR-CAP-MBR-STR-019-01
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: 'As a structure reader request own and foreign unit identities, then attempt a mutation.'
    expected: 'Own reads succeed, foreign rows stay hidden and management is refused.'
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › row-level security › reads nothing of another tenant’s unit by id
      - >-
        services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
        operation names its permission › requires membership.structure.read of every structure read and
        membership.structure.manage of every change
    exercises:
      - CAP-MBR-STR-019
      - CAP-MBR-STR-005
  - id: ATS-MBR-STR-019-08
    title: Setup authority cannot bypass foreign-record isolation
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-STR-018-09
      - BR-CAP-MBR-STR-019-02
    preconditions: An isolated workspace contains the records and current versions needed for the case.
    steps: 'Use a workspace administrator to read, update and delete a record owned by another workspace.'
    expected: All three requests treat that record as absent and leave it unchanged.
    negative: false
    data_needs: Separate fixture records for the accepted and refused operations.
    bound_to: []
    provenance: proposed
    source:
      - 'services-membership:aws/api/route-inputs.ts:found'
      - >-
        services-membership:modules/configuration/aws/api/configuration.routes.ts:configurationModuleRoutes
    exercises:
      - CAP-MBR-STR-019
      - CAP-MBR-STR-018
evidence:
  - >-
    services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts
  - 'services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts'
  - 'services-membership:tests/acceptance/configuration/MBR-ACC-0089.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts'
  - 'services-membership:tests/acceptance/structure/MBR-ACC-0026.acceptance.ts'
  - 'services-membership:tests/e2e/structure-api.e2e.spec.ts'
  - 'services-membership:tests/e2e/terms-api.e2e.spec.ts'
  - 'services-membership:tests/unit/route-authorization.spec.ts'
  - >-
    services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
    operation names its permission › requires membership.structure.read of every structure read and
    membership.structure.manage of every change
  - 'services-membership:modules/configuration/aws/api/configuration.routes.ts:configurationModuleRoutes'
  - 'services-membership:aws/membership.service.ts:STRUCTURE_PERMISSIONS'
  - >-
    services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process › refuses a
    caller who holds no key in the tenant
  - >-
    services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
    units in the database › row-level security › shows another tenant none of the units
  - >-
    services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
    operation names its permission › is allowed or evaluates only keys the published catalog defines
  - 'react-console:lib/authz/permissions.ts:82'
  - >-
    services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts#MBR-ACC-0088: Who may
    read and who may change configuration: the administrator does both, read-only staff and a standard
    user only read, and a chapter officer or a portal member reaches nothing because the keys are
    workspace-level
  - >-
    services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts#MBR-ACC-0025 one structure
    change, seven people
  - >-
    services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process › answers
    the tenant health route to a caller holding membership.application.access there
  - >-
    services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
    units in the database › row-level security › reads nothing of another tenant’s unit by id
  - 'services-membership:aws/api/route-inputs.ts:found'
coverage:
  rule: 'gap: FND-MBR-STR-072'
  transition: not-applicable
  validation: 'gap: FND-MBR-STR-072'
  permission: covered
  edge: 'gap: FND-MBR-STR-072'
  failure: 'gap: FND-MBR-STR-072'
  boundary: covered
  concurrency: 'gap: FND-MBR-STR-072'
  invariant: 'gap: FND-MBR-STR-072'
  interaction: covered
coverage_notes:
  rule: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  transition: >-
    This capability reads or changes facets without owning a standing transition; the owning lifecycle
    specification carries those transitions.
  validation: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  edge: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  failure: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  concurrency: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
  invariant: >-
    No dedicated scenario establishes this category across the capability’s declared operations and
    design obligations.
unproved_rules: []
coverage_obligations:
  permissions:
    - key: membership.structure.read
      scenario_ids:
        - ATS-MBR-STR-019-01
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.structure.manage
      scenario_ids:
        - ATS-MBR-STR-019-01
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.programs.read
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.programs.manage
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.configuration.read
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.configuration.manage
      scenario_ids:
        - ATS-MBR-STR-019-02
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
    - key: membership.application.access
      scenario_ids:
        - ATS-MBR-STR-019-04
      local_scenario_ids: []
      coverage: partial
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
      note: >-
        These cases establish declared authority or representative admission; exhaustive operation and
        caller combinations remain open.
  state_models: []
  related:
    - capability: CAP-MBR-STR-005
      scenario: ATS-MBR-STR-019-07
      provenance: proposed
    - capability: CAP-MBR-STR-018
      scenario: ATS-MBR-STR-019-08
      provenance: proposed
  invariants:
    - id: INV-DOM-MBR-STR-006-01
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-02
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-03
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-04
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-05
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-06
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-07
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
    - id: INV-DOM-MBR-STR-006-08
      scenario_ids: []
      coverage: gap
      gap: FND-MBR-STR-072
      provenance: unknown
      source: FND-MBR-STR-072
  workflows: []
  workflow_interactions: []
rule_coverage:
  - rule: BR-CAP-MBR-STR-019-01
    scenarios:
      - ATS-MBR-STR-019-01
      - ATS-MBR-STR-019-07
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
        operation names its permission › requires membership.structure.read of every structure read and
        membership.structure.manage of every change
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › row-level security › reads nothing of another tenant’s unit by id
      - >-
        services-membership:tests/unit/route-authorization.spec.ts#route authorization: every Membership
        operation names its permission › requires membership.structure.read of every structure read and
        membership.structure.manage of every change
  - rule: BR-CAP-MBR-STR-019-02
    scenarios:
      - ATS-MBR-STR-019-02
      - ATS-MBR-STR-019-08
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/acceptance/configuration/MBR-ACC-0088.acceptance.ts#MBR-ACC-0088: Who
        may read and who may change configuration: the administrator does both, read-only staff and a
        standard user only read, and a chapter officer or a portal member reaches nothing because the
        keys are workspace-level
      - 'services-membership:aws/api/route-inputs.ts:found'
      - >-
        services-membership:modules/configuration/aws/api/configuration.routes.ts:configurationModuleRoutes
  - rule: BR-CAP-MBR-STR-019-03
    scenarios:
      - ATS-MBR-STR-019-03
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/acceptance/structure/MBR-ACC-0025.acceptance.ts#MBR-ACC-0025 one
        structure change, seven people
  - rule: BR-CAP-MBR-STR-019-04
    scenarios:
      - ATS-MBR-STR-019-04
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:tests/e2e/terms-api.e2e.spec.ts#the terms API, end to end in process ›
        answers the tenant health route to a caller holding membership.application.access there
  - rule: BR-CAP-MBR-STR-019-05
    scenarios:
      - ATS-MBR-STR-019-05
    gap: null
    provenance: documented
    source:
      - >-
        services-membership:modules/structure/tests/integration/services/persistence/organizational-units.integration.spec.ts#organizational
        units in the database › row-level security › shows another tenant none of the units
  - rule: BR-CAP-MBR-STR-019-07
    scenarios:
      - ATS-MBR-STR-019-06
    gap: null
    provenance: documented
    source:
      - 'react-console:lib/authz/permissions.ts:82'
narrative_sources:
  - section: Coverage
    provenance: documented
    source:
      - CAP-MBR-STR-019
      - FND-MBR-STR-072
  - section: Interactions With Related Capabilities
    provenance: proposed
    source:
      - ATS-MBR-STR-019-06
      - ATS-MBR-STR-019-07
      - ATS-MBR-STR-019-08
---

# Authorize structure and configuration work: Capability Test Specification

## Coverage

The coverage map distinguishes specified examples from missing proof. A covered category means an expected case is specified; executable bindings and their run results remain separate evidence. Each required rule has a proof link or an explicit coverage finding in the structured rule ledger.

| Required Rule | Scenario or Finding |
|---|---|
| `BR-CAP-MBR-STR-019-01` | `ATS-MBR-STR-019-01`, `ATS-MBR-STR-019-07` |
| `BR-CAP-MBR-STR-019-02` | `ATS-MBR-STR-019-02`, `ATS-MBR-STR-019-08` |
| `BR-CAP-MBR-STR-019-03` | `ATS-MBR-STR-019-03` |
| `BR-CAP-MBR-STR-019-04` | `ATS-MBR-STR-019-04` |
| `BR-CAP-MBR-STR-019-05` | `ATS-MBR-STR-019-05` |
| `BR-CAP-MBR-STR-019-07` | `ATS-MBR-STR-019-06` |

## Interactions With Related Capabilities

Reader access preserves the workspace boundary. As a structure reader request own and foreign unit identities, then attempt a mutation.

Setup authority cannot bypass foreign-record isolation. Use a workspace administrator to read, update and delete a record owned by another workspace.
