Skip to content

Bootstrap Credentials — Development Environment

Environment: Development / local Docker only

The Tenant Service auto-seeds a default organisation, an administrator user, and the service principals at startup — there is no manual bootstrap step. With docker-compose up the seeding runs automatically the first time the Tenant database is empty (DatabaseInitializer in src/Services/Sorcha.Tenant.Service/Data/).


⚠️ Security warning

These are DEVELOPMENT credentials only.

  • ❌ NEVER use these credentials, or the predictable development secrets below, in production.
  • ✅ In any environment other than Development, each service-principal secret is randomly generated at first seed and written once to the Tenant Service startup logs (LogWarning, "SAVE THIS SECRET — it will not be shown again"). Capture it from the logs.
  • ✅ Service-principal secrets are hashed at rest (Argon2id); they are never recoverable from the database. Other Tenant at-rest secrets (TOTP, OIDC client secrets, login tokens) are encrypted with AES-256-GCM (ISecretProtectionProvider, Feature 146).

Default organisation & admin user

PropertyOrganisationAdmin user
ID00000000-0000-0000-0000-00000000000100000000-0000-0000-0001-000000000001
NameSorcha LocalSystem Administrator
Email / Subdomainsorcha-localadmin@sorcha.local
PasswordDev_Pass_2025!
Role / StatusActiveAdministrator / Active

Change the admin password immediately after first login — see Admin → Installation & First Run.

Login (through the API Gateway):

bash
curl -X POST http://localhost/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "admin@sorcha.local", "password": "Dev_Pass_2025!" }'

The Gateway listens on http://localhost (port 80) by default. You can also reach the Tenant Service directly at http://localhost:5450 (Docker) or https://localhost:7110 (Aspire).


Service principal credentials

Service principals authenticate service-to-service via the OAuth2 client-credentials flow. In the Development environment the seed uses predictable secrets of the form {client-id-stem}-service-secret so docker-compose works out of the box. Outside Development the secret is random (see the security warning above).

ServiceClient IDDevelopment secretScopes
Blueprint Serviceservice-blueprintblueprint-service-secretblueprints:read blueprints:write wallets:sign register:write
Wallet Serviceservice-walletwallet-service-secretwallets:read wallets:write wallets:sign wallets:encrypt wallets:decrypt registers:read
Register Serviceregister-serviceregister-service-secretregisters:read registers:write registers:query validator:write wallets:sign
Peer Serviceservice-peerpeer-service-secretpeers:read peers:write registers:read
Validator Servicevalidator-servicevalidator-service-secretvalidator:read validator:write wallets:sign registers:read blueprints:read
Tenant Servicetenant-servicetenant-service-secretwallets:read wallets:sign wallets:verify persona:crypto
HAIP Serviceservice-haiphaip-service-secretblueprints:read

Get a service token (example — Blueprint Service):

bash
curl -X POST http://localhost/api/service-auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=service-blueprint" \
  -d "client_secret=blueprint-service-secret"

Token response & properties

json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 28800,
  "scope": "blueprints:read blueprints:write wallets:sign register:write"
}
  • Lifetime: 8 hours (28,800 s)
  • Type: Bearer (send as Authorization: Bearer <token>)
  • Algorithm: HS256 (HMAC-SHA256, JWT signing key)
  • Issuer: urn:sorcha:{installation} (default installation sorchaurn:sorcha:sorcha). Service tokens carry the {installation}:service audience. See JWT Configuration and the tiered-audience model (Feature 136).

Use the token:

bash
curl -X GET http://localhost/api/blueprints \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Resetting bootstrap data

Seeding is idempotent and re-runs only when the Tenant database is empty. To regenerate everything:

bash
# Stop the stack and DELETE all volumes (wipes Postgres/Mongo/Redis data)
docker-compose down -v

# Bring it back up — the Tenant Service re-seeds the org, admin, and service principals
docker-compose up -d

⚠️ down -v deletes all data, including any organisations, users, wallets, and registers you created. In a non-Development environment the new service-principal secrets are random — capture them from the Tenant Service logs.

To reset only the service principals (keeping the org and users):

bash
docker exec -it sorcha-postgres psql -U sorcha -d sorcha_tenant \
  -c 'DELETE FROM public."ServicePrincipals";'
# Restart the Tenant Service to re-seed them
docker-compose restart tenant-service

Verification

bash
# Organisation
docker exec sorcha-postgres psql -U sorcha -d sorcha_tenant \
  -c 'SELECT "Id","Name","Subdomain","Status" FROM public."Organizations";'

# Admin user
docker exec sorcha-postgres psql -U sorcha -d sorcha_tenant \
  -c 'SELECT "Id","Email","DisplayName","Status" FROM public."UserIdentities";'

# Service principals (expect 7: blueprint, wallet, register, peer, validator, tenant, haip)
docker exec sorcha-postgres psql -U sorcha -d sorcha_tenant \
  -c 'SELECT "ServiceName","ClientId","Status" FROM public."ServicePrincipals";'

Troubleshooting

SymptomCause / fix
invalid client credentialsWrong client ID/secret. In Development use the predictable secrets above; otherwise read the secret from the Tenant Service startup logs.
token is invalid or has expiredService tokens last 8 h — request a new one via /api/service-auth/token.
No service principals seededThe Tenant database was not empty at startup (seeding is one-time). Reset with docker-compose down -v && docker-compose up -d.
Database initialisation failed (Windows/Docker Desktop)Use host.docker.internal as the Postgres host in the connection string.

Released under the MIT License.