---
id: WF-PFM-SEC-005
title: Invite a person and deliver the invitation
trigger: A customer administrator, HQ staff member or provisioning participant invites a person into a console
  or portal boundary.
product_area: platform
module: security
revision: 1
status: draft
design_intent: confirmed
origin: services-platform:docs/jobs.md#6. User provisioning (a job from 2026-10-08, a function since 2026-10-09);
  docs/security/invitation-lifecycle.md
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-SEC-008
- CAP-PFM-SEC-016
- CAP-PFM-SEC-003
moves:
- STATE-PFM-SEC-004
- STATE-PFM-SEC-005
- STATE-PFM-SEC-006
crosses:
- SVC-PFM-SEC-security
idempotency: Preparation finds an existing recorded or named provider account before creating one. Resend replaces
  the invitation; token validity follows the current invitation and digest, not the last e-mail delivered.
  Active memberships use role management, invited memberships use resend and revoked memberships reuse their
  retained row for a new offer.
concurrency: Membership, invitation, pending grants and database history commit together. Uniqueness prevents
  duplicate outstanding invitations within the membership boundary. Provider and e-mail work run after the
  transaction.
hops:
- n: 1
  actor_or_service: Administrator through the console or HQ
  action: Submit the address, name and intended assignments to the boundary’s invitation operation.
  anchor: react-console:components/security/users/invite-user-dialog.tsx
  seam: sync
  on_failure: Return field validation errors to the requesting surface.
  left_inconsistent: No accepted invitation submission has committed.
  observer: The invitation dialog or API caller shows field problems.
  provenance: observed
  source: react-console:lib/security/api.ts:inviteConsoleUser
- n: 2
  actor_or_service: Security service (widening rule)
  action: Check management authority, scope containment, unconditional possession of the offered permissions
    and the self-grant prohibition.
  anchor: services-platform:modules/security/services/invitations/widening.ts:assertMayGrant
  seam: sync
  on_failure: Refuse missing authority and audit the refused attempt after rollback.
  left_inconsistent: No new access is granted.
  observer: The caller receives scope/key refusal details permitted by the API.
  provenance: observed
  source: services-platform:modules/security/services/invitations/widening.ts (header)
- n: 3
  actor_or_service: Security service (one transaction)
  action: Commit an invited membership, tokenless invitation, pending assignments and history.
  anchor: services-platform:modules/security/services/invitations/invite-user.ts
  seam: sync
  on_failure: Roll back related database writes on failure.
  left_inconsistent: No partial invitation transaction remains.
  observer: The caller receives persistence failure.
  provenance: observed
  source: services-platform:modules/security/services/invitations/invite-user.ts (header)
- n: 4
  actor_or_service: Provisioning (after commit, inside the request)
  action: Find or create the provider account with suppressed provider messaging and record its authentication
    identity.
  anchor: services-platform:modules/security/services/provisioning/provision-user.ts
  seam: sync
  on_failure: Refuse an address conflict; log provider failure and emit the delivery-failure metric.
  left_inconsistent: An invited membership can remain without a prepared identity or usable token.
  observer: Delivery results, logs and the failure alarm expose preparation trouble.
  provenance: observed
  source: services-platform:modules/security/aws/logic/security-invitation-delivery.alarm.ts
- n: 5
  actor_or_service: Provisioning (token and e-mail)
  action: Issue and hash the token, then check delivery policy, attempt the shared-sender e-mail and record
    delivery outcome.
  anchor: services-platform:modules/security/services/persistence/invitations.ts:issueInvitationToken
  seam: sync
  on_failure: Retain failed, withheld, refused or skipped delivery status; resend is the available replacement
    path.
  left_inconsistent: A valid digest may remain even though no usable message arrived.
  observer: The invitation delivery result and logs expose the outcome.
  provenance: observed
  source: services-platform:modules/security/services/invitations/invitation-email.ts (header)
branches:
- Resend supersedes the outstanding invitation atomically and prepares its replacement; only invited memberships
  permit resend.
- First-administrator provisioning records the explicit system invitation exemption from ordinary delegation.
- HQ invitations target Rhythm’s customer and platform-scoped staff roles; selecting Rhythm Administrator also
  requires role-management authority.
waits:
- Invitation validity is 168 elapsed hours; sending does not create an extra validity interval.
evidence:
- 'services-platform at ad3f6a65: modules/security/services/invitations/invite-user.ts, invite-staff.ts, resend-invitation.ts,
  resend-staff-invitation.ts, widening.ts, invitation-email.ts; services/provisioning/provision-user.ts; services/persistence/invitations.ts;
  aws/logic/security-invitation-delivery.alarm.ts; modules/tenants/services/lifecycle/first-administrator.ts.'
- 'react-console at baf6dae: components/security/users/invite-user-dialog.tsx; components/console/hq/staff/invite-staff-dialog.tsx.'
examined_at: '2026-10-23'
examiner: codex
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, TC-CHG-007, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-003, 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-002, 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-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Invite a person and deliver the invitation

## What It Does

Invitation persists the offer before any provider or sender call. The hop rows separate delegated authority, database creation, sign-in account preparation, token issuance and message delivery.

## The Flow

```mermaid
flowchart TD
    H1["Submit invitation"]
    H2["Check delegation"]
    H3["Commit offer"]
    H4["Prepare pool account"]
    H5["Issue token and attempt delivery"]
    H1 --> H2
    H2 --> H3
    H3 --> H4
    H4 --> H5
```

The diagram separates the relevant success, alternative and failure paths. The numbered hop rows retain the detailed authority checks, delegated work and retry limits.

## When Something Fails

Delivery failure does not undo the invitation. Issuance can precede policy withholding or failed sending, and concurrent delivery order does not identify the valid link. The recorded finding asks for race proof and a clear retry experience.

Preparation finds an existing recorded or named provider account before creating one. Resend replaces the invitation; token validity follows the current invitation and digest, not the last e-mail delivered. Active memberships use role management, invited memberships use resend and revoked memberships reuse their retained row for a new offer.

Membership, invitation, pending grants and database history commit together. Uniqueness prevents duplicate outstanding invitations within the membership boundary. Provider and e-mail work run after the transaction.

## Open Design Questions

The recorded findings retain any stronger planning expectation, missing writer or unproved recovery path. Observed behavior does not approve those outstanding product choices.
