/** * JWT signing utilities for outbound composed credentials. */ import { deriveAllowedAlgorithms } from '@astrale-os/kernel-core' import { SignJWT, importJWK } from 'jose' /** * Sign a credential JWT with the given claims and identity config. */ export async function signCredential( claims: Record, config: { issuer: string subject: string audience: string privateKey: JsonWebKey /** JWT lifetime as a jose-compatible string (e.g. '60s', '5m', '1h'). Default: '60s'. */ ttl?: string }, ): Promise { const alg = deriveAllowedAlgorithms(config.privateKey)[0] if (!alg) { throw new Error(`Cannot derive algorithm from JWK: kty=${config.privateKey.kty}`) } const key = await importJWK(config.privateKey, alg) return new SignJWT(claims) .setProtectedHeader({ alg }) .setIssuer(config.issuer) .setSubject(config.subject) .setAudience(config.audience) .setIssuedAt() .setExpirationTime(config.ttl ?? '60s') .sign(key) }