Server-side session records rotate identifiers on privilege change, revoke an entire session family on logout or compromise, and expose list-and-revoke evidence in the account UX without storing secrets in cookies.
Package status: reference context ready for human review. The contract and test scenarios are complete, but no claim is made that an adopting implementation has passed them.
Decision
Browser and API sessions are server-side records keyed by an opaque session id. The cookie or bearer token stores only that id. Privilege changes (password change, role grant, MFA enrollment, successful step-up) rotate the id inside the same family: the predecessor becomes rotated and cannot authenticate. Logout of the current device marks that record logged-out. Password-reset success and compromise reports revoke the entire family. The account security view lists living families with last-seen evidence and a revoke action that writes an audit row.
Scope
- Creation, rotation, idle and absolute expiry, logout, family revocation, and list/revoke UX for browser-applications and api-clients.
- Cookie attributes and what must not be stored client-side.
Outside this block
- Refresh-token rotation and reuse detection (related OAuth refresh package).
- Step-up challenge UX (related MFA package) and hashed reset-token issuance (related password-reset package).
Contract
- The client secret is only the opaque session id; user id, tenant, roles, and auth level live on the server record.
- Rotation issues a new id in the same family and makes the old id fail closed on the next request.
- Family revocation invalidates every non-terminal sibling; a later request with any of those ids is unauthenticated.
- The list endpoint returns only sessions for the authenticated user and tenant, with enough evidence to revoke a family, not enough to impersonate.
- Idle ttl and absolute ttl are enforced server-side; presenting a cookie does not extend a record that already expired.
- Logout of one session does not revoke siblings unless the user selects family revoke.
Implementation guidance
- Persist records with a tenant column; do not authorize from an unsigned cookie payload. On rotation, set the new cookie in the same response that completes the privilege change.
- Legal transitions are listed in state-machine.md; rotation never starts a new family_id.
Failure handling and safeguards
- Concurrent requests during rotation may finish with the old id once; subsequent requests fail, and two successors must not be minted.
- If audit write fails after revoke, keep revoke durable and retry the audit.
Verification and operations
- Tests rotate on role-grant and prove the old cookie is rejected; tests revoke a family of two and prove both fail.
The executable-looking examples in this package are fixtures and acceptance contracts. Run
python tools/validate.py from the collection root to check package structure and metadata; then
implement and execute the scenarios in the target repository.
Adoption assumptions
- Names and numeric values in
example.yamlare an adoption profile, not universal defaults. - The adopting team must map actors, data classes, error vocabulary, and ownership to its system.