Skip to content

feat: add authoritative end-user identity lifecycle#16

Draft
andrei-hasna wants to merge 7 commits into
feat/bf69dbe6-identity-foundationfrom
feat/76cfbe9e-user-lifecycle
Draft

feat: add authoritative end-user identity lifecycle#16
andrei-hasna wants to merge 7 commits into
feat/bf69dbe6-identity-foundationfrom
feat/76cfbe9e-user-lifecycle

Conversation

@andrei-hasna

@andrei-hasna andrei-hasna commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add Identities-owned users, tenants, memberships, normalized login identifiers, Argon2id credentials, invitations, verification, recovery, and bootstrap policy
  • add tenant- and scope-bound access-token issuance, hashed refresh rotation/replay detection, hashed JTI revocation, session-family logout, and scoped administration
  • harden lifecycle authority across invite consumption, current membership scopes, tenant-only suspension, atomic revocation, bounded authentication work, recovery timing, and UTS-46 identifier canonicalization
  • require every pending invite creator to remain a current active owner or admin at consumption time in both in-memory and PostgreSQL stores, while preserving management-scope, target-role, tenant-scope, row-lock, and atomicity checks
  • add mountable lifecycle API, OpenAPI/generated SDK coverage, owner-only bootstrap CLI, live PostgreSQL persistence, and reversible versioned migrations

Stacked provenance

  • base PR: feat: add canonical identity and scoped auth contracts #14
  • base branch: feat/bf69dbe6-identity-foundation
  • required base SHA: 2deab178c0d26ee3f1337823b4d9e73e70205503
  • initial lifecycle head: b70a31eb1fb887a6937ec0fa07f7ba72688ce42a
  • Review-F predecessor head: 6a59ce4dd51d8359c6209de862c6c01bf063cbb4
  • exact lifecycle head: b3054234d8f86981fb90739bb2736a433dc50953
  • Todos: 76cfbe9e-9d9c-4650-bd5f-d2df37164e79, predecessor 1f8bfadf-6c56-4996-a820-814f553c0a3f

Verification

  • regression-first RED proof at 6a59ce4: both stores consumed a member invite after owner-to-member demotion; PostgreSQL visibly waited on the creator membership row lock before committing the invalid signup
  • focused Review-F in-memory authority matrix: 14 scenarios, 36 assertions, 0 failures
  • focused live PostgreSQL authority matrix: 14 scenarios, 14 aggregate assertions, 0 failures; creator row-lock wait and atomic no-partial-row rollback proved
  • fresh isolated postgres:16-alpine: TEST_DATABASE_URL=... bun test src/pg-user-lifecycle.test.ts — 45 pass, 0 fail, 133 assertions
  • bun run verify:release — 159 pass, 15 expected live-PostgreSQL skips, 0 fail, 1454 assertions; typecheck, vendor-kit check, declaration emit, and bundle build green
  • deterministic SDK regeneration twice — 16 operations, stable SHA-256 d8dd604b0302bfe34576c4549618b0c9e2a2878e05cc938ff1e1a5cf2742a965, no tracked diff
  • Bun package — 705 files; isolated installed consumer proves demoted-member invite rejection, unconsumed invite, no new user, and SDK/PostgreSQL exports
  • git diff --check, Co-Authored-By/test-weakening scans, staged gitleaks, and exact 6a59ce4dd51d8359c6209de862c6c01bf063cbb4..b3054234d8f86981fb90739bb2736a433dc50953 range scan — green/no leaks

Review status

  • Review-F P1 is regression-proved and remediated; labeled adversarial self-review found P0=0 and P1=0 after an independent reviewer could not be spawned because the session thread limit was full
  • invite creation/consumption authority parity was audited only; creation and consumption now share active-user, active-membership, owner/admin, management-scope, role-order, invite-scope, and tenant-allowlist invariants
  • P2 residual for intermediate architecture review: tenant status/lifecycle is not modeled, so current invariants prove tenant presence only; this focused fix intentionally does not add tenant status lifecycle
  • draft remains open for fresh independent exact-head review of b3054234d8f86981fb90739bb2736a433dc50953
  • no merge, publish, or deploy performed

@andrei-hasna

Copy link
Copy Markdown
Contributor Author

Review-A P1 remediation is pushed at exact head 6bac1e8422b0b8ff3010aa58b88246044649145b.

All seven requested security areas are covered, plus the adversarial self-review closed stale persisted admission reservations after process failure. Final gates: full release 122/0 (1361 assertions), focused lifecycle 23/0 (137), fresh PostgreSQL 3/0 (41), deterministic SDK, build, isolated pack smoke, diff check, and staged/range gitleaks all green.

This remains draft and both Todos roots remain in progress pending two fresh independent exact-head adversarial reviews.

@andrei-hasna

Copy link
Copy Markdown
Contributor Author

Review-B P1 remediation is pushed at exact head 7992a28bf9cbaf1f5f7c1593f3d132501406f273.

Closed all three findings:

  • invite consumption now locks the current tenant allowlist and registration persists the initial session in the same transaction, with a deterministic PostgreSQL interleaving regression proving zero partial user/membership/session/invite state;
  • identifier failure buckets now acquire a separate client-wide admission bucket in deterministic PostgreSQL order, capping eight distinct identifiers at maxConcurrent=2 and releasing both reservations in finally;
  • exported stores omit caller control of managementScope and persist the authorization-owned scope only, with in-memory and PostgreSQL creator-scope-loss regressions.

Verification: focused lifecycle 25/0 (149 assertions), fresh PostgreSQL 16 5/0 (48), full release 129/0 (1421), typecheck, vendor-kit, build, deterministic 16-operation SDK generation, isolated packed-consumer smoke, diff check, and staged/commit-range gitleaks all green.

PR remains draft and both Todos roots remain in progress pending two fresh independent exact-head adversarial reviews. No merge, publish, or deploy performed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant