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:
+60
-14
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user