/* RFC-0558: identity.bootstrap — generate operator keypair, write werkstatt.identity.json, issue self-ownership SiteOwnershipCredential. Do not issue ActorDelegationCredential — that is identity.credential.issue. RFC-0558: initial identity.bootstrap command handler. RFC-1249: wire werkstatt.commands.validate into packages.check + retire CMD-OUTPUT debt */ import type { KernelCommandInput, KernelCommandResult, KernelRuntimeContext, } from "@warpgogol/werkstatt-engine/kernel"; import { generateKeypair } from "@warpgogol/werkstatt-shared/passport/sign"; import { signIdentityCredential } from "@warpgogol/werkstatt-shared/passport/identity-sign"; import type { WerkstattIdentityConfig, SiteOwnershipCredentialSubject, } from "@warpgogol/werkstatt-shared/passport"; import { writeIdentityConfig, generateCredentialId } from "./identity-io.ts"; export interface IdentityBootstrapData { operatorName: string; domain: string; publicKeyMultibase: string; keyVersion: string; authMode: "permissive"; selfOwnershipCredentialId: string; privateKeyHex: string; } function flagString(input: KernelCommandInput, key: string): string | undefined { const v = input.flags[key]; return typeof v === "string" ? v : undefined; } export async function runIdentityBootstrap( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const { workspaceRoot } = context; const operatorName = flagString(input, "operator-name"); const domain = flagString(input, "domain"); if (!operatorName) throw new Error("[identity.bootstrap] --operator-name is required"); if (!domain) throw new Error("[identity.bootstrap] --domain is required"); const keypair = await generateKeypair(); const keyVersion = "v1"; const operatorDid = `did:web:${domain}#operator-${keyVersion}`; const issuedAt = new Date().toISOString(); const subject: SiteOwnershipCredentialSubject = { id: operatorDid, siteId: domain, role: "owner", }; const proof = await signIdentityCredential( subject, keypair.privateKeyHex, `did:web:${domain}#${keyVersion}`, issuedAt, ); const credentialId = generateCredentialId(); const config: WerkstattIdentityConfig = { schemaVersion: "1.0", operatorName, operatorKeyPair: { publicKeyMultibase: keypair.publicKeyMultibase, keyVersion, algId: "Ed25519Signature2020", }, authMode: "permissive", domain, issuedCredentials: [ { credentialId, type: "SiteOwnershipCredential", subject, proof, issuedAt, issuer: `did:web:${domain}`, }, ], revokedCredentialIds: [], }; await writeIdentityConfig(workspaceRoot, config); return { data: { operatorName, domain, publicKeyMultibase: keypair.publicKeyMultibase, keyVersion, authMode: "permissive", selfOwnershipCredentialId: credentialId, privateKeyHex: keypair.privateKeyHex, }, exitCode: 0, summary: "[identity.bootstrap] keypair generated, self-ownership VC issued", }; }