3d370caa62
Implements Phase 3 from docs/NEXT-STEPS.md. Mongoose schemas (services/provisioning/src/schemas/): - Tenant: slug, name, status, plan, domains, billingInfo, plus handles for Authentik group, OCIS space, and Stalwart domain (set in Phase 4) - User: authentikSubjectId, tenantIds[], email, name, role, platformAdmin flag - Subscription: tenantId, plan, status, Stripe IDs (unused until Phase 4) Auth (services/provisioning/src/auth/): - JwtAuthGuard verifies Authentik access tokens against the provider's JWKS with issuer + audience checks. Uses NODE_EXTRA_CA_CERTS to trust the mkcert root for the local Authentik cert - ActorService resolves the verified JWT into a Mongo User document — every controller reads tenantIds + platformAdmin from the DB, not the token - CurrentUser decorator extracts the JWT payload onto controllers CRUD modules: - /tenants, /users, /subscriptions with create/read/update/delete - /users/me upserts the caller's User record on every request, syncing email, name, tenantIds, and platformAdmin from the JWT's groups claim — the only place we read JWT.groups outside the bootstrap Why DB-derived authz: putting all group memberships in the JWT doesn't scale past ~50 tenants per user (header/cookie size limits, no mid-session revocation, stale data until re-login). JWT now carries identity only; the DB is the source of truth for who can see what. Seed (SeedService.OnApplicationBootstrap): idempotent creation of the default 'dezky' tenant + matching subscription. User records are created on first /users/me hit. Infrastructure: - Traefik label exposes provisioning at https://api.dezky.local (dev only) - api.dezky.local added to Docker network aliases on Traefik - mkcert root CA mounted into the provisioning container for JWKS fetch - Authentik 'groups' scope mapping created + attached to dezky-portal provider; portal now requests it as a scope - nuxt.config.ts portal: exposeAccessToken=true so Nitro forwards token; NUXT_OIDC_TOKEN_KEY fixed to base64-encoded 32 bytes (was hex, causing "Invalid key length" once exposeAccessToken turned on) Portal: apps/portal/server/api/me.get.ts is a scaffolding route that forwards the user's access token to provisioning and returns profile + tenants + subscriptions — verifies the full chain end to end.
37 lines
972 B
JSON
37 lines
972 B
JSON
{
|
|
"name": "@dezky/provisioning",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"description": "Dezky tenant provisioning worker — NestJS",
|
|
"scripts": {
|
|
"build": "nest build",
|
|
"start": "nest start",
|
|
"start:dev": "nest start --watch",
|
|
"start:debug": "nest start --debug --watch",
|
|
"start:prod": "node dist/main",
|
|
"test": "jest",
|
|
"typecheck": "tsc --noEmit"
|
|
},
|
|
"dependencies": {
|
|
"@nestjs/common": "^10.4.0",
|
|
"@nestjs/core": "^10.4.0",
|
|
"@nestjs/platform-fastify": "^10.4.0",
|
|
"@nestjs/config": "^3.3.0",
|
|
"@nestjs/mongoose": "^10.1.0",
|
|
"class-transformer": "^0.5.1",
|
|
"class-validator": "^0.14.1",
|
|
"jose": "^5.9.0",
|
|
"mongoose": "^8.7.0",
|
|
"reflect-metadata": "^0.2.2",
|
|
"rxjs": "^7.8.0"
|
|
},
|
|
"devDependencies": {
|
|
"@nestjs/cli": "^10.4.0",
|
|
"@nestjs/testing": "^10.4.0",
|
|
"@types/node": "^20.0.0",
|
|
"typescript": "^5.5.0",
|
|
"ts-node": "^10.9.2"
|
|
},
|
|
"packageManager": "pnpm@9.12.0"
|
|
}
|