Skip to content

CAP-PFM-SEC-005Join through an invitation

Markdown

CAP-PFM-SEC-005

Join through an invitation

Markdown
  • DocumentDraft
  • Product intentConfirmed
  • ImplementationObserved

KindCapabilityProduct areaPlatformModuleSecurity, Customers and WorkspacesRevision1

Read atservices-platform ad3f6a65react-console baf6dae3

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
The invited person identifies the organization and account before joining.Acceptance activates the membership and offered role assignments together.Unusable links give recovery guidance without disclosing private account information.
Surfaces
consoleapi
Intent sources
services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)services-platform:docs/security/security-administration.md#2. Capability checklist (I1 to I10)

Controls

41 controls apply, from the corpus control catalogue.

TC-AVL-001 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-DAT-004 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-MON-003 TC-PI-001 TC-PI-002 TC-PI-003 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

Business Rules

12 rules, 12 to be proved before approval. A rule's product intent is derived from its origin: 12 confirmed by a product decision, the rest inheriting this capability's confirmed.

IdRuleKindEnforced atProvenance
01must prove
Confirmed
Invitation tokens are random, retained as hashes rather than raw values, expire after seven days and permit one activation.
✓ A valid invitation remains usable six days after issue.✗ An invitation used eight days after issue has passed its expiry.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
invariantservice, databasetest
services-platform:modules/security/tests/unit/services/invitations/invite-user.spec.js#expires the invitation 7 days after the execution's clock, on the invitation and on the user
02must prove
Confirmed
An unauthenticated invitation summary exposes only first name, masked e-mail, expiry, organization name and account kind.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
policyservicetest
services-platform:modules/security/tests/unit/services/invitations/invitation-summary.spec.js#answers the first name, a masked e-mail, the expiry, the organization and the kind of account, and nothing else
03must prove
Confirmed
Invalid, unknown, expired, revoked and superseded links use the same backend refusal message with reason codes and no organization details; an accepted link reports success again only while its membership remains active.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
policyservice, consoletest
services-platform:modules/security/tests/unit/services/invitations/accept-invitation.spec.js#answers an expired, a revoked and a superseded token with the same sentence, and records which it was
04must prove
Confirmed
Password acceptance sets the invited account’s password before atomically activating membership and pending roles; password-policy refusal does not spend the invitation.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
lifecycleservicetest
services-platform:modules/security/tests/unit/services/invitations/accept-invitation.spec.js#sets the chosen password in Cognito, then accepts, activates and makes the pending roles real in one transaction
05must prove
Confirmed
Replaying a successfully accepted link for an active membership returns the prior success without another credential or activation write.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
invariantservicetest
services-platform:modules/security/tests/unit/services/invitations/accept-invitation.spec.js#answers a reused token as the success it already was, without touching Cognito again
06must prove
Confirmed
Acceptance rechecks the inviter’s present grant authority; lost authority leaves membership and roles inactive and the token unspent, while the applicant receives the neutral unusable-link refusal.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
permissionservicetest
services-platform:modules/security/tests/integration/services/invitations/inviter-authority.integration.spec.js#refuses the acceptance once the administrator has lost the right, in the one sentence every bad link gets
07must prove
Confirmed
Google acceptance requires a live session for the correct pool, a verified matching e-mail and an unclaimed Google identity; expired or replayed sessions fail.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
validationservicetest
services-platform:modules/security/tests/unit/services/invitations/google-acceptance.spec.js#refuses a bearer token of another Cognito user, or one the pool does not verify (the nonce alone proves nothing)
08must prove
Confirmed
Google sign-in cannot create an unlinked console account without a live invitation-acceptance session, except for eligible active founding staff; refusals disclose no account details.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
policyservicedocumented
services-platform:docs/security/console-authentication.md#(c) A person with a password account and no Google link signs in with Google — refused
09must prove
Confirmed
The console provides no public registration, retired sign-up pages return not found and its pool denies self-registration.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
policyconsole, servicetest
react-console:e2e/dev/sign-in.dev.spec.ts#offers no sign-up link, and the retired routes answer 404
10must prove
Confirmed
The invitation screen blocks acceptance when a different console user is signed in and offers sign-out.
origin: services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final acceptance)
no proof recorded yet
policyconsoletest
react-console:e2e/dev/invitations.dev.spec.ts#refuses to accept an invitation while somebody else's console is on the screen
11must prove
Confirmed
Acceptance and identified invitation refusals produce audit events, successful acceptance names the joining person as actor, and tokens, hashes and passwords are excluded from the inspected audit and logging paths.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
invariantservicetest
services-platform:modules/security/tests/unit/services/invitations/accept-invitation.spec.js#answers a malformed and an unknown token identically, without auditing a user nobody has identified
12must prove
Confirmed
Reinvited revoked members accept onto the existing membership and pool account, preserving identity and enabling sign-in again.
origin: services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11 Final acceptance)
no proof recorded yet
lifecycleservicetest

Scenarios

IdGivenWhenThenProvenance
01An administrator has sent Dana a current invitation.Dana opens the link, checks its masked address and sets a password.Dana can sign in with the access offered by the invitation.test
react-console:e2e/dev/invitations.dev.spec.ts#shows who invited them, then sets their password and opens the console
02Dana’s invitation has been replaced by a resend.Dana follows the earlier e-mail link.The screen directs Dana to the newest invitation rather than accept the superseded link.test
react-console:e2e/dev/invitations.dev.spec.ts#sends somebody to their newest e-mail when a resend superseded the link they opened

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.