Appearance
IAM Invites Task
Agent workflow: follow README.md for Audit -> Investigate -> Code -> Test -> Fix; keep this pack's writable scope and verification commands authoritative.
Dispatch type: orchestrator
Owner: iam-service.
Status: Partial.
Problem:
The IAM schema and routes include invitation concepts. Native create, accept, and revoke flows are implemented. Postgres-backed integration coverage exists as an opt-in test gated by IAM_SERVICE_POSTGRES_TEST_DATABASE_URL.
Legacy source evidence:
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/auth/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/organizations/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/prisma/schema.prisma
Writable files:
services/iam-service/**contracts/openapi/services/iam-service.yamldocs/api/iam-service.mddocs/agents/service-tasks/iam-invites.md
Orchestrator-owned files:
- Gateway route tables, school-service membership boundary decisions, shared deploy manifests, and public invite route promotion.
Tasks:
- [x] Implement invite create and accept flows over service-owned IAM storage.
- [x] Store invite tokens hashed, with expiry and consumed status.
- [x] On accept, create or link account membership through the canonical IAM org membership path.
- [x] Add explicit revoke workflow.
- [x] Record login/security audit events for create/accept/revoke.
- [x] Add Postgres-backed integration tests.
- [x] Add an isolated non-default Gateway and Admin browser candidate proof.
Candidate Gateway + Admin Browser Evidence (2026-07-15)
Orchestrator-owned candidate examples keep the default Gateway table unchanged:
deploy/gateway/routes.iam-invites-native-example.jsontargets the Compose IAM service.deploy/gateway/routes.iam-invites-native-localhost-example.jsontargets an isolated localhost IAM runtime.POST /api/invitesis exact,native_write, and requires anADMINbearer.POST /api/invites/acceptis exact, public, andnative_write; broad/api/invitesand/apifallbacks remain legacy-proxied.
The Admin organization surface enables this candidate only with ?adminInviteGateway=native. It sends the stored Admin Gateway bearer to POST /api/invites, adds the local INVITED row only after HTTP 201, and whitelists the response fields so the raw invite token is not rendered, stored, or tracked. Without the query flag it retains the existing fixture behavior.
Fresh runtime evidence is output/qa/iam-invite-runtime-local-postgres-20260715-015641/. The runner uses a disposable PostgreSQL cluster, local IAM demo seed, non-default Gateway, and Admin Vite process. It proves an Admin browser create, a non-Admin 403, Gateway accept 200, replay 401, active IAM membership persistence, security events without the raw token, and a non-empty persisted token_hash.
This remains local candidate evidence only. It does not modify deploy/gateway/routes.json, promote the public/default route, prove a deployed target, or establish production fixture-organization mapping.
Acceptance:
- Invite token is never stored raw.
- Expired, consumed, and revoked invites are rejected deterministically.
- Accepting an invite either succeeds once or returns a deterministic rejection for retry-safe clients.
- No profile details beyond necessary display/contact fields are stored in IAM.
Verification:
GOTOOLCHAIN=go1.25.11 go test ./services/iam-service/...GOTOOLCHAIN=go1.25.11 go vet ./services/iam-service/...IAM_SERVICE_POSTGRES_TEST_DATABASE_URL=postgres://... GOTOOLCHAIN=go1.25.11 go test ./services/iam-service/internal/repository -run TestPostgresInviteWorkflowIntegration -count=1- OpenAPI YAML parse for IAM service/contract.
make test-iam-invite-routesIAM_INVITE_RUNTIME_CONFIRM=local-postgres make test-iam-invite-runtime