/** * Domain authority — the worker-side mint seam for identities THIS DOMAIN issues. * * A domain worker is a trusted issuer: the kernel resolves any `(iss, sub)` * credential signed with the worker's key back to the graph node carrying that * identity. That makes the worker the natural authority for the principals it * materializes — an App identity a workspace installs, a per-domain role * umbrella, a managed user. `mint` signs such a credential (optionally carrying * a `grant` claim with an unresolved identity expression); `sessionFor` opens a * kernel session presenting it, so the worker can ACT AS an identity it issues * (e.g. call `@::mintDelegationCredential` as the role to obtain a * kernel-issued delegation inner). * * Scope guard: this signs under the WORKER'S OWN issuer only — it cannot forge * another issuer's identities. The kernel still enforces everything downstream * (trust of the issuer, `frozen`, grant resolution, nested-credential rules). */ import type { FnMap } from '@astrale-os/kernel-client' import type { BoundClientSessionView } from '@astrale-os/kernel-client/session' import type { UnresolvedIdentityExpr } from '@astrale-os/kernel-core' import { createUnresolvedGrant } from '@astrale-os/kernel-core' import type { RemoteIdentityConfig } from './identity.js' import { bindCredentialSession } from './kernel-client.js' import { signCredential } from './sign.js' export type DomainAuthorityRef = { /** The issuer ID (used as the `iss` claim in credentials and on Identity nodes). */ readonly iss: string } export type MintIssuedParams = { /** The issued identity's `sub` — must match the graph node's stored subject. */ subject: string /** The credential's audience — the kernel (or worker) it will be presented to. */ audience: string /** * Optional `grant` claim: the identity expression the credential's holder may * act as (wrapped `{v:1, expr}`). Omit for a plain self-authenticating * credential — the kernel falls back to a self-grant for externally-issued * credentials. Nested `credential` leaves MUST be kernel-issued delegation * inners (the kernel refuses non-kernel nested credentials). */ grant?: UnresolvedIdentityExpr /** JWT lifetime, jose-style (`'60s'`, `'5m'`, `'1h'`). Default `'1h'`. */ ttl?: string } export type DomainAuthority = DomainAuthorityRef & { /** Sign a credential AS an identity this domain issues. */ mint(params: MintIssuedParams): Promise /** * A kernel session presenting a pre-signed credential (typically from * {@link DomainAuthority.mint} with `audience = kernelUrl`). */ sessionFor(kernelUrl: string, credential: string): BoundClientSessionView } /** Build the domain authority for one worker identity config. */ export function makeDomainAuthority(identity: RemoteIdentityConfig): DomainAuthority { return { iss: identity.issuer, mint: ({ subject, audience, grant, ttl }) => signCredential(grant !== undefined ? { grant: createUnresolvedGrant(grant) } : {}, { issuer: identity.issuer, subject, audience, privateKey: identity.privateKey, ttl: ttl ?? '1h', }), sessionFor: (kernelUrl, credential) => bindCredentialSession(kernelUrl, credential), } }