feat(dev): local docker-compose stack
ci / shared (pull_request) Successful in 4s
ci / validate (pull_request) Successful in 2s

Adds dev/docker-compose.yml + dev/keycloak/realm-export.json + dev/README.md
and Makefile targets so a developer can:

  make dev-up

and get Keycloak 26 on :8080 with the breakpilot-dev realm pre-imported,
plus pg-app (:5432), Redis (:6379), Mongo (:27017), and MinIO (:9000 + :9001).

Seed users:
  test@breakpilot.dev / test    — IT_ADMIN of tenant 'acme'
  admin@breakpilot.dev / admin  — BREAKPILOT_ADMIN (platform staff)

Realm includes a dev-portal public PKCE client (redirect URIs cover
http://localhost:3000/* and http://*.localhost:3000/* so subdomain routing
works in dev) and a dev-tenant-registry bearer-only client. Protocol
mappers project tenant_id, tenant_slug, org_roles, products, plan, and
tenant_status into every issued JWT — the contract portal + tenant-registry
expect in prod, fronted by Keycloak attributes today.

dev/ lives in orca-platform because this repo already documents the
production topology that this compose mirrors. INFRASTRUCTURE.md §1 sets
dev as 'docker-compose on developer laptops' — this is that compose.

Refs: M0.1+ (precondition for local-dev work on tenant-registry / portal)
This commit is contained in:
2026-05-18 22:37:35 +02:00
parent 8e37f65b8e
commit 2a807d7671
6 changed files with 444 additions and 1 deletions
+199
View File
@@ -0,0 +1,199 @@
{
"realm": "breakpilot-dev",
"enabled": true,
"displayName": "Breakpilot (dev)",
"registrationAllowed": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": true,
"editUsernameAllowed": false,
"bruteForceProtected": true,
"accessTokenLifespan": 900,
"ssoSessionIdleTimeout": 3600,
"ssoSessionMaxLifespan": 36000,
"internationalizationEnabled": false,
"defaultSignatureAlgorithm": "RS256",
"organizationsEnabled": true,
"roles": {
"realm": [
{ "name": "BREAKPILOT_ADMIN", "description": "Platform staff: full backstage access" },
{ "name": "SUPPORT_ENGINEER", "description": "Platform staff: tenant impersonation + read" },
{ "name": "SALES_REP", "description": "Platform staff: demo-tenant access only" }
]
},
"groups": [
{
"name": "IT_ADMIN",
"path": "/IT_ADMIN",
"attributes": { "org_role": ["IT_ADMIN"] }
},
{
"name": "CXO",
"path": "/CXO",
"attributes": { "org_role": ["CXO"] }
},
{
"name": "USER",
"path": "/USER",
"attributes": { "org_role": ["USER"] }
}
],
"users": [
{
"username": "test@breakpilot.dev",
"email": "test@breakpilot.dev",
"emailVerified": true,
"firstName": "Test",
"lastName": "Acme",
"enabled": true,
"credentials": [
{
"type": "password",
"value": "test",
"temporary": false
}
],
"attributes": {
"tenant_id": ["00000000-0000-0000-0000-000000000001"],
"tenant_slug": ["acme"],
"org_roles": ["IT_ADMIN"],
"products": ["certifai", "compliance"],
"plan": ["professional"],
"tenant_status": ["active"]
},
"groups": ["/IT_ADMIN"]
},
{
"username": "admin@breakpilot.dev",
"email": "admin@breakpilot.dev",
"emailVerified": true,
"firstName": "Platform",
"lastName": "Admin",
"enabled": true,
"credentials": [
{
"type": "password",
"value": "admin",
"temporary": false
}
],
"realmRoles": ["BREAKPILOT_ADMIN"]
}
],
"clients": [
{
"clientId": "dev-portal",
"name": "Customer Portal (dev)",
"enabled": true,
"publicClient": true,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": false,
"implicitFlowEnabled": false,
"serviceAccountsEnabled": false,
"rootUrl": "http://localhost:3000",
"baseUrl": "http://localhost:3000",
"redirectUris": [
"http://localhost:3000/*",
"http://acme.localhost:3000/*",
"http://demo.localhost:3000/*"
],
"webOrigins": ["+"],
"attributes": {
"pkce.code.challenge.method": "S256",
"post.logout.redirect.uris": "http://localhost:3000/*##http://*.localhost:3000/*"
},
"protocolMappers": [
{
"name": "tenant_id-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "tenant_id",
"claim.name": "tenant_id",
"jsonType.label": "String",
"id.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
"name": "tenant_slug-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "tenant_slug",
"claim.name": "tenant_slug",
"jsonType.label": "String",
"id.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
"name": "org_roles-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "org_roles",
"claim.name": "org_roles",
"jsonType.label": "String",
"multivalued": "true",
"id.token.claim": "true",
"access.token.claim": "true"
}
},
{
"name": "products-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "products",
"claim.name": "products",
"jsonType.label": "String",
"multivalued": "true",
"id.token.claim": "true",
"access.token.claim": "true"
}
},
{
"name": "plan-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "plan",
"claim.name": "plan",
"jsonType.label": "String",
"id.token.claim": "true",
"access.token.claim": "true"
}
},
{
"name": "tenant_status-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "tenant_status",
"claim.name": "tenant_status",
"jsonType.label": "String",
"id.token.claim": "true",
"access.token.claim": "true"
}
}
]
},
{
"clientId": "dev-tenant-registry",
"name": "Tenant Registry (dev)",
"enabled": true,
"bearerOnly": true,
"publicClient": false,
"standardFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false
}
]
}