docs: mark Phase 4 partial — Authentik real, Stalwart + OCIS stubbed

Honest status for the data-model + provisioning phases. Lists the smoke
test that verified the chain works end-to-end and points at the upstream
docs for the JMAP and libregraph follow-up work.
This commit is contained in:
Ronni Baslund
2026-05-24 00:07:40 +02:00
parent 28766b80c2
commit 467e6a7ab5
+60 -14
View File
@@ -68,24 +68,70 @@ Goal: Users can log in to the portal via Authentik.
- The `dezky` group in Authentik is the single tenant for dev. New tenants in Phase 4 need to create matching Authentik groups - The `dezky` group in Authentik is the single tenant for dev. New tenants in Phase 4 need to create matching Authentik groups
- A `dezky-platform-admins` group doesn't exist yet — for now akadmin's membership in `authentik Admins` does NOT grant platform-admin rights. Create that group if you want admin-only endpoints to work for you - A `dezky-platform-admins` group doesn't exist yet — for now akadmin's membership in `authentik Admins` does NOT grant platform-admin rights. Create that group if you want admin-only endpoints to work for you
## Phase 4: Provisioning automation (week 2-3) ## Phase 4: Provisioning automation (week 2-3) — partial
Goal: Sign up creates tenant resources across all services. Orchestration ships, two of three integrations are still stubs pending
upstream-specific work.
- [ ] Endpoint: `POST /tenants` — creates tenant in MongoDB - [x] `POST /tenants` writes tenant and triggers reconciliation in one call
- [ ] Worker: triggers Authentik tenant/group creation via API - [x] `POST /tenants/:slug/reconcile` retries provisioning for an existing
- [ ] Worker: configures Stalwart domain + DKIM via admin API tenant — idempotent, useful when an upstream was down or external
- [ ] Worker: creates OCIS space state drifted
- [ ] Worker: emails customer with onboarding info - [x] Per-step state recorded on `Tenant.provisioningStatus` (ok / skipped /
error / pending) + `Tenant.provisioningErrors` for the last failure
message; tenant auto-activates when all steps settle
- [x] Worker: Authentik group creation (real, idempotent)
- [ ] Worker: Stalwart domain + DKIM (stubbed — v0.16 dropped REST in favor
of JMAP, see follow-up below)
- [ ] Worker: OCIS space (stubbed — needs libregraph `/drives` endpoint
with service-to-service auth)
- [ ] Worker: onboarding email (no SMTP wired yet)
### Where things live
| Concern | File |
|---|---|
| Integration clients | `services/provisioning/src/integrations/{authentik,stalwart,ocis}.client.ts` |
| Orchestration | `services/provisioning/src/tenants/provisioning.service.ts` |
| `/tenants/:slug/reconcile` | `services/provisioning/src/tenants/tenants.controller.ts` |
| Portal proxy routes | `apps/portal/server/api/tenants/index.post.ts` + `[slug]/reconcile.post.ts` |
### Quick smoke test
From the portal in the browser (signed in), in DevTools:
```js
// Create a fresh tenant
await fetch('/api/tenants', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({ slug: 'acme', name: 'Acme Co', plan: 'pro' })
}).then(r => r.json())
// Re-run provisioning (idempotent)
await fetch('/api/tenants/acme/reconcile', { method: 'POST' }).then(r => r.json())
```
Response should include `provisioningStatus: { authentik: 'ok', stalwart:
'skipped', ocis: 'skipped' }` and `status: 'active'`. Verify the Authentik
group exists via the admin UI at `/if/admin/#/identity/groups`.
### Stub follow-up work
**Stalwart (JMAP)** — v0.16 [moved management off REST](https://stalw.art/docs/api/management/overview).
Need a minimal JMAP client that wraps `Domain/set` (create), `Domain/get`
(idempotency check), `Principal/set` (DKIM-keyed signing identity). Auth
via the persistent admin's bearer token from the OAuth flow we already use
for the web UI.
**OCIS (libregraph)**`POST /graph/v1.0/drives` with body
`{ "name": "<slug>", "driveType": "project" }`. Needs service-to-service
auth: either an OIDC client_credentials grant (requires registering a new
Authentik provider for the worker) or the IDM admin user's bearer token.
### Authentik API examples (for the eventual user-creation flow)
Authentik API examples:
```typescript ```typescript
// Create group (tenant) in Authentik
await authentikClient.coreGroupsCreate({
name: tenant.slug,
attributes: { tenantId: tenant.id, plan: tenant.plan },
})
// Create user // Create user
await authentikClient.coreUsersCreate({ await authentikClient.coreUsersCreate({
username: user.email, username: user.email,