auth/role_schema.ts

Role system — builtin roles, role specs, and extensible role schema factory.

Defines the authorization policy vocabulary: which roles exist, their required credential types, the scope kinds each role applies to, and the grant paths through which each role can be granted. Each role gets a structured RoleSpec; the factory create_role_schema merges builtins with consumer-declared specs and validates every cross-axis field against the corresponding open registries (create_credential_type_schema, create_scope_kind_schema, create_grant_path_schema) at construction time so misconfigurations fire at server startup, not at first call.

RoleSpec carries the four cross-axis fields that the dispatcher branches on: credential type, scope kind, grant path, and the role-name itself. v1 keeps the cross-axis fields informative-only (registry-membership validation, no INSERT-time enforcement); v2 may add (role, scope_kind) enforcement once the shape is clear from real consumer usage.

Declarations
#

12 declarations

view source

BUILTIN_ROLE_SPECS_BY_NAME
#

auth/role_schema.ts view source

ReadonlyMap<string, RoleSpec>

Builtin role specs, keyed by role name. Not overridable by consumers — read once at startup by create_role_schema and the action factories that fall back to builtins when no consumer roles is supplied. ReadonlyMap encodes the contract; runtime mutation has no effect on already-built role schemas (the factory copies entries into a fresh Map).

BUILTIN_ROLES
#

BuiltinRole
#

create_role_schema
#

auth/role_schema.ts view source

(consumer_roles: readonly RoleSpec[], options?: CreateRoleSchemaOptions): RoleSchemaResult

Create a role schema and spec map that extends the builtins with app-defined roles.

Call once at server init. The returned Role schema validates role strings at I/O boundaries (grant endpoint, role_grant queries). The role_specs map is read by middleware for required_credential_types checks and by admin / self-service factories to derive their default eligibility filters from RoleSpec.grant_paths.

Construction-time guards (all fire on misconfiguration):

1. Every consumer_roles[i].name matches RoleName regex. 2. No two consumer roles share a name. 3. No consumer role collides with a builtin (keeper / admin). 4. When options.credential_types is supplied, every entry in required_credential_types is registered in that map. 5. When options.scope_kinds is supplied, every entry in applicable_scope_kinds is registered in that map. (Builtins declare empty applicable_scope_kinds, so they pass any registry.) 6. When options.grant_paths is supplied, every entry in grant_paths is registered in that map. (Builtins use only 'admin' and 'bootstrap', both of which are builtin grant paths, so they pass the default registry from create_grant_path_schema().)

consumer_roles

app-defined role specs

type readonly RoleSpec[]

options

optional registries for cross-axis validation

default {}

returns

RoleSchemaResult

{Role, role_specs} — Zod schema and full spec map

throws

  • Error - if any `consumer_roles` entry fails any of the construction-time guards above

examples

// visiones — opt into all four registries for full construction-time validation const credential_types = create_credential_type_schema(); const scope_kinds = create_scope_kind_schema({ classroom: {description: 'A classroom — teacher and student role_grants scope here.'}, }); const grant_paths = create_grant_path_schema(); const {Role, role_specs} = create_role_schema( [ { name: 'teacher', description: 'Educator role. Web-grantable; applies at classroom scope.', grant_paths: ['admin'], applicable_scope_kinds: ['classroom'], }, ], {credential_types, scope_kinds, grant_paths}, );

CreateRoleSchemaOptions
#

auth/role_schema.ts view source

CreateRoleSchemaOptions

Optional registries to validate RoleSpec cross-axis fields against at construction time.

credential_types

Pass create_credential_type_schema() to validate RoleSpec.required_credential_types entries.

scope_kinds

Pass create_scope_kind_schema() to validate RoleSpec.applicable_scope_kinds entries.

grant_paths

Pass create_grant_path_schema() to validate RoleSpec.grant_paths entries.

list_roles_with_grant_path
#

auth/role_schema.ts view source

(role_specs: ReadonlyMap<string, RoleSpec>, grant_path: string): string[]

Filter helper: list every role whose grant_paths includes the given path.

role_specs

type ReadonlyMap<string, RoleSpec>

grant_path

type string

returns

string[]

ROLE_ADMIN
#

role_has_grant_path
#

auth/role_schema.ts view source

(role_specs: ReadonlyMap<string, RoleSpec>, role: string, grant_path: string): boolean

Predicate over a RoleSpec map: does the named role include the given grant path? Returns false for unknown roles. Used by admin_actions.create_admin_actions (path = 'admin') and self_service_role_actions.create_self_service_role_actions (path = 'self_service') to derive their default eligibility filters.

role_specs

type ReadonlyMap<string, RoleSpec>

role

type string

grant_path

type string

returns

boolean

ROLE_KEEPER
#

RoleName
#

RoleSchemaResult
#

auth/role_schema.ts view source

RoleSchemaResult

The result of create_role_schema — a Zod schema and spec map for all roles.

Role

Zod schema that validates role strings. Use at I/O boundaries (grant endpoint, role_grant queries).

type z.ZodType<string>

role_specs

Specs for every role (builtins + app-defined). Keyed by role name.

type ReadonlyMap<string, RoleSpec>

RoleSpec
#

auth/role_schema.ts view source

RoleSpec

Configuration for a role.

Each role declares the credential types its holders must use, the scope kinds it applies to, and the grant paths through which it can be granted. Every cross-axis field is an open-registry string array — required_credential_types against create_credential_type_schema, applicable_scope_kinds against create_scope_kind_schema, grant_paths against create_grant_path_schema. Pass the registry results to create_role_schema and every entry is checked at construction time.

Empty arrays carry meaning:

- required_credential_types: [] — any authenticated credential type may exercise the role (the default for app-defined roles). - applicable_scope_kinds: [] — the role applies at the global scope only (no scope_kind / scope_id set on its role_grants). This is the default for app-defined roles; consumers add scope kinds explicitly. - grant_paths: [] — the role has no grant path declared in this registry; it is unreachable through admin / self-service / system flows. Only useful for diagnostic snapshotting.

Builtins (keeper, admin) ship preconfigured in BUILTIN_ROLE_SPECS_BY_NAME.

name

Unique role name. Must match RoleName regex; collisions with builtins throw.

type string

description

Admin-UI-facing copy describing the role's intent.

type string

required_credential_types

Credential types whose holders are permitted to exercise this role. Each entry is checked at construction time against the credential_types registry passed to create_role_schema. Empty array = any authenticated credential type.

type ReadonlyArray<string>

applicable_scope_kinds

Scope kinds at which this role's role_grants may be granted. Each entry is checked at construction time against the scope_kinds registry passed to create_role_schema. Empty array = global only. v1 keeps this informative-only (no INSERT-time enforcement).

type ReadonlyArray<string>

grant_paths

Grant paths through which this role can be granted. Each entry is checked at construction time against the grant_paths registry passed to create_role_schema. Drives downstream defaults:

- admin_actions.grantable_roles ⊇ {role : 'admin' ∈ grant_paths} - self_service_role_actions default eligibility ⊇ {role : 'self_service' ∈ grant_paths}

Empty array = role is not granted via any registered path (only exists for diagnostic / future use).

type ReadonlyArray<string>

Depends on
#

Imported by
#