Skip to content

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.yaml
  • docs/api/iam-service.md
  • docs/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.json targets the Compose IAM service.
  • deploy/gateway/routes.iam-invites-native-localhost-example.json targets an isolated localhost IAM runtime.
  • POST /api/invites is exact, native_write, and requires an ADMIN bearer.
  • POST /api/invites/accept is exact, public, and native_write; broad /api/invites and /api fallbacks 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-routes
  • IAM_INVITE_RUNTIME_CONFIRM=local-postgres make test-iam-invite-runtime

Go-platform documentation is generated from repository Markdown.