---
id: CAP-PFM-SEC-014
title: Derive member access from appointments and eligibility
feature: FEAT-PFM-SEC-04
product_area: platform
module: security
revision: 1
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
intent_sources:
  - >-
    services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
    Andrew 2026-10-17)
  - >-
    services-platform:docs/milestones/PLAT-M13-eligibility-roles-and-permissions.md#Scope in one
    paragraph
purpose: >-
  Automatic assignments connect portal access to contact facts supplied by appointments or eligibility
  evaluation.
outcomes:
  - Derived assignments remain attributable to their source.
  - Reconciliation preserves manual grants while updating rule-based access.
  - Sign-in and scheduled work provide additional opportunities to refresh eligibility-derived grants.
concepts:
  - CON-PFM-SEC-003
actors:
  - ACT-PFM-006
  - ACT-PFM-001
  - ACT-PFM-003
surfaces:
  - api
  - job
  - portal
preconditions: []
postconditions: []
permissions:
  - key: platform.security-roles.manage
    where_checked: api
    scope: tenant
  - key: platform.eligibility.reconcile
    where_checked: api
    scope: global
rules:
  - id: BR-CAP-PFM-SEC-014-01
    proved_by: [ATS-PFM-SEC-014-01, ATS-PFM-SEC-014-13, ATS-PFM-SEC-020-13, TST-PFM-SEC-053]
    statement: >-
      Derived assignments attach to contacts before portal login exists and authorize only the
      workspace’s portal membership linked to that contact, never console memberships.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/derived-assignments.e2e.spec.js#is refused once the
      member is no longer linked to the contact, so the link is what carries the grant
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-02
    proved_by: [ATS-PFM-SEC-014-02, TST-PFM-SEC-135]
    statement: >-
      The system synchronization path accepts only listed derivation sources and valid workspace/resource
      scopes and active roles within the customer; invalid source, scope or role rejects the desired set
      without partial insertion.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/persistence/assignments.derived.integration.spec.js#refuses
      a whole desired set when one entry is refused, inserting none of the others
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-03
    proved_by: [ATS-PFM-SEC-014-03, TST-PFM-SEC-135]
    statement: >-
      Synchronization updates validity in place, revokes undesired grants and audits changes as system
      work, while an unchanged desired set produces no mutations.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/persistence/assignments.derived.integration.spec.js#revokes
      by omission: a row of the key that is no longer desired is revoked, by the actor, and audited
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-04
    proved_by: [ATS-PFM-SEC-010-22, ATS-PFM-SEC-014-04, ATS-PFM-SEC-014-11, TST-PFM-SEC-103, TST-PFM-SEC-135]
    statement: >-
      Ordinary assignment management refuses derived-grant edits and withdrawal and directs
      administrators to the originating appointment or rule.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/persistence/assignments.derived.integration.spec.js#refuses
      an amendment 409 derived_assignment, naming where to change it
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-05
    proved_by: [ATS-PFM-SEC-014-05, TST-PFM-SEC-053]
    statement: >-
      Request-time evaluation applies a derived grant’s stored validity boundary even when the signed
      authorization context predates its expiry.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/derived-assignments.e2e.spec.js#refuses the same
      still-unexpired context once valid_until has passed, because validity is read per request
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-06
    proved_by: []
    statement: The member’s access document identifies derived assignments and their source.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/derived-assignments.e2e.spec.js#lists the derived
      grant in the member’s own access document, saying it is derived by committees from its key
    origin: >-
      services-platform:docs/security/security-administration.md#4a. Derived assignments (D-31, D-32,
      Andrew 2026-10-17)
  - id: BR-CAP-PFM-SEC-014-07
    proved_by: [ATS-PFM-SEC-014-06, TST-PFM-SEC-064, TST-PFM-SEC-075]
    statement: >-
      An editable customer role can reference one workspace eligibility binding with a five-minute to
      thirty-day refresh interval and one-day default; built-ins, wrong binding kinds and duplicate role
      bindings fail.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/role-eligibility.e2e.spec.js#refuses a built-in role
      as a conflict, because no tenant’s rule may assign Rhythm’s role
    origin: none
  - id: BR-CAP-PFM-SEC-014-08
    proved_by: [ATS-PFM-SEC-014-07, TST-PFM-SEC-103]
    statement: >-
      Eligibility reconciliation creates or reconfirms contact grants for eligible subjects, revokes
      ineligible grants, preserves indeterminate results and manual grants, and does not derive
      organization access.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/derived-assignments/reconcile.integration.spec.js#never
      touches the manual assignment: no derivation, no window, its first version
    origin: none
  - id: BR-CAP-PFM-SEC-014-09
    proved_by: [ATS-PFM-SEC-014-08, ATS-PFM-SEC-014-12, ATS-PFM-SEC-019-12, TST-PFM-SEC-104]
    statement: >-
      Portal password sign-in reconciles the linked member’s eligibility roles before returning tokens;
      evaluator failure is logged without blocking sign-in.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/derived-assignments/sign-in-reconcile.integration.spec.js#signs
      a member in even when the evaluator fails, which it was asked
    origin: none
  - id: BR-CAP-PFM-SEC-014-10
    proved_by: []
    statement: >-
      Nightly reconciliation uses one job identity per workspace and night to avoid duplicate
      submissions.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/lifecycle/derived-assignment-nightly/nightly-reconcile.integration.spec.js#submits
      one job for the tenant, under the tenant and the night, and the same job when the schedule fires
      again
    origin: none
  - id: BR-CAP-PFM-SEC-014-11
    proved_by: [ATS-PFM-SEC-014-09, TST-PFM-SEC-113]
    statement: >-
      Staff-requested reconciliation accepts at most 100 contacts, queues pending subjects once and
      handles redelivery without duplicate assignments.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/dispatch/derived-assignment-reconciles.integration.spec.js#refuses
      more than 100 subjects
    origin: none
  - id: BR-CAP-PFM-SEC-014-12
    proved_by: [ATS-PFM-SEC-012-18, ATS-PFM-SEC-014-10, TST-PFM-SEC-054, TST-PFM-SEC-099]
    statement: >-
      Eligibility-conditioned policy rules must reference assignment-condition bindings from the owning
      customer’s workspaces.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/definitions/eligibility-conditions.integration.spec.js#refuses
      a binding of another customer’s tenant, naming it, and stores no policy
    origin: none
  - id: BR-CAP-PFM-SEC-014-13
    proved_by: []
    statement: >-
      The product should complete the role editor’s automatic-assignment control and settle
      contact-versus-login ownership before accepting the proposed milestone.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: unknown
    source: FND-PFM-SEC-008
    origin: none
scenarios:
  - id: SC-CAP-PFM-SEC-014-01
    given: Dana holds a dated board appointment represented by a contact.
    when: The appointment owner synchronizes the corresponding authority.
    then: Dana’s linked portal membership can use the resulting scoped role within its validity window.
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/derived-assignments.e2e.spec.js#serves the protected
      route for the unit the grant names, inside its validity
edge_cases: []
constraints: []
depends_on:
  - CAP-PFM-SEC-012
related:
  - CAP-PFM-SEC-010
  - CAP-PFM-SEC-019
  - CAP-PFM-SEC-020
journeys: []
open_questions: []
evidence:
  - >-
    Pinned services-platform references for the structured rows:
    docs/milestones/PLAT-M13-eligibility-roles-and-permissions.md;
    docs/security/security-administration.md; modules/security/tests/e2e/derived-assignments.e2e.spec.js;
    modules/security/tests/e2e/role-eligibility.e2e.spec.js;
    modules/security/tests/integration/lifecycle/derived-assignment-nightly/nightly-reconcile.integration.spec.js;
    modules/security/tests/integration/services/definitions/eligibility-conditions.integration.spec.js;
    modules/security/tests/integration/services/derived-assignments/reconcile.integration.spec.js;
    modules/security/tests/integration/services/derived-assignments/sign-in-reconcile.integration.spec.js;
    modules/security/tests/integration/services/dispatch/derived-assignment-reconciles.integration.spec.js;
    modules/security/tests/integration/services/persistence/assignments.derived.integration.spec.js.
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-003, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-SEC-001, TC-SEC-002, TC-SEC-003, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
exercised_by: [FAS-PFM-SEC-04-04, FAS-PFM-SEC-04-05]
suites: [TST-PFM-SEC-053, TST-PFM-SEC-054, TST-PFM-SEC-064, TST-PFM-SEC-075, TST-PFM-SEC-099, TST-PFM-SEC-103, TST-PFM-SEC-104, TST-PFM-SEC-113, TST-PFM-SEC-135]
---
# Derive member access from appointments and eligibility

## Purpose

Automatic grants let portal authority follow a person’s recorded responsibilities or eligibility. Staff can identify the underlying fact instead of maintain a second manual assignment for the same decision.

## How It Works

The source owner synchronizes the authority implied by an appointment or other supported fact. The contact supplies a stable subject before that person has a login. A linked portal membership can then use the derived assignment. Its source information lets administrators understand where to correct it. Eligibility-backed roles use reconciliation to refresh qualifying contacts while preserving hand-managed assignments. An indeterminate rule result preserves the prior assignment rather than invent a new decision. Password sign-in and nightly work supplement explicit reconciliation requests. A stored end time remains part of request-time evaluation, while changes to a contact claim require a freshly evaluated context. The proposed milestone still needs its console control and product decision on subject ownership.

## Relationships

- Customer roles define the authority that eligibility can assign.
- Committees and Eligibility own the source facts and binding evaluations.
- Portal contact linking connects the login claim to the derived subject.
