# 8.7 — `X-Service: iam` adapter, Authentik admin surface (GREEN) Phase: 8 — ServiceAdapter CRD rollout Stage: RED Depends on: 8.1, 8.2, 8.3 Design contract: [API_ROUTING_HYBRID_DESIGN.md](../API_ROUTING_HYBRID_DESIGN.md) §3. - [ ] `internal/iam/handler.go` (new) implements the §3 mapping table: `user` GET/POST → `/api/v3/core/users/`, `user/{id}` GET/PATCH/DELETE → `/api/v3/core/users/{id}/`, `service-account` POST → `/api/v3/core/users/service_account/`, `role` GET/POST → `/api/v3/core/groups/`, `permission` GET/POST → `/api/v3/rbac/permissions/`, `flow` GET → `/api/v3/flows/instances/` - [ ] `k8s/serviceadapter-iam.yaml` CR: `serviceName: iam`, upstream = Authentik's internal Service, `auth.capability: iam:admin` (default — this surface is admin-only, tighter than the other adapters' read/write split) - [ ] `requestSchema` on `POST user` and `POST service-account` — fields matching Authentik's actual `/api/v3/core/users/` create-user body, confirmed against the live API, not invented - [ ] This is additive to `core iam` CLI subcommand (`~/workplace/core/src/cmd/iam/`), not a replacement — different caller (server vs. local CLI), same upstream. Do not modify the `core` CLI as part of this task - [ ] No token without `iam:admin` reaches any of these resources, including `flow` (GET-only, but still admin-scoped per the design doc — do not default it to a lower/no-auth tier because it's read-only) ## Verify ```bash curl -s -o /dev/null -w '%{http_code}\n' https://api.riotpiao.com/ \ -H 'X-Service: iam' -H 'X-Resource: user' # expected: 401 without a token curl -s -o /dev/null -w '%{http_code}\n' \ -H "Authorization: Bearer $NON_ADMIN_TOKEN" \ https://api.riotpiao.com/ -H 'X-Service: iam' -H 'X-Resource: user' # expected: 403 — token lacks iam:admin curl -s -H "Authorization: Bearer $IAM_ADMIN_TOKEN" \ https://api.riotpiao.com/ -H 'X-Service: iam' -H 'X-Resource: user' # expected: 200, Authentik's user list, proxied through /api/v3/core/users/ curl -s -X POST https://api.riotpiao.com/ \ -H "Authorization: Bearer $IAM_ADMIN_TOKEN" \ -H 'X-Service: iam' -H 'X-Resource: role' -d '{}' # expected: 400 — requestSchema rejects an empty group-create body ```