---
id: CAP-PFM-SEC-008
title: Offer and manage an invitation
feature: FEAT-PFM-SEC-03
product_area: platform
module: security
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
    Final acceptance)
  - >-
    services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-13/14
    Final acceptance)
  - >-
    services-platform:docs/security/security-administration.md#2. Capability checklist (U4, U13, I1 to
    I9)
purpose: >-
  Security administrators invite colleagues with appropriate roles and follow delivery, resend and
  withdrawal from the membership record.
outcomes:
  - Administrators can distinguish a committed invitation from successful e-mail delivery.
  - Offered assignments respect the inviter’s authority and membership boundary.
  - Resend and withdrawal give administrators recovery actions for outstanding invitations.
concepts:
  - CON-PFM-SEC-003
actors:
  - ACT-PFM-001
  - ACT-PFM-006
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: platform.security-access.manage
    where_checked: api
    scope: tenant
  - key: platform.users.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-PFM-SEC-008-01
    statement: >-
      Invitation creation, resend, withdrawal and direct activation require access-management authority
      within the addressed customer; unknown or outside-customer targets return not found without
      creating membership records.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/invitations.e2e.spec.js#refuses an invitation into a
      customer the caller does not reach, as 404, and leaves nothing behind
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-13/14
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-02
    statement: >-
      Invitation creation requires a valid e-mail address and stores its canonical form; missing or
      invalid addresses create no person.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/invite-user.spec.js#refuses an
      invalid e-mail address as ObjectInvalid naming email_address, creating nobody
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-03
    statement: >-
      Existing active members are directed to role management, already-invited members to resend, and
      revoked members return through their existing account and history.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/invite-user.spec.js#refuses
      somebody already invited to that wall as already_invited, telling the administrator to resend
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-04
    statement: >-
      Creation commits the membership and invitation together before provisioning sign-in and sending
      mail; the response reports delivery status and reason without the raw token, and delivery failure
      preserves the committed records.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/invite-user.spec.js#keeps the
      user and the invitation when the e-mail could not be sent, and says why so the administrator can
      resend
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-05
    statement: >-
      Inviters can offer only unconditionally allowed permissions at the proposed scopes, cannot invite
      roles onto their own account and receive the failing keys and scopes when delegation is refused.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/invitations.e2e.spec.js#refuses a role that grants
      more than the caller may do there, and names what was missing
    origin: 'services-platform:docs/security/security-administration.md#4. Delegation, escalation and lockout'
  - id: BR-CAP-PFM-SEC-008-06
    statement: >-
      Offered assignments remain pending until acceptance; grants outside a console member’s customer or
      outside a portal member’s single workspace fail before membership creation.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/invite-user.spec.js#refuses a
      grant that reaches outside the wall the user is being created in, before a user exists
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-07
    statement: >-
      Resend replaces outstanding invitations with a fresh seven-day link for an invited membership;
      already-accepted members are refused and directed to password recovery.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/resend-invitation.spec.js#supersedes
      the outstanding invitations and issues a new one with a new token, in one transaction
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-08
    statement: >-
      Withdrawing an invitation revokes membership so that the old link cannot activate the person or
      their pending roles.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/invitations.e2e.spec.js#revoking a membership stops
      the link already in the inbox, and the account cannot come back by accepting it
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-09
    statement: >-
      The user list reports the newest invitation’s pending, expired, accepted or revoked state with send
      and delivery information and supports invited, expired and never-invited filters.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/console-users.e2e.spec.js#answers the newest
      invitation of a row, and explicitly none for somebody never invited
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-13/14
      Final acceptance)
  - id: BR-CAP-PFM-SEC-008-10
    statement: >-
      Direct activation requires an already-linked sign-in identity on a never-invited membership; a
      member with an invitation must accept it instead.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/activate-user.spec.js#refuses a
      user that was invited (accept or resend instead), an unprovisioned one and a disabled one, writing
      nothing
    origin: none
  - id: BR-CAP-PFM-SEC-008-11
    statement: >-
      Workspace-scoped invitation and member-list operations can administer that workspace’s portal
      members, and the portal list excludes console memberships.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/invitations.e2e.spec.js#invites a member of the
      tenant's portal and lists the tenant's members, the console users left out
    origin: none
  - id: BR-CAP-PFM-SEC-008-12
    statement: >-
      Invitation mail uses Rhythm’s sender and a first-name greeting, includes expiry when available and
      keeps the raw link token out of the subject; display-name escaping prevents header and markup
      injection.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/unit/services/invitations/invitation-email.spec.js#strips
      the quote and the newline of an injected display name, leaving one header line
    origin: none
scenarios:
  - id: SC-CAP-PFM-SEC-008-01
    given: An administrator offers a colleague customer-wide Read Only access.
    when: E-mail delivery fails after the invitation is committed.
    then: 'The colleague remains Invited with delivery information, and resend can issue a new link.'
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/lifecycle/user-provisioning/user-provisioning.integration.spec.js#answers
      the delivery as failed, telling the administrator to resend
  - id: SC-CAP-PFM-SEC-008-02
    given: The requested colleague is already an active member of this customer.
    when: An administrator attempts another invitation.
    then: The refusal points the administrator toward the existing membership rather than create a duplicate.
    provenance: test
    source: >-
      react-console:e2e/security/invitations.spec.ts#refuses to invite an address that already belongs to
      a user, and offers the user instead
edge_cases: []
constraints: []
depends_on: []
related:
  - CAP-PFM-SEC-005
  - CAP-PFM-SEC-009
  - CAP-PFM-SEC-010
journeys:
  - JNY-PFM-SEC-003
open_questions: []
evidence:
  - >-
    Pinned services-platform references for the structured rows:
    docs/security/security-administration.md; modules/security/tests/e2e/console-users.e2e.spec.js;
    modules/security/tests/e2e/invitations.e2e.spec.js;
    modules/security/tests/integration/lifecycle/user-provisioning/user-provisioning.integration.spec.js;
    modules/security/tests/unit/services/invitations/activate-user.spec.js;
    modules/security/tests/unit/services/invitations/invitation-email.spec.js;
    modules/security/tests/unit/services/invitations/invite-user.spec.js;
    modules/security/tests/unit/services/invitations/resend-invitation.spec.js.
  - 'Pinned react-console references for the structured rows: e2e/security/invitations.spec.ts.'
controls: [TC-AVL-001, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, 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-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, 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-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Offer and manage an invitation

## Purpose

Administrators bring colleagues into the customer’s console and follow whether the invitation reached them. Invitation management keeps access choices, delivery information and recovery actions together.

## How It Works

The administrator starts from Security Users and enters the colleague’s identity. Role selection expresses the access being offered before the colleague joins. If delegation is refused, the response identifies the authority the inviter lacks. Successful creation returns delivery information, which the administrator checks before telling the colleague to look for an e-mail. A committed invitation can remain visible even when provisioning or sending did not succeed. Resend provides a recovery path for that case and for a lost invitation. The newest-invitation information helps staff distinguish expiration from a member who has never been invited. Withdrawal ends the offer when the person should no longer join. A returning member follows reinvitation through the existing identity, retaining the connection to prior history.

## Relationships

- Acceptance turns the offered membership into active access.
- Role assignment supplies the delegation and scope checks.
- Security history records invitation management outcomes.
