Skip to content

Development users and tenants

Local development tools, such as a user or tenant picker, need something to pick from. Hard-coding that list in the tool means it drifts from your application. Arc serves two discovery routes, anonymous by default only in Development, which return nothing until you opt in with fixture data from your own code.

const builder = ArcApplication.createBuilder({
environmentName: 'Development',
development: true,
developmentUsers: () => [{
microsoftIdentity: {
identityProvider: 'development',
userId: 'ada',
userDetails: 'Ada',
userRoles: ['editor'],
claims: [{ typ: 'tenants', val: 'acme' }]
}
}],
developmentTenants: () => [{ id: 'acme', name: 'Acme' }]
});

GET /.cratis/users and GET /.cratis/tenants return [] until you set development: true and supply developmentUsers(context) or developmentTenants(context). Each option takes a provider function, a promise-returning function, or an array of them; results are aggregated in order.

RouteEntry shape
/.cratis/users{ microsoftIdentity: { identityProvider, userId, userDetails, userRoles, claims: [{ typ, val }] }, details? }
/.cratis/tenants{ id, name }

Results are capped at 100 entries and 32 KiB, keep provider order and duplicates, and an invalid or failing provider answers a generic 500. Each request gets its own service scope.

Tenant resolution is separate: listing a tenant here does not select or authorize it. See Tenancy.

A tool such as Lens reads both routes to fill its pickers, then sends identity and tenant headers with your application’s requests. Arc only turns those identity headers into a principal when you registered microsoftIdentityPlatform(). Simulate a signed-in user locally shows that setup on a loopback host.