{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/grant.ts","../src/policy.ts","../src/lease-adapter.ts","../src/postgres-lease-adapter.ts","../src/postgres-secret-backend.ts","../src/provision.ts","../src/secret-store.ts","../src/env-kek-provider.ts","../src/kms-kek-provider.ts","../src/scoped-secret-keyring.ts","../src/resolve-receipt.ts","../src/secrets-manifest.ts","../src/secret-access-policy.ts","../src/secret-resolver.ts","../src/needs-key-trait.ts","../src/vault-bootstrap.ts","../src/service-identity.ts","../src/service-secret-resolver.ts"],"sourcesContent":["/**\n * @holoscript/secrets-broker — Sovereign primitive for AI-surface capability tokens\n *\n * Generalizes the per-brain `HOLOMESH_API_KEY_<HANDLE>_X402` + x402 pattern (S.IDENT,\n * docs/headless-agents.md) into a typed, framework-agnostic contract usable by any\n * AI surface (mobile, desktop, headless, hardware). The broker server holds wallets\n * and long-lived bearers; surfaces present a short-lived, scoped capability token\n * per session.\n *\n * Companion to:\n *   - `/protocol` (HoloScript Protocol economic layer) for commercialization (D.013)\n *   - HoloMesh signing-middleware for signed-attribution coverage (S.IDENT triangle)\n *   - `packages/studio/src/lib/workspace/secretBroker.ts` (workspace-scoped grants;\n *     this package generalizes that pattern to surface-scoped agent bearers)\n *\n * Scope of this scaffold (P5 FOUNDATION first iteration):\n *   - Typed contract for surfaces / handles / capabilities / capability tokens\n *   - Pure (no I/O) capability-token mint + validate + revoke logic\n *   - Device-flow pairing contract (interface only; transport in follow-up task)\n *   - Audit-receipt shape compatible with existing HoloDoor policy emission\n *\n * Out of scope (filed as follow-up tasks):\n *   - HTTP transport / HoloMesh server routes\n *   - Wallet storage / x402 bearer minting against real Anthropic / GitHub\n *   - /protocol on-chain commercialization wiring\n *   - Per-surface UX (mobile paste flow, desktop OAuth)\n *\n * @module @holoscript/secrets-broker\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\n\n// =============================================================================\n// SURFACES & HANDLES\n// =============================================================================\n\n/**\n * Surface kind — drives auto-numbering of handles and capability defaults.\n * Mirrors the per-window handle revamp from `research/2026-04-27_identity-revamp-per-window.md`.\n */\nexport type SurfaceKind =\n  | 'claude'\n  | 'cursor'\n  | 'copilot'\n  | 'gemini'\n  | 'codex'\n  | 'mobile'\n  | 'headless';\n\n/**\n * Surface trust tier — gates which capabilities a surface can request.\n * Mobile defaults to a reduced tier (S-3 / S-4 from mobile-as-seat memo).\n */\nexport type SurfaceTrust = 'full' | 'reduced' | 'read-only';\n\n/**\n * Auto-numbered per-window handle (e.g. `claude1`, `cursor2`, `mobile1`).\n * Naming convention: surface name + small-int slot, NOT editor name.\n */\nexport type Handle = `${SurfaceKind}${number}`;\n\n/**\n * Capability strings — what a capability token can do.\n * Closed set so the broker can enforce policy without inspecting payloads.\n */\nexport type Capability =\n  | 'mesh:read'\n  | 'mesh:message'\n  | 'mesh:claim'\n  | 'mesh:done'\n  | 'mesh:knowledge.write'\n  | 'mesh:suggestion.write'\n  | 'mesh:suggestion.vote'\n  | 'mesh:sign'\n  | 'protocol:lookup'\n  | 'protocol:publish'\n  | 'protocol:collect'\n  | 'github:read'\n  | 'github:pr.comment';\n\n/**\n * Capability set returned for a given surface kind under a trust tier.\n * Pure data table; consumers may override via {@link CapabilityPolicy}.\n */\nexport const DEFAULT_CAPABILITY_BY_TRUST: Record<SurfaceTrust, readonly Capability[]> = {\n  'read-only': ['mesh:read', 'protocol:lookup', 'github:read'],\n  reduced: [\n    'mesh:read',\n    'mesh:message',\n    'mesh:knowledge.write',\n    'mesh:suggestion.vote',\n    'protocol:lookup',\n    'github:read',\n  ],\n  full: [\n    'mesh:read',\n    'mesh:message',\n    'mesh:claim',\n    'mesh:done',\n    'mesh:knowledge.write',\n    'mesh:suggestion.write',\n    'mesh:suggestion.vote',\n    'mesh:sign',\n    'protocol:lookup',\n    'protocol:publish',\n    'protocol:collect',\n    'github:read',\n    'github:pr.comment',\n  ],\n} as const;\n\n/**\n * Per-surface trust defaults. Mobile + headless start at `reduced` per S-3\n * (mobile-as-seat memo) and headless-agents cost discipline.\n */\nexport const DEFAULT_TRUST_BY_SURFACE: Record<SurfaceKind, SurfaceTrust> = {\n  claude: 'full',\n  cursor: 'full',\n  copilot: 'full',\n  gemini: 'full',\n  codex: 'full',\n  mobile: 'reduced',\n  headless: 'reduced',\n} as const;\n\n// =============================================================================\n// CAPABILITY TOKEN MODEL\n// =============================================================================\n\n/**\n * Minted, opaque-from-client capability token.\n * Server holds the underlying bearer / wallet keys; client only ever sees this token.\n *\n * Shape is JSON-stable so it can be serialised to HTTP headers, mobile push payloads,\n * or x402 challenges without renegotiation.\n */\nexport interface CapabilityToken {\n  readonly version: 1;\n  readonly event: 'capability.minted';\n  readonly tokenId: string;\n  readonly handle: Handle;\n  readonly surface: SurfaceKind;\n  readonly trust: SurfaceTrust;\n  readonly capabilities: readonly Capability[];\n  readonly issuedAt: string;\n  readonly expiresAt: string;\n  /** Random opaque secret. Server stores a hash; never log this plaintext. */\n  readonly tokenSecret: string;\n  /** Hash of the canonical token record. */\n  readonly receiptHash: string;\n}\n\n/**\n * Server-side stored shape: same as {@link CapabilityToken} minus the plaintext\n * `tokenSecret`. Stored for revocation + lookup.\n */\nexport type StoredCapabilityToken = Omit<CapabilityToken, 'tokenSecret'> & {\n  readonly tokenSecretHash: string;\n  revokedAt?: string;\n  revokeReason?: string;\n};\n\n/**\n * Input to {@link mintCapabilityToken}.\n */\nexport interface MintInput {\n  handle: Handle;\n  surface: SurfaceKind;\n  /** Override the surface default trust. Cannot exceed `full`. */\n  trust?: SurfaceTrust;\n  /** Subset of capabilities to grant. Must be a subset of the trust tier's defaults. */\n  capabilities?: readonly Capability[];\n  /** TTL in seconds. Clamped to [{@link MIN_TTL_SECONDS}, {@link MAX_TTL_SECONDS}]. */\n  ttlSeconds?: number;\n  /** Inject a deterministic clock + RNG for testing. */\n  now?: Date;\n  randomBytes?: (size: number) => Buffer;\n}\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\nexport const MIN_TTL_SECONDS = 60;\n/** 1 hour upper bound — short-lived per S-7 memo. */\nexport const MAX_TTL_SECONDS = 60 * 60;\n/** Default TTL when caller doesn't specify one. */\nexport const DEFAULT_TTL_SECONDS = 15 * 60;\n\n// =============================================================================\n// ERRORS\n// =============================================================================\n\nexport type CapabilityTokenErrorCode =\n  | 'INVALID_HANDLE'\n  | 'TRUST_NOT_ALLOWED'\n  | 'CAPABILITY_NOT_IN_TRUST_TIER'\n  | 'TTL_OUT_OF_RANGE'\n  | 'TOKEN_REVOKED'\n  | 'TOKEN_EXPIRED'\n  | 'TOKEN_INVALID_SECRET';\n\nexport class CapabilityTokenError extends Error {\n  constructor(\n    message: string,\n    public readonly code: CapabilityTokenErrorCode\n  ) {\n    super(message);\n    this.name = 'CapabilityTokenError';\n  }\n}\n\n// =============================================================================\n// PURE HELPERS\n// =============================================================================\n\nconst HANDLE_RE = /^(claude|cursor|copilot|gemini|codex|mobile|headless)(\\d+)$/;\n\n/**\n * Parse a handle string into {surface, slot}. Returns null on malformed input.\n */\nexport function parseHandle(handle: string): { surface: SurfaceKind; slot: number } | null {\n  const m = HANDLE_RE.exec(handle);\n  if (!m) return null;\n  return { surface: m[1] as SurfaceKind, slot: Number(m[2]) };\n}\n\n/**\n * Assert a handle is well-formed and matches the claimed surface. Throws otherwise.\n */\nexport function assertHandle(handle: string, surface: SurfaceKind): asserts handle is Handle {\n  const parsed = parseHandle(handle);\n  if (!parsed) {\n    throw new CapabilityTokenError(`Malformed handle: ${handle}`, 'INVALID_HANDLE');\n  }\n  if (parsed.surface !== surface) {\n    throw new CapabilityTokenError(\n      `Handle ${handle} does not match surface ${surface}`,\n      'INVALID_HANDLE'\n    );\n  }\n}\n\nfunction clampTtl(seconds: number | undefined): number {\n  if (seconds === undefined) return DEFAULT_TTL_SECONDS;\n  if (!Number.isFinite(seconds)) {\n    throw new CapabilityTokenError(`Non-finite ttlSeconds: ${seconds}`, 'TTL_OUT_OF_RANGE');\n  }\n  const floored = Math.floor(seconds);\n  if (floored < MIN_TTL_SECONDS || floored > MAX_TTL_SECONDS) {\n    throw new CapabilityTokenError(\n      `ttlSeconds ${floored} outside [${MIN_TTL_SECONDS}, ${MAX_TTL_SECONDS}]`,\n      'TTL_OUT_OF_RANGE'\n    );\n  }\n  return floored;\n}\n\nfunction canonicalHash(value: unknown): string {\n  return `sha256:${createHash('sha256').update(JSON.stringify(value)).digest('hex')}`;\n}\n\n// =============================================================================\n// CORE: MINT / VALIDATE / REVOKE\n// =============================================================================\n\n/**\n * Mint a fresh capability token for a surface handle.\n *\n * Pure: caller injects {@link MintInput.now} and {@link MintInput.randomBytes} for\n * determinism. No I/O. Throws {@link CapabilityTokenError} on policy violations.\n */\nexport function mintCapabilityToken(input: MintInput): CapabilityToken {\n  assertHandle(input.handle, input.surface);\n\n  const surfaceDefault = DEFAULT_TRUST_BY_SURFACE[input.surface];\n  const trust = input.trust ?? surfaceDefault;\n\n  // A surface cannot escalate above its default trust tier (e.g. mobile cannot ask for full).\n  const trustRank: Record<SurfaceTrust, number> = { 'read-only': 0, reduced: 1, full: 2 };\n  if (trustRank[trust] > trustRank[surfaceDefault]) {\n    throw new CapabilityTokenError(\n      `Surface ${input.surface} cannot request trust=${trust} (max=${surfaceDefault})`,\n      'TRUST_NOT_ALLOWED'\n    );\n  }\n\n  const allowed = DEFAULT_CAPABILITY_BY_TRUST[trust];\n  const requested = input.capabilities ?? allowed;\n  for (const cap of requested) {\n    if (!allowed.includes(cap)) {\n      throw new CapabilityTokenError(\n        `Capability ${cap} not in trust tier ${trust}`,\n        'CAPABILITY_NOT_IN_TRUST_TIER'\n      );\n    }\n  }\n\n  const ttl = clampTtl(input.ttlSeconds);\n  const issuedAtDate = input.now ?? new Date();\n  const issuedAt = issuedAtDate.toISOString();\n  const expiresAt = new Date(issuedAtDate.getTime() + ttl * 1000).toISOString();\n\n  const rng = input.randomBytes ?? randomBytes;\n  // 32 bytes = 256 bits of entropy; hex-encoded for transport.\n  const tokenSecret = rng(32).toString('hex');\n\n  const tokenIdSeed = `${input.handle}|${input.surface}|${issuedAt}|${tokenSecret}`;\n  const tokenId = `captok_${createHash('sha256').update(tokenIdSeed).digest('hex').slice(0, 24)}`;\n\n  const unsigned: Omit<CapabilityToken, 'receiptHash' | 'tokenSecret'> = {\n    version: 1,\n    event: 'capability.minted',\n    tokenId,\n    handle: input.handle,\n    surface: input.surface,\n    trust,\n    capabilities: Object.freeze([...requested]),\n    issuedAt,\n    expiresAt,\n  };\n\n  return Object.freeze({\n    ...unsigned,\n    tokenSecret,\n    receiptHash: canonicalHash({ ...unsigned, tokenSecret }),\n  });\n}\n\n/**\n * Convert a minted {@link CapabilityToken} into the server-side {@link StoredCapabilityToken}\n * shape. Strips plaintext `tokenSecret`, hashes it for later verification.\n */\nexport function storeCapabilityToken(token: CapabilityToken): StoredCapabilityToken {\n  const { tokenSecret, ...rest } = token;\n  return Object.freeze({\n    ...rest,\n    tokenSecretHash: `sha256:${createHash('sha256').update(tokenSecret).digest('hex')}`,\n  });\n}\n\nexport interface ValidateInput {\n  presentedSecret: string;\n  stored: StoredCapabilityToken;\n  /** Capability the caller wants to exercise. Must be in stored.capabilities. */\n  needsCapability: Capability;\n  /** Inject a deterministic clock for testing. */\n  now?: Date;\n}\n\n/**\n * Validate a presented capability token against its stored record.\n *\n * Returns `true` only when ALL of:\n *  - not revoked\n *  - not expired (vs `now`)\n *  - presented secret hashes to the stored hash\n *  - `needsCapability` is in the token's granted capability set\n *\n * Throws {@link CapabilityTokenError} on first failure; never returns false (G.GOLD.013:\n * computed-truth assertions need the false-case test, which lives in `index.test.ts`).\n */\nexport function validateCapabilityToken(input: ValidateInput): true {\n  const nowDate = input.now ?? new Date();\n\n  if (input.stored.revokedAt) {\n    throw new CapabilityTokenError(\n      `Token ${input.stored.tokenId} revoked: ${input.stored.revokeReason ?? 'no reason'}`,\n      'TOKEN_REVOKED'\n    );\n  }\n\n  if (new Date(input.stored.expiresAt).getTime() <= nowDate.getTime()) {\n    throw new CapabilityTokenError(\n      `Token ${input.stored.tokenId} expired at ${input.stored.expiresAt}`,\n      'TOKEN_EXPIRED'\n    );\n  }\n\n  const presentedHash = `sha256:${createHash('sha256').update(input.presentedSecret).digest('hex')}`;\n  if (presentedHash !== input.stored.tokenSecretHash) {\n    throw new CapabilityTokenError(\n      `Token ${input.stored.tokenId} secret mismatch`,\n      'TOKEN_INVALID_SECRET'\n    );\n  }\n\n  if (!input.stored.capabilities.includes(input.needsCapability)) {\n    throw new CapabilityTokenError(\n      `Token ${input.stored.tokenId} does not grant ${input.needsCapability}`,\n      'CAPABILITY_NOT_IN_TRUST_TIER'\n    );\n  }\n\n  return true;\n}\n\n/**\n * Mark a stored token as revoked. Returns a new frozen object; does not mutate input.\n */\nexport function revokeCapabilityToken(\n  stored: StoredCapabilityToken,\n  reason: string,\n  now: Date = new Date()\n): StoredCapabilityToken {\n  return Object.freeze({\n    ...stored,\n    revokedAt: now.toISOString(),\n    revokeReason: reason,\n  });\n}\n\n// =============================================================================\n// DEVICE-FLOW PAIRING CONTRACT\n// =============================================================================\n\n/**\n * Stage-1 of device-flow: server issues a short user-code + opaque device-code.\n * Surface shows the user-code to the operator; operator visits the verification URL\n * on a paired desktop, confirms identity, and the server resolves the device-code\n * to a minted capability token.\n *\n * This package defines the CONTRACT only — transport + UI are deferred to follow-up\n * tasks (`packages/mcp-server/holomesh/routes/secrets-broker-routes.ts` plus a Studio\n * verify page).\n */\nexport interface DeviceFlowChallenge {\n  readonly version: 1;\n  readonly event: 'device-flow.challenge';\n  readonly deviceCode: string;\n  readonly userCode: string;\n  readonly verificationUri: string;\n  readonly expiresAt: string;\n  readonly intervalSeconds: number;\n  readonly receiptHash: string;\n}\n\nexport interface CreateDeviceFlowChallengeInput {\n  verificationUri: string;\n  /** TTL of the device-code itself; user-code expires together. */\n  ttlSeconds?: number;\n  /** Polling interval the surface should respect. Defaults to 5s. */\n  intervalSeconds?: number;\n  now?: Date;\n  randomBytes?: (size: number) => Buffer;\n}\n\n/**\n * Mint a device-flow challenge. Pure; transport-agnostic.\n */\nexport function createDeviceFlowChallenge(\n  input: CreateDeviceFlowChallengeInput\n): DeviceFlowChallenge {\n  const ttl = clampTtl(input.ttlSeconds ?? 10 * 60);\n  const interval = input.intervalSeconds ?? 5;\n  if (interval < 1 || interval > 60 || !Number.isFinite(interval)) {\n    throw new CapabilityTokenError(\n      `intervalSeconds ${interval} outside [1, 60]`,\n      'TTL_OUT_OF_RANGE'\n    );\n  }\n\n  const rng = input.randomBytes ?? randomBytes;\n  const deviceCode = rng(24).toString('hex');\n  // 8-char user-code, alphabet excludes ambiguous chars (0/O/1/I/L).\n  const alphabet = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789';\n  const userBuf = rng(8);\n  let userCode = '';\n  for (let i = 0; i < 8; i++) {\n    userCode += alphabet[userBuf[i] % alphabet.length];\n  }\n  // Hyphenate for human readability: ABCD-EFGH\n  userCode = `${userCode.slice(0, 4)}-${userCode.slice(4)}`;\n\n  const issuedAt = input.now ?? new Date();\n  const expiresAt = new Date(issuedAt.getTime() + ttl * 1000).toISOString();\n\n  const unsigned: Omit<DeviceFlowChallenge, 'receiptHash'> = {\n    version: 1,\n    event: 'device-flow.challenge',\n    deviceCode,\n    userCode,\n    verificationUri: input.verificationUri,\n    expiresAt,\n    intervalSeconds: interval,\n  };\n\n  return Object.freeze({\n    ...unsigned,\n    receiptHash: canonicalHash(unsigned),\n  });\n}\n\n// =============================================================================\n// CAPABILITY TOKEN REGISTRY\n// =============================================================================\n\n/**\n * In-memory store for {@link StoredCapabilityToken}, keyed on `tokenId`.\n *\n * Composes the existing pure mint / validate / revoke functions into a usable\n * server-side surface: a route handler can `put` a stored token after minting,\n * later `get` it by id from a presented capability-token header, and `revoke`\n * it when the owning seat retires or a compromise is detected.\n *\n * Phase 1 storage is in-memory only — the registry is rebuilt on server boot\n * from a persistence layer when that ships (mirrors the AttestationRegistry\n * Phase-1 pattern at `packages/mcp-server/src/holomesh/identity/attestation-registry.ts`).\n *\n * No automatic expiry sweep: callers either let {@link validateCapabilityToken}\n * reject expired tokens at validate-time (cheap, lazy), or call\n * {@link CapabilityTokenRegistry.pruneExpired} on a timer.\n *\n * @see mintCapabilityToken\n * @see storeCapabilityToken\n * @see validateCapabilityToken\n * @see revokeCapabilityToken\n */\nexport class CapabilityTokenRegistry {\n  private readonly byId = new Map<string, StoredCapabilityToken>();\n\n  /**\n   * Add or replace a stored token. Replacement is idempotent on identical\n   * input; callers re-storing a revoked token (e.g. on resurrection during\n   * key rotation) should explicitly mint a fresh token instead.\n   */\n  put(stored: StoredCapabilityToken): void {\n    if (!stored.tokenId) throw new CapabilityTokenError('put: tokenId required', 'INVALID_HANDLE');\n    this.byId.set(stored.tokenId, stored);\n  }\n\n  /** Look up a stored token by id. Returns `undefined` when not found. */\n  get(tokenId: string): StoredCapabilityToken | undefined {\n    return this.byId.get(tokenId);\n  }\n\n  /** True iff the registry holds a token under this id (regardless of revoked/expired state). */\n  has(tokenId: string): boolean {\n    return this.byId.has(tokenId);\n  }\n\n  /**\n   * Revoke the stored token under `tokenId`. Returns the new (revoked) record\n   * or `null` if no token exists under that id. Idempotent on already-revoked\n   * tokens — re-revoking returns the existing revoked record without overwriting\n   * the original `revokedAt` / `revokeReason`.\n   */\n  revoke(tokenId: string, reason: string, now: Date = new Date()): StoredCapabilityToken | null {\n    const existing = this.byId.get(tokenId);\n    if (!existing) return null;\n    if (existing.revokedAt) return existing;\n    const revoked = revokeCapabilityToken(existing, reason, now);\n    this.byId.set(tokenId, revoked);\n    return revoked;\n  }\n\n  /** Number of stored tokens (active + revoked + expired). */\n  size(): number {\n    return this.byId.size;\n  }\n\n  /** Snapshot of all stored tokens. Returned array is independent of internal state. */\n  list(): readonly StoredCapabilityToken[] {\n    return Array.from(this.byId.values());\n  }\n\n  /**\n   * Drop expired tokens from the registry. Returns the count removed.\n   * Callers can run this on a timer to bound memory; not running it is fine —\n   * {@link validateCapabilityToken} rejects expired tokens lazily.\n   */\n  pruneExpired(now: Date = new Date()): number {\n    const cutoff = now.getTime();\n    let removed = 0;\n    for (const [id, t] of this.byId) {\n      if (new Date(t.expiresAt).getTime() <= cutoff) {\n        this.byId.delete(id);\n        removed += 1;\n      }\n    }\n    return removed;\n  }\n\n  /**\n   * Convenience: combine {@link get} + {@link validateCapabilityToken} into a\n   * single call. The caller presents a token id + plaintext secret + the\n   * capability they want to exercise; returns `true` on full success or\n   * throws {@link CapabilityTokenError} otherwise.\n   *\n   * Returns `true` only — never `false` — matching the existing validator\n   * contract. Use this in HTTP route handlers wrapping mutating operations.\n   */\n  validateById(\n    tokenId: string,\n    presentedSecret: string,\n    needsCapability: Capability,\n    now: Date = new Date()\n  ): true {\n    const stored = this.byId.get(tokenId);\n    if (!stored) {\n      throw new CapabilityTokenError(`Token ${tokenId} not found`, 'TOKEN_INVALID_SECRET');\n    }\n    return validateCapabilityToken({ presentedSecret, stored, needsCapability, now });\n  }\n\n  /** Test-only: drop all entries. */\n  clear(): void {\n    this.byId.clear();\n  }\n}\n\n// =============================================================================\n// SECRET GRANT PRIMITIVES (extracted from Studio, generalized for core)\n// =============================================================================\n\nexport * from './types';\nexport { createSecretGrant, checkSecretGrantPolicy, createPolicyGatedSecretGrant } from './grant';\nexport { allowOnly, denyAll, allowAgentForRef, fromHoloDoorPolicy } from './policy';\nexport { createMemoryLeaseAdapter, createNoOpLeaseAdapter } from './lease-adapter';\nexport {\n  createPostgresLeaseAdapter,\n  SECRET_LEASES_DDL,\n  type LeaseQueryRunner,\n  type PostgresLeaseAdapterDeps,\n} from './postgres-lease-adapter';\nexport {\n  createPostgresSecretBackend,\n  type SecretQueryRunner,\n  type PostgresSecretBackendDeps,\n} from './postgres-secret-backend';\nexport { provisionBrokeredSession, localFileProvisionAdapter } from './provision';\nexport {\n  createSecretStore,\n  createInMemorySecretBackend,\n  SECRET_STORE_DDL,\n  OwnerMismatchError,\n  SecretNotFoundError,\n  DecryptError,\n  InsecureKekError,\n  type SecretStore,\n  type SecretStoreDeps,\n  type SecretStoreBackend,\n  type KekProvider,\n  type SecretRow,\n  type PutInput,\n  type PutResult,\n  type GetInput,\n  type GetResult,\n  type SecretMetadata,\n  type RotateKekInput,\n  type RotateKekResult,\n} from './secret-store';\nexport {\n  createEnvKekProvider,\n  generateKekBase64,\n  kekEnvVar,\n  KEK_CURRENT_ENV,\n  EnvKekConfigError,\n  type EnvKekProviderDeps,\n} from './env-kek-provider';\nexport {\n  createKmsKekProvider,\n  KmsKekError,\n  type KmsKeyring,\n  type KmsKekProviderDeps,\n} from './kms-kek-provider';\nexport {\n  createScopedSecretKeyring,\n  ScopedSecretKeyringError,\n  type ScopedSecretKeyringDeps,\n} from './scoped-secret-keyring';\nexport {\n  sealResolveReceipt,\n  verifyResolveReceiptChain,\n  type SecretResolveReceipt,\n} from './resolve-receipt';\nexport {\n  compileSecretsManifest,\n  SecretsManifestError,\n  type SecretDecl,\n  type SecretsManifest,\n  type SecretsCompileTarget,\n} from './secrets-manifest';\nexport {\n  createSecretResolver,\n  AuthRequiredError,\n  type SecretResolver,\n  type SecretResolverDeps,\n  type ResolveInput,\n  type SecretResolveAudit,\n} from './secret-resolver';\nexport {\n  checkSecretAccess,\n  PolicyDeniedError,\n  type SecretAccessPolicy,\n  type SecretAccessDecision,\n} from './secret-access-policy';\nexport {\n  createNeedsKeyHandler,\n  registerNeedsKeyTrait,\n  type NeedsKeyConfig,\n  type NeedsKeyResolution,\n  type NeedsKeyDispatchContext,\n  type NeedsKeyTraitHandler,\n} from './needs-key-trait';\nexport {\n  createHoloKeyVault,\n  PROD_KEK_CURRENT_ENV,\n  type HoloKeyVault,\n  type CreateHoloKeyVaultOpts,\n} from './vault-bootstrap';\nexport {\n  createServiceSecretResolver,\n  type ServiceSecretResolver,\n  type ServiceSecretResolverOpts,\n} from './service-secret-resolver';\nexport {\n  resolveServiceIdentity,\n  normalizeServiceSecretRef,\n  infraSecretRef,\n  type ServiceIdentity,\n  type ServiceIdentitySource,\n  type ResolveServiceIdentityOpts,\n  type NormalizedServiceSecretRef,\n} from './service-identity';\n","/**\n * Core types for the HoloScript Secrets Broker.\n *\n * A secrets broker issues short-lived, scope-bounded capability receipts\n * (\"handles\") instead of exposing secret material. Any AI surface — mobile,\n * desktop, headless — receives a handle valid for one session or task.\n *\n * Design principles:\n *   1. Handles-only: the broker never returns plaintext in-band.\n *   2. Scope-bounded: each grant lists exact secret refs the agent may resolve.\n *   3. Time-bounded: TTL enforces session-scoped, not long-lived, credentials.\n *   4. Policy-gated: HoloDoor (or equivalent) checks every issuance.\n *   5. Audit-heavy: every grant, resolve, and revocation emits a signed receipt.\n *\n * @module secrets-broker/types\n */\n\n/** A canonical reference to a secret. Format: `<surface>:<key>` or URI-style infra refs.\n *  Surface may be `env`, `x402`, `custodial`, `gold`, `vault`, or `infra`.\n *  The string is the audit-safe label — NEVER the value. */\nexport type SecretRef = string;\n\n/** A canonical capability reference. Format: `cap://<domain>/<capability>`.\n *  Only `cap://daemon/secrets/*` capabilities are accepted for brokered grants. */\nexport type CapabilityRef = string;\n\n/** Policy outcome from the gatekeeper (HoloDoor or adapter). */\nexport type PolicyOutcome = 'allow' | 'warn' | 'block';\n\n/** Issuance parameters for a brokered secret grant. */\nexport interface SecretGrantInput {\n  /** Namespace that scopes the secretRef (workspace, team, project, etc.). */\n  namespaceId: string;\n  /** Registered agent identity (x402 seat, HoloMesh agentId, etc.). */\n  agentId: string;\n  /** Canonical secret reference the agent needs access to. */\n  secretRef: SecretRef;\n  /** Capability the agent claims it needs (must be `cap://daemon/secrets/*`). */\n  capabilityRef: CapabilityRef;\n  /** Human-readable purpose for audit and compliance. */\n  purpose: string;\n  /** TTL in seconds (default 15 min, max 1 h). */\n  ttlSeconds?: number;\n  /** Optional fixed clock for deterministic tests. */\n  now?: Date;\n  /** If the grant was pre-checked by a policy gate, record the decision id. */\n  policyDecisionId?: string;\n  /** If the grant was pre-checked, record the outcome. */\n  policyOutcome?: PolicyOutcome;\n}\n\n/** Immutable receipt issued when a secret grant succeeds.\n *  Contains ZERO secret material — only handles, hashes, and audit metadata. */\nexport interface SecretGrantReceipt {\n  version: 1;\n  event: 'secret.granted';\n  /** Deterministic grant id. */\n  grantId: string;\n  namespaceId: string;\n  agentId: string;\n  /** Convenience alias matching agentId. */\n  agent: string;\n  /** The canonical secret handle. */\n  secretRef: SecretRef;\n  /** Convenience alias matching secretRef. */\n  ref: SecretRef;\n  capabilityRef: CapabilityRef;\n  purpose: string;\n  issuedAt: string;\n  expiresAt: string;\n  /** Always `brokered-handle` — plaintext is NEVER returned in-band. */\n  accessMode: 'brokered-handle';\n  plaintextReturned: false;\n  /** HoloDoor decision id that gated this grant, if any. */\n  policyDecisionId: string | null;\n  /** HoloDoor outcome, if any. */\n  policyOutcome: Exclude<PolicyOutcome, 'block'> | null;\n  /** SHA-256 over the canonical JSON of this receipt (minus receiptHash). */\n  receiptHash: string;\n  auditTags: string[];\n}\n\n/** Policy configuration enforced before a grant is issued. */\nexport interface SecretGrantPolicyConfig {\n  allowedSecretRefPrefixes?: string[];\n  blockedSecretRefPrefixes?: string[];\n  allowedCapabilityRefs?: string[];\n  blockedCapabilityRefs?: string[];\n  allowedAgentIds?: string[];\n  blockedAgentIds?: string[];\n  maxTtlSeconds?: number;\n  requirePurpose?: boolean;\n}\n\n/** Structured policy gate definition consumed by the broker. */\nexport interface SecretBrokerPolicy {\n  secretGrants?: SecretGrantPolicyConfig;\n  enforcement?: {\n    onViolation?: 'warn' | 'block';\n  };\n}\n\n/** Result of a policy check before issuance. */\nexport interface PolicyDecision {\n  version: 1;\n  event: 'holodoor.policy.checked';\n  decisionId: string;\n  outcome: PolicyOutcome;\n  reasons: string[];\n  namespaceId: string;\n  agentId: string;\n  secretRef: SecretRef;\n  capabilityRef: CapabilityRef;\n  requestedTtlSeconds: number;\n  effectiveTtlSeconds: number;\n  checkedAt: string;\n  plaintextReturned: false;\n  receiptHash: string;\n  auditTags: string[];\n}\n\n/** Combined result when a grant is gated by policy. */\nexport interface PolicyGatedGrant {\n  policyDecision: PolicyDecision;\n  grant: SecretGrantReceipt;\n}\n\n/** Error thrown when policy blocks a grant. */\nexport class SecretGrantPolicyError extends Error {\n  readonly decision: PolicyDecision;\n  constructor(decision: PolicyDecision) {\n    super('Policy gate blocked this secret grant request');\n    this.name = 'SecretGrantPolicyError';\n    this.decision = decision;\n  }\n}\n\n/** A handle entry in the broker manifest. */\nexport interface BrokerSecretHandle {\n  name: string;\n  ref: SecretRef;\n  usedBy: string[];\n  access: 'broker-only';\n}\n\n/** Manifest that maps human-readable names to scoped secret refs. */\nexport interface BrokerManifest {\n  version: 1;\n  namespaceId: string;\n  storage: 'server-side' | 'github-actions-secret' | 'env-file' | 'vault';\n  plaintextInNamespace: false;\n  handlesOnly: true;\n  handles: BrokerSecretHandle[];\n  grantEndpoint: string;\n  brokerCapabilities: CapabilityRef[];\n}\n\n/** Lease adapter interface — the broker never holds leases itself;\n *  it delegates to a vault-lease registry (e.g. HoloMesh vault-lease-registry). */\nexport interface LeaseAdapter {\n  /** Issue a lease scoped to the given task and agent. */\n  issueLease(params: {\n    taskId: string;\n    agentId: string;\n    scope: SecretRef[];\n    durationMs?: number;\n  }): Promise<{ leaseId: string; expiresAt: string }>;\n\n  /** Resolve whether the lease permits reading `secretRef`. Returns boolean;\n   *  the actual value is fetched by a separate secret-store adapter. */\n  resolveLease(params: {\n    leaseId: string;\n    agentId: string;\n    secretRef: SecretRef;\n  }): Promise<{ ok: boolean; reason?: string }>;\n\n  /** Revoke a lease early (task done, agent compromise, rotation, etc.). */\n  revokeLease(params: { leaseId: string; reason: string; by: string }): Promise<{ ok: boolean }>;\n}\n\n/** Device-flow provisioning result for a new AI surface. */\nexport interface DeviceFlowProvisionResult {\n  status: 'executed' | 'reused';\n  handle: string;\n  surface: string;\n  seatId: string;\n  walletAddress: string;\n  bearer?: string;\n  agentId?: string;\n  envVarLines: string[];\n}\n","/**\n * Secret grant issuance — handles-only, deterministic, audit-heavy.\n *\n * Extracted from `@holoscript/studio/src/lib/workspace/secretBroker.ts`\n * and generalized into a sovereign primitive so any package or service\n * can issue brokered grants without depending on Studio internals.\n *\n * @module secrets-broker/grant\n */\n\nimport { createHash } from 'crypto';\nimport {\n  type SecretGrantInput,\n  type SecretGrantReceipt,\n  type SecretBrokerPolicy,\n  type PolicyDecision,\n  type PolicyGatedGrant,\n  SecretGrantPolicyError,\n} from './types';\n\nexport { SecretGrantPolicyError };\n\nconst MIN_TTL_SECONDS = 60;\nconst MAX_TTL_SECONDS = 60 * 60;\n\nfunction normalizeRequired(value: string, field: string): string {\n  const normalized = value.trim();\n  if (!normalized) throw new Error(`${field} is required`);\n  if (/[\\r\\n]/.test(normalized)) throw new Error(`${field} must be single-line`);\n  return normalized;\n}\n\nfunction ttlSeconds(value: number | undefined): number {\n  if (value === undefined) return 15 * 60;\n  if (!Number.isFinite(value)) return 15 * 60;\n  return Math.min(MAX_TTL_SECONDS, Math.max(MIN_TTL_SECONDS, Math.floor(value)));\n}\n\nfunction assertNamespaceSecret(namespaceId: string, secretRef: string): void {\n  const prefix = `secret://namespace/${namespaceId}/`;\n  if (!secretRef.startsWith(prefix)) {\n    throw new Error('secretRef must be a secret:// handle scoped to the namespace');\n  }\n}\n\nfunction assertCapability(capabilityRef: string): void {\n  if (!capabilityRef.startsWith('cap://daemon/secrets/')) {\n    throw new Error('capabilityRef must be a daemon secret capability');\n  }\n}\n\nfunction hashReceipt(value: Omit<SecretGrantReceipt, 'receiptHash'>): string {\n  const canonical = JSON.stringify(value);\n  return `sha256:${createHash('sha256').update(canonical).digest('hex')}`;\n}\n\nfunction hashPolicyDecision(value: Omit<PolicyDecision, 'receiptHash'>): string {\n  const canonical = JSON.stringify(value);\n  return `sha256:${createHash('sha256').update(canonical).digest('hex')}`;\n}\n\nfunction list(value: string[] | undefined): string[] {\n  return Array.isArray(value)\n    ? value.filter((item): boolean => typeof item === 'string' && item.length > 0)\n    : [];\n}\n\nfunction hasPrefix(value: string, prefixes: string[]): boolean {\n  return prefixes.some((prefix) => value.startsWith(prefix));\n}\n\nfunction includes(value: string, entries: string[]): boolean {\n  return entries.includes(value);\n}\n\nfunction policyMaxTtl(value: number | undefined): number {\n  if (value === undefined || !Number.isFinite(value)) return MAX_TTL_SECONDS;\n  return Math.min(MAX_TTL_SECONDS, Math.max(MIN_TTL_SECONDS, Math.floor(value)));\n}\n\n/**\n * Check a grant request against a policy gate without issuing the grant.\n * Returns a `PolicyDecision` that can be stored, audited, and later passed\n * to `createSecretGrant` via `policyDecisionId` / `policyOutcome`.\n */\nexport function checkSecretGrantPolicy(\n  input: SecretGrantInput,\n  policy: SecretBrokerPolicy = {}\n): PolicyDecision {\n  const namespaceId = normalizeRequired(input.namespaceId, 'namespaceId');\n  const agentId = normalizeRequired(input.agentId, 'agentId');\n  const secretRef = normalizeRequired(input.secretRef, 'secretRef');\n  const capabilityRef = normalizeRequired(input.capabilityRef, 'capabilityRef');\n  normalizeRequired(input.purpose, 'purpose');\n\n  const secretPolicy = policy.secretGrants ?? {};\n  const onViolation = policy.enforcement?.onViolation === 'block' ? 'block' : 'warn';\n  const reasons: string[] = [];\n  let outcome: 'allow' | 'warn' | 'block' = 'allow';\n\n  const requestedTtlSeconds = ttlSeconds(input.ttlSeconds);\n  const maxTtlSeconds = policyMaxTtl(secretPolicy.maxTtlSeconds);\n  const effectiveTtlSeconds = Math.min(requestedTtlSeconds, maxTtlSeconds);\n\n  const allowedSecretRefPrefixes = list(secretPolicy.allowedSecretRefPrefixes);\n  const blockedSecretRefPrefixes = list(secretPolicy.blockedSecretRefPrefixes);\n  const allowedCapabilityRefs = list(secretPolicy.allowedCapabilityRefs);\n  const blockedCapabilityRefs = list(secretPolicy.blockedCapabilityRefs);\n  const allowedAgentIds = list(secretPolicy.allowedAgentIds);\n  const blockedAgentIds = list(secretPolicy.blockedAgentIds);\n\n  function registerViolation(reason: string, hardBlock = false): void {\n    reasons.push(reason);\n    if (hardBlock || onViolation === 'block') {\n      outcome = 'block';\n    } else if (outcome === 'allow') {\n      outcome = 'warn';\n    }\n  }\n\n  if (includes(agentId, blockedAgentIds)) registerViolation('agent_blocked', true);\n  if (blockedSecretRefPrefixes.length > 0 && hasPrefix(secretRef, blockedSecretRefPrefixes)) {\n    registerViolation('secret_ref_blocked', true);\n  }\n  if (includes(capabilityRef, blockedCapabilityRefs)) registerViolation('capability_blocked', true);\n\n  const defaultSecretPrefix = `secret://namespace/${namespaceId}/`;\n  const effectiveAllowedPrefixes =\n    allowedSecretRefPrefixes.length > 0 ? allowedSecretRefPrefixes : [defaultSecretPrefix];\n  if (!hasPrefix(secretRef, effectiveAllowedPrefixes)) registerViolation('secret_ref_not_allowed');\n  if (allowedCapabilityRefs.length > 0 && !includes(capabilityRef, allowedCapabilityRefs)) {\n    registerViolation('capability_not_allowed');\n  }\n  if (allowedAgentIds.length > 0 && !includes(agentId, allowedAgentIds)) {\n    registerViolation('agent_not_allowed');\n  }\n  if (requestedTtlSeconds > effectiveTtlSeconds) {\n    reasons.push('ttl_clamped_to_policy');\n    if (outcome === 'allow') outcome = 'warn';\n  }\n\n  const checkedAtDate = input.now ?? new Date();\n  const checkedAt = checkedAtDate.toISOString();\n  const decisionSeed = [\n    namespaceId,\n    agentId,\n    secretRef,\n    capabilityRef,\n    requestedTtlSeconds,\n    effectiveTtlSeconds,\n    checkedAt,\n    outcome,\n  ].join('|');\n\n  const unsigned: Omit<PolicyDecision, 'receiptHash'> = {\n    version: 1,\n    event: 'holodoor.policy.checked',\n    decisionId: `hdoor_${createHash('sha256').update(decisionSeed).digest('hex').slice(0, 24)}`,\n    outcome,\n    reasons,\n    namespaceId,\n    agentId,\n    secretRef,\n    capabilityRef,\n    requestedTtlSeconds,\n    effectiveTtlSeconds,\n    checkedAt,\n    plaintextReturned: false,\n    auditTags: ['holodoor', 'policy-checked', 'secret-grant'],\n  };\n\n  return {\n    ...unsigned,\n    receiptHash: hashPolicyDecision(unsigned),\n  };\n}\n\n/**\n * Issue a brokered secret grant receipt. NEVER returns the plaintext value.\n * The receipt is deterministic and self-hashing — any party can verify it\n * was issued by a broker that checked the namespace scope and capability.\n */\nexport function createSecretGrant(input: SecretGrantInput): SecretGrantReceipt {\n  const namespaceId = normalizeRequired(input.namespaceId, 'namespaceId');\n  const agentId = normalizeRequired(input.agentId, 'agentId');\n  const secretRef = normalizeRequired(input.secretRef, 'secretRef');\n  const capabilityRef = normalizeRequired(input.capabilityRef, 'capabilityRef');\n  const purpose = normalizeRequired(input.purpose, 'purpose');\n  assertNamespaceSecret(namespaceId, secretRef);\n  assertCapability(capabilityRef);\n\n  const issuedAtDate = input.now ?? new Date();\n  const expiresAtDate = new Date(issuedAtDate.getTime() + ttlSeconds(input.ttlSeconds) * 1000);\n  const issuedAt = issuedAtDate.toISOString();\n  const expiresAt = expiresAtDate.toISOString();\n  const grantSeed = [namespaceId, agentId, secretRef, capabilityRef, purpose, issuedAt].join('|');\n  const grantId = `sgrant_${createHash('sha256').update(grantSeed).digest('hex').slice(0, 24)}`;\n\n  const unsigned: Omit<SecretGrantReceipt, 'receiptHash'> = {\n    version: 1,\n    event: 'secret.granted',\n    grantId,\n    namespaceId,\n    agentId,\n    agent: agentId,\n    secretRef,\n    ref: secretRef,\n    capabilityRef,\n    purpose,\n    issuedAt,\n    expiresAt,\n    accessMode: 'brokered-handle',\n    plaintextReturned: false,\n    policyDecisionId: input.policyDecisionId ?? null,\n    policyOutcome:\n      input.policyOutcome === 'allow' || input.policyOutcome === 'warn'\n        ? input.policyOutcome\n        : null,\n    auditTags: [\n      'agent-secret-grant',\n      'handles-only',\n      'no-plaintext',\n      ...(input.policyDecisionId ? ['holodoor-policy-checked'] : []),\n    ],\n  };\n\n  return {\n    ...unsigned,\n    receiptHash: hashReceipt(unsigned),\n  };\n}\n\n/**\n * Policy-gated convenience wrapper: check policy, then issue grant.\n * Throws `SecretGrantPolicyError` when the policy outcome is `block`.\n */\nexport function createPolicyGatedSecretGrant(\n  input: SecretGrantInput,\n  policy: SecretBrokerPolicy = {}\n): PolicyGatedGrant {\n  const policyDecision = checkSecretGrantPolicy(input, policy);\n  if (policyDecision.outcome === 'block') {\n    throw new SecretGrantPolicyError(policyDecision);\n  }\n\n  const grant = createSecretGrant({\n    ...input,\n    ttlSeconds: policyDecision.effectiveTtlSeconds,\n    now: new Date(policyDecision.checkedAt),\n    policyDecisionId: policyDecision.decisionId,\n    policyOutcome: policyDecision.outcome,\n  });\n\n  return { policyDecision, grant };\n}\n","/**\n * Policy gate helpers for the secrets broker.\n *\n * The canonical policy check lives in `grant.ts` (`checkSecretGrantPolicy`).\n * This module exports convenience builders for common policy shapes.\n *\n * @module secrets-broker/policy\n */\n\nimport { type SecretBrokerPolicy, type SecretGrantPolicyConfig } from './types';\n\n/** Build a policy that only allows a specific set of secret refs. */\nexport function allowOnly(refs: string[]): SecretBrokerPolicy {\n  return {\n    secretGrants: {\n      allowedSecretRefPrefixes: refs,\n      allowedCapabilityRefs: ['cap://daemon/secrets/broker-only'],\n      requirePurpose: true,\n    },\n    enforcement: { onViolation: 'block' },\n  };\n}\n\n/** Build a policy that blocks everything (deny-by-default). */\nexport function denyAll(): SecretBrokerPolicy {\n  return {\n    secretGrants: {\n      allowedSecretRefPrefixes: [],\n      allowedCapabilityRefs: [],\n      blockedAgentIds: ['*'],\n    },\n    enforcement: { onViolation: 'block' },\n  };\n}\n\n/** Build a policy that allows a single agent and a single secret ref. */\nexport function allowAgentForRef(agentId: string, ref: string): SecretBrokerPolicy {\n  return {\n    secretGrants: {\n      allowedAgentIds: [agentId],\n      allowedSecretRefPrefixes: [ref],\n      allowedCapabilityRefs: ['cap://daemon/secrets/broker-only'],\n      requirePurpose: true,\n    },\n    enforcement: { onViolation: 'block' },\n  };\n}\n\n/** Build a policy from a workspace-like HoloDoor policy JSON shape. */\nexport function fromHoloDoorPolicy(shape: {\n  secretGrants?: SecretGrantPolicyConfig;\n  enforcement?: { onViolation?: 'warn' | 'block' };\n}): SecretBrokerPolicy {\n  return {\n    secretGrants: shape.secretGrants,\n    enforcement: shape.enforcement,\n  };\n}\n","/**\n * Lease adapter — bridge between the secrets broker and a vault-lease registry.\n *\n * The broker itself never stores leases. It delegates to an adapter that\n * wraps a vault implementation (e.g. HoloMesh vault-lease-registry,\n * HashiCorp Vault, AWS Secrets Manager, or an in-memory mock for tests).\n *\n * @module secrets-broker/lease-adapter\n */\n\nimport { type SecretRef, type LeaseAdapter } from './types';\n\n/**\n * In-memory lease adapter for tests and local development.\n * NOT for production — secrets are not persisted and leases evaporate\n * on process exit.\n */\nexport function createMemoryLeaseAdapter(): LeaseAdapter {\n  const leases = new Map<\n    string,\n    {\n      leaseId: string;\n      taskId: string;\n      agentId: string;\n      scope: SecretRef[];\n      expiresAt: string;\n      revoked?: boolean;\n    }\n  >();\n\n  return {\n    async issueLease(params) {\n      const leaseId = `lease-mem-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;\n      const durationMs = params.durationMs ?? 15 * 60 * 1000;\n      const expiresAt = new Date(Date.now() + durationMs).toISOString();\n      leases.set(leaseId, {\n        leaseId,\n        taskId: params.taskId,\n        agentId: params.agentId,\n        scope: [...params.scope],\n        expiresAt,\n      });\n      return { leaseId, expiresAt };\n    },\n\n    async resolveLease(params) {\n      const lease = leases.get(params.leaseId);\n      if (!lease) return { ok: false, reason: 'lease_not_found' };\n      if (lease.revoked) return { ok: false, reason: 'lease_revoked' };\n      if (new Date(lease.expiresAt) <= new Date()) return { ok: false, reason: 'lease_expired' };\n      if (lease.agentId !== params.agentId) return { ok: false, reason: 'lease_agent_mismatch' };\n      if (!lease.scope.includes(params.secretRef))\n        return { ok: false, reason: 'lease_scope_violation' };\n      return { ok: true };\n    },\n\n    async revokeLease(params) {\n      const lease = leases.get(params.leaseId);\n      if (!lease) return { ok: false };\n      lease.revoked = true;\n      return { ok: true };\n    },\n  };\n}\n\n/**\n * No-op lease adapter that always denies. Useful as a safe default\n * when no vault is configured.\n */\nexport function createNoOpLeaseAdapter(): LeaseAdapter {\n  return {\n    async issueLease() {\n      return { leaseId: 'noop', expiresAt: new Date().toISOString() };\n    },\n    async resolveLease() {\n      return { ok: false, reason: 'no_op_adapter' };\n    },\n    async revokeLease() {\n      return { ok: false };\n    },\n  };\n}\n","/**\n * Postgres-backed lease adapter — production persistence for the secrets broker.\n *\n * Like {@link createMemoryLeaseAdapter}, this NEVER returns secret material:\n * `resolveLease` answers only the boolean question \"may this agent read this\n * ref under this lease?\". The plaintext is fetched by a separate secret-store\n * adapter after the lease check passes.\n *\n * ── Decoupling ──────────────────────────────────────────────────────────────\n * The adapter takes an INJECTED `query` runner rather than a hardcoded `pg.Pool`,\n * so it is testable with an in-memory fake and reusable across any driver. The\n * established in-repo pattern is `pg.Pool#query` — e.g.\n * `packages/mcp-server/src/auth/postgres-token-store.ts` does\n * `import type { Pool } from 'pg'` then `this.pool.query(sql, params)`, and the\n * holomesh stores (`team-store.ts`, `state-store.ts`) use the same shape. To\n * wire this adapter against a real database, pass that pool's bound method:\n *\n * ```ts\n * import { Pool } from 'pg';\n * import { createPostgresLeaseAdapter, SECRET_LEASES_DDL } from './postgres-lease-adapter';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * await pool.query(SECRET_LEASES_DDL); // or run the migration\n * const adapter = createPostgresLeaseAdapter({\n *   query: (sql, params) => pool.query(sql, params as unknown[]),\n * });\n * ```\n *\n * The adapter itself imports no driver — only `node:crypto` — so this package\n * adds no runtime dependency.\n *\n * @module secrets-broker/postgres-lease-adapter\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { type SecretRef, type LeaseAdapter } from './types';\n\n/**\n * Minimal query-runner contract the adapter depends on. Structurally compatible\n * with `pg.Pool#query` / `pg.PoolClient#query` (those return additional fields\n * such as `rowCount`, which this contract simply ignores).\n */\nexport interface LeaseQueryRunner {\n  query(sql: string, params: readonly unknown[]): Promise<{ rows: Array<Record<string, unknown>> }>;\n}\n\n/** Dependencies for {@link createPostgresLeaseAdapter}. */\nexport interface PostgresLeaseAdapterDeps {\n  /** Injected query runner (e.g. a bound `pg.Pool#query`). */\n  query: LeaseQueryRunner['query'];\n  /** Injectable clock for deterministic time math. Defaults to `() => new Date()`. */\n  now?: () => Date;\n}\n\n/**\n * DDL for the `secret_leases` table. Idempotent (`IF NOT EXISTS`) so it can be\n * run on boot or applied as a migration. Exported so callers can ensure the\n * schema without depending on a migration runner.\n */\nexport const SECRET_LEASES_DDL = `\nCREATE TABLE IF NOT EXISTS secret_leases (\n  lease_id       TEXT PRIMARY KEY,\n  task_id        TEXT NOT NULL,\n  agent_id       TEXT NOT NULL,\n  scope          JSONB NOT NULL,\n  expires_at     TIMESTAMPTZ NOT NULL,\n  revoked        BOOLEAN NOT NULL DEFAULT FALSE,\n  revoked_reason TEXT,\n  revoked_by     TEXT,\n  created_at     TIMESTAMPTZ NOT NULL DEFAULT now()\n);\nCREATE INDEX IF NOT EXISTS idx_secret_leases_agent ON secret_leases (agent_id);\nCREATE INDEX IF NOT EXISTS idx_secret_leases_task ON secret_leases (task_id);\nCREATE INDEX IF NOT EXISTS idx_secret_leases_expires ON secret_leases (expires_at);\n`;\n\n/** Default lease duration — 15 minutes, matching {@link createMemoryLeaseAdapter}. */\nconst DEFAULT_DURATION_MS = 15 * 60 * 1000;\n\n// ── Row narrowing (strict, no `any`) ─────────────────────────────────────────\n\n/** The columns `resolveLease` reads back from a `secret_leases` row. */\ninterface LeaseRowView {\n  agentId: string;\n  scope: readonly string[];\n  expiresAt: Date;\n  revoked: boolean;\n}\n\n/** Coerce an unknown column value to a string, or `null` if not coercible. */\nfunction asString(value: unknown): string | null {\n  return typeof value === 'string' ? value : null;\n}\n\n/** Coerce an unknown column value to a boolean (Postgres BOOLEAN → JS boolean). */\nfunction asBoolean(value: unknown): boolean {\n  return value === true;\n}\n\n/**\n * Coerce a `TIMESTAMPTZ` column to a `Date`. The `pg` driver returns a JS `Date`\n * for timestamptz; a fake may return an ISO string or epoch number. Returns\n * `null` when the value cannot be interpreted as a valid date.\n */\nfunction asDate(value: unknown): Date | null {\n  if (value instanceof Date) {\n    return Number.isNaN(value.getTime()) ? null : value;\n  }\n  if (typeof value === 'string' || typeof value === 'number') {\n    const d = new Date(value);\n    return Number.isNaN(d.getTime()) ? null : d;\n  }\n  return null;\n}\n\n/**\n * Coerce a `JSONB` scope column to a `string[]`. The `pg` driver parses jsonb\n * into a JS value (here an array); a fake may hand back the raw JSON string.\n * Non-string array members are dropped. Returns `[]` on any non-array shape.\n */\nfunction asScope(value: unknown): readonly string[] {\n  let parsed: unknown = value;\n  if (typeof value === 'string') {\n    try {\n      parsed = JSON.parse(value);\n    } catch {\n      return [];\n    }\n  }\n  if (!Array.isArray(parsed)) return [];\n  return parsed.filter((item): item is string => typeof item === 'string');\n}\n\n/**\n * Narrow a raw DB row to {@link LeaseRowView}. Returns `null` when required\n * columns are missing or malformed (treated by the caller as `lease_not_found`).\n */\nfunction narrowLeaseRow(row: Record<string, unknown> | undefined): LeaseRowView | null {\n  if (!row) return null;\n  const agentId = asString(row.agent_id);\n  const expiresAt = asDate(row.expires_at);\n  if (agentId === null || expiresAt === null) return null;\n  return {\n    agentId,\n    scope: asScope(row.scope),\n    expiresAt,\n    revoked: asBoolean(row.revoked),\n  };\n}\n\n/**\n * Create a production Postgres-backed {@link LeaseAdapter}.\n *\n * `resolveLease` applies the EXACT same checks, in the same order, as\n * {@link createMemoryLeaseAdapter}: not-found → revoked → expired →\n * agent-mismatch → scope-violation. It returns a boolean verdict and NEVER a\n * secret value.\n *\n * The adapter performs no schema management itself — run {@link SECRET_LEASES_DDL}\n * (or the migration) before first use.\n */\nexport function createPostgresLeaseAdapter(deps: PostgresLeaseAdapterDeps): LeaseAdapter {\n  const { query } = deps;\n  const clock = deps.now ?? (() => new Date());\n\n  return {\n    async issueLease(params) {\n      const leaseId = `lease-${randomUUID()}`;\n      const durationMs = params.durationMs ?? DEFAULT_DURATION_MS;\n      const expiresAtDate = new Date(clock().getTime() + durationMs);\n      const expiresAt = expiresAtDate.toISOString();\n      // scope is a SecretRef[]; serialize for the jsonb column.\n      const scopeJson = JSON.stringify([...params.scope]);\n\n      await query(\n        `INSERT INTO secret_leases (lease_id, task_id, agent_id, scope, expires_at)\n         VALUES ($1, $2, $3, $4::jsonb, $5)`,\n        [leaseId, params.taskId, params.agentId, scopeJson, expiresAt]\n      );\n\n      return { leaseId, expiresAt };\n    },\n\n    async resolveLease(params) {\n      const { rows } = await query(\n        `SELECT agent_id, scope, expires_at, revoked\n         FROM secret_leases WHERE lease_id = $1`,\n        [params.leaseId]\n      );\n\n      const lease = narrowLeaseRow(rows[0]);\n      // Same checks, same order, as createMemoryLeaseAdapter:\n      if (!lease) return { ok: false, reason: 'lease_not_found' };\n      if (lease.revoked) return { ok: false, reason: 'lease_revoked' };\n      if (lease.expiresAt.getTime() <= clock().getTime()) {\n        return { ok: false, reason: 'lease_expired' };\n      }\n      if (lease.agentId !== params.agentId) {\n        return { ok: false, reason: 'lease_agent_mismatch' };\n      }\n      if (!lease.scope.includes(params.secretRef)) {\n        return { ok: false, reason: 'lease_scope_violation' };\n      }\n      return { ok: true };\n    },\n\n    async revokeLease(params) {\n      const { rows } = await query(\n        `UPDATE secret_leases\n         SET revoked = TRUE, revoked_reason = $2, revoked_by = $3\n         WHERE lease_id = $1 AND revoked = FALSE\n         RETURNING lease_id`,\n        [params.leaseId, params.reason, params.by]\n      );\n      // 0 rows → lease absent or already revoked.\n      return { ok: rows.length > 0 };\n    },\n  };\n}\n\n// `SecretRef` is referenced in docs/serialization above; keep the import meaningful\n// for consumers that build scope arrays against the same nominal type.\nexport type { SecretRef };\n","/**\n * Postgres-backed SecretStore backend — production persistence for HoloKey.\n *\n * This is the storage half of the encrypted per-owner SecretStore\n * (`secret-store.ts`). It holds ONLY ciphertext + crypto metadata; the\n * plaintext value is never a column, never a param, never logged. Envelope\n * encryption lives in the store; this module just persists the sealed\n * {@link SecretRow} and reads it back, byte-for-byte, into and out of the\n * `secret_store` table ({@link SECRET_STORE_DDL}).\n *\n * ── Decoupling (mirrors {@link createPostgresLeaseAdapter}) ──────────────────\n * The backend takes an INJECTED `query` runner rather than a hardcoded\n * `pg.Pool`, so it is testable with an in-memory fake and reusable across any\n * driver. The established in-repo pattern is `pg.Pool#query` — e.g.\n * `packages/mcp-server/src/auth/postgres-token-store.ts` does\n * `import type { Pool } from 'pg'` then `this.pool.query(sql, params)`. To wire\n * this backend against a real database, pass that pool's bound method:\n *\n * ```ts\n * import { Pool } from 'pg';\n * import { createPostgresSecretBackend } from './postgres-secret-backend';\n * import { SECRET_STORE_DDL, createSecretStore } from './secret-store';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * await pool.query(SECRET_STORE_DDL); // or run the migration\n * const backend = createPostgresSecretBackend({\n *   query: (sql, params) => pool.query(sql, params as unknown[]),\n * });\n * const store = createSecretStore({ backend, kekProvider });\n * ```\n *\n * The backend itself imports NO driver, only `SecretStoreBackend`/`SecretRow`\n * types — this package adds no runtime dependency.\n *\n * ── bytea ⇄ Buffer ──────────────────────────────────────────────────────────\n * The `pg` driver returns a Node `Buffer` for `bytea` columns and accepts a\n * `Buffer` param for them. So the seven ciphertext/crypto columns round-trip as\n * Buffers with no encoding step. Every read column is narrowed with a strict\n * helper (no `any`); a malformed/missing required column throws rather than\n * silently coercing — a corrupt secret row must fail loud, never return garbage.\n *\n * ── timestamptz ⇄ ISO string ────────────────────────────────────────────────\n * `SecretRow.createdAt` is an ISO string and `lastUsedAt` is `string | null`.\n * The `pg` driver hands back a JS `Date` for `timestamptz` (a fake may hand back\n * an ISO string), so reads normalize via `asIsoString` / `asNullableIsoString`.\n * Writes pass ISO strings as params; Postgres parses them into `timestamptz`.\n *\n * @module secrets-broker/postgres-secret-backend\n */\n\nimport type { SecretRef } from './types';\nimport type { SecretRow, SecretStoreBackend } from './secret-store';\n\n/**\n * Minimal query-runner contract the backend depends on. Structurally compatible\n * with `pg.Pool#query` / `pg.PoolClient#query` (those return additional fields\n * such as `rowCount`, which this contract simply ignores). Identical in shape to\n * the lease adapter's `LeaseQueryRunner`.\n */\nexport interface SecretQueryRunner {\n  query(sql: string, params: readonly unknown[]): Promise<{ rows: Array<Record<string, unknown>> }>;\n}\n\n/** Dependencies for {@link createPostgresSecretBackend}. */\nexport interface PostgresSecretBackendDeps {\n  /** Injected query runner (e.g. a bound `pg.Pool#query`). */\n  query: SecretQueryRunner['query'];\n}\n\n// ── Column narrowing (strict, no `any`) ──────────────────────────────────────\n\n/**\n * Coerce a `bytea` column to a `Buffer`. The `pg` driver returns a `Buffer`; a\n * fake may hand back a `Uint8Array`. Throws on any non-binary value — a secret's\n * ciphertext/crypto bytes must never be silently dropped or coerced.\n */\nfunction asBuffer(value: unknown, column: string): Buffer {\n  if (Buffer.isBuffer(value)) return value;\n  if (value instanceof Uint8Array) return Buffer.from(value);\n  throw new TypeError(`postgres-secret-backend: column \"${column}\" is not bytea/Buffer`);\n}\n\n/** Coerce a required `text`/`uuid` column to a string. Throws if not a string. */\nfunction asString(value: unknown, column: string): string {\n  if (typeof value === 'string') return value;\n  throw new TypeError(`postgres-secret-backend: column \"${column}\" is not a string`);\n}\n\n/**\n * Coerce a required numeric column (`int`) to a number. The `pg` driver returns\n * a JS number for `int4`; a fake may return a numeric string. Throws on a\n * non-finite/unparseable value.\n */\nfunction asNumber(value: unknown, column: string): number {\n  if (typeof value === 'number' && Number.isFinite(value)) return value;\n  if (typeof value === 'string') {\n    const n = Number(value);\n    if (Number.isFinite(n)) return n;\n  }\n  throw new TypeError(`postgres-secret-backend: column \"${column}\" is not a finite number`);\n}\n\n/** Coerce a nullable `text` column to `string | null`. Throws on a non-string non-null. */\nfunction asNullableString(value: unknown, column: string): string | null {\n  if (value === null || value === undefined) return null;\n  if (typeof value === 'string') return value;\n  throw new TypeError(`postgres-secret-backend: column \"${column}\" is not string|null`);\n}\n\n/**\n * Normalize a required `timestamptz` column to an ISO 8601 string. `pg` returns\n * a `Date`; a fake may return an ISO string or epoch number. Throws on an\n * invalid/missing date — `SecretRow.createdAt` is `string`, never optional.\n */\nfunction asIsoString(value: unknown, column: string): string {\n  const iso = toIso(value);\n  if (iso === null) {\n    throw new TypeError(`postgres-secret-backend: column \"${column}\" is not a valid timestamp`);\n  }\n  return iso;\n}\n\n/** Normalize a nullable `timestamptz` column to `string | null`. */\nfunction asNullableIsoString(value: unknown, column: string): string | null {\n  if (value === null || value === undefined) return null;\n  const iso = toIso(value);\n  if (iso === null) {\n    throw new TypeError(\n      `postgres-secret-backend: column \"${column}\" is not a valid timestamp|null`\n    );\n  }\n  return iso;\n}\n\n/** Best-effort ISO-string conversion for a Date / ISO-string / epoch-number. */\nfunction toIso(value: unknown): string | null {\n  if (value instanceof Date) {\n    return Number.isNaN(value.getTime()) ? null : value.toISOString();\n  }\n  if (typeof value === 'string' || typeof value === 'number') {\n    const d = new Date(value);\n    return Number.isNaN(d.getTime()) ? null : d.toISOString();\n  }\n  return null;\n}\n\n/**\n * Narrow a raw `secret_store` row into a {@link SecretRow}. Every column is\n * checked; a missing/malformed required column throws (a corrupt row fails loud\n * rather than decrypting garbage). `ref` is the broker's `vault:<name>` label,\n * typed as {@link SecretRef}.\n */\nfunction narrowSecretRow(row: Record<string, unknown>): SecretRow {\n  return {\n    id: asString(row.id, 'id'),\n    ownerId: asString(row.owner_id, 'owner_id'),\n    name: asString(row.name, 'name'),\n    ref: asString(row.ref, 'ref') as SecretRef,\n    ciphertext: asBuffer(row.ciphertext, 'ciphertext'),\n    iv: asBuffer(row.iv, 'iv'),\n    authTag: asBuffer(row.auth_tag, 'auth_tag'),\n    wrappedDek: asBuffer(row.wrapped_dek, 'wrapped_dek'),\n    dekIv: asBuffer(row.dek_iv, 'dek_iv'),\n    dekAuthTag: asBuffer(row.dek_auth_tag, 'dek_auth_tag'),\n    kekId: asString(row.kek_id, 'kek_id'),\n    version: asNumber(row.version, 'version'),\n    createdAt: asIsoString(row.created_at, 'created_at'),\n    lastUsedAt: asNullableIsoString(row.last_used_at, 'last_used_at'),\n  };\n}\n\n/** Columns selected by every read path, in stable order. */\nconst SELECT_COLUMNS =\n  'id, owner_id, name, ref, ciphertext, iv, auth_tag, wrapped_dek, dek_iv, dek_auth_tag, kek_id, version, created_at, last_used_at';\n\n/**\n * Create a production Postgres-backed {@link SecretStoreBackend}.\n *\n * Implements every method of the interface against the `secret_store` table:\n *   - `insert` UPSERTs on `UNIQUE(owner_id, name)` so a re-put supersedes the\n *     prior row and carries the bumped version — matching the in-memory backend.\n *   - `getByRef` / `getByName` are owner-scoped single-row reads.\n *   - `listByOwner` is owner-scoped; `listByKekId` spans owners (rotation only).\n *   - `deleteByRef` returns whether a row was removed (RETURNING).\n *   - `touchLastUsed` / `updateWrappedDek` are id-keyed updates.\n *\n * The backend performs no schema management — run {@link SECRET_STORE_DDL}\n * (or the migration) before first use.\n */\nexport function createPostgresSecretBackend(deps: PostgresSecretBackendDeps): SecretStoreBackend {\n  const { query } = deps;\n\n  return {\n    /**\n     * Insert a fully-sealed row. UPSERT on the UNIQUE(owner_id, name) constraint:\n     * a re-put (new version) for the same owner+name OVERWRITES every crypto\n     * column plus ref/kek_id/version/created_at, so the latest put supersedes\n     * exactly as the in-memory backend's replace-on-conflict does. `last_used_at`\n     * is reset to NULL on supersede (a freshly-sealed row has never been read).\n     */\n    async insert(row: SecretRow): Promise<void> {\n      await query(\n        `INSERT INTO secret_store (\n           id, owner_id, name, ref,\n           ciphertext, iv, auth_tag,\n           wrapped_dek, dek_iv, dek_auth_tag,\n           kek_id, version, created_at, last_used_at\n         ) VALUES (\n           $1, $2, $3, $4,\n           $5, $6, $7,\n           $8, $9, $10,\n           $11, $12, $13, $14\n         )\n         ON CONFLICT (owner_id, name) DO UPDATE SET\n           ref          = EXCLUDED.ref,\n           ciphertext   = EXCLUDED.ciphertext,\n           iv           = EXCLUDED.iv,\n           auth_tag     = EXCLUDED.auth_tag,\n           wrapped_dek  = EXCLUDED.wrapped_dek,\n           dek_iv       = EXCLUDED.dek_iv,\n           dek_auth_tag = EXCLUDED.dek_auth_tag,\n           kek_id       = EXCLUDED.kek_id,\n           version      = EXCLUDED.version,\n           created_at   = EXCLUDED.created_at,\n           last_used_at = EXCLUDED.last_used_at`,\n        [\n          row.id,\n          row.ownerId,\n          row.name,\n          row.ref,\n          row.ciphertext,\n          row.iv,\n          row.authTag,\n          row.wrappedDek,\n          row.dekIv,\n          row.dekAuthTag,\n          row.kekId,\n          row.version,\n          row.createdAt,\n          row.lastUsedAt,\n        ]\n      );\n    },\n\n    async getByRef({ ownerId, ref }): Promise<SecretRow | null> {\n      const { rows } = await query(\n        `SELECT ${SELECT_COLUMNS} FROM secret_store WHERE owner_id = $1 AND ref = $2`,\n        [ownerId, ref]\n      );\n      const first = rows[0];\n      return first ? narrowSecretRow(first) : null;\n    },\n\n    async getByName({ ownerId, name }): Promise<SecretRow | null> {\n      const { rows } = await query(\n        `SELECT ${SELECT_COLUMNS} FROM secret_store WHERE owner_id = $1 AND name = $2`,\n        [ownerId, name]\n      );\n      const first = rows[0];\n      return first ? narrowSecretRow(first) : null;\n    },\n\n    async listByOwner(ownerId: string): Promise<SecretRow[]> {\n      const { rows } = await query(\n        `SELECT ${SELECT_COLUMNS} FROM secret_store WHERE owner_id = $1`,\n        [ownerId]\n      );\n      return rows.map(narrowSecretRow);\n    },\n\n    async listByKekId(kekId: string): Promise<SecretRow[]> {\n      // Spans owners deliberately — rotation re-wraps every row under a KEK.\n      const { rows } = await query(`SELECT ${SELECT_COLUMNS} FROM secret_store WHERE kek_id = $1`, [\n        kekId,\n      ]);\n      return rows.map(narrowSecretRow);\n    },\n\n    async deleteByRef({ ownerId, ref }): Promise<boolean> {\n      const { rows } = await query(\n        `DELETE FROM secret_store WHERE owner_id = $1 AND ref = $2 RETURNING id`,\n        [ownerId, ref]\n      );\n      return rows.length > 0;\n    },\n\n    async touchLastUsed({ id, lastUsedAt }): Promise<void> {\n      await query(`UPDATE secret_store SET last_used_at = $2 WHERE id = $1`, [id, lastUsedAt]);\n    },\n\n    async updateWrappedDek({ id, wrappedDek, dekIv, dekAuthTag, kekId }): Promise<void> {\n      await query(\n        `UPDATE secret_store\n         SET wrapped_dek = $2, dek_iv = $3, dek_auth_tag = $4, kek_id = $5\n         WHERE id = $1`,\n        [id, wrappedDek, dekIv, dekAuthTag, kekId]\n      );\n    },\n  };\n}\n","/**\n * Device-flow provisioning + broker integration.\n *\n * Generalises the per-brain `HOLOMESH_API_KEY_<HANDLE>_X402` pattern into\n * a public service: pair once, server holds wallets/bearers, any surface\n * gets short-lived scoped capabilities per session.\n *\n * This module defines the **interface** for x402+broker provisioning.\n * A concrete adapter (e.g. `@holoscript/holoscript-agent/provision` or\n * a cloud HSM wrapper) implements the async `provisionAgent` call.\n *\n * @module secrets-broker/provision\n */\n\nimport { type DeviceFlowProvisionResult } from './types';\n\n/**\n * Parameters for provisioning a new AI surface (mobile, desktop, headless).\n */\nexport interface ProvisionSurfaceInput {\n  handle: string;\n  surface: 'mobile' | 'desktop' | 'headless' | 'web' | string;\n  meshApiBase?: string;\n  founderBearer: string;\n  autoJoinTeamId?: string;\n}\n\n/**\n * Provisioning adapter interface. Implementations may use:\n *   - `@holoscript/holoscript-agent` (local file-based wallets)\n *   - Cloud HSM (AWS KMS, GCP Cloud KMS)\n *   - Hardware wallet (Trezor, Ledger)\n *\n * The broker primitive does NOT mandate the storage backend.\n */\nexport interface ProvisionAdapter {\n  provisionAgent(\n    input: ProvisionSurfaceInput,\n    opts: { execute: boolean; force?: boolean }\n  ): Promise<DeviceFlowProvisionResult>;\n}\n\n/**\n * Create a brokered session after provisioning.\n *\n * 1. Provisions the surface (wallet + x402 bearer) via the adapter.\n * 2. Issues a brokered secret grant scoped to the surface's namespace.\n * 3. Returns both the provision result and the grant receipt.\n *\n * The secret material (private key, bearer token) NEVER leaves the\n * provision adapter. Only handles and receipts surface here.\n */\nexport async function provisionBrokeredSession(\n  input: ProvisionSurfaceInput,\n  opts: { execute: boolean; force?: boolean },\n  adapter: ProvisionAdapter\n): Promise<{\n  provision: DeviceFlowProvisionResult;\n}> {\n  const provision = await adapter.provisionAgent(input, opts);\n  if (provision.status !== 'executed' && provision.status !== 'reused') {\n    throw new Error(`Provisioning failed for handle=${input.handle}`);\n  }\n  return { provision };\n}\n\n/**\n * Convenience builder for a local-file-based provision adapter.\n * Wraps the same shape as `@holoscript/holoscript-agent/src/provision.ts`\n * without creating a runtime dependency on that package.\n */\nexport function localFileProvisionAdapter(\n  impl: (\n    input: ProvisionSurfaceInput,\n    opts: { execute: boolean; force?: boolean }\n  ) => Promise<DeviceFlowProvisionResult>\n): ProvisionAdapter {\n  return { provisionAgent: impl };\n}\n","/**\n * Encrypted per-owner SecretStore — the value-holding half of the secrets broker.\n *\n * The lease adapter (`lease-adapter.ts`) only answers \"may this agent read this\n * ref?\" — it never stores or decrypts the secret VALUE. This module is that\n * missing half: it holds the encrypted value behind a `vault:<key>` SecretRef\n * (`types.ts`), keyed per OWNER, and only decrypts for the authenticated owner.\n *\n * ── Crypto: envelope encryption (matches the house style in\n *    `packages/mcp-server/src/holomesh/identity/custodial-wallet.ts`) ──────────\n *\n *   value  ──AES-256-GCM(DEK, iv12)──▶  { ciphertext, iv, authTag }\n *   DEK    ──AES-256-GCM(KEK, dekIv12)─▶ { wrappedDek, dekIv, dekAuthTag }\n *\n *   - One fresh 32-byte DEK per secret (`crypto.randomBytes(32)`).\n *   - One master KEK, sourced by an INJECTED `kekProvider` — this module NEVER\n *     reads `process.env`; the provider owns env-now / KMS-later key sourcing.\n *   - Every row records the `kekId` of the KEK that wrapped its DEK, so\n *     `rotateKek` can find and re-wrap exactly the rows under an old KEK.\n *\n * ── Security invariant ──────────────────────────────────────────────────────\n *   `get()` enforces owner isolation INSIDE the function: it fetches the row by\n *   ref, and if `row.owner_id !== ownerId` it throws `OwnerMismatchError`\n *   WITHOUT decrypting. Isolation is never assumed to live in an upstream gate.\n *\n * GCM's authentication tag is the integrity guarantee: any tamper of the\n * ciphertext, or an attempt to unwrap a DEK with the wrong KEK, fails the tag\n * check and surfaces as `DecryptError` — the store never returns a wrong/garbled\n * value, it refuses.\n *\n * Errors carry ZERO secret material. Storage is behind an injected `backend`\n * interface so the crypto is testable without Postgres; an in-memory backend\n * and a Postgres DDL (`SECRET_STORE_DDL`) are exported.\n *\n * @module secrets-broker/secret-store\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes, randomUUID } from 'node:crypto';\n\nimport type { SecretRef } from './types';\n\n// ── Crypto constants ────────────────────────────────────────────────────────\n\n/** AES-256 key length in bytes (DEK and KEK are both 256-bit). */\nconst KEY_BYTES = 32;\n\n/** AES-GCM IV length — 96 bits per NIST SP 800-38D (fresh per encryption). */\nconst IV_BYTES = 12;\n\n/** AES-GCM authentication tag length — 128 bits. */\nconst AUTH_TAG_BYTES = 16;\n\n/** Cipher used for both the value (under the DEK) and the DEK (under the KEK). */\nconst CIPHER = 'aes-256-gcm' as const;\n\n// ── KEK provider (injected — the store never reads process.env) ──────────────\n\n/**\n * Key-encryption-key provider. The store calls this to obtain the master KEK\n * used to wrap/unwrap per-secret DEKs. The provider owns key sourcing — env in\n * dev, a KMS in production — so this module stays free of `process.env`.\n *\n * `getKek(kekId?)` MUST return a 32-byte Buffer. When `kekId` is given the\n * provider returns THAT specific KEK (needed to unwrap historical rows and to\n * rotate); when omitted it returns the current KEK.\n */\nexport interface KekProvider {\n  /** Resolve a 32-byte KEK. With `kekId`, resolve that exact KEK version. */\n  getKek(kekId?: string): Promise<Buffer>;\n  /** The id of the KEK that `getKek()` (no arg) currently returns. */\n  currentKekId(): string;\n  /**\n   * Whether this provider sources the KEK from a production-grade store (KMS / HSM /\n   * service-scoped secret) rather than a shared-surface env var. The env provider sets\n   * `false`; the KMS provider sets `true`. Read by the SecretStore's\n   * `requireProductionGradeKek` gate — `undefined` is treated as NOT production-grade.\n   */\n  readonly productionGrade?: boolean;\n}\n\n// ── Stored row (ciphertext only — never plaintext) ──────────────────────────\n\n/**\n * A row as persisted by the backend. Holds ONLY ciphertext + crypto metadata;\n * the plaintext value is never stored or logged. Buffers map to Postgres\n * `bytea` columns (see {@link SECRET_STORE_DDL}).\n */\nexport interface SecretRow {\n  /** Row id (uuid). */\n  id: string;\n  /** Authenticated owner identity that put this secret. */\n  ownerId: string;\n  /** Human-readable name, unique per owner. */\n  name: string;\n  /** Canonical ref — `vault:${name}`. */\n  ref: SecretRef;\n  /** AES-256-GCM ciphertext of the value (under the DEK). */\n  ciphertext: Buffer;\n  /** 12-byte IV used to encrypt the value. */\n  iv: Buffer;\n  /** 16-byte GCM auth tag over the value ciphertext. */\n  authTag: Buffer;\n  /** The DEK, itself AES-256-GCM-encrypted under the KEK. */\n  wrappedDek: Buffer;\n  /** 12-byte IV used to wrap the DEK. */\n  dekIv: Buffer;\n  /** 16-byte GCM auth tag over the wrapped DEK. */\n  dekAuthTag: Buffer;\n  /** Id of the KEK that wrapped `wrappedDek` (tracks rotation). */\n  kekId: string;\n  /** Monotonic version, bumped on overwrite of an existing name. */\n  version: number;\n  /** ISO 8601 creation timestamp. */\n  createdAt: string;\n  /** ISO 8601 timestamp of the last successful owner-authorized get, or null. */\n  lastUsedAt: string | null;\n}\n\n/**\n * Storage backend. Crypto lives in the store; persistence lives here, so the\n * envelope encryption is testable without Postgres. All lookups are scoped by\n * `ownerId` at the call site; the backend must additionally treat\n * `(ownerId, name)` as unique.\n */\nexport interface SecretStoreBackend {\n  /** Insert a fully-encrypted row. */\n  insert(row: SecretRow): Promise<void>;\n  /** Fetch a single row by `(ownerId, ref)`, or null. */\n  getByRef(params: { ownerId: string; ref: SecretRef }): Promise<SecretRow | null>;\n  /** Fetch a single row by `(ownerId, name)`, or null (used to bump version). */\n  getByName(params: { ownerId: string; name: string }): Promise<SecretRow | null>;\n  /** All rows for an owner — WITHOUT decrypting. Used by metadata `list()`. */\n  listByOwner(ownerId: string): Promise<SecretRow[]>;\n  /** All rows wrapped under `kekId`, across owners — used only by rotation. */\n  listByKekId(kekId: string): Promise<SecretRow[]>;\n  /** Delete a single row by `(ownerId, ref)`. Returns whether a row was removed. */\n  deleteByRef(params: { ownerId: string; ref: SecretRef }): Promise<boolean>;\n  /** Update last-used timestamp after a successful owner-authorized get. */\n  touchLastUsed(params: { id: string; lastUsedAt: string }): Promise<void>;\n  /** Re-wrap a row's DEK under a new KEK (rotation). Ciphertext is untouched. */\n  updateWrappedDek(params: {\n    id: string;\n    wrappedDek: Buffer;\n    dekIv: Buffer;\n    dekAuthTag: Buffer;\n    kekId: string;\n  }): Promise<void>;\n}\n\n// ── Errors (NEVER include secret material in messages) ───────────────────────\n\n/**\n * Thrown by `get()`/`delete()` when the authenticated caller does not own the\n * row. Carries only the ref (an audit-safe label) — never the value.\n */\nexport class OwnerMismatchError extends Error {\n  readonly ref: SecretRef;\n  constructor(ref: SecretRef) {\n    super(`secret-store: caller is not the owner of ${ref}`);\n    this.name = 'OwnerMismatchError';\n    this.ref = ref;\n  }\n}\n\n/** Thrown when no secret exists for the given owner+ref. */\nexport class SecretNotFoundError extends Error {\n  readonly ref: SecretRef;\n  constructor(ref: SecretRef) {\n    super(`secret-store: no secret found for ${ref}`);\n    this.name = 'SecretNotFoundError';\n    this.ref = ref;\n  }\n}\n\n/**\n * Thrown when decryption fails: a tampered value ciphertext (GCM tag mismatch),\n * or a DEK that cannot be unwrapped because the wrong KEK was supplied. Carries\n * only the ref — never plaintext, key bytes, or the underlying crypto error\n * detail (which can leak oracle signal).\n */\nexport class DecryptError extends Error {\n  readonly ref: SecretRef;\n  constructor(ref: SecretRef) {\n    super(`secret-store: failed to decrypt ${ref}`);\n    this.name = 'DecryptError';\n    this.ref = ref;\n  }\n}\n\n/**\n * Thrown at construction when `requireProductionGradeKek` is set but the KEK provider is\n * not production-grade (e.g. the env provider). The Phase-3 gate: no real user secret may\n * be backed by a shared-surface env KEK in production.\n */\nexport class InsecureKekError extends Error {\n  constructor() {\n    super(\n      'secret-store: requireProductionGradeKek is set but the KEK provider is not ' +\n        'production-grade — use createKmsKekProvider (KMS / HSM / service-scoped secret), ' +\n        'not the env provider, before storing real user secrets'\n    );\n    this.name = 'InsecureKekError';\n  }\n}\n\n// ── Public API surface ───────────────────────────────────────────────────────\n\nexport interface PutInput {\n  /** Authenticated owner identity. */\n  ownerId: string;\n  /** Human-readable secret name (unique per owner). `ref` is `vault:${name}`. */\n  name: string;\n  /** The plaintext secret value to encrypt at rest. */\n  value: string;\n}\n\nexport interface PutResult {\n  ref: SecretRef;\n  version: number;\n}\n\nexport interface GetInput {\n  /** Authenticated caller identity — REQUIRED; owner isolation enforced here. */\n  ownerId: string;\n  /** Canonical ref of the secret to read. */\n  ref: SecretRef;\n}\n\nexport interface GetResult {\n  value: string;\n}\n\n/** Metadata-only view of a secret — NEVER includes the value or ciphertext. */\nexport interface SecretMetadata {\n  name: string;\n  ref: SecretRef;\n  version: number;\n  createdAt: string;\n  lastUsedAt: string | null;\n}\n\nexport interface RotateKekInput {\n  /** KEK id whose rows should be re-wrapped. */\n  fromKekId: string;\n  /** KEK id to re-wrap them under. */\n  toKekId: string;\n}\n\nexport interface RotateKekResult {\n  /** Number of rows re-wrapped from `fromKekId` to `toKekId`. */\n  rotated: number;\n}\n\n/** The store's dependencies — both injected, nothing read from the ambient env. */\nexport interface SecretStoreDeps {\n  backend: SecretStoreBackend;\n  kekProvider: KekProvider;\n  /**\n   * Phase-3 safety gate: when true, the store REFUSES to construct unless\n   * `kekProvider.productionGrade` is true — so a dev/env KEK can never back real user\n   * secrets in production. The app sets this from NODE_ENV (or an explicit flag).\n   */\n  requireProductionGradeKek?: boolean;\n  /** Optional fixed clock for deterministic tests. */\n  now?: () => Date;\n}\n\nexport interface SecretStore {\n  /** Encrypt + store a value. Bumps version if `name` already exists for owner. */\n  put(input: PutInput): Promise<PutResult>;\n  /** Owner-isolated decrypt. Throws `OwnerMismatchError` for a non-owner. */\n  get(input: GetInput): Promise<GetResult>;\n  /** Metadata for all of the owner's secrets — never values. */\n  list(input: { ownerId: string }): Promise<SecretMetadata[]>;\n  /** Owner-scoped delete. */\n  delete(input: { ownerId: string; ref: SecretRef }): Promise<{ deleted: boolean }>;\n  /** Re-wrap every DEK under `fromKekId` with `toKekId`. Values unchanged. */\n  rotateKek(input: RotateKekInput): Promise<RotateKekResult>;\n}\n\n/** Build the canonical ref for a secret name. */\nfunction refForName(name: string): SecretRef {\n  return `vault:${name}`;\n}\n\n/**\n * Encrypt `plaintext` under a fresh DEK, then wrap that DEK under `kek`.\n * Returns all ciphertext components plus the wrapped-DEK components.\n */\nfunction sealValue(\n  plaintext: string,\n  kek: Buffer\n): {\n  ciphertext: Buffer;\n  iv: Buffer;\n  authTag: Buffer;\n  wrappedDek: Buffer;\n  dekIv: Buffer;\n  dekAuthTag: Buffer;\n} {\n  // Fresh per-secret DEK.\n  const dek = randomBytes(KEY_BYTES);\n\n  // Encrypt the value with the DEK.\n  const iv = randomBytes(IV_BYTES);\n  const valueCipher = createCipheriv(CIPHER, dek, iv, { authTagLength: AUTH_TAG_BYTES });\n  const ciphertext = Buffer.concat([valueCipher.update(plaintext, 'utf8'), valueCipher.final()]);\n  const authTag = valueCipher.getAuthTag();\n\n  // Wrap the DEK with the KEK.\n  const { wrappedDek, dekIv, dekAuthTag } = wrapDek(dek, kek);\n\n  return { ciphertext, iv, authTag, wrappedDek, dekIv, dekAuthTag };\n}\n\n/** Wrap (encrypt) a DEK with a KEK using AES-256-GCM and a fresh IV. */\nfunction wrapDek(\n  dek: Buffer,\n  kek: Buffer\n): { wrappedDek: Buffer; dekIv: Buffer; dekAuthTag: Buffer } {\n  const dekIv = randomBytes(IV_BYTES);\n  const dekCipher = createCipheriv(CIPHER, kek, dekIv, { authTagLength: AUTH_TAG_BYTES });\n  const wrappedDek = Buffer.concat([dekCipher.update(dek), dekCipher.final()]);\n  const dekAuthTag = dekCipher.getAuthTag();\n  return { wrappedDek, dekIv, dekAuthTag };\n}\n\n/**\n * Unwrap a DEK with a KEK. A wrong KEK (or a tampered wrapped DEK) fails the GCM\n * tag and throws — the caller maps that to `DecryptError`.\n */\nfunction unwrapDek(row: SecretRow, kek: Buffer): Buffer {\n  const decipher = createDecipheriv(CIPHER, kek, row.dekIv, {\n    authTagLength: AUTH_TAG_BYTES,\n  });\n  decipher.setAuthTag(row.dekAuthTag);\n  return Buffer.concat([decipher.update(row.wrappedDek), decipher.final()]);\n}\n\n/**\n * Decrypt a row's value given its already-unwrapped DEK. A tampered ciphertext\n * fails the GCM tag and throws — the caller maps that to `DecryptError`.\n */\nfunction openValue(row: SecretRow, dek: Buffer): string {\n  const decipher = createDecipheriv(CIPHER, dek, row.iv, {\n    authTagLength: AUTH_TAG_BYTES,\n  });\n  decipher.setAuthTag(row.authTag);\n  const plaintext = Buffer.concat([decipher.update(row.ciphertext), decipher.final()]);\n  return plaintext.toString('utf8');\n}\n\n/**\n * Create an encrypted per-owner SecretStore over an injected backend + KEK\n * provider. The store performs envelope encryption; the backend persists\n * ciphertext; the provider sources KEKs. Nothing is read from `process.env`.\n */\nexport function createSecretStore(deps: SecretStoreDeps): SecretStore {\n  const { backend, kekProvider } = deps;\n  // Phase-3 gate: refuse to back real secrets with a non-production KEK in production.\n  if (deps.requireProductionGradeKek && !kekProvider.productionGrade) {\n    throw new InsecureKekError();\n  }\n  const now = deps.now ?? (() => new Date());\n\n  return {\n    async put(input: PutInput): Promise<PutResult> {\n      const { ownerId, name, value } = input;\n      if (!ownerId) throw new TypeError('secret-store.put: ownerId required');\n      if (!name) throw new TypeError('secret-store.put: name required');\n\n      const ref = refForName(name);\n      const kekId = kekProvider.currentKekId();\n      const kek = await kekProvider.getKek();\n\n      const sealed = sealValue(value, kek);\n\n      // Bump version if this owner already has a secret under `name`.\n      const existing = await backend.getByName({ ownerId, name });\n      const version = existing ? existing.version + 1 : 1;\n\n      const row: SecretRow = {\n        id: randomUUID(),\n        ownerId,\n        name,\n        ref,\n        ciphertext: sealed.ciphertext,\n        iv: sealed.iv,\n        authTag: sealed.authTag,\n        wrappedDek: sealed.wrappedDek,\n        dekIv: sealed.dekIv,\n        dekAuthTag: sealed.dekAuthTag,\n        kekId,\n        version,\n        createdAt: now().toISOString(),\n        lastUsedAt: null,\n      };\n\n      await backend.insert(row);\n      return { ref, version };\n    },\n\n    /**\n     * ── SECURITY INVARIANT (owner isolation enforced HERE, inside get) ──\n     * `ownerId` is the AUTHENTICATED CALLER. We fetch by ref; if the stored\n     * row's owner differs we throw `OwnerMismatchError` and DO NOT decrypt.\n     * Only on an owner match do we unwrap the DEK and open the value.\n     */\n    async get(input: GetInput): Promise<GetResult> {\n      const { ownerId, ref } = input;\n      if (!ownerId) throw new TypeError('secret-store.get: ownerId required');\n\n      const row = await backend.getByRef({ ownerId, ref });\n      if (!row) throw new SecretNotFoundError(ref);\n\n      // Owner isolation: never decrypt another owner's secret.\n      if (row.ownerId !== ownerId) {\n        throw new OwnerMismatchError(ref);\n      }\n\n      // Unwrap the DEK with the KEK that wrapped THIS row, then open the value.\n      // Any GCM failure (wrong KEK, tampered ciphertext) → DecryptError.\n      let value: string;\n      try {\n        const kek = await kekProvider.getKek(row.kekId);\n        const dek = unwrapDek(row, kek);\n        value = openValue(row, dek);\n      } catch {\n        throw new DecryptError(ref);\n      }\n\n      await backend.touchLastUsed({ id: row.id, lastUsedAt: now().toISOString() });\n      return { value };\n    },\n\n    async list(input: { ownerId: string }): Promise<SecretMetadata[]> {\n      const { ownerId } = input;\n      if (!ownerId) throw new TypeError('secret-store.list: ownerId required');\n\n      const rows = await backend.listByOwner(ownerId);\n      // Metadata ONLY — never the value or any ciphertext component.\n      return rows.map((row) => ({\n        name: row.name,\n        ref: row.ref,\n        version: row.version,\n        createdAt: row.createdAt,\n        lastUsedAt: row.lastUsedAt,\n      }));\n    },\n\n    async delete(input: { ownerId: string; ref: SecretRef }): Promise<{ deleted: boolean }> {\n      const { ownerId, ref } = input;\n      if (!ownerId) throw new TypeError('secret-store.delete: ownerId required');\n\n      const deleted = await backend.deleteByRef({ ownerId, ref });\n      return { deleted };\n    },\n\n    async rotateKek(input: RotateKekInput): Promise<RotateKekResult> {\n      const { fromKekId, toKekId } = input;\n      if (fromKekId === toKekId) {\n        throw new TypeError('secret-store.rotateKek: fromKekId and toKekId must differ');\n      }\n\n      const oldKek = await kekProvider.getKek(fromKekId);\n      const newKek = await kekProvider.getKek(toKekId);\n\n      const rows = await backend.listByKekId(fromKekId);\n      let rotated = 0;\n      for (const row of rows) {\n        // Unwrap the DEK under the OLD KEK; the value ciphertext is untouched.\n        let dek: Buffer;\n        try {\n          dek = unwrapDek(row, oldKek);\n        } catch {\n          throw new DecryptError(row.ref);\n        }\n        // Re-wrap the same DEK under the NEW KEK and persist the new wrapping.\n        const rewrapped = wrapDek(dek, newKek);\n        await backend.updateWrappedDek({\n          id: row.id,\n          wrappedDek: rewrapped.wrappedDek,\n          dekIv: rewrapped.dekIv,\n          dekAuthTag: rewrapped.dekAuthTag,\n          kekId: toKekId,\n        });\n        rotated += 1;\n      }\n      return { rotated };\n    },\n  };\n}\n\n// ── In-memory backend (exported, for tests / local dev) ──────────────────────\n\n/**\n * In-memory {@link SecretStoreBackend} for tests and local development. Holds\n * encrypted rows only — it never sees plaintext (the store seals before insert).\n * NOT for production: rows evaporate on process exit and enforce uniqueness in\n * a single process only.\n */\nexport function createInMemorySecretBackend(): SecretStoreBackend {\n  // Keyed by row id; secondary lookups scan (fine for tests / small dev sets).\n  const rows = new Map<string, SecretRow>();\n\n  const findByRef = (ownerId: string, ref: SecretRef): SecretRow | undefined => {\n    for (const row of rows.values()) {\n      if (row.ownerId === ownerId && row.ref === ref) return row;\n    }\n    return undefined;\n  };\n\n  return {\n    async insert(row: SecretRow): Promise<void> {\n      // Enforce UNIQUE(owner_id, name): replace any prior row for this pair so\n      // a re-put (version bump) supersedes rather than duplicates.\n      for (const [id, existing] of rows) {\n        if (existing.ownerId === row.ownerId && existing.name === row.name) {\n          rows.delete(id);\n        }\n      }\n      rows.set(row.id, row);\n    },\n\n    async getByRef({ ownerId, ref }): Promise<SecretRow | null> {\n      return findByRef(ownerId, ref) ?? null;\n    },\n\n    async getByName({ ownerId, name }): Promise<SecretRow | null> {\n      for (const row of rows.values()) {\n        if (row.ownerId === ownerId && row.name === name) return row;\n      }\n      return null;\n    },\n\n    async listByOwner(ownerId: string): Promise<SecretRow[]> {\n      return [...rows.values()].filter((row) => row.ownerId === ownerId);\n    },\n\n    async listByKekId(kekId: string): Promise<SecretRow[]> {\n      return [...rows.values()].filter((row) => row.kekId === kekId);\n    },\n\n    async deleteByRef({ ownerId, ref }): Promise<boolean> {\n      for (const [id, row] of rows) {\n        if (row.ownerId === ownerId && row.ref === ref) {\n          rows.delete(id);\n          return true;\n        }\n      }\n      return false;\n    },\n\n    async touchLastUsed({ id, lastUsedAt }): Promise<void> {\n      const row = rows.get(id);\n      if (row) row.lastUsedAt = lastUsedAt;\n    },\n\n    async updateWrappedDek({ id, wrappedDek, dekIv, dekAuthTag, kekId }): Promise<void> {\n      const row = rows.get(id);\n      if (!row) return;\n      row.wrappedDek = wrappedDek;\n      row.dekIv = dekIv;\n      row.dekAuthTag = dekAuthTag;\n      row.kekId = kekId;\n    },\n  };\n}\n\n// ── Postgres DDL (documented; this module does not execute SQL) ──────────────\n\n/**\n * Postgres schema for a production {@link SecretStoreBackend}. Ciphertext and\n * crypto metadata are `bytea`; plaintext is NEVER a column. `UNIQUE(owner_id,\n * name)` enforces one current secret per name per owner (re-put bumps version),\n * and `owner_id` is indexed for owner-scoped lookups and `list()`.\n *\n * Map this module's camelCase fields to the snake_case columns in the adapter.\n */\nexport const SECRET_STORE_DDL = `\nCREATE TABLE IF NOT EXISTS secret_store (\n  id            uuid PRIMARY KEY,\n  owner_id      text NOT NULL,\n  name          text NOT NULL,\n  ref           text NOT NULL,\n  ciphertext    bytea NOT NULL,\n  iv            bytea NOT NULL,\n  auth_tag      bytea NOT NULL,\n  wrapped_dek   bytea NOT NULL,\n  dek_iv        bytea NOT NULL,\n  dek_auth_tag  bytea NOT NULL,\n  kek_id        text NOT NULL,\n  version       int NOT NULL DEFAULT 1,\n  created_at    timestamptz NOT NULL DEFAULT now(),\n  last_used_at  timestamptz,\n  UNIQUE (owner_id, name)\n);\n\nCREATE INDEX IF NOT EXISTS secret_store_owner_id_idx ON secret_store (owner_id);\nCREATE INDEX IF NOT EXISTS secret_store_kek_id_idx ON secret_store (kek_id);\n` as const;\n","/**\n * Environment-backed KEK provider — DEV / BOOTSTRAP ONLY.\n *\n * Implements {@link KekProvider} by reading the master key-encryption-key(s) from\n * environment variables. This is the ONLY module in the secrets-broker that reads\n * `process.env` — the SecretStore itself never does; it depends on this provider\n * so the key source can be swapped without touching the crypto.\n *\n * ┌─ ⚠ PHASE-3 GATE (vault premortem, 2026-06-08) ──────────────────────────────┐\n * │ An env-var KEK is a SINGLE POINT OF TOTAL COMPROMISE: one leaked variable    │\n * │ unwraps EVERY user's stored secret. On this monorepo's shared deploy surface │\n * │ — where committed keys were found TWICE in the last 60 days — that risk is   │\n * │ unacceptable for real user secrets. Therefore:                              │\n * │   • This provider is for local dev, tests, and pre-GA bring-up ONLY.        │\n * │   • Before ANY real user secret is stored (GA), replace it with a           │\n * │     KMS/HSM-backed provider implementing the SAME `KekProvider` interface — │\n * │     no SecretStore change required. (premortem Phase 3.)                    │\n * └─────────────────────────────────────────────────────────────────────────────┘\n *\n * Env contract:\n *   SECRETS_VAULT_KEK_CURRENT = <kekId>          # e.g. \"v1\" — the active KEK id\n *   SECRETS_VAULT_KEK_<KEKID>  = <base64 32 bytes># e.g. SECRETS_VAULT_KEK_V1=...\n * Multiple `SECRETS_VAULT_KEK_<id>` vars may coexist so {@link SecretStore.rotateKek}\n * can unwrap historical rows under their original KEK while re-wrapping under the new one.\n *\n * @module secrets-broker/env-kek-provider\n */\n\nimport { randomBytes } from 'node:crypto';\nimport type { KekProvider } from './secret-store';\n\n/** AES-256 KEK length in bytes. */\nconst KEK_BYTES = 32;\n\n/** kekIds map to env var names, so constrain them to a safe token charset. */\nconst KEK_ID_RE = /^[A-Za-z0-9_]+$/;\n\n/** Thrown when the env KEK material is missing or malformed. Carries no key bytes. */\nexport class EnvKekConfigError extends Error {\n  constructor(message: string) {\n    super(`env-kek-provider: ${message}`);\n    this.name = 'EnvKekConfigError';\n  }\n}\n\nexport interface EnvKekProviderDeps {\n  /** Environment to read from. Defaults to `process.env`. Injectable for tests. */\n  env?: Record<string, string | undefined>;\n}\n\n/** The env var that names the current KEK id. */\nexport const KEK_CURRENT_ENV = 'SECRETS_VAULT_KEK_CURRENT';\n\n/** Build the env var name that holds the KEK bytes for a given id. */\nexport function kekEnvVar(kekId: string): string {\n  return `SECRETS_VAULT_KEK_${kekId.toUpperCase()}`;\n}\n\n/**\n * Generate a fresh 32-byte KEK, base64-encoded for placing in an env var.\n * Setup helper — print once, store in the secret manager, never log thereafter.\n */\nexport function generateKekBase64(): string {\n  return randomBytes(KEK_BYTES).toString('base64');\n}\n\nfunction assertKekId(kekId: string): void {\n  if (!KEK_ID_RE.test(kekId)) {\n    throw new EnvKekConfigError(`invalid kekId \"${kekId}\" (allowed: [A-Za-z0-9_])`);\n  }\n}\n\nfunction decodeKek(raw: string, kekId: string): Buffer {\n  const buf = Buffer.from(raw, 'base64');\n  if (buf.length !== KEK_BYTES) {\n    // Never include the value — only the (wrong) length.\n    throw new EnvKekConfigError(\n      `KEK \"${kekId}\" must be base64 of ${KEK_BYTES} bytes (got ${buf.length})`\n    );\n  }\n  return buf;\n}\n\n/**\n * Create an environment-backed {@link KekProvider}. DEV/BOOTSTRAP ONLY — see the\n * Phase-3 gate banner above before using with real user secrets.\n */\nexport function createEnvKekProvider(deps: EnvKekProviderDeps = {}): KekProvider {\n  const env = deps.env ?? process.env;\n\n  const currentKekId = (): string => {\n    const id = env[KEK_CURRENT_ENV];\n    if (!id) throw new EnvKekConfigError(`${KEK_CURRENT_ENV} is not set`);\n    assertKekId(id);\n    return id;\n  };\n\n  return {\n    // DEV/BOOTSTRAP only — the SecretStore's requireProductionGradeKek gate rejects this.\n    productionGrade: false,\n    currentKekId,\n    async getKek(kekId?: string): Promise<Buffer> {\n      const id = kekId ?? currentKekId();\n      assertKekId(id);\n      const raw = env[kekEnvVar(id)];\n      if (!raw) throw new EnvKekConfigError(`${kekEnvVar(id)} is not set`);\n      return decodeKek(raw, id);\n    },\n  };\n}\n","/**\n * KMS-backed KEK provider — the PRODUCTION KEK source for HoloKey (Phase-3 gate).\n *\n * The env provider (`env-kek-provider.ts`) keeps the master KEK in an environment\n * variable on the shared deploy surface — one leaked var unwraps the entire vault, and\n * committed-key incidents have hit that exact surface. This provider instead sources the\n * KEK from a vendor-agnostic **KMS / secret-manager keyring** — AWS KMS, GCP Secret\n * Manager, HashiCorp Vault, or a Railway secret scoped to ONLY the resolving service —\n * so the KEK is never on the shared env surface and key access is audited by the manager.\n *\n * Vendor-agnostic by construction: inject a {@link KmsKeyring} adapter; this module has\n * NO vendor SDK dependency. A vendor adapter is ~10 lines (call the SDK's get-secret /\n * decrypt and return 32 bytes). Marked `productionGrade: true`, so the SecretStore's\n * production gate (`requireProductionGradeKek`) accepts it where it rejects the env provider.\n *\n * NOTE on strength: this resolves the KEK BYTES into app memory at use-time (the\n * \"scoped secret manager\" pattern — the minimum the premortem requires). A stronger\n * future variant has the KMS/HSM wrap+unwrap the per-secret DEK directly so the root key\n * never leaves the HSM; that is a separate `KmsDekWrapper` seam, not this provider.\n *\n * @module secrets-broker/kms-kek-provider\n */\n\nimport type { KekProvider } from './secret-store';\n\n/** AES-256 KEK length in bytes. */\nconst KEK_BYTES = 32;\n\n/** Thrown when the KMS returns malformed key material. Carries no key bytes. */\nexport class KmsKekError extends Error {\n  constructor(message: string) {\n    super(`kms-kek-provider: ${message}`);\n    this.name = 'KmsKekError';\n  }\n}\n\n/**\n * Vendor-agnostic keyring the provider delegates to. A vendor adapter (AWS/GCP/Vault/\n * Railway-scoped) implements these two methods over its SDK — no other contract.\n */\nexport interface KmsKeyring {\n  /** Resolve the raw 32-byte KEK for `kekId` from the KMS / scoped secret store. */\n  resolveKekBytes(kekId: string): Promise<Buffer>;\n  /** The id of the KEK that `resolveKekBytes` returns for the current epoch. */\n  currentKekId(): string;\n}\n\nexport interface KmsKekProviderDeps {\n  keyring: KmsKeyring;\n}\n\n/**\n * Create the production {@link KekProvider} backed by a {@link KmsKeyring}. Validates the\n * returned material is exactly 32 bytes (never echoing it) and is marked production-grade.\n */\nexport function createKmsKekProvider(deps: KmsKekProviderDeps): KekProvider {\n  const { keyring } = deps;\n  return {\n    productionGrade: true,\n    currentKekId: () => keyring.currentKekId(),\n    async getKek(kekId?: string): Promise<Buffer> {\n      const id = kekId ?? keyring.currentKekId();\n      const kek = await keyring.resolveKekBytes(id);\n      if (!Buffer.isBuffer(kek) || kek.length !== KEK_BYTES) {\n        // Length only — never the value.\n        const len = Buffer.isBuffer(kek) ? kek.length : 'non-buffer';\n        throw new KmsKekError(\n          `KEK \"${id}\" from the keyring must be ${KEK_BYTES} bytes (got ${len})`\n        );\n      }\n      return kek;\n    },\n  };\n}\n","/**\n * Scoped-secret KMS keyring — the production KEK source for a Railway-style deploy.\n *\n * Implements {@link KmsKeyring} (consumed by `createKmsKekProvider`) by reading the KEK\n * from a DEDICATED, service-scoped secret namespace — distinct from the shared-surface\n * env the dev provider uses. The premortem's accepted minimum: \"a Railway secret scoped\n * to ONLY the one service that decrypts, never the shared root.\"\n *\n * Deployment contract (load-bearing — this is what makes it production-grade):\n *   - Set `HOLOKEY_PROD_KEK_CURRENT` + `HOLOKEY_PROD_KEK_<KEKID>` ONLY on the single\n *     service that resolves secrets, NEVER on the shared monorepo deploy root.\n *   - These vars must NOT appear in any `.env`, Dockerfile, or `railway.toml` committed to\n *     the repo — provision them in the platform secret UI for that one service.\n *\n * The distinct `HOLOKEY_PROD_*` prefix (vs the dev provider's `SECRETS_VAULT_KEK_*`) is the\n * signal that these are production, service-scoped material. Wrapping this in\n * `createKmsKekProvider` yields a `productionGrade: true` provider the SecretStore gate accepts.\n *\n * For a true cloud KMS / HSM (AWS KMS, GCP Secret Manager, Vault), write a ~10-line adapter\n * implementing the same {@link KmsKeyring} over its SDK instead of this env reader.\n *\n * @module secrets-broker/scoped-secret-keyring\n */\n\nimport type { KmsKeyring } from './kms-kek-provider';\n\nconst KEK_BYTES = 32;\nconst KEK_ID_RE = /^[A-Za-z0-9_]+$/;\nconst DEFAULT_PREFIX = 'HOLOKEY_PROD_KEK';\n\n/** Thrown when the scoped secret material is missing or malformed. Carries no key bytes. */\nexport class ScopedSecretKeyringError extends Error {\n  constructor(message: string) {\n    super(`scoped-secret-keyring: ${message}`);\n    this.name = 'ScopedSecretKeyringError';\n  }\n}\n\nexport interface ScopedSecretKeyringDeps {\n  /** Environment to read from. Defaults to `process.env`. Injectable for tests. */\n  env?: Record<string, string | undefined>;\n  /** Override the var prefix (default `HOLOKEY_PROD_KEK`). The `_CURRENT` / `_<KEKID>` suffixes apply. */\n  prefix?: string;\n}\n\n/**\n * Create a {@link KmsKeyring} backed by service-scoped secret env vars. Pass the result to\n * `createKmsKekProvider` to get the production KEK provider.\n */\nexport function createScopedSecretKeyring(deps: ScopedSecretKeyringDeps = {}): KmsKeyring {\n  const env = deps.env ?? process.env;\n  const prefix = deps.prefix ?? DEFAULT_PREFIX;\n  const currentVar = `${prefix}_CURRENT`;\n  const kekVar = (kekId: string): string => `${prefix}_${kekId.toUpperCase()}`;\n\n  const currentKekId = (): string => {\n    const id = env[currentVar];\n    if (!id) throw new ScopedSecretKeyringError(`${currentVar} is not set`);\n    if (!KEK_ID_RE.test(id))\n      throw new ScopedSecretKeyringError(`invalid kekId \"${id}\" (allowed: [A-Za-z0-9_])`);\n    return id;\n  };\n\n  return {\n    currentKekId,\n    async resolveKekBytes(kekId: string): Promise<Buffer> {\n      if (!KEK_ID_RE.test(kekId)) throw new ScopedSecretKeyringError(`invalid kekId \"${kekId}\"`);\n      const raw = env[kekVar(kekId)];\n      if (!raw) throw new ScopedSecretKeyringError(`${kekVar(kekId)} is not set`);\n      const buf = Buffer.from(raw, 'base64');\n      if (buf.length !== KEK_BYTES) {\n        throw new ScopedSecretKeyringError(\n          `${kekVar(kekId)} must be base64 of ${KEK_BYTES} bytes (got ${buf.length})`\n        );\n      }\n      return buf;\n    },\n  };\n}\n","/**\n * HoloKey resolve receipts — tamper-evident provenance for the custody \"log\" step.\n *\n * The resolver emits a {@link SecretResolveAudit} for every key handout (allowed or denied).\n * This module seals each audit into a hash-chained RECEIPT — a SHA-256 over the audit content\n * plus the previous receipt's hash — so the resolve log becomes append-only and tamper-evident:\n * any edit, deletion, or reorder breaks the chain and {@link verifyResolveReceiptChain} pinpoints\n * where. This is HoloKey's contribution to HoloGate's audit-receipt-chain (cf. `verify_cael_trace`),\n * the `log` in `identify → authorize → scope → admit → log`.\n *\n * Receipts carry ZERO secret material — only owner, ref, outcome, reason, time, and hashes.\n * Additive + side-effect-free: the resolver is untouched; an audit sink seals + persists.\n *\n * @module secrets-broker/resolve-receipt\n */\n\nimport { createHash } from 'node:crypto';\nimport type { SecretResolveAudit } from './secret-resolver';\n\n/** A sealed, hash-chained resolve receipt. Extends the audit with chain hashes. */\nexport interface SecretResolveReceipt extends SecretResolveAudit {\n  /** Hash of the previous receipt in the chain, or null at genesis. */\n  readonly prevHash: string | null;\n  /** `sha256:<hex>` over this receipt's content + prevHash. */\n  readonly receiptHash: string;\n}\n\n/** Canonical content hash (fixed field order; excludes receiptHash). */\nfunction contentHash(r: SecretResolveAudit & { prevHash: string | null }): string {\n  const canonical = JSON.stringify([\n    r.event,\n    r.ownerId,\n    r.ref,\n    r.purpose,\n    r.outcome,\n    r.reason,\n    r.at,\n    r.prevHash,\n  ]);\n  return `sha256:${createHash('sha256').update(canonical).digest('hex')}`;\n}\n\n/**\n * Seal a resolve audit into a chained receipt: stamps `prevHash` (the prior receipt's\n * `receiptHash`, or null for the first) and a content hash over the whole. Pure.\n */\nexport function sealResolveReceipt(\n  audit: SecretResolveAudit,\n  prevHash: string | null\n): SecretResolveReceipt {\n  return { ...audit, prevHash, receiptHash: contentHash({ ...audit, prevHash }) };\n}\n\n/**\n * Verify a receipt chain end-to-end. Returns `{ ok: true }` only when every receipt's\n * `receiptHash` matches its recomputed content hash AND its `prevHash` links to the prior\n * receipt's `receiptHash` (the first's `prevHash` must be null). On failure, `brokenAt` is\n * the index of the first receipt that fails — any tampered field, deletion, or reorder.\n */\nexport function verifyResolveReceiptChain(receipts: readonly SecretResolveReceipt[]): {\n  ok: boolean;\n  brokenAt: number | null;\n} {\n  let prev: string | null = null;\n  for (let i = 0; i < receipts.length; i++) {\n    const r = receipts[i];\n    if (r.prevHash !== prev) return { ok: false, brokenAt: i };\n    const expected = contentHash({\n      event: r.event,\n      ownerId: r.ownerId,\n      ref: r.ref,\n      purpose: r.purpose,\n      outcome: r.outcome,\n      reason: r.reason,\n      at: r.at,\n      prevHash: r.prevHash,\n    });\n    if (expected !== r.receiptHash) return { ok: false, brokenAt: i };\n    prev = r.receiptHash;\n  }\n  return { ok: true, brokenAt: null };\n}\n","/**\n * HoloKey secrets manifest — declare an app's secret NEEDS once, compile to many backends.\n *\n * This is the \"secrets-as-a-compile-target\" innovation: the `BrokerManifest.storage` enum\n * already anticipated `vault | github-actions-secret | env-file`, and this turns that into a\n * real emitter. A single {@link SecretsManifest} (names + descriptions, NEVER values)\n * compiles to:\n *   - `env-template`    — a `.env.example`-style scaffold (names only) for local onboarding.\n *   - `github-actions`  — `gh secret set …` commands + a workflow `env:` block that references them.\n *   - `holokey-vault`   — the `vault:<name>` refs + how to store (SecretStore.put) and consume\n *                         (`@needs_key`) them in HoloKey natively.\n *\n * So \"native vault vs GitHub secrets vs env\" stops being a fork: you declare once and emit the\n * backend your deployment needs. The manifest carries ZERO secret material — only names + metadata.\n *\n * @module secrets-broker/secrets-manifest\n */\n\n/** One declared secret an app needs. Carries NO value — only the name + metadata. */\nexport interface SecretDecl {\n  /** Env-var-style secret name, e.g. `OPENAI_API_KEY`. Becomes the `vault:<name>` key. */\n  name: string;\n  /** Human-readable description for templates / docs. */\n  description?: string;\n  /** Whether the app requires it. Defaults to true. */\n  required?: boolean;\n}\n\n/** An app's full secret-needs declaration. */\nexport interface SecretsManifest {\n  /** App / namespace name (used in headers). */\n  app: string;\n  secrets: readonly SecretDecl[];\n}\n\n/** Supported compile targets — mirrors `BrokerManifest.storage`. */\nexport type SecretsCompileTarget =\n  | 'env-template'\n  | 'github-actions'\n  | 'holokey-vault'\n  | 'infra-namespace';\n\n/** Thrown when a manifest is malformed (e.g. a non-env-var-style name). */\nexport class SecretsManifestError extends Error {\n  constructor(message: string) {\n    super(`secrets-manifest: ${message}`);\n    this.name = 'SecretsManifestError';\n  }\n}\n\nconst NAME_RE = /^[A-Z][A-Z0-9_]*$/;\n\nfunction validate(manifest: SecretsManifest): void {\n  if (!manifest.app) throw new SecretsManifestError('manifest.app is required');\n  if (!Array.isArray(manifest.secrets) || manifest.secrets.length === 0) {\n    throw new SecretsManifestError('manifest.secrets must be a non-empty array');\n  }\n  const seen = new Set<string>();\n  for (const s of manifest.secrets) {\n    if (!NAME_RE.test(s.name)) {\n      throw new SecretsManifestError(\n        `secret name \"${s.name}\" must be UPPER_SNAKE (^[A-Z][A-Z0-9_]*$)`\n      );\n    }\n    if (seen.has(s.name)) throw new SecretsManifestError(`duplicate secret name \"${s.name}\"`);\n    seen.add(s.name);\n  }\n}\n\nfunction isRequired(s: SecretDecl): boolean {\n  return s.required !== false;\n}\n\nfunction emitEnvTemplate(m: SecretsManifest): string {\n  const lines = [\n    `# ${m.app} — required secrets (.env). Fill values locally; never commit this file.`,\n    '',\n  ];\n  for (const s of m.secrets) {\n    const tag = isRequired(s) ? 'required' : 'optional';\n    if (s.description) lines.push(`# ${s.description}`);\n    lines.push(`# (${tag})`);\n    lines.push(`${s.name}=`);\n    lines.push('');\n  }\n  return lines.join('\\n').trimEnd() + '\\n';\n}\n\nfunction emitGithubActions(m: SecretsManifest): string {\n  const setCmds = [\n    `# Set ${m.app} secrets as GitHub Actions secrets (run once; values are prompted, never echoed):`,\n  ];\n  for (const s of m.secrets) {\n    if (s.description) setCmds.push(`# ${s.description}`);\n    setCmds.push(`gh secret set ${s.name}`);\n  }\n  const envBlock = ['', '# Reference them in a workflow step:', 'env:'];\n  for (const s of m.secrets) {\n    envBlock.push(`  ${s.name}: \\${{ secrets.${s.name} }}`);\n  }\n  return [...setCmds, ...envBlock].join('\\n') + '\\n';\n}\n\nfunction emitHoloKeyVault(m: SecretsManifest): string {\n  const lines = [\n    `# ${m.app} — HoloKey native vault refs`,\n    '#',\n    '# Store (server-side, per authenticated owner):',\n    `#   store.put({ ownerId, name: '<NAME>', value })`,\n    '# Consume in a HoloScript composition (value resolved at use-time, never in source):',\n    `#   object \"<X>\" @needs_key { ref: \"vault:<NAME>\", purpose: \"<why>\" }`,\n    '',\n  ];\n  for (const s of m.secrets) {\n    const tag = isRequired(s) ? 'required' : 'optional';\n    lines.push(`vault:${s.name}${s.description ? `   # ${s.description}` : ''} (${tag})`);\n  }\n  return lines.join('\\n') + '\\n';\n}\n\nfunction emitInfraNamespace(m: SecretsManifest): string {\n  const lines = [\n    `# ${m.app} — HoloKey infra namespace refs`,\n    '#',\n    '# Use from a Railway service, Jetson, or fleet worker after service identity is present.',\n    '# The resolver binds the value to the service owner and maps infra://<NAME> to vault:<NAME>.',\n    '# No human workspace secret:// ref or plaintext value is required.',\n    '',\n  ];\n  for (const s of m.secrets) {\n    const tag = isRequired(s) ? 'required' : 'optional';\n    lines.push(`infra://${s.name}${s.description ? `   # ${s.description}` : ''} (${tag})`);\n  }\n  return lines.join('\\n') + '\\n';\n}\n\n/**\n * Compile a {@link SecretsManifest} to a backend artifact. Pure; emits text only and never\n * includes secret values (the manifest has none).\n */\nexport function compileSecretsManifest(\n  manifest: SecretsManifest,\n  target: SecretsCompileTarget\n): string {\n  validate(manifest);\n  switch (target) {\n    case 'env-template':\n      return emitEnvTemplate(manifest);\n    case 'github-actions':\n      return emitGithubActions(manifest);\n    case 'holokey-vault':\n      return emitHoloKeyVault(manifest);\n    case 'infra-namespace':\n      return emitInfraNamespace(manifest);\n    default: {\n      // Exhaustiveness guard.\n      const never: never = target;\n      throw new SecretsManifestError(`unknown target \"${String(never)}\"`);\n    }\n  }\n}\n","/**\n * Secret access policy — the HoloGate `scope` axis for value resolution.\n *\n * HoloGate admits an entity through `identify → authorize → scope → admit → log`.\n * The {@link import('./secret-resolver').SecretResolver} already does identify/authorize\n * (fail-closed auth), admit (owner-bound `SecretStore.get`), and log (audit). This module\n * supplies the missing **scope** step: a least-authority constraint over WHICH refs a given\n * execution context may resolve — even for secrets the authenticated owner genuinely owns.\n *\n * Why ownership is not enough: a Brittney chat session and a Fleet deploy job can run under\n * the SAME authenticated owner, yet a chat turn has no business resolving `vault:FLEET_DEPLOY_KEY`.\n * Ownership answers \"is this yours?\"; scope answers \"may THIS context touch it?\". Defense in\n * depth — a mis-scoped consumer is contained to its allowlist instead of the owner's whole vault.\n *\n * Shape mirrors HoloDoor's allow/block lists (cf. `holodoor-routes.ts`): glob patterns over the\n * canonical `<surface>:<key>` ref. Semantics, chosen to fail in the SAFE direction:\n *   - `block` wins: a ref matching ANY block glob is denied, even if `allow` also matches it.\n *   - `allow` present (the key exists) ⇒ allowlist mode: the ref MUST match one entry.\n *       `allow: []` is therefore deny-all (an empty allowlist admits nothing) — programmatic\n *       callers whose `allow` collapses to empty fail CLOSED, never open.\n *   - `allow` absent (undefined) ⇒ no allowlist constraint (block-only mode).\n *   - `{}` (neither key) ⇒ no constraint; the policy is a no-op and ownership alone governs.\n *\n * This module is pure (no I/O, no secret material) and carries only ref labels — never values.\n *\n * @module secrets-broker/secret-access-policy\n */\n\nimport type { SecretRef } from './types';\n\n/**\n * A scope policy over secret refs. Glob patterns (`*` = any run incl. empty, `?` = one char)\n * match against the whole canonical ref (e.g. `vault:OPENAI_API_KEY`). See module docs for the\n * block-wins / allowlist-presence semantics.\n */\nexport interface SecretAccessPolicy {\n  /** Globs a ref MUST match (when the key is present). `[]` denies all; absent = unconstrained. */\n  readonly allow?: readonly string[];\n  /** Globs that, when matched, deny regardless of {@link allow}. */\n  readonly block?: readonly string[];\n}\n\n/** Outcome of {@link checkSecretAccess}. `reason` is the denial cause, or null when allowed. */\nexport interface SecretAccessDecision {\n  readonly allowed: boolean;\n  /** `'blocked'` | `'not-in-allowlist'` when denied; `null` when allowed. */\n  readonly reason: 'blocked' | 'not-in-allowlist' | null;\n}\n\n/** Thrown by the resolver when a scope policy denies a ref. Carries the ref + cause, no patterns. */\nexport class PolicyDeniedError extends Error {\n  readonly ref: SecretRef;\n  /** Why it was denied: `'blocked'` or `'not-in-allowlist'`. */\n  readonly reason: 'blocked' | 'not-in-allowlist';\n  constructor(ref: SecretRef, reason: 'blocked' | 'not-in-allowlist') {\n    super(`secret-access-policy: ${ref} denied by scope (${reason})`);\n    this.name = 'PolicyDeniedError';\n    this.ref = ref;\n    this.reason = reason;\n  }\n}\n\nconst REGEX_META = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * Compile a glob (`*` / `?` wildcards) to an anchored RegExp. Every other character is treated\n * literally — regex metacharacters are escaped so a ref like `vault:K.EY` cannot be matched by\n * an unintended `.`. Never throws.\n */\nfunction globToRegExp(glob: string): RegExp {\n  let out = '^';\n  for (const ch of glob) {\n    if (ch === '*') out += '.*';\n    else if (ch === '?') out += '.';\n    else out += ch.replace(REGEX_META, '\\\\$&');\n  }\n  return new RegExp(`${out}$`);\n}\n\n/**\n * Decide whether `ref` may be resolved under `policy`. Pure; evaluates block-first, then the\n * allowlist (see module docs). Returns a decision — it does NOT throw; the resolver turns a\n * `{ allowed: false }` into a {@link PolicyDeniedError} so the value boundary stays single-sourced.\n */\nexport function checkSecretAccess(policy: SecretAccessPolicy, ref: SecretRef): SecretAccessDecision {\n  // block wins — a blocked ref is denied even if an allow entry would admit it.\n  if (policy.block) {\n    for (const pattern of policy.block) {\n      if (globToRegExp(pattern).test(ref)) return { allowed: false, reason: 'blocked' };\n    }\n  }\n  // allowlist — presence of the key means \"only these\"; an empty list admits nothing.\n  if (policy.allow !== undefined) {\n    const matched = policy.allow.some((pattern) => globToRegExp(pattern).test(ref));\n    if (!matched) return { allowed: false, reason: 'not-in-allowlist' };\n  }\n  return { allowed: true, reason: null };\n}\n","/**\n * Secret resolver — the FAIL-CLOSED, audited value-resolution entry point.\n *\n * This is the one blessed path through which server-side consumers (Studio /\n * Brittney, the Fleet job runner) turn an authenticated user identity + a\n * `vault:<key>` ref into a plaintext secret. Secret VALUES never cross the MCP\n * wire — the broker tools stay handle/lease-only; value resolution happens here,\n * inside the trusted server, with the caller's OWN established auth.\n *\n * ── Gate-first invariant (vault premortem, 2026-06-08) ───────────────────────\n *   1. FAIL CLOSED: a resolve with no authenticated owner is DENIED — it never\n *      reaches the store and never returns a value. There is no admin/default\n *      fallback. (This is the \"gate is live and tested to DENY before it is\n *      taught to return a value\" requirement, enforced at the value boundary.)\n *   2. SCOPED (optional): when an access policy is supplied — at the resolver\n *      level and/or per call — the ref is checked against it BEFORE the store is\n *      touched, so an out-of-scope ref never decrypts (no value, no timing\n *      oracle). This is HoloGate's `scope` axis: least-authority per execution\n *      context, layered on top of ownership. Either layer can deny; neither widens.\n *   3. OWNER-BOUND: the authenticated owner is passed straight to\n *      `SecretStore.get`, which re-checks ownership inside itself — so isolation\n *      holds even if a future caller is mis-wired.\n *   4. AUDITED: every attempt (allowed OR denied) emits an audit event carrying\n *      only owner + ref + outcome — never the value.\n *\n * Consumers MUST derive `authenticatedOwnerId` from verified auth (Studio\n * session subject, Fleet seat owner) — NEVER from untrusted request input.\n *\n * @module secrets-broker/secret-resolver\n */\n\nimport {\n  DecryptError,\n  OwnerMismatchError,\n  SecretNotFoundError,\n  type SecretStore,\n} from './secret-store';\nimport {\n  checkSecretAccess,\n  PolicyDeniedError,\n  type SecretAccessPolicy,\n} from './secret-access-policy';\nimport type { SecretRef } from './types';\n\n/** Thrown when a resolve is attempted without an authenticated owner identity. */\nexport class AuthRequiredError extends Error {\n  readonly ref: SecretRef;\n  constructor(ref: SecretRef) {\n    super(`secret-resolver: refusing to resolve ${ref} without an authenticated owner`);\n    this.name = 'AuthRequiredError';\n    this.ref = ref;\n  }\n}\n\n/** Audit record emitted on EVERY resolve attempt. Carries no secret material. */\nexport interface SecretResolveAudit {\n  readonly event: 'secret.resolve';\n  /** Authenticated owner that attempted the resolve (or '<none>' when unauthenticated). */\n  readonly ownerId: string;\n  /** The ref that was requested. */\n  readonly ref: SecretRef;\n  /** Optional human-readable purpose for compliance. */\n  readonly purpose: string | null;\n  /** Whether a value was returned. */\n  readonly outcome: 'allowed' | 'denied';\n  /** Denial reason (error name) when `outcome === 'denied'`. */\n  readonly reason: string | null;\n  /** ISO 8601 timestamp. */\n  readonly at: string;\n}\n\nexport interface SecretResolverDeps {\n  store: SecretStore;\n  /** Audit sink — called for every attempt (allowed + denied). Defaults to no-op. */\n  audit?: (event: SecretResolveAudit) => void;\n  /**\n   * Optional resolver-level scope policy (HoloGate `scope`). When set it is enforced on\n   * EVERY resolve as a backstop — an out-of-scope ref is denied BEFORE the store is touched\n   * (no decrypt, no value, no timing oracle). A per-call {@link ResolveInput.scope} narrows\n   * it further; neither layer can widen what ownership already permits.\n   */\n  policy?: SecretAccessPolicy;\n  /** Optional fixed clock for deterministic tests. */\n  now?: () => Date;\n}\n\nexport interface ResolveInput {\n  /**\n   * Authenticated caller identity. MUST come from verified server-side auth\n   * (Studio session / Fleet seat) — never from untrusted request input. An empty\n   * or missing value is treated as unauthenticated and DENIED.\n   */\n  authenticatedOwnerId: string | undefined | null;\n  /** Canonical ref of the secret to resolve. */\n  ref: SecretRef;\n  /** Optional purpose recorded in the audit trail. */\n  purpose?: string;\n  /**\n   * Optional per-call scope policy (HoloGate `scope`). Narrows the resolver-level\n   * {@link SecretResolverDeps.policy} for THIS execution context (e.g. a Brittney chat\n   * turn vs a Fleet deploy job sharing one owner). Both must allow; a scope can only\n   * restrict, never widen.\n   */\n  scope?: SecretAccessPolicy;\n}\n\nexport interface SecretResolver {\n  /**\n   * Resolve a secret value for an authenticated owner. Throws — never returns a\n   * value — when unauthenticated ({@link AuthRequiredError}), when a scope policy\n   * denies the ref ({@link PolicyDeniedError}, before the store is touched), when\n   * the owner does not own the secret ({@link OwnerMismatchError}), when it is\n   * absent ({@link SecretNotFoundError}), or on a decrypt failure ({@link DecryptError}).\n   */\n  resolve(input: ResolveInput): Promise<{ value: string }>;\n}\n\n/**\n * Create a fail-closed, audited {@link SecretResolver} over a {@link SecretStore}.\n */\nexport function createSecretResolver(deps: SecretResolverDeps): SecretResolver {\n  const audit = deps.audit ?? (() => {});\n  const now = deps.now ?? (() => new Date());\n\n  const emit = (\n    ownerId: string,\n    ref: SecretRef,\n    purpose: string | null,\n    outcome: 'allowed' | 'denied',\n    reason: string | null\n  ): void => {\n    audit({\n      event: 'secret.resolve',\n      ownerId,\n      ref,\n      purpose,\n      outcome,\n      reason,\n      at: now().toISOString(),\n    });\n  };\n\n  return {\n    async resolve({\n      authenticatedOwnerId,\n      ref,\n      purpose,\n      scope,\n    }: ResolveInput): Promise<{ value: string }> {\n      const purposeOrNull = purpose ?? null;\n\n      // (1) FAIL CLOSED — no authenticated owner means no value, full stop.\n      if (!authenticatedOwnerId) {\n        emit('<none>', ref, purposeOrNull, 'denied', 'AuthRequiredError');\n        throw new AuthRequiredError(ref);\n      }\n\n      // (2) SCOPE — least-authority per execution context (HoloGate `scope`).\n      // Checked BEFORE the store so an out-of-scope ref never decrypts: no value\n      // is produced and no timing oracle separates out-of-scope from absent. The\n      // resolver-level policy is a backstop; the per-call scope narrows it. Either\n      // may deny; neither widens what ownership already permits.\n      for (const policy of [deps.policy, scope]) {\n        if (!policy) continue;\n        const decision = checkSecretAccess(policy, ref);\n        if (!decision.allowed) {\n          emit(authenticatedOwnerId, ref, purposeOrNull, 'denied', 'PolicyDeniedError');\n          throw new PolicyDeniedError(ref, decision.reason ?? 'not-in-allowlist');\n        }\n      }\n\n      // (3) OWNER-BOUND — the store re-checks ownership inside get().\n      try {\n        const { value } = await deps.store.get({ ownerId: authenticatedOwnerId, ref });\n        // (4) AUDITED — record the allow.\n        emit(authenticatedOwnerId, ref, purposeOrNull, 'allowed', null);\n        return { value };\n      } catch (err) {\n        const reason =\n          err instanceof OwnerMismatchError ||\n          err instanceof SecretNotFoundError ||\n          err instanceof DecryptError\n            ? err.name\n            : err instanceof Error\n              ? err.name\n              : 'UnknownError';\n        // (4) AUDITED — record the denial, then propagate (no value escapes).\n        emit(authenticatedOwnerId, ref, purposeOrNull, 'denied', reason);\n        throw err;\n      }\n    },\n  };\n}\n","/**\n * `@needs_key` — HoloKey's HoloScript-native trait: secrets as composable capabilities.\n *\n * This is the differentiating piece of HoloKey (the custody axis of HoloGate). A\n * HoloScript object declares the keys it needs as a TRAIT — the source carries only\n * the audit-safe REF, never the value:\n *\n *   object \"BrittneyCall\" @needs_key { ref: \"vault:OPENAI_API_KEY\", purpose: \"llm-call\" }\n *\n * At runtime the trait resolves the secret AT USE-TIME through HoloKey's fail-closed,\n * owner-bound resolver (`secret-resolver.ts`) and stashes the plaintext TRANSIENTLY on\n * the in-memory node carrier (`node.__resolvedSecrets[ref]`) for sibling traits on the\n * same node to consume — it is NEVER written to durable runtime state and NEVER placed\n * in an emitted event payload.\n *\n * Wiring is the same `registerTrait(name, handler)` seam the domain-plugin traits use,\n * so a runtime that has registered `@needs_key` dispatches it like any other trait. The\n * app binds the resolver + the AUTHENTICATED OWNER (from a Studio session / Fleet seat)\n * when it registers the trait — so a runtime with no authenticated owner FAILS CLOSED:\n * the trait emits `needs_key_denied`, no secret is resolved.\n *\n * Events (none carry the value):\n *   - `needs_key_ready`  { nodeId, ref, purpose }   — secret resolved + stashed for siblings.\n *   - `needs_key_denied` { nodeId, ref, reason }    — fail-closed (unauthenticated / not_owner / not_found / decrypt_failed).\n *   - `needs_key_error`  { nodeId, error }          — malformed config (missing ref).\n *\n * @module secrets-broker/needs-key-trait\n */\n\nimport { DecryptError, OwnerMismatchError, SecretNotFoundError } from './secret-store';\nimport type { SecretRef } from './types';\nimport { AuthRequiredError, type SecretResolver } from './secret-resolver';\n\n/** Config carried by an orb's `@needs_key` directive. `ref` is required (`vault:<name>`). */\nexport interface NeedsKeyConfig {\n  ref?: SecretRef;\n  /** Optional purpose recorded in the HoloKey resolve audit. */\n  purpose?: string;\n}\n\n/**\n * The slice of the runtime trait-dispatch context `@needs_key` uses. `emit` is the\n * standard trait event sink; `provideSecret` (optional) lets the runtime route the\n * resolved value to sibling traits through a channel of its choosing — the trait also\n * always stashes it on `node.__resolvedSecrets` regardless.\n */\nexport interface NeedsKeyDispatchContext {\n  emit(event: string, payload?: unknown): void;\n  /** Optional: hand the resolved value to the runtime for same-node sibling use. */\n  provideSecret?(ref: SecretRef, value: string): void;\n}\n\n/**\n * Binding the app supplies when registering the trait: the HoloKey resolver plus the\n * AUTHENTICATED owner for this runtime. `authenticatedOwnerId` MUST come from verified\n * server-side auth (Studio session subject / Fleet seat owner) — never user input. An\n * absent/empty owner makes every resolve fail closed.\n */\nexport interface NeedsKeyResolution {\n  resolver: SecretResolver;\n  authenticatedOwnerId?: string | null;\n}\n\n/** Structural trait handler shape (matches the domain-plugin trait handlers). */\nexport interface NeedsKeyTraitHandler {\n  name: 'needs_key';\n  onAttach(\n    node: unknown,\n    config: NeedsKeyConfig | undefined,\n    context: NeedsKeyDispatchContext\n  ): Promise<void>;\n  onUpdate(\n    node: unknown,\n    config: NeedsKeyConfig | undefined,\n    context: NeedsKeyDispatchContext\n  ): Promise<void>;\n}\n\n/** In-memory node carrier for the transient resolved-secret slot. Never persisted. */\ninterface NeedsKeyNode {\n  id?: string;\n  name?: string;\n  /** Transient, in-memory plaintext for sibling traits on this node. NEVER persisted/emitted. */\n  __resolvedSecrets?: Record<string, string>;\n}\n\n/** Map a resolver error to an audit-safe, value-free denial reason. */\nfunction denialReason(err: unknown): string {\n  if (err instanceof AuthRequiredError) return 'unauthenticated';\n  if (err instanceof OwnerMismatchError) return 'not_owner';\n  if (err instanceof SecretNotFoundError) return 'not_found';\n  if (err instanceof DecryptError) return 'decrypt_failed';\n  return 'error';\n}\n\n/**\n * Create the `@needs_key` trait handler bound to a {@link NeedsKeyResolution}. The\n * handler resolves the declared ref through HoloKey at attach/update and stashes the\n * value transiently for sibling traits — fail-closed and value-free in all events.\n */\nexport function createNeedsKeyHandler(resolution: NeedsKeyResolution): NeedsKeyTraitHandler {\n  async function resolveOnto(\n    node: unknown,\n    config: NeedsKeyConfig | undefined,\n    context: NeedsKeyDispatchContext\n  ): Promise<void> {\n    const carrier = node as NeedsKeyNode;\n    const nodeId = carrier.id ?? carrier.name ?? 'unknown';\n    const ref = config?.ref;\n\n    if (!ref) {\n      context.emit('needs_key_error', {\n        nodeId,\n        error: 'needs_key trait requires config.ref (a vault:<name> SecretRef)',\n      });\n      return;\n    }\n\n    try {\n      const { value } = await resolution.resolver.resolve({\n        authenticatedOwnerId: resolution.authenticatedOwnerId,\n        ref,\n        purpose: config?.purpose,\n      });\n      // Transient, in-memory ONLY — for sibling traits on this node. Never persisted,\n      // never emitted. The runtime's durable state never sees the plaintext.\n      carrier.__resolvedSecrets = { ...(carrier.__resolvedSecrets ?? {}), [ref]: value };\n      context.provideSecret?.(ref, value);\n      // The \"ready\" signal carries the ref + purpose, NOT the value.\n      context.emit('needs_key_ready', { nodeId, ref, purpose: config?.purpose ?? null });\n    } catch (err) {\n      // Fail closed: no value reached the node, and none is emitted.\n      context.emit('needs_key_denied', { nodeId, ref, reason: denialReason(err) });\n    }\n  }\n\n  return { name: 'needs_key', onAttach: resolveOnto, onUpdate: resolveOnto };\n}\n\n/** A runtime that can register behavioral trait handlers (e.g. HoloScriptRuntime). */\nexport interface TraitRegistrarTarget {\n  registerTrait(name: string, handler: unknown): void;\n}\n\n/**\n * Register the `@needs_key` trait into a runtime, bound to a resolver + authenticated\n * owner. After this, the runtime's directive dispatch resolves `@needs_key` orbs through\n * HoloKey at use-time. Mirrors the domain-plugin `register*TraitHandlers` shape.\n */\nexport function registerNeedsKeyTrait(\n  registrar: TraitRegistrarTarget,\n  resolution: NeedsKeyResolution\n): void {\n  registrar.registerTrait('needs_key', createNeedsKeyHandler(resolution));\n}\n","/**\n * HoloKey vault bootstrap — the single place that turns the encrypted value-store ON.\n *\n * Phase 0 of the operational-secret migration (research/2026-06-16_holokey-operational-\n * secret-migration.md). The secrets-broker package ships every piece — `SecretStore`,\n * the Postgres backend, KEK providers, the fail-closed resolver — but nothing instantiates\n * them in a live server: only an in-memory *lease* adapter runs (W.705, built-but-dead-\n * wired). This factory assembles them from config so an agent/service can finally\n * `put`/`get`/`resolve` a secret at runtime.\n *\n * FLAG-GATED so it can never break a boot: with no KEK configured it returns `null` and\n * the caller falls back to its prior behavior. A misconfigured prod KEK (a dev KEK under\n * `NODE_ENV=production`) is logged and also returns `null` rather than throwing. So wiring\n * `createHoloKeyVault()` into a server bootstrap is purely additive — absent config = the\n * exact prior behavior.\n *\n * The bootstrap secret model (research §bootstrap): a service is configured with ONE\n * KEK (a Railway managed/sealed var) and a DB URL; with those it decrypts every other\n * secret from the vault at runtime. N plaintext keys per service → 1 rotatable KEK.\n *\n * @module secrets-broker/vault-bootstrap\n */\n\nimport {\n  createSecretStore,\n  createInMemorySecretBackend,\n  type SecretStore,\n  type SecretStoreBackend,\n  type KekProvider,\n} from './secret-store';\nimport { createPostgresSecretBackend, type SecretQueryRunner } from './postgres-secret-backend';\nimport { createEnvKekProvider, KEK_CURRENT_ENV } from './env-kek-provider';\nimport { createScopedSecretKeyring } from './scoped-secret-keyring';\nimport { createKmsKekProvider } from './kms-kek-provider';\nimport {\n  createSecretResolver,\n  type SecretResolver,\n  type SecretResolveAudit,\n} from './secret-resolver';\n\ntype Env = Record<string, string | undefined>;\n\n/** Env var naming the current PRODUCTION, service-scoped KEK id (vs the dev `SECRETS_VAULT_KEK_*`). */\nexport const PROD_KEK_CURRENT_ENV = 'HOLOKEY_PROD_KEK_CURRENT';\n\nexport interface HoloKeyVault {\n  /** Encrypt + store / metadata / delete / rotate. Owner-isolated. */\n  readonly store: SecretStore;\n  /** Fail-closed, owner-bound, audited value resolution for trusted server-side consumers. */\n  readonly resolver: SecretResolver;\n  /** Which KEK backed the store — `production` (KMS/scoped-keyring) or `dev` (env KEK). */\n  readonly kekGrade: 'production' | 'dev';\n  /** Which persistence backend — `postgres` (durable) or `in-memory` (non-persistent / tests). */\n  readonly backend: 'postgres' | 'in-memory';\n}\n\nexport interface CreateHoloKeyVaultOpts {\n  /** Environment to read KEK material + NODE_ENV from. Defaults to `process.env`. */\n  env?: Env;\n  /** Injected pg query runner (a bound `pool.query`). Absent → in-memory backend (non-persistent). */\n  query?: SecretQueryRunner['query'];\n  /** Audit sink for every resolve attempt (allowed + denied). Never carries the value. */\n  audit?: (e: SecretResolveAudit) => void;\n}\n\n/**\n * Pick a KEK provider from env: prefer the production scoped-keyring (`HOLOKEY_PROD_KEK_*`,\n * `productionGrade: true`); fall back to the dev env KEK (`SECRETS_VAULT_KEK_*`). Returns\n * null when NEITHER is set — the flag-gate that keeps the vault OFF.\n */\nfunction pickKek(env: Env): { kek: KekProvider; grade: 'production' | 'dev' } | null {\n  if (env[PROD_KEK_CURRENT_ENV]) {\n    return {\n      kek: createKmsKekProvider({ keyring: createScopedSecretKeyring({ env }) }),\n      grade: 'production',\n    };\n  }\n  if (env[KEK_CURRENT_ENV]) {\n    return { kek: createEnvKekProvider({ env }), grade: 'dev' };\n  }\n  return null;\n}\n\n/**\n * Assemble the HoloKey vault from config, or return `null` (vault OFF) when no KEK is\n * configured or the prod gate rejects a dev KEK. Never throws on config — a boot wiring\n * this in keeps its prior behavior when unconfigured.\n */\nexport function createHoloKeyVault(opts: CreateHoloKeyVaultOpts = {}): HoloKeyVault | null {\n  const env = opts.env ?? process.env;\n  const picked = pickKek(env);\n  if (!picked) return null; // no KEK → vault OFF; caller keeps its prior behavior.\n\n  const backend: SecretStoreBackend = opts.query\n    ? createPostgresSecretBackend({ query: opts.query })\n    : createInMemorySecretBackend();\n\n  const requireProductionGradeKek = env.NODE_ENV === 'production';\n  let store: SecretStore;\n  try {\n    store = createSecretStore({ backend, kekProvider: picked.kek, requireProductionGradeKek });\n  } catch (err) {\n    // InsecureKekError (prod + dev KEK) or a KEK config error — stay OFF rather than break the boot.\n    // eslint-disable-next-line no-console\n    console.warn(\n      `[holokey] vault NOT enabled: ${err instanceof Error ? err.name : 'config error'} ` +\n        `(kekGrade=${picked.grade}, NODE_ENV=${env.NODE_ENV ?? 'unset'}). Falling back to vault-off.`\n    );\n    return null;\n  }\n\n  const resolver = createSecretResolver({ store, audit: opts.audit });\n  return {\n    store,\n    resolver,\n    kekGrade: picked.grade,\n    backend: opts.query ? 'postgres' : 'in-memory',\n  };\n}\n","/**\n * Service/fleet HoloKey identity.\n *\n * Studio users already arrive with a human owner id. Operational services do\n * not: they boot from Railway, Jetson seats, fleet workers, or an x402 bearer.\n * This module turns those runtime facts into an audit-safe owner id in the\n * `infra://` namespace, then normalizes `infra://<SECRET>` refs to the existing\n * encrypted `vault:<SECRET>` store key for that owner.\n *\n * The x402 path hashes the bearer. A bearer may prove custody, but it must not\n * become an owner id or log line in plaintext.\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type { SecretRef } from './types';\n\ntype Env = Record<string, string | undefined>;\n\nexport type ServiceIdentitySource =\n  | 'explicit'\n  | 'holomesh-agent'\n  | 'fleet-seat'\n  | 'railway-service'\n  | 'x402-bearer'\n  | 'fallback';\n\nexport interface ServiceIdentity {\n  /** Owner id used against SecretStore/SecretResolver. */\n  readonly ownerId: string;\n  /** Where the owner id came from. */\n  readonly source: ServiceIdentitySource;\n  /** Operational secrets live outside human workspace refs. */\n  readonly namespace: 'infra';\n  /** Human-readable audit label. Carries no secret material. */\n  readonly label: string;\n}\n\nexport interface ResolveServiceIdentityOpts {\n  /** Environment to inspect. Defaults to process.env at the call site. */\n  env?: Env;\n  /** Explicit owner override. Preserves compatibility with HOLOKEY_OWNER. */\n  owner?: string;\n  /** Final fallback when no operational identity signal is present. */\n  fallbackOwner?: string;\n}\n\nexport interface NormalizedServiceSecretRef {\n  /** Store-level ref. HoloKey value storage remains vault-backed. */\n  readonly ref: SecretRef;\n  /** Environment variable name used for fallback reads. */\n  readonly envName: string;\n  /** Ref namespace the caller used. */\n  readonly namespace: 'infra' | 'vault' | 'env-name';\n}\n\nconst SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;\n\nfunction firstSet(env: Env, names: readonly string[]): string | undefined {\n  for (const name of names) {\n    const value = env[name]?.trim();\n    if (value) return value;\n  }\n  return undefined;\n}\n\nfunction ownerUri(kind: 'agent' | 'fleet-seat' | 'service' | 'x402', raw: string): string {\n  return `infra://${kind}/${encodeURIComponent(raw)}`;\n}\n\nfunction bearerFingerprint(raw: string): string {\n  return createHash('sha256').update(raw).digest('hex').slice(0, 20);\n}\n\nfunction identity(ownerId: string, source: ServiceIdentitySource, label: string): ServiceIdentity {\n  return Object.freeze({ ownerId, source, namespace: 'infra' as const, label });\n}\n\n/**\n * Resolve the current service/fleet owner identity from explicit config or\n * operational runtime facts, ordered from strongest stable identity to weakest.\n */\nexport function resolveServiceIdentity(opts: ResolveServiceIdentityOpts = {}): ServiceIdentity {\n  const env = opts.env ?? process.env;\n  const explicit = opts.owner?.trim() || env.HOLOKEY_OWNER?.trim();\n  if (explicit) return identity(explicit, 'explicit', explicit);\n\n  const agentId = firstSet(env, ['HOLOMESH_AGENT_ID', 'HOLOMESH_AGENTID', 'AGENT_ID']);\n  if (agentId) {\n    return identity(ownerUri('agent', agentId), 'holomesh-agent', `HoloMesh agent ${agentId}`);\n  }\n\n  const fleetSeat = firstSet(env, [\n    'HOLOMESH_FLEET_SEAT',\n    'FLEET_SEAT_ID',\n    'FLEET_AGENT_ID',\n    'HOLOMESH_HANDLE',\n  ]);\n  if (fleetSeat) {\n    return identity(\n      ownerUri('fleet-seat', fleetSeat),\n      'fleet-seat',\n      `HoloMesh fleet seat ${fleetSeat}`\n    );\n  }\n\n  const railwayService = firstSet(env, ['RAILWAY_SERVICE_ID', 'RAILWAY_SERVICE_NAME']);\n  if (railwayService) {\n    return identity(\n      ownerUri('service', railwayService),\n      'railway-service',\n      `Railway service ${railwayService}`\n    );\n  }\n\n  const x402Bearer = firstSet(env, [\n    'HOLOMESH_X402_BEARER',\n    'X402_BEARER',\n    'HOLOMESH_API_KEY_X402',\n  ]);\n  if (x402Bearer) {\n    const fp = bearerFingerprint(x402Bearer);\n    return identity(ownerUri('x402', fp), 'x402-bearer', `x402 bearer sha256:${fp}`);\n  }\n\n  const fallback = opts.fallbackOwner ?? 'infra';\n  return identity(fallback, 'fallback', fallback);\n}\n\nfunction assertSecretName(name: string, original: string): string {\n  const trimmed = name.trim();\n  if (!SECRET_NAME_RE.test(trimmed)) {\n    throw new TypeError(\n      `service-secret-ref: \"${original}\" must resolve to an UPPER_SNAKE secret name`\n    );\n  }\n  return trimmed;\n}\n\nfunction lastPathSegment(ref: string): string {\n  const parts = ref.split('/').filter(Boolean);\n  return parts[parts.length - 1] ?? '';\n}\n\n/**\n * Normalize service secret refs.\n *\n * Accepted inputs:\n *   - `OPENAI_API_KEY`             -> env fallback + `vault:OPENAI_API_KEY`\n *   - `vault:OPENAI_API_KEY`       -> explicit vault ref\n *   - `infra://OPENAI_API_KEY`     -> operational namespace for this service\n *   - `infra://mcp/OPENAI_API_KEY` -> same, with an audit-friendly grouping path\n */\nexport function normalizeServiceSecretRef(input: string): NormalizedServiceSecretRef {\n  const raw = input.trim();\n  if (raw.startsWith('infra://')) {\n    const body = raw.slice('infra://'.length);\n    const decoded = decodeURIComponent(lastPathSegment(body));\n    const envName = assertSecretName(decoded, input);\n    return { ref: `vault:${envName}`, envName, namespace: 'infra' };\n  }\n  if (raw.startsWith('vault:')) {\n    const envName = assertSecretName(raw.slice('vault:'.length), input);\n    return { ref: `vault:${envName}`, envName, namespace: 'vault' };\n  }\n  const envName = assertSecretName(raw, input);\n  return { ref: `vault:${envName}`, envName, namespace: 'env-name' };\n}\n\n/** Build the operational namespace ref for a service secret name. */\nexport function infraSecretRef(name: string): SecretRef {\n  const envName = assertSecretName(name, name);\n  return `infra://${envName}`;\n}\n","/**\n * Service-side secret resolution — the Phase 1 \"resolve from the vault, else process.env\" bridge.\n *\n * A long-running service (or fleet agent) resolves its OWN config secrets through one helper: if the\n * HoloKey vault is ON and holds the secret for this service's owner, return it (decrypted at\n * use-time); otherwise FALL BACK to `process.env[name]` — the exact prior behavior. So a consumer\n * can swap `process.env.OPENAI_API_KEY` for `resolve('OPENAI_API_KEY')` with ZERO risk: until the\n * key is put in the vault nothing changes; once it is, the consumer transparently picks it up. This\n * is the incremental migration off per-service plaintext env — no flag day, no boot coupling.\n *\n * Service identity (Phase 1): the owner is derived from `HOLOKEY_OWNER`, HoloMesh agent id,\n * fleet seat, Railway service id/name, or an x402 bearer fingerprint. Operational secret refs may\n * use the `infra://<NAME>` namespace; they resolve for the service owner without going through\n * Studio's human workspace namespace.\n *\n * Fail-safe by construction: the vault is built lazily on first resolve and cached; ANY failure\n * (no KEK, DDL/pool error, decrypt error, not-found, denied) falls through to `process.env`. The\n * helper logs ONE affirmation line (vault ON / OFF) so a silently-off vault is observable — the\n * premortem's explicit-affirmation requirement.\n *\n * @module secrets-broker/service-secret-resolver\n */\n\nimport { createHoloKeyVault, type HoloKeyVault } from './vault-bootstrap';\nimport type { SecretQueryRunner } from './postgres-secret-backend';\nimport type { SecretResolveAudit } from './secret-resolver';\nimport {\n  normalizeServiceSecretRef,\n  resolveServiceIdentity,\n  type ServiceIdentity,\n  type NormalizedServiceSecretRef,\n} from './service-identity';\n\ntype Env = Record<string, string | undefined>;\n\nexport interface ServiceSecretResolverOpts {\n  /** Environment to read KEK material + fall-back values from. Defaults to `process.env`. */\n  env?: Env;\n  /** Injected pg query runner (bound `pool.query`). Absent → in-memory backend (non-persistent / dev). */\n  query?: SecretQueryRunner['query'];\n  /**\n   * Owner identity this service resolves as. When absent, derived from HoloKey/HoloMesh/fleet/\n   * Railway/x402 env signals, with legacy fallback `infra`.\n   */\n  owner?: string;\n  /** Audit sink for every resolve attempt. */\n  audit?: (e: SecretResolveAudit) => void;\n  /** One-time affirmation logger (default `console.log`). Pass a no-op to silence (tests). */\n  log?: (msg: string) => void;\n  /**\n   * Inject a pre-built vault instead of building one from env. `undefined` → build via\n   * createHoloKeyVault; an explicit `HoloKeyVault | null` is used as-is (advanced wiring + tests).\n   */\n  vault?: HoloKeyVault | null;\n}\n\nexport interface ServiceSecretResolver {\n  /**\n   * Vault value for this owner if present, else `process.env[name]`, else `undefined`.\n   * Accepts `NAME`, `vault:NAME`, or `infra://NAME`. Never throws for vault failures.\n   */\n  resolve(nameOrRef: string): Promise<string | undefined>;\n  /** Whether the vault is ON for this resolver (lazily determined on first call). */\n  vaultEnabled(): boolean;\n  /** Service/fleet owner identity used for HoloKey owner isolation and audit. */\n  identity(): ServiceIdentity;\n}\n\nfunction isOperationalSecretRef(value: string | undefined): value is string {\n  const trimmed = value?.trim();\n  return Boolean(trimmed && (trimmed.startsWith('vault:') || trimmed.startsWith('infra://')));\n}\n\nasync function resolveVaultValue(args: {\n  vault: HoloKeyVault;\n  serviceIdentity: ServiceIdentity;\n  normalized: NormalizedServiceSecretRef;\n}): Promise<string | undefined> {\n  try {\n    const { value } = await args.vault.resolver.resolve({\n      authenticatedOwnerId: args.serviceIdentity.ownerId,\n      ref: args.normalized.ref,\n      purpose: 'service-config',\n    });\n    return value;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction tryNormalizeServiceSecretRef(input: string): NormalizedServiceSecretRef | null {\n  try {\n    return normalizeServiceSecretRef(input);\n  } catch {\n    return null;\n  }\n}\n\nexport function createServiceSecretResolver(\n  opts: ServiceSecretResolverOpts = {}\n): ServiceSecretResolver {\n  const env = opts.env ?? process.env;\n  const serviceIdentity = resolveServiceIdentity({ env, owner: opts.owner });\n  const log = opts.log ?? ((m: string) => console.log(m));\n  let built = false;\n  let vault: HoloKeyVault | null = null;\n\n  function ensureVault(): HoloKeyVault | null {\n    if (built) return vault;\n    built = true;\n    if (opts.vault !== undefined) {\n      vault = opts.vault;\n    } else {\n      try {\n        vault = createHoloKeyVault({ env, query: opts.query, audit: opts.audit });\n      } catch {\n        vault = null; // never throw — fall back to env\n      }\n    }\n    log(\n      vault\n        ? `[holokey] vault ON (owner=${serviceIdentity.ownerId} source=${serviceIdentity.source} backend=${vault.backend} kek=${vault.kekGrade}) — service secrets resolve from the vault, else process.env`\n        : `[holokey] vault OFF (no KEK / not configured) — service secrets resolve from process.env`\n    );\n    return vault;\n  }\n\n  return {\n    async resolve(nameOrRef: string): Promise<string | undefined> {\n      const normalized = normalizeServiceSecretRef(nameOrRef);\n      const v = ensureVault();\n      if (v) {\n        try {\n          const value = await resolveVaultValue({ vault: v, serviceIdentity, normalized });\n          if (value !== undefined) return value;\n        } catch {\n          // not-in-vault / denied / decrypt error → fall back to env (the migration bridge).\n        }\n      }\n      const fallback = env[normalized.envName];\n      if (isOperationalSecretRef(fallback)) {\n        const fallbackRef = tryNormalizeServiceSecretRef(fallback);\n        if (v && fallbackRef) {\n          return resolveVaultValue({ vault: v, serviceIdentity, normalized: fallbackRef });\n        }\n        return undefined;\n      }\n      return fallback;\n    },\n    vaultEnabled(): boolean {\n      return ensureVault() !== null;\n    },\n    identity(): ServiceIdentity {\n      return serviceIdentity;\n    },\n  };\n}\n"],"mappings":"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","names":["MAX_TTL_SECONDS","MIN_TTL_SECONDS","import_node_crypto","asString","asString","import_node_crypto","import_node_crypto","KEK_BYTES","KEK_BYTES","KEK_ID_RE","import_node_crypto","import_node_crypto","envName","MIN_TTL_SECONDS","MAX_TTL_SECONDS"]}