@homeflare/alchemy 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,23 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/openbao/auth-role.ts", "../src/openbao/digest.ts", "../src/openbao/mount-form.ts", "../src/openbao/auth-role-form.ts", "../src/openbao/bao-http.ts", "../src/openbao/bao-address.ts", "../src/openbao/bao-status.ts", "../src/openbao/cloudflare-role.ts", "../src/openbao/cloudflare-group-scope.ts", "../src/openbao/cloudflare-permission-groups.ts", "../src/openbao/cloudflare-policy.ts", "../src/openbao/cloudflare-role-wire.ts", "../src/openbao/cloudflare-role-form.ts", "../src/openbao/mount.ts", "../src/openbao/mount-wire.ts", "../src/openbao/pki-role.ts", "../src/openbao/pki-role-form.ts", "../src/openbao/policy.ts", "../src/openbao/policy-assembly.ts", "../src/openbao/policy-wire.ts", "../src/openbao/proxmox-role.ts", "../src/openbao/proxmox-role-form.ts", "../src/openbao/ssh-role.ts", "../src/openbao/ssh-role-form.ts"],
3
+ "sources": ["../src/openbao/auth-role.ts", "../src/openbao/digest.ts", "../src/openbao/mount-form.ts", "../src/openbao/auth-role-form.ts", "../src/openbao/bao-http.ts", "../src/openbao/bao-address.ts", "../src/openbao/bao-status.ts", "../src/openbao/cloudflare-role.ts", "../src/openbao/cloudflare-group-scope.ts", "../src/openbao/cloudflare-permission-groups.ts", "../src/openbao/cloudflare-permission-groups-solve.ts", "../src/openbao/cloudflare-policy.ts", "../src/openbao/cloudflare-role-wire.ts", "../src/openbao/cloudflare-role-form.ts", "../src/openbao/cloudflare-roles-expand.ts", "../src/openbao/cloudflare-roles-config.ts", "../src/openbao/mount.ts", "../src/openbao/mount-wire.ts", "../src/openbao/pki-role.ts", "../src/openbao/pki-role-form.ts", "../src/openbao/policy.ts", "../src/openbao/policy-assembly.ts", "../src/openbao/policy-wire.ts", "../src/openbao/proxmox-role.ts", "../src/openbao/proxmox-role-form.ts", "../src/openbao/ssh-role.ts", "../src/openbao/ssh-role-form.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * An OpenBao AppRole auth role — token_policies, TTLs and bind flags. METADATA ONLY.\n *\n * ⛔ NO SECRET IN PROPS OR ATTRIBUTES — see policy.ts for why. `role_id` and `secret_id`\n * are credential issuance, not configuration, and are OUT OF SCOPE. This declares the\n * role shape an approle login inherits — policy names and TTL strings only.\n *\n * ★ `defaultRemovalPolicy: 'retain'` — deleting a role revokes every token bound to it.\n * Opt in with `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport {\n type BaoAuthRoleAttributes,\n type BaoAuthRoleProps,\n attributesOf,\n matches,\n readPath,\n writeBody,\n} from './auth-role-form.ts';\nimport { baoDelete, baoRead, baoWrite } from './bao-http.ts';\n\nexport type { BaoAuthRoleAttributes, BaoAuthRoleProps };\n\nexport interface BaoAuthRole extends Resource<\n 'Bao.AuthRole',\n BaoAuthRoleProps,\n BaoAuthRoleAttributes,\n never,\n HttpClient.HttpClient\n> {}\n\nexport const BaoAuthRole = Resource<BaoAuthRole>('Bao.AuthRole', {\n defaultRemovalPolicy: 'retain',\n});\n\nconst readRole = (props: BaoAuthRoleProps) =>\n Effect.gen(function* () {\n const live = yield* baoRead(readPath(props.name));\n if (live === undefined) return undefined;\n return attributesOf(props, live);\n });\n\nexport const BaoAuthRoleProvider = () =>\n Provider.effect(\n BaoAuthRole,\n Effect.succeed(\n BaoAuthRole.Provider.of({\n /**\n * ⛔ `bao list auth/approle/role` IS NOT A LIST OF THINGS THIS OWNS. Every role\n * in the namespace answers, including break-glass and bootstrap ones. Returning\n * them would invite Alchemy to adopt — and then delete — roles it never created.\n */\n list: () => Effect.succeed([]),\n\n read: Effect.fn(function* ({ olds }) {\n return yield* readRole(olds);\n }),\n\n /**\n * ⛔ IT COMPARES THE LIVE ROLE, NOT THE STORED DIGEST. A role edited in the OpenBao\n * UI is exactly the drift the check-* gates exist to catch.\n */\n diff: Effect.fn(function* ({ news, output }) {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readRole(news);\n if (live === undefined) return { action: 'update' } as const;\n if (matches(live, news)) return { action: 'noop' } as const;\n return { action: 'update' } as const;\n }),\n\n reconcile: Effect.fn(function* ({ news }) {\n const live = yield* readRole(news);\n if (live === undefined || !matches(live, news)) {\n yield* baoWrite('PUT', readPath(news.name), writeBody(news));\n }\n const after = yield* readRole(news);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `Bao.AuthRole ${news.name}: write returned no error but the role is still absent.`,\n ),\n );\n }\n return after;\n }),\n\n /**\n * ⛔ DELETING A ROLE REVOKES EVERY TOKEN BOUND TO IT. Idempotent as Alchemy requires\n * — already gone is success — but retain is the default for a reason.\n */\n delete: Effect.fn(function* ({ output }) {\n yield* baoDelete(readPath(output.name));\n return undefined;\n }),\n }),\n ),\n );\n",
6
6
  "/**\n * The digest every Bao.* family persists instead of a value — moved here from the retired\n * bao-shell.ts, unchanged, when the package stopped shelling out to `bao`.\n */\n\n/** ⚠️ Bun's hasher, not node:crypto — this runs under `bun --bun alchemy`. */\n/**\n * The only form a policy body may be hashed or compared in.\n *\n * ⛔ OPENBAO STRIPS THE TRAILING NEWLINE AND THAT ALONE WAS A FOREVER-DIFF. MEASURED on the live\n * server: the assembler emits each fragment followed by a newline, so `homeflare-llm` goes in as\n * 41 lines and `bao policy read` hands back 40 — identical text, one `\\n` apart, two different\n * digests. Every plan therefore reported `update`, every deploy rewrote the same policy, and the\n * stack could never settle. It was invisible until the stack planned for the first time today.\n * ★ THE HTTP API HANDS BACK THE SAME STRIPPED TEXT. `bao policy read` printed `data.policy` of\n * `GET /v1/sys/policies/acl/<name>` (openbao v2.6.2 api/sys_policy.go:60-81), which is what\n * policy-wire.ts now reads directly — so the canonicalisation is still load-bearing.\n *\n * ⚠️ `trimEnd` ONLY. Leading and interior whitespace are part of the HCL and must not be touched —\n * a policy that differs by an indent really is a different document, and quietly folding that\n * away would hide an edit rather than a formatting artifact.\n */\nexport const canonical = (text: string) => text.trimEnd();\n\nexport const sha256 = (text: string) =>\n new Bun.CryptoHasher('sha256').update(canonical(text)).digest('hex');\n",
7
7
  "import { sha256 } from './digest.ts';\n\n/** Mount path without a trailing slash — props and `sys/mounts/<path>` use this shape. */\nexport const mountPath = (path: string) => path.replace(/\\/+$/, '');\n\nconst DURATION = /^(\\d+)([smhd])$/;\n\n/** Parse a Vault duration string (`15m`, `768h`, `0`) to seconds. */\nexport const parseDuration = (text: string): number | undefined => {\n const trimmed = text.trim();\n if (trimmed === '0') return 0;\n const match = DURATION.exec(trimmed);\n if (match === null) return undefined;\n const amount = Number(match[1]);\n switch (match[2]) {\n case 's':\n return amount;\n case 'm':\n return amount * 60;\n case 'h':\n return amount * 3600;\n case 'd':\n return amount * 86400;\n default:\n return undefined;\n }\n};\n\n/** Seconds from live JSON (`2764800`) or a duration prop (`768h`). */\nexport const ttlSeconds = (value: unknown): number | undefined => {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string') return parseDuration(value);\n return undefined;\n};\n\nexport interface BaoMountProps {\n /** Mount path without trailing slash, as `sys/mounts/<path>` takes it. */\n path: string;\n /** Secrets engine type, e.g. `kv`, `pki`, `openbao-plugin-secrets-cloudflare`. */\n type: string;\n /** Human description — tuned via `sys/mounts/<path>/tune`, as apply-roles.py describe_mounts does. */\n description?: string;\n /** Default lease TTL, e.g. `768h`. */\n defaultLeaseTtl?: string;\n /** Max lease TTL, e.g. `8760h`. */\n maxLeaseTtl?: string;\n /** KV only — sent as `options.version` on enable, as `-version=2` was. Immutable after create. */\n version?: 1 | 2;\n}\n\nexport interface BaoMountAttributes {\n path: string;\n type: string;\n description: string;\n defaultLeaseTtl: string;\n maxLeaseTtl: string;\n /** SHA-256 of the managed fields — safe to persist; see policy.ts. */\n digest: string;\n}\n\nconst configOf = (live: Record<string, unknown>) =>\n typeof live['config'] === 'object' && live['config'] !== null\n ? (live['config'] as Record<string, unknown>)\n : {};\n\nconst text = (value: unknown) => (typeof value === 'string' ? value : '');\n\nconst ttlProp = (seconds: number | undefined, fallback = '') => {\n if (seconds === undefined) return fallback;\n if (seconds % 86400 === 0) return `${String(seconds / 86400)}d`;\n if (seconds % 3600 === 0) return `${String(seconds / 3600)}h`;\n if (seconds % 60 === 0) return `${String(seconds / 60)}m`;\n return `${String(seconds)}s`;\n};\n\nexport const attributesOf = (\n props: BaoMountProps,\n live: Record<string, unknown>,\n): BaoMountAttributes => {\n const config = configOf(live);\n const defaultLeaseTtl = ttlProp(ttlSeconds(config['default_lease_ttl']));\n const maxLeaseTtl = ttlProp(ttlSeconds(config['max_lease_ttl']));\n const attrs = {\n path: mountPath(props.path),\n type: text(live['type']) || props.type,\n description: text(live['description']),\n defaultLeaseTtl,\n maxLeaseTtl,\n };\n return { ...attrs, digest: sha256(JSON.stringify(attrs)) };\n};\n\n/** `sys/mounts/<path>` — read, enable and disable all address the mount here. */\nexport const readPath = (path: string) => `sys/mounts/${mountPath(path)}`;\n\n/**\n * ★ NO TRAILING SLASH NEEDED ON THE WIRE. `bao secrets tune` appended one itself; the server's\n * route `mounts/(?P<path>.+?)/tune$` captures the bare path and `sanitizePath` appends the slash\n * OpenBao stores in sys/mounts (openbao v2.6.2 vault/logical_system_paths.go:4248,\n * vault/logical_system.go:4825-4833).\n */\nexport const tunePath = (path: string) => `${readPath(path)}/tune`;\n\n/**\n * The enable body. `-version=2` on the CLI became `options.version = \"2\"` (openbao v2.6.2\n * command/secrets_enable.go:278 into api MountInput.Options), so that is what is sent.\n *\n * ⚠️ DESCRIPTION AND TTLs ARE NOT SENT HERE. reconcile tunes them straight after the enable,\n * exactly as the CLI path did, so a create and an update converge through the same call.\n */\nexport const enableBody = (props: BaoMountProps): Record<string, unknown> =>\n props.version === 2 ? { options: { version: '2' }, type: props.type } : { type: props.type };\n\n/**\n * The tune body — only the fields the declaration names.\n *\n * ★ AN OMITTED FIELD IS LEFT ALONE. The server reads an absent TTL as \"\" and keeps the mount's\n * current value for \"\" (vault/logical_system.go:1614-1630), and applies `description` only when\n * present (:1725). The CLI sent unset TTL flags as \"\" and set description only when given\n * (command/secrets_tune.go Visit), so omitting them is the same request.\n */\nexport const tuneBody = (props: BaoMountProps): Record<string, string> => {\n const body: Record<string, string> = {};\n if (props.description !== undefined) body['description'] = props.description;\n if (props.defaultLeaseTtl !== undefined) body['default_lease_ttl'] = props.defaultLeaseTtl;\n if (props.maxLeaseTtl !== undefined) body['max_lease_ttl'] = props.maxLeaseTtl;\n return body;\n};\n\nconst sameTtl = (want: string | undefined, have: string) => {\n if (want === undefined) return true;\n const wantSeconds = ttlSeconds(want);\n const haveSeconds = ttlSeconds(have);\n return wantSeconds !== undefined && wantSeconds === haveSeconds;\n};\n\n/** True when live already matches the declaration on every managed field. */\nexport const matches = (attributes: BaoMountAttributes, props: BaoMountProps) =>\n attributes.type === props.type &&\n (props.description === undefined || attributes.description === props.description) &&\n sameTtl(props.defaultLeaseTtl, attributes.defaultLeaseTtl) &&\n sameTtl(props.maxLeaseTtl, attributes.maxLeaseTtl);\n\nexport const wantsTune = (props: BaoMountProps) =>\n props.description !== undefined ||\n props.defaultLeaseTtl !== undefined ||\n props.maxLeaseTtl !== undefined;\n",
8
8
  "import { sha256 } from './digest.ts';\nimport { parseDuration, ttlSeconds } from './mount-form.ts';\n\nexport interface BaoAuthRoleProps {\n /** AppRole name, as `auth/approle/role/{name}` takes it. */\n name: string;\n /** Policies bound to tokens minted through this role. Names only — never a secret. */\n tokenPolicies: readonly string[];\n /** Token TTL, e.g. `15m`. */\n tokenTtl: string;\n /** Token max TTL, e.g. `1h`. */\n tokenMaxTtl: string;\n /** Secret ID TTL — `0` means non-expiring, as reconcile.sh and apply-consumers.py set. */\n secretIdTtl: string;\n /** Whether login requires a secret_id. Defaults to true when omitted on write. */\n bindSecretId?: boolean;\n /** `0` means unlimited uses — the shape reconcile.sh writes for headless roles. */\n secretIdNumUses?: number;\n}\n\nexport interface BaoAuthRoleAttributes {\n name: string;\n tokenPolicies: readonly string[];\n tokenTtl: string;\n tokenMaxTtl: string;\n secretIdTtl: string;\n bindSecretId: boolean;\n secretIdNumUses: number;\n /** SHA-256 of the managed fields — safe to persist; see policy.ts. */\n digest: string;\n}\n\nconst policiesOf = (live: Record<string, unknown>): readonly string[] => {\n const raw = live['token_policies'];\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((entry): entry is string => typeof entry === 'string')\n .slice()\n .sort();\n};\n\nconst bool = (value: unknown, fallback: boolean) => (typeof value === 'boolean' ? value : fallback);\n\nconst int = (value: unknown, fallback: number) =>\n typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n\nconst ttlText = (seconds: number | undefined, fallback = '') => {\n if (seconds === undefined) return fallback;\n if (seconds % 86400 === 0) return `${String(seconds / 86400)}d`;\n if (seconds % 3600 === 0) return `${String(seconds / 3600)}h`;\n if (seconds % 60 === 0) return `${String(seconds / 60)}m`;\n return `${String(seconds)}s`;\n};\n\nexport const attributesOf = (\n props: BaoAuthRoleProps,\n live: Record<string, unknown>,\n): BaoAuthRoleAttributes => {\n const attrs = {\n name: props.name,\n tokenPolicies: policiesOf(live),\n tokenTtl: ttlText(ttlSeconds(live['token_ttl'])),\n tokenMaxTtl: ttlText(ttlSeconds(live['token_max_ttl'])),\n secretIdTtl: ttlText(ttlSeconds(live['secret_id_ttl']), '0'),\n bindSecretId: bool(live['bind_secret_id'], true),\n secretIdNumUses: int(live['secret_id_num_uses'], 0),\n };\n return { ...attrs, digest: sha256(JSON.stringify(attrs)) };\n};\n\nexport const readPath = (name: string) => `auth/approle/role/${name}`;\n\n/**\n * The body for `PUT auth/approle/role/<name>`.\n *\n * ★ ALL STRINGS, EXACTLY THE `k=v` PAIRS `bao write` USED TO SEND — see `baoWrite` in bao-http.ts.\n */\nexport const writeBody = (props: BaoAuthRoleProps): Record<string, string> => {\n const body: Record<string, string> = {\n token_policies: props.tokenPolicies.join(','),\n token_ttl: props.tokenTtl,\n token_max_ttl: props.tokenMaxTtl,\n secret_id_ttl: props.secretIdTtl,\n };\n if (props.bindSecretId !== undefined) body['bind_secret_id'] = String(props.bindSecretId);\n if (props.secretIdNumUses !== undefined) {\n body['secret_id_num_uses'] = String(props.secretIdNumUses);\n }\n return body;\n};\n\nconst samePolicies = (want: readonly string[], have: readonly string[]) =>\n want.length === have.length && want.every((policy, index) => policy === have[index]);\n\nconst sameTtl = (want: string, have: string) => {\n const wantSeconds = parseDuration(want);\n const haveSeconds = ttlSeconds(have);\n return wantSeconds !== undefined && wantSeconds === haveSeconds;\n};\n\n/** True when live already matches the declaration on every managed field. */\nexport const matches = (attributes: BaoAuthRoleAttributes, props: BaoAuthRoleProps) => {\n const wantPolicies = props.tokenPolicies.slice().sort();\n return (\n samePolicies(wantPolicies, attributes.tokenPolicies) &&\n sameTtl(props.tokenTtl, attributes.tokenTtl) &&\n sameTtl(props.tokenMaxTtl, attributes.tokenMaxTtl) &&\n sameTtl(props.secretIdTtl, attributes.secretIdTtl) &&\n (props.bindSecretId === undefined || attributes.bindSecretId === props.bindSecretId) &&\n (props.secretIdNumUses === undefined || attributes.secretIdNumUses === props.secretIdNumUses)\n );\n};\n",
9
- "/**\n * One call to OpenBao's HTTP API through Effect's `HttpClient` — the transport every Bao.* family\n * uses since it stopped shelling out to `bao`.\n *\n * ★ `HttpClient`, THE SAME PATTERN house/proxmox and house/forgejo USE AGAINST THEIR APIs, decided\n * 2026-09-14. It buys a typed error channel, interruption when a plan is cancelled, the runtime's\n * tracing, and a client a test can point at a fake server — and it needs no Alchemy session, so\n * every call here works from all four operations. (`CommandExecutor.run` was tried on Bao.Policy\n * first and blocked read/diff: Alchemy passes a session to reconcile/delete but NOT to read/diff,\n * Provider.ts:258-289. The ChildProcessSpawner that fixed that is gone with the CLI.)\n * ⚠️ THE STACK MUST PROVIDE `FetchHttpClient.layer`. alchemy.run.ts does, the way\n * house/proxmox/alchemy.run.ts does.\n */\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\nimport * as Semaphore from 'effect/Semaphore';\nimport * as FetchHttpClient from 'effect/unstable/http/FetchHttpClient';\nimport * as Headers from 'effect/unstable/http/Headers';\nimport * as HttpClient from 'effect/unstable/http/HttpClient';\nimport * as HttpClientRequest from 'effect/unstable/http/HttpClientRequest';\nimport { type BaoEnvironment, headersFor, resolveAddress } from './bao-address.ts';\nimport { BaoError, type BaoIntent, settle } from './bao-status.ts';\n\n/**\n * The environment a call resolves BAO_ADDR, BAO_NAMESPACE and BAO_TOKEN from — `process.env`,\n * read at call time, unless a test provides another.\n */\nexport const BaoEnv = Context.Reference<BaoEnvironment>('homeflare/openbao/BaoEnv', {\n defaultValue: () => process.env,\n});\n\n/**\n * ⛔ AT MOST EIGHT EXCHANGES WITH OPENBAO AT ONCE — ACROSS EVERY Bao.* FAMILY, IN ONE PROCESS.\n *\n * 🔴 MEASURED 2026-09-14 10:41: A DEPLOY OF THIS STACK TOOK OPENBAO's API OFF THE MINI. Alchemy fans\n * resources out with a hard-coded `concurrency: \"unbounded\"` (alchemy Plan.ts:476, Apply.ts:259,\n * :263, :303 — no option reaches it), and 555 Bao.CloudflareRole resources each read, diff,\n * reconcile and read back: well over a thousand requests at one loopback listener within seconds.\n * OpenBao logged\n * HTTP server (listening on 127.0.0.1:8200) exited with error: set tcp\n * 127.0.0.1:8200->127.0.0.1:57974: setsockopt: invalid argument\n * and KEPT RUNNING with 8200 closed. launchd saw a live process and restarted nothing. Everything\n * on the mini that talks to 127.0.0.1:8200 was cut off, starting with the agent's templates, until\n * a manual restart.\n * ★ THE LISTENER DYING IS A GO-ON-DARWIN FAILURE, NOT OURS TO FIX. Traefik lost its entrypoints the\n * same way on darwin/arm64 (traefik issue 8841). The BURST is ours. The adoption deploy an hour\n * earlier made the same calls and survived, so a cap narrows a race; it does not prove it closed.\n * ★ A SEMAPHORE, NOT `HttpClient.withRateLimiter`. That limits requests per window and needs a\n * RateLimiter service. The failure is simultaneous connections, and only a cap on in-flight\n * exchanges bounds those whatever each one's latency.\n * ⚠️ A Context.Reference SO A TEST CAN PROVIDE ITS OWN GATE. The default is built ONCE and cached on\n * the reference (effect Context.ts:1582-1588), so every call in the process shares one gate.\n * ⚠️ EIGHT IS A CHOICE, NOT A MEASUREMENT OF WHAT THE LISTENER TOLERATES. Nothing here can find that\n * number without re-running the failure against production.\n */\nexport const MAX_IN_FLIGHT = 8;\n\nexport const BaoGate = Context.Reference<Semaphore.Semaphore>('homeflare/openbao/BaoGate', {\n defaultValue: () => Semaphore.makeUnsafe(MAX_IN_FLIGHT),\n});\n\n/**\n * ⚠️ THE CLI's DEFAULT CLIENT TIMEOUT (openbao v2.6.2 api/client.go:324). A hung agent or a server\n * that accepts and never answers would otherwise hang the plan with no line saying why.\n */\nconst TIMEOUT = '60 seconds';\n\n/**\n * ⛔ EFFECT RECORDS EVERY REQUEST HEADER ON THE CLIENT SPAN and redacts only the names in\n * `Headers.CurrentRedactedNames` — by default authorization, cookie, set-cookie and x-api-key\n * (effect Headers.ts:753-762; HttpClient.ts:842-849, with `TracerHeaderFilter` defaulting to\n * true). `X-Vault-Token` is not on that list, so under any tracer the token would be exported as\n * a span attribute. It is added for every call made here.\n */\nconst redactingToken = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Effect.gen(function* () {\n const names = yield* Headers.CurrentRedactedNames;\n return yield* Effect.provideService(effect, Headers.CurrentRedactedNames, [\n ...names,\n 'x-vault-token',\n ]);\n });\n\n/**\n * Route the exchange over a unix socket when the address is one.\n *\n * ★ BUN's `fetch` TAKES A `unix` OPTION (bun-types globals.d.ts BunFetchRequestInit.unix), AND\n * `FetchHttpClient.RequestInit` IS EFFECT'S DOCUMENTED WAY TO PASS FETCH OPTIONS. The fetch client\n * spreads that service into every call (effect FetchHttpClient.ts:59-72), reading it from the\n * CALLING fiber's context — and `layerMergedContext` merges the caller's context over the layer's\n * (HttpClient.ts:2065-2076), so providing it around one call routes that call alone. Any defaults\n * already provided are kept.\n * ⛔ IT ONLY WORKS ON BUN, SO ANYWHERE ELSE IT REFUSES. Node's fetch ignores `unix` and would send\n * the request to http://localhost:80 — a silent wrong server, which is the one outcome this\n * package exists to prevent. It also assumes the provided `HttpClient` is the fetch one.\n */\nconst overSocket =\n (socket: string | undefined, method: string, path: string) =>\n <A, R>(effect: Effect.Effect<A, BaoError, R>): Effect.Effect<A, BaoError, R> => {\n if (socket === undefined) return effect;\n if (typeof Bun === 'undefined') {\n return Effect.fail(\n new BaoError(0, method, path, ['a unix:// address needs Bun fetch; this is not Bun']),\n );\n }\n return Effect.flatMap(Effect.serviceOption(FetchHttpClient.RequestInit), (defaults) => {\n const init: BunFetchRequestInit = { ...Option.getOrElse(defaults, () => ({})), unix: socket };\n return Effect.provideService(effect, FetchHttpClient.RequestInit, init);\n });\n };\n\n/** One exchange, classified. The body is the parsed JSON object, or undefined for absent / 204. */\nexport const baoCall = (\n intent: BaoIntent,\n method: 'DELETE' | 'GET' | 'POST' | 'PUT',\n path: string,\n body?: Readonly<Record<string, unknown>>,\n) =>\n Effect.gen(function* () {\n const env = yield* BaoEnv;\n const address = resolveAddress(env);\n const client = yield* HttpClient.HttpClient;\n // ⚠️ The content type goes on `bodyText`, never in the header map: `bodyText` overwrites it.\n // house/proxmox/src/client.ts has the scar.\n const request = HttpClientRequest.make(method)(`${address.base}/v1/${path}`).pipe(\n HttpClientRequest.setHeaders(headersFor(address, env)),\n body === undefined\n ? (self) => self\n : HttpClientRequest.bodyText(JSON.stringify(body), 'application/json'),\n );\n // ★ Status first, body read exactly once, as text — an error body is not reliably JSON.\n const exchange = client.execute(request).pipe(\n Effect.flatMap((response) =>\n Effect.map(response.text, (text) => ({ status: response.status, text })),\n ),\n Effect.timeout(TIMEOUT),\n // ⛔ `.message` ONLY: the HttpClientError message is the reason, method and URL. The error\n // object itself holds the request, whose headers hold the token.\n Effect.mapError((cause) => new BaoError(0, method, path, [cause.message])),\n );\n // ★ THE PERMIT WRAPS THE TIMEOUT, NOT THE REVERSE: a call queued behind the gate is not yet\n // talking to OpenBao, so its wait must not count against the 60 seconds.\n const gate = yield* BaoGate;\n const { status, text } = yield* exchange.pipe(\n overSocket(address.socket, method, path),\n redactingToken,\n Semaphore.withPermits(gate, 1),\n );\n const outcome = settle(intent, method, path, status, text);\n return 'error' in outcome ? yield* Effect.fail(outcome.error) : outcome.body;\n });\n\n/**\n * The `data` of a read, or undefined when OpenBao says the object is ABSENT (404).\n *\n * ★ `bao read -format=json` printed this same response body; the old helper took `data` when it was\n * an object and the whole body otherwise, and so does this.\n */\nexport const baoRead = (path: string) =>\n Effect.map(baoCall('read', 'GET', path), (body) => {\n if (body === undefined) return undefined;\n const data = body['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : (body as Record<string, unknown>);\n });\n\n/**\n * A write whose SUCCESS MATTERS. Any non-2xx fails, 404 included.\n *\n * ★ `PUT` IS WHAT `bao write` SENT (openbao v2.6.2 api/logical.go Write); `sys/mounts` enable and\n * tune are `POST` in the same client (api/sys_mounts.go:57, :201).\n * ⚠️ ROLE BODIES STAY ALL-STRING ON PURPOSE. `bao write k=v` put every value in the JSON body as a\n * string — MEASURED with `-output-curl-string`, see ssh-role-form.ts — and the form files still\n * build exactly that body, so the server parses the same request it was always sent.\n */\nexport const baoWrite = (\n method: 'POST' | 'PUT',\n path: string,\n body: Readonly<Record<string, unknown>>,\n) => Effect.asVoid(baoCall('write', method, path, body));\n\n/** A delete: idempotent — already gone (404) is success — and refused (403, 5xx) is a failure. */\nexport const baoDelete = (path: string) => Effect.asVoid(baoCall('delete', 'DELETE', path));\n",
9
+ "/**\n * One call to OpenBao's HTTP API through Effect's `HttpClient` — the transport every Bao.* family\n * uses since it stopped shelling out to `bao`.\n *\n * ★ `HttpClient`, THE SAME PATTERN house/proxmox and house/forgejo USE AGAINST THEIR APIs, decided\n * 2026-09-14. It buys a typed error channel, interruption when a plan is cancelled, the runtime's\n * tracing, and a client a test can point at a fake server — and it needs no Alchemy session, so\n * every call here works from all four operations. (`CommandExecutor.run` was tried on Bao.Policy\n * first and blocked read/diff: Alchemy passes a session to reconcile/delete but NOT to read/diff,\n * Provider.ts:258-289. The ChildProcessSpawner that fixed that is gone with the CLI.)\n * ⚠️ THE STACK MUST PROVIDE `FetchHttpClient.layer`. alchemy.run.ts does, the way\n * house/proxmox/alchemy.run.ts does.\n */\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\nimport * as Schedule from 'effect/Schedule';\nimport * as Semaphore from 'effect/Semaphore';\nimport * as FetchHttpClient from 'effect/unstable/http/FetchHttpClient';\nimport * as Headers from 'effect/unstable/http/Headers';\nimport * as HttpClient from 'effect/unstable/http/HttpClient';\nimport * as HttpClientRequest from 'effect/unstable/http/HttpClientRequest';\nimport { type BaoEnvironment, headersFor, resolveAddress } from './bao-address.ts';\nimport { BaoError, type BaoIntent, settle } from './bao-status.ts';\n\n/**\n * The environment a call resolves BAO_ADDR, BAO_NAMESPACE and BAO_TOKEN from — `process.env`,\n * read at call time, unless a test provides another.\n */\nexport const BaoEnv = Context.Reference<BaoEnvironment>('homeflare/openbao/BaoEnv', {\n defaultValue: () => process.env,\n});\n\n/**\n * ⛔ AT MOST EIGHT EXCHANGES WITH OPENBAO AT ONCE — ACROSS EVERY Bao.* FAMILY, IN ONE PROCESS.\n *\n * 🔴 MEASURED 2026-09-14 10:41: A DEPLOY OF THIS STACK TOOK OPENBAO's API OFF THE MINI. Alchemy fans\n * resources out with a hard-coded `concurrency: \"unbounded\"` (alchemy Plan.ts:476, Apply.ts:259,\n * :263, :303 — no option reaches it), and 555 Bao.CloudflareRole resources each read, diff,\n * reconcile and read back: well over a thousand requests at one loopback listener within seconds.\n * OpenBao logged\n * HTTP server (listening on 127.0.0.1:8200) exited with error: set tcp\n * 127.0.0.1:8200->127.0.0.1:57974: setsockopt: invalid argument\n * and KEPT RUNNING with 8200 closed. launchd saw a live process and restarted nothing. Everything\n * on the mini that talks to 127.0.0.1:8200 was cut off, starting with the agent's templates, until\n * a manual restart.\n * ★ THE LISTENER DYING IS A GO-ON-DARWIN FAILURE, NOT OURS TO FIX. Traefik lost its entrypoints the\n * same way on darwin/arm64 (traefik issue 8841). The BURST is ours. The adoption deploy an hour\n * earlier made the same calls and survived, so a cap narrows a race; it does not prove it closed.\n * ★ A SEMAPHORE, NOT `HttpClient.withRateLimiter`. That limits requests per window and needs a\n * RateLimiter service. The failure is simultaneous connections, and only a cap on in-flight\n * exchanges bounds those whatever each one's latency.\n * ⚠️ A Context.Reference SO A TEST CAN PROVIDE ITS OWN GATE. The default is built ONCE and cached on\n * the reference (effect Context.ts:1582-1588), so every call in the process shares one gate.\n * ⚠️ EIGHT IS A CHOICE, NOT A MEASUREMENT OF WHAT THE LISTENER TOLERATES. Nothing here can find that\n * number without re-running the failure against production.\n */\nexport const MAX_IN_FLIGHT = 8;\n\nexport const BaoGate = Context.Reference<Semaphore.Semaphore>('homeflare/openbao/BaoGate', {\n defaultValue: () => Semaphore.makeUnsafe(MAX_IN_FLIGHT),\n});\n\n/**\n * ⚠️ THE CLI's DEFAULT CLIENT TIMEOUT (openbao v2.6.2 api/client.go:324). A hung agent or a server\n * that accepts and never answers would otherwise hang the plan with no line saying why.\n */\nconst TIMEOUT = '60 seconds';\n\n/**\n * Mesh in front of a remote OpenBao drops connections under Alchemy's unbounded\n * fan-out. Status 0 is transport, not an OpenBao 4xx — retry twice. Measured\n * 2026-09-16 against api.v.homeflare.dev: a 585-role plan died mid-diff with\n * `no response: (no errors given)` while the vault stayed unsealed.\n */\nconst retryTransport = <A, R>(effect: Effect.Effect<A, BaoError, R>) =>\n Effect.retry(effect, {\n schedule: Schedule.spaced('750 millis'),\n times: 2,\n while: (error: BaoError) => error.status === 0,\n });\n\n/**\n * ⛔ EFFECT RECORDS EVERY REQUEST HEADER ON THE CLIENT SPAN and redacts only the names in\n * `Headers.CurrentRedactedNames` — by default authorization, cookie, set-cookie and x-api-key\n * (effect Headers.ts:753-762; HttpClient.ts:842-849, with `TracerHeaderFilter` defaulting to\n * true). `X-Vault-Token` is not on that list, so under any tracer the token would be exported as\n * a span attribute. It is added for every call made here.\n */\nconst redactingToken = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Effect.gen(function* () {\n const names = yield* Headers.CurrentRedactedNames;\n return yield* Effect.provideService(effect, Headers.CurrentRedactedNames, [\n ...names,\n 'x-vault-token',\n ]);\n });\n\n/**\n * Route the exchange over a unix socket when the address is one.\n *\n * ★ BUN's `fetch` TAKES A `unix` OPTION (bun-types globals.d.ts BunFetchRequestInit.unix), AND\n * `FetchHttpClient.RequestInit` IS EFFECT'S DOCUMENTED WAY TO PASS FETCH OPTIONS. The fetch client\n * spreads that service into every call (effect FetchHttpClient.ts:59-72), reading it from the\n * CALLING fiber's context — and `layerMergedContext` merges the caller's context over the layer's\n * (HttpClient.ts:2065-2076), so providing it around one call routes that call alone. Any defaults\n * already provided are kept.\n * ⛔ IT ONLY WORKS ON BUN, SO ANYWHERE ELSE IT REFUSES. Node's fetch ignores `unix` and would send\n * the request to http://localhost:80 — a silent wrong server, which is the one outcome this\n * package exists to prevent. It also assumes the provided `HttpClient` is the fetch one.\n */\nconst overSocket =\n (socket: string | undefined, method: string, path: string) =>\n <A, R>(effect: Effect.Effect<A, BaoError, R>): Effect.Effect<A, BaoError, R> => {\n if (socket === undefined) return effect;\n if (typeof Bun === 'undefined') {\n return Effect.fail(\n new BaoError(0, method, path, ['a unix:// address needs Bun fetch; this is not Bun']),\n );\n }\n return Effect.flatMap(Effect.serviceOption(FetchHttpClient.RequestInit), (defaults) => {\n const init: BunFetchRequestInit = { ...Option.getOrElse(defaults, () => ({})), unix: socket };\n return Effect.provideService(effect, FetchHttpClient.RequestInit, init);\n });\n };\n\n/** One exchange, classified. The body is the parsed JSON object, or undefined for absent / 204. */\nexport const baoCall = (\n intent: BaoIntent,\n method: 'DELETE' | 'GET' | 'POST' | 'PUT',\n path: string,\n body?: Readonly<Record<string, unknown>>,\n) =>\n Effect.gen(function* () {\n const env = yield* BaoEnv;\n const address = resolveAddress(env);\n const client = yield* HttpClient.HttpClient;\n // ⚠️ The content type goes on `bodyText`, never in the header map: `bodyText` overwrites it.\n // house/proxmox/src/client.ts has the scar.\n const request = HttpClientRequest.make(method)(`${address.base}/v1/${path}`).pipe(\n HttpClientRequest.setHeaders(headersFor(address, env)),\n body === undefined\n ? (self) => self\n : HttpClientRequest.bodyText(JSON.stringify(body), 'application/json'),\n );\n // ★ Status first, body read exactly once, as text — an error body is not reliably JSON.\n const exchange = client.execute(request).pipe(\n Effect.flatMap((response) =>\n Effect.map(response.text, (text) => ({ status: response.status, text })),\n ),\n Effect.timeout(TIMEOUT),\n // ⛔ `.message` ONLY: the HttpClientError message is the reason, method and URL. The error\n // object itself holds the request, whose headers hold the token.\n Effect.mapError((cause) => new BaoError(0, method, path, [cause.message])),\n );\n // ★ THE PERMIT WRAPS THE TIMEOUT, NOT THE REVERSE: a call queued behind the gate is not yet\n // talking to OpenBao, so its wait must not count against the 60 seconds.\n const gate = yield* BaoGate;\n const { status, text } = yield* retryTransport(\n exchange.pipe(\n overSocket(address.socket, method, path),\n redactingToken,\n Semaphore.withPermits(gate, 1),\n ),\n );\n const outcome = settle(intent, method, path, status, text);\n return 'error' in outcome ? yield* Effect.fail(outcome.error) : outcome.body;\n });\n\n/**\n * The `data` of a read, or undefined when OpenBao says the object is ABSENT (404).\n *\n * ★ `bao read -format=json` printed this same response body; the old helper took `data` when it was\n * an object and the whole body otherwise, and so does this.\n */\nexport const baoRead = (path: string) =>\n Effect.map(baoCall('read', 'GET', path), (body) => {\n if (body === undefined) return undefined;\n const data = body['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)\n : (body as Record<string, unknown>);\n });\n\n/**\n * A write whose SUCCESS MATTERS. Any non-2xx fails, 404 included.\n *\n * ★ `PUT` IS WHAT `bao write` SENT (openbao v2.6.2 api/logical.go Write); `sys/mounts` enable and\n * tune are `POST` in the same client (api/sys_mounts.go:57, :201).\n * ⚠️ ROLE BODIES STAY ALL-STRING ON PURPOSE. `bao write k=v` put every value in the JSON body as a\n * string — MEASURED with `-output-curl-string`, see ssh-role-form.ts — and the form files still\n * build exactly that body, so the server parses the same request it was always sent.\n */\nexport const baoWrite = (\n method: 'POST' | 'PUT',\n path: string,\n body: Readonly<Record<string, unknown>>,\n) => Effect.asVoid(baoCall('write', method, path, body));\n\n/** A delete: idempotent — already gone (404) is success — and refused (403, 5xx) is a failure. */\nexport const baoDelete = (path: string) => Effect.asVoid(baoCall('delete', 'DELETE', path));\n",
10
10
  "/**\n * Where an OpenBao call goes and which headers it carries — resolved from the environment the way\n * the `bao` CLI resolves it, so the provider and `bao kv get` can never disagree about which server\n * or namespace this machine is talking to.\n *\n * ★ READ FROM openbao v2.6.2, NOT RECALLED:\n * · api/client.go:34-66 — BAO_ADDR, BAO_AGENT_ADDR, BAO_NAMESPACE, BAO_TOKEN, and the header\n * names `X-Vault-Namespace` and `X-Vault-Token`.\n * · api/client.go:370 — the default address, `https://127.0.0.1:8200`.\n * · api/client.go:503-507, 617-618, 761-762 — BAO_AGENT_ADDR, when set, WINS over BAO_ADDR.\n * · api/env.go:22-34 — every BAO_* falls back to its VAULT_* twin, but a BAO_* that is present\n * and EMPTY still wins over the VAULT_* one.\n * · api/client.go:776-785 — the token and namespace are applied only when non-empty, and every\n * request carries `X-Vault-Request: true`.\n * · api/client.go:1349-1354 — the request path is joined onto the address's own path.\n *\n * ⛔ WHAT THE CLI DOES AND THIS DELIBERATELY DOES NOT: with BAO_TOKEN unset, `bao` falls back to its\n * token helper (a token file in $HOME). This never reads that file. No BAO_TOKEN means AGENT\n * MODE — see `headersFor`.\n * ⚠️ NOT CARRIED OVER: BAO_CACERT / BAO_SKIP_VERIFY / client certificates, SRV lookup, and the CLI's\n * retries on 5xx. An https address needs a certificate the runtime already trusts; a TLS failure\n * fails the call loudly rather than being skipped.\n */\n\nexport type BaoEnvironment = Readonly<Record<string, string | undefined>>;\n\nexport type BaoAddress = {\n /** Scheme, host and any path prefix, no trailing slash. `http://localhost` for a socket. */\n readonly base: string;\n /** The socket path when the address is `unix:///path`, otherwise undefined. */\n readonly socket: string | undefined;\n /** The namespace to send, when there is one. */\n readonly namespace: string | undefined;\n};\n\nexport const DEFAULT_ADDRESS = 'https://127.0.0.1:8200';\n\nconst UNIX = 'unix://';\n\n/** api/env.go ReadBaoVariable: present (even empty) BAO_* wins, else the VAULT_* twin. */\nexport const readBaoVariable = (env: BaoEnvironment, name: `BAO_${string}`): string =>\n env[name] ?? env[`VAULT_${name.slice('BAO_'.length)}`] ?? '';\n\n/**\n * The address and namespace for this environment. Carries no token, so it is safe to log.\n *\n * ★ UNIX SOCKETS, BECAUSE AN AGENT LISTENER CAN BE ONE. OpenBao Agent's `listener \"unix\"` serves\n * the same API on a socket (website/content/docs/agent-and-proxy/agent/index.mdx:382-384), and the\n * agent advertises such a listener as `unix://<path>` (command/agent.go:565-566). The CLI handles\n * that address by dialling the socket and speaking plain HTTP to host `localhost`\n * (api/client.go:654-667); `base` and `socket` are exactly those two halves.\n */\nexport const resolveAddress = (env: BaoEnvironment): BaoAddress => {\n const agent = readBaoVariable(env, 'BAO_AGENT_ADDR');\n const direct = readBaoVariable(env, 'BAO_ADDR');\n const raw = agent !== '' ? agent : direct !== '' ? direct : DEFAULT_ADDRESS;\n const namespace = readBaoVariable(env, 'BAO_NAMESPACE');\n const socket = raw.startsWith(UNIX) ? raw.slice(UNIX.length) : undefined;\n return {\n base: socket === undefined ? raw.replace(/\\/+$/, '') : 'http://localhost',\n namespace: namespace === '' ? undefined : namespace,\n socket,\n };\n};\n\n/**\n * The headers one call sends.\n *\n * ★ AGENT MODE IS \"NO TOKEN HEADER AT ALL\", AND THAT IS THE AGENT'S OWN CONTRACT. Read in openbao\n * v2.6.2 command/agentproxyshared/cache/handler.go:29-38: the proxy handler takes the request's\n * `X-Vault-Token`, and only when it is EMPTY and an auto-auth sink exists does it substitute the\n * agent's own token. command/agent.go:517-541 creates that sink exactly when\n * `api_proxy { use_auto_auth_token = true }` is set; command/agent/config/config.go:288-292 and\n * 635-637 map the older `cache { use_auto_auth_token }` onto the same setting; and\n * command/proxy.go:495-518 wires OpenBao Proxy identically. The docs say the same in words\n * (website/content/docs/agent-and-proxy/agent/apiproxy.mdx:57-62): a request without a token is\n * forwarded with the auto-auth token, a request that bears one keeps its own, and `\"force\"`\n * overwrites it.\n * ⛔ SO AN EMPTY `X-Vault-Token: ` WOULD BE WRONG IN BOTH DIRECTIONS: harmless to the agent,\n * which reads empty as absent, but an explicit unauthenticated request to a server. The header\n * is omitted, never blanked.\n * ★ THE NAMESPACE RIDES THROUGH THE AGENT UNTOUCHED. The proxy clones its client and replaces that\n * client's headers with the incoming request's (cache/api_proxy.go:50-54 and :78), so the\n * `X-Vault-Namespace` sent here is the one OpenBao sees.\n * ⚠️ `X-Vault-Request: true` IS NOT DECORATION. An agent listener with `require_request_header`\n * refuses any request without it (command/agent.go:544-548); the CLI always sends it.\n *\n * ⛔ THE RETURN VALUE HOLDS THE TOKEN. Hand it to the request and nowhere else: never to an error,\n * a log line, an attribute, or a span — bao-http.ts adds the header to the redacted names.\n */\nexport const headersFor = (address: BaoAddress, env: BaoEnvironment): Record<string, string> => {\n const headers: Record<string, string> = { 'X-Vault-Request': 'true' };\n if (address.namespace !== undefined) headers['X-Vault-Namespace'] = address.namespace;\n const token = readBaoVariable(env, 'BAO_TOKEN');\n if (token !== '') headers['X-Vault-Token'] = token;\n return headers;\n};\n",
11
11
  "/**\n * How a finished OpenBao HTTP exchange reads: a body, a genuinely absent object, or an error.\n *\n * ★ STATUS CODES, NEVER WORDS. The `bao` CLI this replaced reported every outcome as stderr text,\n * and deciding by that text broke twice: every failure once read as absent (a bad token planned 33\n * updates), and then `bao policy read` turned out to say \"absent\" in different words from\n * `bao read`, so a new policy could not be created (b3c18a33e). The API itself answers 404 for\n * absent, 403 for denied and 503 for sealed — openbao v2.6.2 sdk/logical/response_util.go:\n * RespondErrorCommon (a read that finds nothing is 404; ErrPermissionDenied is 403) and\n * AdjustErrorStatusCode (ErrSealed is 503).\n */\n\nexport type BaoIntent = 'read' | 'write' | 'delete';\n\n/**\n * A failed call, naming the method, the path and OpenBao's own `errors` array.\n *\n * ⛔ IT NEVER CARRIES THE TOKEN, AND IT NEVER CARRIES A RESPONSE BODY IT DID NOT PARSE. It is built\n * from the method, the API path and OpenBao's error strings only — no request, no headers, no\n * `cause` — because an Effect `HttpClientRequest` inspects its headers through a redaction list\n * that does not name `x-vault-token`. A 2xx body can hold a credential, and a foreign error page\n * can echo the request back, so a body that is not OpenBao's is described, never quoted.\n */\nexport class BaoError extends Error {\n constructor(\n readonly status: number,\n readonly method: string,\n readonly path: string,\n readonly errors: readonly string[],\n ) {\n const code = status === 0 ? 'no response' : String(status);\n super(`OpenBao ${method} /v1/${path} -> ${code}: ${errors.join('; ') || '(no errors given)'}`);\n this.name = 'BaoError';\n }\n}\n\nexport type Settled =\n | { readonly body: Record<string, unknown> | undefined }\n | { readonly error: BaoError };\n\nconst objectOf = (text: string): Record<string, unknown> | undefined => {\n try {\n const parsed: unknown = JSON.parse(text);\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * OpenBao's `errors` array, or undefined for a body that is not OpenBao's.\n *\n * ★ EVERY ERROR OPENBAO WRITES IS `{\"errors\": [...]}` WITH A JSON CONTENT TYPE, 404 included —\n * sdk/logical/response_util.go RespondError:180-196 — and every entry is a STRING.\n * ⛔ AN ARRAY WITH ANY NON-STRING ENTRY IS NOT OPENBAO. The first version filtered the non-strings\n * out, which turned a JSON gateway's `{\"errors\":[{\"code\":1000,\"message\":\"Not Found\"}]}` into an\n * empty OpenBao error list — and a 404 carrying it into \"absent\" on a read and \"done\" on a delete,\n * the plan-CREATE-over-something-that-exists failure arriving through a wrong BAO_ADDR. Found by\n * grok's review on 2026-09-14. An EMPTY array is still OpenBao's: a plain 404 carries exactly that.\n */\nconst errorsOf = (text: string): readonly string[] | undefined => {\n const raw = objectOf(text)?.['errors'];\n return Array.isArray(raw) && raw.every((entry) => typeof entry === 'string')\n ? (raw as string[])\n : undefined;\n};\n\n/**\n * Classify one exchange.\n *\n * ★ PURE AND EXPORTED SO THE ONE DECISION EVERY READ AND DELETE HERE RESTS ON CAN BE TESTED WITHOUT\n * A VAULT. It has been wrong in both directions already — every failure once read as absent, and\n * one command's absence wording was assumed for another's — see bao-status.test.ts.\n *\n * ⛔ 404 IS ABSENCE ONLY ON A READ, AND ONLY WHEN OPENBAO SAID IT. MEASURED 2026-09-13 with the CLI,\n * and the discriminator is real but NARROW: a genuinely absent object, read by a token that IS\n * allowed to read that path, is a 404. ⛔ AND THE SAME READ UNDER A NARROWER TOKEN IS A DENIAL:\n * under the agent lane the identical read answered `Code: 403 … permission denied`, because the\n * policy grants named paths and an unnamed one is refused rather than reported missing. So\n * \"absent\" is only knowable to a caller that could have read it — which is exactly why 403 is an\n * ERROR rather than a shrug. A resource that cannot tell absence from denial plans CREATE for\n * something that exists, which is the failure this estate has now found four separate times.\n * ⚠️ A 404 WHOSE BODY IS NOT `{\"errors\": […strings]}` IS NOT OPENBAO. A BAO_ADDR pointing at the\n * wrong server — a reverse proxy's HTML 404, a gateway's JSON one — must not read as \"nothing\".\n *\n * 🔴 THE SHELL HELPER USED TO RETURN `''` FOR EVERY NON-ZERO EXIT, AND THAT IS A LIE WITH\n * CONSEQUENCES. An expired BAO_TOKEN, a sealed server or a missing grant all came back as \"the\n * mount is not there\", so `diff` answered `update`, `reconcile` ran `secrets enable`, and the plan\n * reported a CREATE on infrastructure that exists. The failure the operator sees is about the\n * wrong thing entirely, at the worst possible moment — a sealed vault. ⚠️ SO 403, 5xx AND ANYTHING\n * ELSE THAT IS NOT 2xx FAILS. The cost is that a genuinely-absent read under a too-narrow token\n * becomes an error instead of a create, and that is the right way round: \"I could not tell\" is a\n * true statement, and \"it is not there\" was not.\n *\n * 🔴 THE DELETES ALL USED THE READ HELPER, WHICH DISCARDED THE EXIT CODE. A refused\n * `secrets disable` was reported as a successful delete: the resource left Alchemy's state while\n * the mount stayed live, so the next plan showed nothing and the object was orphaned in silence.\n * ⚠️ ABSENCE IS STILL NOT AN ERROR FOR A DELETE, because a delete must be idempotent: Alchemy\n * retries, and the second attempt legitimately finds nothing. So a delete's 404 is success and\n * its 403 is not.\n * ★ DISABLING A MOUNT THAT IS ALREADY GONE IS NOT EVEN A 404. A review on 2026-09-14 said it failed\n * with `no matching mount` and would wedge a retried delete. The server says otherwise: it answers\n * success for a missing mount so as not to reveal whether one existed — openbao v2.6.2\n * vault/logical_system.go:1211-1216 — and the CLI printed \"Disabled the secrets engine (if it\n * existed)\" (command/secrets_disable.go:87).\n */\nexport const settle = (\n intent: BaoIntent,\n method: string,\n path: string,\n status: number,\n text: string,\n): Settled => {\n const fail = (errors: readonly string[]) => ({\n error: new BaoError(status, method, path, errors),\n });\n if (status < 200 || status >= 300) {\n const errors = errorsOf(text);\n if (errors === undefined) {\n // ⛔ DESCRIBED, NEVER QUOTED. A proxy or gateway error page can echo the request back, headers\n // and all, so quoting it could carry X-Vault-Token into an error that Alchemy logs (grok,\n // 2026-09-14). mint in house/proxmox/src/credentials.ts already did it this way.\n return fail([`not an OpenBao error body (${String(text.length)} bytes)`]);\n }\n if (status === 404 && intent !== 'write') return { body: undefined };\n return fail(errors);\n }\n // ★ A write or delete answering 204 has nothing to say. A READ with no body has told us nothing,\n // and OpenBao never does that — a read that finds nothing is a 404 (RespondErrorCommon).\n if (text.trim() === '') {\n return intent === 'read' ? fail(['a successful read with an empty body']) : { body: undefined };\n }\n const body = objectOf(text);\n return body === undefined ? fail(['a success body that is not a JSON object']) : { body };\n};\n",
12
12
  "/**\n * A role on one of the six Cloudflare secrets-engine mounts — what one consumer may mint: the\n * Cloudflare policy its tokens carry and the lease bounds they get. METADATA ONLY.\n *\n * ★ THE PORT OF apply-roles.py's WRITE. roles.yaml expands to these (cloudflare-roles-expand.ts),\n * and what used to be `bao write <mount>/roles/<name> ttl= max_ttl= description= policies=` is\n * reconcile below. The props name permission groups; CloudflarePermissionGroups turns them into\n * IDs at diff and reconcile time.\n *\n * ⛔ NO SECRET IN PROPS OR ATTRIBUTES — see cloudflare-role-form.ts. ⛔ AND ISSUANCE IS NOT THIS\n * RESOURCE: `<mount>/creds/<name>` returns a LIVE Cloudflare token, and a token declared as a\n * resource would outlive its lease in Alchemy's unencrypted state (proxmox-role.ts has the four\n * places it would land). This declares the door; minting is a runtime call.\n *\n * ★ `defaultRemovalPolicy: 'retain'` — deleting a role breaks every consumer that mints from it,\n * and apply-roles.py never deleted one either: an unexplained role was reported UNTRACKED and\n * left alone (apply-roles.py:190-196). Opt in with `.pipe(RemovalPolicy.destroy())`.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { groupKey, scopeOfResource } from './cloudflare-group-scope.ts';\nimport { CloudflarePermissionGroups, type GroupRef } from './cloudflare-permission-groups.ts';\nimport { resolvePolicies } from './cloudflare-policy.ts';\nimport {\n type BaoCloudflareRoleAttributes,\n type BaoCloudflareRoleProps,\n attributesOf,\n differences,\n refusalOf,\n rolePath,\n writeBody,\n} from './cloudflare-role-form.ts';\nimport {\n deleteCloudflareRole,\n readCloudflareRole,\n writeCloudflareRole,\n} from './cloudflare-role-wire.ts';\n\nexport type { BaoCloudflareRoleAttributes, BaoCloudflareRoleProps };\n\n/**\n * ⚠️ CloudflarePermissionGroups IS NOT A REQUIREMENT OF THE RESOURCE. The provider takes it once, when\n * it is built (`yield* CloudflarePermissionGroups` below), and alchemy.run.ts supplies it to the\n * provider layer with `Layer.provide`. Listing it here as well made it a requirement of the STACK\n * body, which Alchemy only lets name its own provider and stack services — tsc refused the wiring.\n */\nexport interface BaoCloudflareRole extends Resource<\n 'Bao.CloudflareRole',\n BaoCloudflareRoleProps,\n BaoCloudflareRoleAttributes,\n never,\n HttpClient.HttpClient\n> {}\n\nexport const BaoCloudflareRole = Resource<BaoCloudflareRole>('Bao.CloudflareRole', {\n defaultRemovalPolicy: 'retain',\n});\n\nexport const BaoCloudflareRoleProvider = () =>\n Provider.effect(\n BaoCloudflareRole,\n Effect.gen(function* () {\n const groups = yield* CloudflarePermissionGroups;\n\n /**\n * The declaration with IDs. ⛔ A name that does not resolve fails here — never a guess.\n *\n * ⛔ ONE REF PER (NAME, SCOPE), NOT PER NAME. The entry's resource is what says which scope\n * its groups are gated at, so a role whose zone entry and account entry name one group asks\n * for both ids; deduplicating by name alone would ask for one and use it for both.\n */\n const resolved = (props: BaoCloudflareRoleProps) =>\n Effect.gen(function* () {\n const refs = new Map<string, GroupRef>();\n for (const policy of props.policies) {\n /** ⛔ THE SAME PREFERENCE resolvePolicies MAKES — ask for the id the entry will use. */\n const scope = policy.scope ?? scopeOfResource(policy.resource);\n for (const name of policy.groups) refs.set(groupKey(name, scope), { name, scope });\n }\n const ids = yield* groups.resolve(props.mount, [...refs.values()]);\n const { missing, policies } = resolvePolicies(props.policies, ids);\n if (missing.length > 0) {\n return yield* Effect.die(\n new Error(\n `Bao.CloudflareRole ${rolePath(props.mount, props.name)}: groups ` +\n `${missing.join(', ')} came back unresolved from a lookup that reported success.`,\n ),\n );\n }\n return policies;\n });\n\n return BaoCloudflareRole.Provider.of({\n /**\n * ⛔ `<mount>/roles` IS NOT A LIST OF THINGS THIS OWNS. MEASURED 2026-09-14: 586 live roles,\n * 585 of which roles.yaml declares — and the 586th, cloudflare-<account>-platform/\n * alchemy-os-create, is exactly the role nobody has decided about. Returning it would\n * invite Alchemy to adopt, then delete, a role that may be someone's live credential.\n */\n list: () => Effect.succeed([]),\n\n read: Effect.fn(function* ({ olds }) {\n const live = yield* readCloudflareRole(olds.mount, olds.name);\n return live === undefined ? undefined : attributesOf(olds, live);\n }),\n\n /**\n * ⛔ IT COMPARES THE LIVE ROLE, NOT THE STORED DIGEST. A policy widened by hand in the\n * OpenBao UI changes what every future token can do while the digest in Postgres still\n * says everything is fine.\n *\n * ⚠️ NO `replace`, EVEN FOR A NAME OR MOUNT CHANGE. A different path is a different object,\n * so diff reads the new path, finds it absent and plans `update`; reconcile creates it and\n * the old role is left live, retained and unmanaged — the same outcome apply-roles.py's\n * UNTRACKED report had. declareCloudflareRoles puts mount and name in the resource id, so\n * a rename there is a new resource anyway.\n */\n diff: Effect.fn(function* ({ news, output }) {\n if (output === undefined || !isResolved(news)) return undefined;\n /**\n * ⚠️ A DECLARATION reconcile WOULD REFUSE MUST NEVER PLAN AS noop — route it to reconcile,\n * which says why (pki-role.ts has the same guard).\n */\n if (refusalOf(news) !== undefined) return { action: 'update' } as const;\n const policies = yield* resolved(news);\n const live = yield* readCloudflareRole(news.mount, news.name);\n if (live === undefined) return { action: 'update' } as const;\n return differences(news, policies, live).length === 0\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: Effect.fn(function* ({ news }) {\n const path = rolePath(news.mount, news.name);\n const refusal = refusalOf(news);\n if (refusal !== undefined) {\n return yield* Effect.die(new Error(`Bao.CloudflareRole ${path}: ${refusal}.`));\n }\n const policies = yield* resolved(news);\n const live = yield* readCloudflareRole(news.mount, news.name);\n /**\n * ⛔ ADOPTING A ROLE THAT ALREADY MATCHES MUST NOT REWRITE IT. Alchemy's `adopted` action\n * routes through reconcile (policy.ts has the Apply.ts reading), so without this guard\n * the first deploy would PUT all 585 roles — byte-identical in the happy case, and a\n * silent rewrite of live grants the moment the port disagreed with production.\n */\n if (live === undefined || differences(news, policies, live).length > 0) {\n yield* writeCloudflareRole(news.mount, news.name, writeBody(news, policies));\n }\n const after = yield* readCloudflareRole(news.mount, news.name);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(`Bao.CloudflareRole ${path}: the write succeeded but the role is absent.`),\n );\n }\n /**\n * ⛔ THE WRITE IS NOT TRUSTED, IT IS RE-READ. The engine re-marshals `policies` from structs\n * (path_roles.go:199-207), so a document it stored differently from what was sent — a\n * dropped group, a merged resource — shows up here as a named field, not as a green\n * deploy followed by a 403 at mint time.\n */\n const left = differences(news, policies, after);\n if (left.length > 0) {\n return yield* Effect.die(\n new Error(\n `Bao.CloudflareRole ${path}: wrote cleanly but reads back different in ` +\n `${left.map((d) => d.field).join(', ')}. Inspect the role before retrying.`,\n ),\n );\n }\n return attributesOf(news, after);\n }),\n\n /**\n * ⛔ DELETING A ROLE DOES NOT REVOKE THE TOKENS IT MINTED. They are leases on Cloudflare API\n * tokens and live to their own expiry, so this is an availability change for every\n * consumer of `creds/<name>`, never a containment action — to contain a leak, revoke the\n * lease. Idempotent: already gone is success (bao-status.ts).\n */\n delete: Effect.fn(function* ({ output }) {\n yield* deleteCloudflareRole(output.mount, output.name);\n return undefined;\n }),\n });\n }),\n );\n",
13
13
  "/**\n * The three resources a Cloudflare policy entry can name, and the SCOPE its permission groups are\n * looked up at — one vocabulary, both directions.\n *\n * ★ EXTRACTED FROM cloudflare-roles-expand.ts 2026-09-15, which had reached 270 lines (AGENTS.md\n * rule 5, code ≤250). The split is by CONCERN, not by size: expand.ts turns roles.yaml into\n * roles, this answers \"which of the two ids named `Logs Read` does this entry mean\".\n */\n\n/** cfhf.py:172-173. */\nexport const zoneResource = (zoneId: string) => `com.cloudflare.api.account.zone.${zoneId}`;\nexport const accountResource = (accountId: string) => `com.cloudflare.api.account.${accountId}`;\n\n/**\n * One R2 bucket, which is a DIFFERENT RESOURCE NAMESPACE from the two above.\n *\n * ⛔ `com.cloudflare.edge.r2.bucket.…`, NOT `com.cloudflare.api.account.…`, and the three parts are\n * joined by UNDERSCORES inside the last segment — `<accountId>_<jurisdiction>_<bucket>`. Getting\n * the separator wrong produces a syntactically fine resource that matches no bucket, and the\n * token mints successfully and is refused on first use, which reads exactly like a missing\n * permission group. Per Cloudflare's R2 API-token documentation, read 2026-09-15.\n * ⚠️ AND IT ONLY BINDS THE `Bucket Item` GROUPS. `Workers R2 Storage Write` / `… Read` are gated at\n * the ACCOUNT scope; the bucket-scoped pair is `Workers R2 Storage Bucket Item Write` / `… Read`.\n * Pairing an account group with this resource is the same silent 403.\n */\nexport const bucketResource = (accountId: string, jurisdiction: string, bucket: string) =>\n `com.cloudflare.edge.r2.bucket.${accountId}_${jurisdiction}_${bucket}`;\n\n/**\n * The three scopes this expansion can ask for — the namespaces of the three resources above, which\n * is exactly what the engine reports as a group's `scopes`.\n *\n * ★ MEASURED on `cloudflare-<account>-platform/permission-groups`, 2026-09-15 12:10: 401 groups,\n * every one with exactly ONE scope, over five values — 297 `com.cloudflare.api.account`, 94\n * `com.cloudflare.api.account.zone`, 2 `com.cloudflare.edge.r2.bucket` and four each of\n * `…account.flagship.app` and `com.cloudflare.edge.worker.script`, which no resource here builds.\n * The testing account's list is byte-identical, so the ids are Cloudflare's, not an account's.\n */\nexport const GROUP_SCOPES = {\n account: 'com.cloudflare.api.account',\n bucket: 'com.cloudflare.edge.r2.bucket',\n zone: 'com.cloudflare.api.account.zone',\n} as const;\n\n/**\n * The short word roles.yaml writes in `groups_scope:` → the namespace: `zone` becomes\n * `com.cloudflare.api.account.zone`. Undefined for a word that is not one of the three KEYS above.\n *\n * ⛔ THE yaml SAYS THE SHORT WORD AND NEVER THE NAMESPACE. A namespace typed into roles.yaml would\n * be accepted by any check that only asked for a string, and a misspelt one resolves no group at\n * all — an unknown-group failure naming a scope nobody wrote on purpose, instead of the line.\n * ⚠️ `Object.entries(…).find`, NOT an index with a narrowing `as`: codex standard 2 bans the cast,\n * and the lookup has three entries.\n */\nexport const groupScopeNamed = (word: string): string | undefined =>\n Object.entries(GROUP_SCOPES).find(([name]) => name === word)?.[1];\n\n/**\n * The scope the groups of one policy entry are gated at: its resource namespace, the instance id\n * dropped. A zone entry asks for zone groups, an account entry for account groups, a bucket entry\n * for the two `com.cloudflare.edge.r2.bucket` ones.\n *\n * ⛔ ZONE IS TESTED BEFORE ACCOUNT, because `com.cloudflare.api.account.zone.<id>` also starts with\n * the account namespace, and the wrong order would call every zone entry an account one.\n * ⚠️ A RESOURCE IN NO KNOWN NAMESPACE BECOMES ITS OWN SCOPE, which matches no group, so it fails as\n * an unresolvable name naming the scope it asked for — never by borrowing another scope's id.\n * ⚠️ IT IS THE DEFAULT, NOT THE LAST WORD. An entry carrying an explicit `scope` overrides it —\n * see DeclaredPolicy.scope (cloudflare-roles-expand.ts) and resolvePolicies.\n */\nexport const scopeOfResource = (resource: string) => {\n const scopes = [GROUP_SCOPES.zone, GROUP_SCOPES.bucket, GROUP_SCOPES.account];\n return scopes.find((scope) => resource.startsWith(`${scope}.`)) ?? resource;\n};\n\n/**\n * What a resolved group is filed under.\n *\n * ⛔ A NAME ALONE IS NOT A KEY. MEASURED 2026-09-15 on the live list: SEVEN names are listed twice,\n * once at `com.cloudflare.api.account` and once at `com.cloudflare.api.account.zone` — `Access:\n * Apps and Policies Read` / `… Revoke` / `… Write`, `Disable ESC Read` / `… Write`, `Logs Read`\n * and `Logs Write`. cfhf.py:148 keyed by name and the last one read won in silence.\n */\nexport const groupKey = (name: string, scope: string) => `${scope} ${name}`;\n",
14
14
  "/**\n * Permission-group (name, SCOPE) → ID, behind ONE interface with two sources.\n *\n * ⛔ THE KEY IS THE PAIR, AND THAT IS NOT PEDANTRY. MEASURED 2026-09-15 the hour the grant went\n * live: of the account's 401 groups, SEVEN names are listed twice — `Access: Apps and Policies\n * Read`/`Revoke`/`Write`, `Disable ESC Read`/`Write`, `Logs Read`/`Write` — each pair one id\n * scoped `com.cloudflare.api.account` and one scoped `com.cloudflare.api.account.zone`. Keyed by\n * name alone the whole plan fails as ambiguous; keyed by name alone and forgiving, cfhf.py:148's\n * last-one-wins picks a group gated at the wrong scope and the token is refused at first use.\n * The asking ENTRY says which: its `scope` (roles.yaml `groups_scope:`), else its resource.\n *\n * ★ A SERVICE, NOT A TABLE. roles.yaml names groups (`DNS Read`); a role stores IDs. apply-roles.py\n * resolved them per account with a Cloudflare parent credential (cfhf.py:147-148), which agents\n * may not use. So Bao.CloudflareRole asks this service, and the stack chooses the source:\n *\n * a) `permissionGroupsFromEngine` — `GET <mount>/permission-groups` on the Cloudflare engine,\n * answered under the mount's own parent. ★ DEPLOYED AND WIRED 2026-09-15: `bao path-help\n * cloudflare-<account>-platform` lists `^permission-groups$` on plugin v0.0.0-dev, and\n * cloudflare-roles.ts now provides this source to the stack.\n * b) `permissionGroupsFromLiveRoles` — ⚠️ TEMPORARY, AND STILL HERE ON PURPOSE. 2026-09-15: no\n * longer the stack's source, and NOT yet deletable. Two things gate that — (1) the live\n * `result_info` envelope pinned in ../../platform/secrets/vault/plugin/cloudflare/\n * client_result_info.go, whose own header names this deletion as what it gates, and (2)\n * cloudflare-parity.ts, which calls cloudflare-permission-groups-solve.ts directly for the\n * OFFLINE proof against a production export and has no engine to ask. So (b) and the solver\n * stay, one import from being the layer again (cloudflare-roles.ts), until the last step of\n * docs/ledger/openbao-permission-groups-engine-2026-09-15.md is done.\n *\n * ⛔ AN UNKNOWN NAME FAILS THE OPERATION. Dropping it would write a policy one group short, and the\n * engine refuses an empty ID (path_roles.go:181-185) but not a SHORTER list: the minted token is\n * quietly narrower than declared, and the consumer finds out at 403.\n */\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { baoRead } from './bao-http.ts';\nimport type { BaoError } from './bao-status.ts';\nimport { groupKey } from './cloudflare-group-scope.ts';\nimport {\n describeProblems,\n observationsOf,\n solveGroups,\n} from './cloudflare-permission-groups-solve.ts';\nimport { type WirePolicy, atEveryScope } from './cloudflare-policy.ts';\nimport { readCloudflareRole } from './cloudflare-role-wire.ts';\nimport type { ExpandedRole } from './cloudflare-roles-expand.ts';\nimport { mountPath } from './mount-form.ts';\n\nexport class CloudflareGroupsError extends Error {\n constructor(\n readonly scope: string,\n readonly problems: readonly string[],\n ) {\n super(`Cloudflare permission groups for ${scope}: ${problems.join('; ')}`);\n this.name = 'CloudflareGroupsError';\n }\n}\n\n/** ⛔ Keyed by `groupKey(name, scope)` throughout — see cloudflare-group-scope.ts. */\ntype Groups = ReadonlyMap<string, string>;\ntype Lookup = Effect.Effect<Groups, BaoError | CloudflareGroupsError, HttpClient.HttpClient>;\n\n/** One group a role asks for: its name, and the scope the entry naming it is gated at. */\nexport interface GroupRef {\n readonly name: string;\n readonly scope: string;\n}\n\nexport class CloudflarePermissionGroups extends Context.Service<\n CloudflarePermissionGroups,\n {\n /** The ID of every ref, keyed by `groupKey` — or a failure naming what did not resolve. */\n readonly resolve: (\n mount: string,\n refs: readonly GroupRef[],\n ) => Effect.Effect<Groups, BaoError | CloudflareGroupsError, HttpClient.HttpClient>;\n }\n>()('homeflare/openbao/CloudflarePermissionGroups') {}\n\nconst pick = (mount: string, groups: Groups, refs: readonly GroupRef[], hint: string) => {\n const unknown = refs.filter((ref) => !groups.has(groupKey(ref.name, ref.scope)));\n if (unknown.length > 0) {\n const problems = unknown.map(\n (ref) => `unknown group ${JSON.stringify(ref.name)} at scope ${ref.scope} — ${hint}`,\n );\n return Effect.fail(new CloudflareGroupsError(mount, problems));\n }\n return Effect.succeed(\n new Map(\n refs.flatMap((ref) => {\n const key = groupKey(ref.name, ref.scope);\n const id = groups.get(key);\n return id === undefined ? [] : [[key, id] as const];\n }),\n ),\n );\n};\n\nconst isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * ⛔ A 403 IS A MISSING GRANT, AND IT SAYS SO. `BaoError` alone reports `GET /v1/<mount>/\n * permission-groups -> 403: permission denied` — true, and it points nowhere: the path is\n * deployed, the token is valid, and the one thing to change is a policy file. MEASURED 2026-09-15\n * 10:19 on the macmini-admin lane, where `bao write sys/capabilities-self` answered `[deny]` on\n * this exact path. bao-status.ts argues that a failure must name what it is; this is that\n * argument one level up.\n */\nconst deniedHint = (mount: string) =>\n `GET ${mountPath(mount)}/permission-groups answered 403 — this token's policy carries no ` +\n `\\`path \"${mountPath(mount)}/permission-groups\" { capabilities = [\"read\"] }\\` grant. ` +\n 'It is declared in ../platform/secrets/vault/policies/homeflare-admin/' +\n '20-cloudflare-permission-groups.hcl and applies with `alchemy deploy` of this stack';\n\nconst deniedNamed = <A, R>(mount: string, read: Effect.Effect<A, BaoError, R>) =>\n Effect.catchIf(\n read,\n (error) => error.status === 403,\n () => Effect.fail(new CloudflareGroupsError(mount, [deniedHint(mount)])),\n );\n\n/**\n * a) The engine's list, parsed.\n *\n * ★ THE SHAPE IS THE PLUGIN'S OWN, READ FROM ITS SOURCE 2026-09-15:\n * `{\"permission_groups\":[{\"id\",\"name\",\"scopes\"}]}` built row by row in\n * ../../platform/secrets/vault/plugin/cloudflare/path_permission_groups.go:42-54. baoRead takes\n * `data` when the body has one and the whole body otherwise (bao-http.ts:160-167), so either\n * envelope parses.\n * ⚠️ PAGINATION IS THE PLUGIN'S PROBLEM, NOT THIS PARSER'S. client_permission_groups.go:52-119 walks\n * Cloudflare's pages and ends every guard in an error rather than a shorter list, so what arrives\n * here is complete or absent. ⛔ ITS `result_info` GUARDS ARE STILL UNMEASURED against a live\n * envelope (client_result_info.go:22-28) — that capture, not this file, is what gates deleting (b).\n * ⛔ ONE NAME WITH TWO IDS IS NOT AN ERROR; ONE (NAME, SCOPE) WITH TWO IDS IS. cfhf.py:148 built\n * `{g[\"name\"]: g[\"id\"]}` and the LAST duplicate won in silence. MEASURED 2026-09-15 on the live\n * list: seven names ARE listed twice, each pair one account-scoped id and one zone-scoped id, so\n * the plugin's \"does not choose between them\" (path_permission_groups.go:69-70) is the shape in\n * front of us, not a hypothetical. `scopes` tells them apart; the header above says who picks.\n * ⚠️ AN EMPTY `scopes` IS NOT AN ERROR. Such a group is reachable only by the one-id rule below —\n * a name nothing else claims answers wherever it is asked — so a group Cloudflare ships without\n * a scope resolves, and never holds the other 398 hostage.\n */\nconst engineGroups = (mount: string): Lookup =>\n Effect.flatMap(deniedNamed(mount, baoRead(`${mountPath(mount)}/permission-groups`)), (data) => {\n const list = data?.['permission_groups'];\n if (data === undefined) {\n // ⚠️ 404 IS NOW A MOUNT-SHAPED ANSWER, NOT THE EXPECTED ONE. The path IS deployed\n // estate-wide (measured 2026-09-15), so a 404 here means this mount is served by an older\n // plugin binary or BAO_ADDR is not the mini — never \"no groups\".\n const why = 'GET <mount>/permission-groups answered 404 — the endpoint is not deployed here';\n return Effect.fail(new CloudflareGroupsError(mount, [why]));\n }\n if (!Array.isArray(list)) {\n return Effect.fail(new CloudflareGroupsError(mount, ['no permission_groups array in reply']));\n }\n const scoped = new Map<string, string>();\n const idsOf = new Map<string, Set<string>>();\n const problems: string[] = [];\n for (const item of list) {\n const name = isRecord(item) ? item['name'] : undefined;\n const id = isRecord(item) ? item['id'] : undefined;\n const scopes = isRecord(item) ? item['scopes'] : undefined;\n if (\n typeof name !== 'string' ||\n typeof id !== 'string' ||\n !Array.isArray(scopes) ||\n !scopes.every((scope) => typeof scope === 'string')\n ) {\n problems.push('an entry without a string name, id and scopes');\n continue;\n }\n idsOf.set(name, (idsOf.get(name) ?? new Set()).add(id));\n for (const scope of scopes) {\n const key = groupKey(name, scope);\n if (scoped.has(key) && scoped.get(key) !== id) {\n problems.push(\n `ambiguous: ${JSON.stringify(name)} is listed with two ids at scope ${scope}`,\n );\n } else {\n scoped.set(key, id);\n }\n }\n }\n /**\n * ★ A NAME WITH ONE ID NEEDS NO SCOPE, and answers at every scope an entry can ask for: there\n * is nothing to choose between, and 385 of the list's 392 names are in that case. It is only\n * the seven two-id names the asking scope has to separate — and for those, a scope the name\n * is not listed at resolves to nothing and fails by name, never to the other scope's id.\n */\n const sole = new Map(\n [...idsOf].flatMap(([name, ids]) => {\n const only = [...ids];\n return ids.size === 1 && only[0] !== undefined ? [[name, only[0]] as const] : [];\n }),\n );\n return problems.length > 0\n ? Effect.fail(new CloudflareGroupsError(mount, problems))\n : Effect.succeed(new Map([...atEveryScope(sole), ...scoped]));\n });\n\n/**\n * ★ ONE FETCH PER MOUNT PER RUN, not one per role — 586 roles would otherwise ask 586 times.\n * ⚠️ A FAILURE IS CACHED TOO (Effect.cached keeps the Exit), so one sealed-vault 503 fails every\n * role on that mount for the rest of the run. That is the honest outcome for a plan: retrying\n * 586 times against a sealed server would only make the failure slower.\n */\nexport const permissionGroupsFromEngine = () =>\n Effect.sync(() => {\n const cache = new Map<string, Lookup>();\n const cachedFor = (mount: string) =>\n Effect.suspend(() => {\n const hit = cache.get(mountPath(mount));\n if (hit !== undefined) return hit;\n return Effect.flatMap(Effect.cached(engineGroups(mount)), (lookup) => {\n cache.set(mountPath(mount), lookup);\n return lookup;\n });\n });\n return CloudflarePermissionGroups.of({\n resolve: (mount, refs) =>\n Effect.flatMap(cachedFor(mount), (groups) =>\n pick(mount, groups, refs, 'the engine does not list it for this account at that scope'),\n ),\n });\n });\n\n/**\n * b) ⚠️ TEMPORARY, AND NO LONGER THE STACK'S SOURCE SINCE 2026-09-15 — see the header for the two\n * things that gate deleting it. Reads every DECLARED role of an account — no LIST, because an\n * undeclared live role carries IDs with no names to pair them with — and solves the account at\n * once.\n * 🔴 WHAT RETIRED IT, 2026-09-15 10:13: `alchemy deploy` could not create\n * `cloudflare-{<account>,testing}-platform/roles/r2-backup-mini` — `unknown group \"Workers R2\n * Storage Bucket Item Write\" — no live role on account <account> carries it; a NEW group needs\n * the engine endpoint`. That is this source's documented blind spot arriving, not a bug in it.\n *\n * ★ PER ACCOUNT, NOT PER MOUNT, BECAUSE ONE MOUNT CANNOT SOLVE ITSELF. MEASURED on the snapshot:\n * `aimto-app-alchemy-os-create` on the platform mount pairs `Email Routing Rules Write` and\n * `DNS Write` with two unknown IDs, and neither group appears alone on that mount. The dns and\n * security mounts of the same account isolate them. apply-roles.py's map was per account too\n * (apply-roles.py:117).\n */\nexport const permissionGroupsFromLiveRoles = (\n declared: ReadonlyMap<string, readonly ExpandedRole[]>,\n) =>\n Effect.gen(function* () {\n const accountOf = new Map<string, string>();\n const byAccount = new Map<string, ExpandedRole[]>();\n for (const [mount, roles] of declared) {\n for (const role of roles) {\n accountOf.set(mount, role.account);\n byAccount.set(role.account, [...(byAccount.get(role.account) ?? []), role]);\n }\n }\n const solved = new Map<string, Lookup>();\n for (const [account, roles] of byAccount) {\n const solve = Effect.gen(function* () {\n const live = new Map<string, readonly WirePolicy[]>();\n // ★ `Effect.all` over mapped reads, not `Effect.forEach`: oxlint's unicorn/no-array-for-each\n // matches the method NAME and cannot tell Effect's from Array's.\n yield* Effect.all(\n roles.map((role) =>\n Effect.map(readCloudflareRole(role.mount, role.name), (read) => {\n if (read?.policies !== undefined) {\n live.set(`${role.mount}/${role.name}`, read.policies);\n }\n }),\n ),\n { concurrency: 8, discard: true },\n );\n const result = solveGroups(observationsOf(roles, live));\n const problems = describeProblems(result);\n if (problems.length > 0) {\n return yield* Effect.fail(new CloudflareGroupsError(`account ${account}`, problems));\n }\n /**\n * ⚠️ IT ANSWERS AT EVERY SCOPE BECAUSE IT CANNOT SEE ONE. A live role carries ids and no\n * scopes, so the solver learns `name → id` and nothing more; the seven two-id names\n * resolve here to whichever id the estate happens to carry, at whatever scope is asked.\n * That is this source's blind spot, not a second opinion — (a) keys by (name, scope).\n */\n return atEveryScope(result.groups);\n });\n solved.set(account, yield* Effect.cached(solve));\n }\n return CloudflarePermissionGroups.of({\n resolve: (mount, refs) => {\n const account = accountOf.get(mountPath(mount));\n const lookup = account === undefined ? undefined : solved.get(account);\n if (account === undefined || lookup === undefined) {\n const why = 'no declared role on this mount, so no live role can vouch for its groups';\n return Effect.fail(new CloudflareGroupsError(mount, [why]));\n }\n const hint = `no live role on account ${account} carries it; a NEW group needs the engine endpoint`;\n return Effect.flatMap(lookup, (groups) => pick(mount, groups, refs, hint));\n },\n });\n });\n",
15
+ "/**\n * ⚠️ TEMPORARY — DELETE WITH `permissionGroupsFromLiveRoles` (cloudflare-permission-groups.ts) ONCE\n * `GET <mount>/permission-groups` IS DEPLOYED ON THE CLOUDFLARE ENGINE.\n *\n * The pure half of the bootstrap: recover permission-group name → ID from roles whose names are\n * declared (roles.yaml) and whose IDs are live (the engine).\n *\n * ★ WHY IT EXISTS AT ALL. apply-roles.py resolved names with\n * `GET /accounts/<id>/tokens/permission_groups` (cfhf.py:147-148) under a Cloudflare parent\n * credential, which agents may not use. The engine is gaining an endpoint that answers under its\n * own credential; until it ships, the only other witness is the roles apply-roles.py already\n * wrote, each pairing a list of names with a list of IDs.\n *\n * ⛔ NEVER A GUESS.\n * 1. Every entry with exactly one name and one ID binds that pair.\n * 2. Then, until nothing changes: an entry left with exactly ONE name and ONE ID not yet known\n * binds those two.\n * 3. Once settled, every entry is checked against the map: one that declares a known name without\n * carrying that name's ID CONTRADICTS it.\n * POSITIONS ARE NEVER USED, even where the Python kept yaml order — a hand-edited role would\n * otherwise teach the map a wrong pair in silence. A name bound to two IDs, or an ID bound to two\n * names, is AMBIGUOUS; a name nothing isolates is UNRESOLVED; and a contradiction is exactly\n * that. Each is an error for the whole account, not a best effort.\n *\n * ⛔ THE CONTRADICTION CHECK IS THE ONE THAT BITES, AND IT WAS FOUND BY A TEST, NOT BY DESIGN. When a\n * name has ONE single-group witness and that role was edited by hand, step 1 learns the edited ID,\n * and the multi-group roles carrying the real one merely fail to eliminate. Unchecked, diff would\n * then plan every one of those roles as an update TO THE EDITED ID — a hand edit propagated by the\n * tool meant to catch it. Which side is wrong is unknowable here; only Cloudflare knows.\n * ⚠️ THE PRICE: SOURCE (b) CANNOT PLAN A GROUP ADDED TO, OR SWAPPED IN, AN EXISTING ROLE. That edit\n * looks exactly like the hand edit above — declared names disagreeing with live IDs — so it fails\n * the account. New roles and removed groups still plan. (b) is for ADOPTION; changes wait for (a).\n *\n * ⛔ IT KEYS BY NAME AND THE ENGINE SOURCE KEYS BY (NAME, SCOPE) — DELIBERATELY UNCHANGED, 2026-09-15.\n * A live role is a list of ids with no scopes, so a name is all this can key on; seven names the\n * engine lists TWICE (once account-scoped, once zone-scoped) are one entry here, holding whichever\n * id the estate happens to carry. cloudflare-policy.ts `atEveryScope` is where that map is widened\n * to the scoped key the resolver now uses, and it is the honest shape of this blind spot: this file\n * is the OFFLINE PARITY PROOF against a production export, and rewriting it to a key it cannot\n * observe would make it agree with the engine by construction instead of by measurement.\n *\n * ⚠️ WHAT IT CANNOT CATCH. The names come from roles.yaml itself, so a group misnamed CONSISTENTLY\n * — every use of `DNS Read` spelled `DNS Reed` — pairs the wrong name with the right ID and\n * resolves cleanly, where Cloudflare would have refused it. cloudflare/parity.ts cross-checks the\n * catalog documents apply-roles.py wrote, which hold names that DID resolve against Cloudflare at\n * the last apply, for exactly that reason. The engine endpoint has no such blind spot.\n */\nimport type { WirePolicy } from './cloudflare-policy.ts';\nimport type { ExpandedRole } from './cloudflare-roles-expand.ts';\n\nexport interface Observation {\n /** `<mount>/<role>[<entry>]`, for messages. */\n readonly where: string;\n readonly names: readonly string[];\n readonly ids: readonly string[];\n}\n\nexport interface Conflict {\n /** `name` bound to several IDs, or `id` bound to several names. */\n readonly kind: 'id' | 'name';\n readonly value: string;\n readonly bound: readonly string[];\n}\n\n/** An entry declaring `name`, whose ID the map knows as `id`, without carrying `id`. */\nexport interface Contradiction {\n readonly where: string;\n readonly name: string;\n readonly id: string;\n}\n\nexport interface Solved {\n readonly groups: ReadonlyMap<string, string>;\n readonly ambiguous: readonly Conflict[];\n readonly unresolved: readonly string[];\n readonly contradicted: readonly Contradiction[];\n}\n\n/**\n * One observation per declared entry whose resource matches exactly one live entry of that role.\n *\n * ★ PAIRED BY RESOURCE, NOT BY POSITION. A zone role's account groups sit on the account resource\n * and nowhere else, whatever order the entries were stored in. An entry that shares its resource\n * with a sibling, or finds no single live match, observes nothing — the diff reports it instead.\n */\nexport const observationsOf = (\n declared: readonly ExpandedRole[],\n live: ReadonlyMap<string, readonly WirePolicy[]>,\n): Observation[] =>\n declared.flatMap((role) => {\n const entries = live.get(`${role.mount}/${role.name}`);\n if (entries === undefined) return [];\n return role.policies.flatMap((policy, i) => {\n const twins = role.policies.filter((other) => other.resource === policy.resource);\n const matching = entries.filter(\n (entry) => Object.keys(entry.resources).length === 1 && policy.resource in entry.resources,\n );\n const [only] = matching;\n if (twins.length !== 1 || matching.length !== 1 || only === undefined) return [];\n return [\n {\n ids: only.groupIds,\n names: policy.groups,\n where: `${role.mount}/${role.name}[${String(i)}]`,\n },\n ];\n });\n });\n\nconst unique = (items: readonly string[]) => [...new Set(items)];\n\nexport const solveGroups = (observations: readonly Observation[]): Solved => {\n const idsOf = new Map<string, Set<string>>();\n const namesOf = new Map<string, Set<string>>();\n const bind = (name: string, id: string) => {\n const ids = idsOf.get(name) ?? new Set<string>();\n const fresh = !ids.has(id);\n idsOf.set(name, ids.add(id));\n namesOf.set(id, (namesOf.get(id) ?? new Set<string>()).add(name));\n return fresh;\n };\n /** Known only while the name has one ID and that ID has only this name. */\n const known = (name: string) => {\n const ids = idsOf.get(name);\n const [id] = ids ?? [];\n return ids?.size === 1 && id !== undefined && namesOf.get(id)?.size === 1 ? id : undefined;\n };\n\n const shaped = observations.map((o) => ({ ids: unique(o.ids), names: unique(o.names) }));\n // 1. Every single-group entry binds, unconditionally — so a contradicting one is RECORDED as a\n // conflict rather than skipped because its name happened to be learned first.\n for (const { ids, names } of shaped) {\n const [name] = names;\n const [id] = ids;\n if (names.length === 1 && ids.length === 1 && name !== undefined && id !== undefined) {\n bind(name, id);\n }\n }\n // 2. Elimination. ⚠️ A count mismatch proves nothing about which name is which ID, so it is skipped.\n for (let changed = true; changed;) {\n changed = false;\n for (const { ids, names } of shaped) {\n if (names.length !== ids.length) continue;\n const knownIds = new Set(names.map(known));\n const openNames = names.filter((name) => known(name) === undefined);\n const openIds = ids.filter((id) => !knownIds.has(id));\n const [name] = openNames;\n const [id] = openIds;\n if (\n openNames.length === 1 &&\n openIds.length === 1 &&\n name !== undefined &&\n id !== undefined\n ) {\n changed = bind(name, id) || changed;\n }\n }\n }\n // 3. Contradictions — including entries step 2 skipped for a count mismatch.\n const contradicted: Contradiction[] = [];\n for (const o of observations) {\n for (const name of unique(o.names)) {\n const id = known(name);\n if (id !== undefined && !o.ids.includes(id)) contradicted.push({ id, name, where: o.where });\n }\n }\n\n const groups = new Map<string, string>();\n const ambiguous: Conflict[] = [];\n const unresolved: string[] = [];\n for (const name of unique(observations.flatMap((o) => o.names)).sort()) {\n const ids = idsOf.get(name);\n const id = known(name);\n if (ids === undefined) unresolved.push(name);\n else if (ids.size > 1) ambiguous.push({ bound: [...ids].sort(), kind: 'name', value: name });\n else if (id !== undefined) groups.set(name, id);\n }\n for (const [id, names] of [...namesOf].sort(([a], [b]) => (a < b ? -1 : 1))) {\n if (names.size > 1) ambiguous.push({ bound: [...names].sort(), kind: 'id', value: id });\n }\n return { ambiguous, contradicted, groups, unresolved };\n};\n\n/** Every conflict, unresolved name and contradiction, one line each. */\nexport const describeProblems = (solved: Solved): string[] => [\n ...solved.ambiguous.map((c) =>\n c.kind === 'name'\n ? `ambiguous: name ${JSON.stringify(c.value)} is bound to ids ${c.bound.join(', ')}`\n : `ambiguous: id ${c.value} is bound to names ${c.bound.map((n) => JSON.stringify(n)).join(', ')}`,\n ),\n ...solved.unresolved.map(\n (name) => `unresolved: no live role isolates ${JSON.stringify(name)} to one id`,\n ),\n ...solved.contradicted.map(\n (c) => `contradicted: ${c.where} declares ${JSON.stringify(c.name)} but lacks its id ${c.id}`,\n ),\n];\n",
15
16
  "/**\n * A Cloudflare policy document as the engine stores it — resolution from names, parsing from a\n * read, and the one comparison every Bao.CloudflareRole plan rests on.\n *\n * MEASURED from the engine source (house/platform/secrets/vault/plugin/cloudflare/path_roles.go)\n * and the 2026-09-14 snapshot of all 586 live roles:\n * • `policies` is a STRING field holding a JSON array (path_roles.go:67-72). Each entry is\n * `{effect, resources: map[string]string, permission_groups: [{id}]}` (:25-33).\n * • A read hands back `json.Marshal` of the stored slice (:199-207): no whitespace, entry and\n * group order preserved (Go slices), resource keys sorted (Go maps). Every snapshot role has\n * exactly that shape.\n */\nimport { GROUP_SCOPES, groupKey, scopeOfResource } from './cloudflare-group-scope.ts';\nimport type { DeclaredPolicy } from './cloudflare-roles-expand.ts';\n\nexport interface WirePolicy {\n readonly effect: string;\n readonly resources: Readonly<Record<string, string>>;\n readonly groupIds: readonly string[];\n}\n\n/** A declared entry with its IDs, still carrying how its group order is to be compared. */\nexport interface ResolvedPolicy extends WirePolicy {\n readonly groupOrder: DeclaredPolicy['groupOrder'];\n}\n\n/**\n * One name at every scope — what a source that cannot see scopes can honestly offer.\n *\n * ⚠️ IT IS A WIDENING, AND IT IS THE ASYMMETRY BETWEEN THE TWO SOURCES. The live-roles bootstrap\n * and cloudflare-permission-groups-solve.ts recover `name → id` from roles that carry ids and no\n * scopes, so they cannot tell the seven two-id names apart; the id they learned is offered for\n * whatever scope an entry asks. The engine source keys by (name, scope) and never does this.\n */\nexport const atEveryScope = (byName: ReadonlyMap<string, string>): ReadonlyMap<string, string> =>\n new Map(\n [...byName].flatMap(([name, id]) =>\n Object.values(GROUP_SCOPES).map((scope) => [groupKey(name, scope), id] as const),\n ),\n );\n\n/**\n * Declared names to IDs, or the names `ids` lacks.\n *\n * ⛔ AN ENTRY LOOKS ITS GROUPS UP AT ITS OWN SCOPE (`groupKey`), not by name: a zone entry and an\n * account entry of the same role can name one group and mean two different ids.\n * ★ THE ACCOUNT ENTRY IS SORTED BY ID, EXACTLY AS cfhf.py:180 DID. ⚠️ Plain `sort()`, never\n * `localeCompare`: Python's `sorted()` on str is codepoint order, and JavaScript's default sort\n * is UTF-16 code-unit order, which agree on the lowercase hex these IDs are made of.\n */\nexport const resolvePolicies = (\n declared: readonly DeclaredPolicy[],\n ids: ReadonlyMap<string, string>,\n): { readonly policies: ResolvedPolicy[]; readonly missing: string[] } => {\n const missing = new Set<string>();\n const policies = declared.map((policy) => {\n /**\n * ⛔ THE ENTRY'S OWN WORD BEATS ITS RESOURCE. `scope` is roles.yaml `groups_scope:` reaching\n * here unchanged; `scopeOfResource` is the default for the 639 of 643 references that say\n * nothing. The four that do are `logs`/`logs-read` on both security mounts — ACCOUNT roles\n * whose live entry carries the ZONE-scoped `Logs` ids, which is how Cloudflare writes \"all\n * zones from an account\" (cf-mint-analytics-tokens.py:155-158).\n */\n const scope = policy.scope ?? scopeOfResource(policy.resource);\n const groupIds = policy.groups.flatMap((name) => {\n const id = ids.get(groupKey(name, scope));\n if (id === undefined) missing.add(name);\n return id === undefined ? [] : [id];\n });\n return {\n effect: policy.effect,\n groupIds: policy.groupOrder === 'by-id' ? [...groupIds].sort() : groupIds,\n groupOrder: policy.groupOrder,\n resources: { [policy.resource]: '*' },\n };\n });\n return { missing: [...missing].sort(), policies };\n};\n\nconst isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst stringMap = (value: unknown): Readonly<Record<string, string>> | undefined => {\n if (!isRecord(value)) return undefined;\n const out: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n out[key] = item;\n }\n return out;\n};\n\nconst entryOf = (entry: unknown): WirePolicy | undefined => {\n if (!isRecord(entry) || typeof entry['effect'] !== 'string') return undefined;\n const resources = stringMap(entry['resources']);\n const groups = entry['permission_groups'];\n if (resources === undefined || !Array.isArray(groups)) return undefined;\n const groupIds = groups.flatMap((group) =>\n isRecord(group) && typeof group['id'] === 'string' ? [group['id']] : [],\n );\n return groupIds.length === groups.length\n ? { effect: entry['effect'], groupIds, resources }\n : undefined;\n};\n\n/**\n * The live `policies` string parsed, or undefined when it is not a policy document.\n *\n * ⚠️ UNDEFINED IS NOT ABSENCE. It means the role exists and its policies could not be read, which\n * compares unequal to every declaration — so it plans `update`, and reconcile's re-read refuses\n * to call a write that still reads back like that a success.\n */\nexport const parseLivePolicies = (raw: unknown): WirePolicy[] | undefined => {\n if (typeof raw !== 'string') return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!Array.isArray(parsed)) return undefined;\n const policies = parsed.map(entryOf);\n return policies.every((policy): policy is WirePolicy => policy !== undefined)\n ? policies\n : undefined;\n};\n\n/**\n * The `policies` field for a write — the array cfhf.py:174-180 built, serialized.\n *\n * ⚠️ NOT BYTE-IDENTICAL TO WHAT PYTHON SENT, AND IT NEED NOT BE. `json.dumps` put a space after\n * every `:` and `,`; this emits none. The engine unmarshals the string into structs\n * (path_roles.go:161-166) and stores those, never the text, so the stored role and the read\n * that diff compares are the same either way.\n */\nexport const policiesJson = (policies: readonly WirePolicy[]) =>\n JSON.stringify(\n policies.map((policy) => ({\n effect: policy.effect,\n resources: policy.resources,\n permission_groups: policy.groupIds.map((id) => ({ id })),\n })),\n );\n\nconst sameList = (a: readonly string[], b: readonly string[]) =>\n a.length === b.length && a.every((item, i) => item === b[i]);\n\nconst sameResources = (\n a: Readonly<Record<string, string>>,\n b: Readonly<Record<string, string>>,\n) => {\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);\n};\n\n/**\n * ⛔ THE POLICY EQUALITY.\n *\n * • Entry count and entry ORDER must match: cfhf.py always wrote the scope entry first and the\n * account entry second (cfhf.py:174-180).\n * • Within an entry: effect, the resource map, and the group IDs — IN ORDER for a `declared`\n * entry, because cfhf.py:175 kept yaml order; AS A SORTED LIST for a `by-id` entry, because\n * cfhf.py:180 sorted it, so its order never carried meaning.\n *\n * ⚠️ NOT ORDER-INSENSITIVE EVERYWHERE, ON PURPOSE. Cloudflare treats a group list as a set, so a\n * reordered `declared` entry mints an identical token — and still plans `update` here. The\n * Python would have rewritten it as well, and an adoption that is noop only up to reordering\n * would not prove the port exact.\n */\nexport const samePolicies = (want: readonly ResolvedPolicy[], have: readonly WirePolicy[]) =>\n want.length === have.length &&\n want.every((w, i) => {\n const h = have[i];\n if (h === undefined || w.effect !== h.effect || !sameResources(w.resources, h.resources)) {\n return false;\n }\n return w.groupOrder === 'by-id'\n ? sameList([...w.groupIds].sort(), [...h.groupIds].sort())\n : sameList(w.groupIds, h.groupIds);\n });\n",
16
17
  "/**\n * The OpenBao calls Bao.CloudflareRole and the live-roles bootstrap make — read, write and delete\n * of `<mount>/roles/<name>`. Split out so each can be tested against fake-bao.\n */\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { baoDelete, baoRead, baoWrite } from './bao-http.ts';\nimport type { BaoError } from './bao-status.ts';\nimport { type LiveCloudflareRole, liveRoleOf, rolePath } from './cloudflare-role-form.ts';\n\n/**\n * The live role, or undefined when the engine answers 404.\n *\n * ⚠️ A MISSING MOUNT AND A MISSING ROLE BOTH READ AS UNDEFINED — both are a 404 from OpenBao, the\n * first as \"no handler for route\". That is proxmox-role.ts's ⚠️ in full: the WRITE is what tells\n * them apart, and it lets OpenBao's own `errors` through. A 403 or 503 is never absence\n * (bao-status.ts).\n */\nexport const readCloudflareRole = (\n mount: string,\n name: string,\n): Effect.Effect<LiveCloudflareRole | undefined, BaoError, HttpClient.HttpClient> =>\n Effect.map(baoRead(rolePath(mount, name)), (data) =>\n data === undefined ? undefined : liveRoleOf(data),\n );\n\n/** ★ `PUT`, which is what `bao write` sent (bao-http.ts). A 404 here fails — see readCloudflareRole. */\nexport const writeCloudflareRole = (\n mount: string,\n name: string,\n body: Readonly<Record<string, string>>,\n) => baoWrite('PUT', rolePath(mount, name), body);\n\n/**\n * Idempotent as Alchemy requires — already gone (404) is success, a refusal is not.\n *\n * ⚠️ THE ENGINE'S DELETE IS ONE STORAGE DELETE (path_roles.go:214-216). Tokens the role already\n * minted are leases, and they live to their own expiry.\n */\nexport const deleteCloudflareRole = (mount: string, name: string) =>\n baoDelete(rolePath(mount, name));\n",
17
18
  "/**\n * Props, attributes and field comparison for Bao.CloudflareRole — the resource is\n * cloudflare-role.ts, the policy document rules are cloudflare-policy.ts.\n *\n * MEASURED from the engine (house/platform/secrets/vault/plugin/cloudflare/path_roles.go) and the\n * 2026-09-14 snapshot of all 586 live roles:\n * • A role is name, description, policies, ttl and max_ttl AND NOTHING ELSE (path_roles.go:14-20\n * stores those; :204-210 returns them). Every snapshot read carries exactly those five keys, so\n * `differences` below covers the whole server-side object — no unmanaged field can drift\n * behind a green plan.\n * • ttl and max_ttl are TypeDurationSecond (:73-80) and read back as integer seconds.\n * • ⚠️ A WRITE MERGES, IT DOES NOT REPLACE (:117-146). The handler loads the stored role and\n * overwrites only the fields present — the opposite of the proxmox engine, where an omitted\n * field is zeroed. writeBody sends all four anyway, so a write always lands the whole\n * declaration and can never leave an old description behind a new policy.\n *\n * ⛔ NO SECRET IN PROPS OR ATTRIBUTES, AND THERE IS NONE TO LEAK. A role is permission-group IDs, a\n * zone or account resource, a sentence and two TTLs. The parent token lives at `<mount>/config`\n * and a minted token at `<mount>/creds/<name>`; nothing in this family reads either path. Keep\n * it that way — Alchemy persists attributes unencrypted (see policy.ts).\n */\nimport {\n type ResolvedPolicy,\n type WirePolicy,\n parseLivePolicies,\n policiesJson,\n samePolicies,\n} from './cloudflare-policy.ts';\nimport type { DeclaredPolicy } from './cloudflare-roles-expand.ts';\nimport { sha256 } from './digest.ts';\nimport { mountPath, parseDuration } from './mount-form.ts';\n\nexport interface BaoCloudflareRoleProps {\n /** Mount of the Cloudflare secrets engine, e.g. `cloudflare-<account>-dns`. */\n mount: string;\n /** Role name. ⛔ Consumers mint by it — see cloudflare-roles-expand.ts before changing one. */\n name: string;\n /** The description as written: a zone role's carries its ` (zone: <name>)` suffix. */\n description: string;\n /** Default lease TTL, e.g. `5m`. */\n ttl: string;\n /** Maximum lease TTL, e.g. `1h`. */\n maxTtl: string;\n /**\n * Policy entries, groups by NAME. The provider resolves them through CloudflarePermissionGroups\n * at diff and reconcile time; an ID is never a prop, so a plan can never persist a guessed one.\n */\n policies: DeclaredPolicy[];\n}\n\nexport interface BaoCloudflareRoleAttributes {\n mount: string;\n name: string;\n description: string;\n /** Live ttl in seconds, as the engine stores it. */\n ttl: number;\n /** Live max_ttl in seconds. */\n maxTtl: number;\n /** Live `policies` JSON — group IDs and a resource, never a credential. */\n policies: string;\n /** SHA-256 of the fields above — safe to persist; see policy.ts. */\n digest: string;\n}\n\n/** One live role, as a read returns it. */\nexport interface LiveCloudflareRole {\n readonly name: string;\n readonly description: string;\n readonly ttl: number | undefined;\n readonly maxTtl: number | undefined;\n readonly policiesText: string;\n /** Undefined when `policies` is not a policy document — see parseLivePolicies. */\n readonly policies: readonly WirePolicy[] | undefined;\n}\n\nexport interface RoleDifference {\n readonly field: 'description' | 'max_ttl' | 'policies' | 'ttl';\n readonly want: string;\n readonly have: string;\n}\n\n/** `cloudflare-<account>-dns/roles/homeflare-dev-dns-read` — read, write and delete use it. */\nexport const rolePath = (mount: string, name: string) => `${mountPath(mount)}/roles/${name}`;\n\nconst seconds = (value: unknown) =>\n typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n\n/** A read's `data`, shaped. Lenient on purpose: a malformed field compares unequal, loudly. */\nexport const liveRoleOf = (data: Readonly<Record<string, unknown>>): LiveCloudflareRole => ({\n description: typeof data['description'] === 'string' ? data['description'] : '',\n maxTtl: seconds(data['max_ttl']),\n name: typeof data['name'] === 'string' ? data['name'] : '',\n policies: parseLivePolicies(data['policies']),\n policiesText: typeof data['policies'] === 'string' ? data['policies'] : '',\n ttl: seconds(data['ttl']),\n});\n\n/**\n * ⚠️ Every value is taken from `live`, the prop only standing in for a missing `name` — the same\n * split the sibling families use, so a read never launders the declaration back as \"current\".\n */\nexport const attributesOf = (\n props: Pick<BaoCloudflareRoleProps, 'mount' | 'name'>,\n live: LiveCloudflareRole,\n): BaoCloudflareRoleAttributes => {\n const attrs = {\n description: live.description,\n maxTtl: live.maxTtl ?? 0,\n mount: mountPath(props.mount),\n name: live.name || props.name,\n policies: live.policiesText,\n ttl: live.ttl ?? 0,\n };\n return { ...attrs, digest: sha256(JSON.stringify(attrs)) };\n};\n\n/**\n * Why reconcile must refuse this declaration, or undefined.\n *\n * ⛔ AN UNPARSEABLE TTL IS A REFUSAL, NOT A ZERO: it can never equal the live seconds, so it would\n * plan `update` forever. ⛔ AN EMPTY POLICY LIST OR AN ENTRY WITH NO GROUPS IS A REFUSAL TOO — the\n * engine rejects both (path_roles.go:147-149, :175-180), and saying so before the write names the\n * declaration instead of quoting the server.\n */\nexport const refusalOf = (props: BaoCloudflareRoleProps): string | undefined => {\n const bad = [\n ...(parseDuration(props.ttl) === undefined ? [`ttl=${props.ttl}`] : []),\n ...(parseDuration(props.maxTtl) === undefined ? [`maxTtl=${props.maxTtl}`] : []),\n ];\n if (bad.length > 0) return `unparseable duration ${bad.join(', ')} (use 30s / 5m / 1h / 1d)`;\n if (props.policies.length === 0) return 'no policy entries';\n if (props.policies.some((policy) => policy.groups.length === 0)) return 'a policy with no groups';\n return undefined;\n};\n\n/**\n * The body for `PUT <mount>/roles/<name>` — the four `k=v` pairs apply-roles.py:157-162 sent.\n *\n * ★ THE TTLs GO AS THE DECLARED TEXT (`5m`), which is what `bao write ttl=5m` put in the JSON body,\n * and TypeDurationSecond parses it server-side. `policies` is a string because the field is a\n * string (path_roles.go:67-68), not because the engine wants the whole body stringly-typed.\n */\nexport const writeBody = (props: BaoCloudflareRoleProps, policies: readonly WirePolicy[]) => ({\n description: props.description,\n max_ttl: props.maxTtl,\n policies: policiesJson(policies),\n ttl: props.ttl,\n});\n\nconst sameTtl = (want: string, have: number | undefined) => {\n const wantSeconds = parseDuration(want);\n return wantSeconds !== undefined && wantSeconds === have;\n};\n\n/**\n * Every field where live differs from the resolved declaration. Empty means noop.\n *\n * ⛔ apply-roles.py --verify COMPARED NONE OF THESE. It lists `<mount>/roles` and reports names\n * only: MISSING when roles.yaml has a role the vault lacks, UNTRACKED for the reverse\n * (apply-roles.py:136-141, :167-173, :179-185). It never read a role. So this equality is new: the\n * four fields --apply WRITES (apply-roles.py:157-162), compared the way the engine reads them back\n * — durations as seconds, description exactly, policies by the rules in samePolicies.\n */\nexport const differences = (\n props: Pick<BaoCloudflareRoleProps, 'description' | 'maxTtl' | 'ttl'>,\n policies: readonly ResolvedPolicy[],\n live: LiveCloudflareRole,\n): RoleDifference[] => {\n const out: RoleDifference[] = [];\n if (props.description !== live.description) {\n out.push({ field: 'description', have: live.description, want: props.description });\n }\n if (!sameTtl(props.ttl, live.ttl)) {\n out.push({ field: 'ttl', have: String(live.ttl), want: props.ttl });\n }\n if (!sameTtl(props.maxTtl, live.maxTtl)) {\n out.push({ field: 'max_ttl', have: String(live.maxTtl), want: props.maxTtl });\n }\n if (live.policies === undefined || !samePolicies(policies, live.policies)) {\n out.push({ field: 'policies', have: live.policiesText, want: policiesJson(policies) });\n }\n return out;\n};\n",
19
+ "/**\n * The roles.yaml expansion — surfaces × accounts × zones into concrete roles — ported from\n * cfroles.py `expand` and cfhf.py `policy_for`, with permission groups still by NAME.\n *\n * ★ PURE, AND NAMES STAY NAMES. The Python resolved names to IDs in the same pass\n * (apply-roles.py:144-150), with a Cloudflare credential in hand. Agents may not hold that\n * credential, so resolution is a separate step behind one interface\n * (cloudflare-permission-groups.ts) and nothing here knows where IDs come from.\n *\n * ⛔ THE NAMING AND THE ZONE RULES ARE CONTRACTS WITH EVERY CONSUMER. apply-consumers.py grants\n * `creds/<slug(zone)>-*` by zone (apply-consumers.py:117-120) and agents mint by role name, so a\n * role a port renames is a role nothing can mint. Each rule cites the line it came from, and\n * cloudflare/parity.ts proves the whole expansion against production.\n */\nimport { accountResource, bucketResource, zoneResource } from './cloudflare-group-scope.ts';\nimport type { AccountSpec, RoleTemplate, RolesConfig } from './cloudflare-roles-config.ts';\n\n/** A zone as the expansion needs it — what cfhf.py load_account listed (cfhf.py:134-146). */\nexport interface CloudflareZone {\n readonly name: string;\n readonly id: string;\n /** From the `type=internal` listing. ⚠️ Shares its NAME with the public zone, never its id. */\n readonly internal: boolean;\n}\n\n/**\n * One policy entry, groups by name.\n *\n * ★ `groupOrder` CARRIES A PYTHON RULE THAT ONLY EXISTS AFTER RESOLUTION. cfhf.py:180 sorts the\n * account entry's group IDS — not its names — so that order cannot be computed here, only\n * promised. A `declared` entry keeps roles.yaml order, exactly as cfhf.py:175 emitted it.\n */\nexport interface DeclaredPolicy {\n readonly effect: 'allow';\n readonly resource: string;\n readonly groups: readonly string[];\n readonly groupOrder: 'declared' | 'by-id';\n /**\n * The scope these NAMES resolve at, when it is not this entry's own resource namespace —\n * roles.yaml `groups_scope:`, already a GROUP_SCOPES value. Undefined on every entry that does\n * not say otherwise, which is 639 of the estate's 643 group references.\n *\n * ⛔ IT MOVES THE LOOKUP, NEVER THE RESOURCE. The entry still binds the groups to the resource\n * above; only the id chosen for each name changes. That is the shape Cloudflare calls \"all\n * zones from an account\" — the ACCOUNT resource carrying ZONE-scoped groups\n * (house/nix/homeflare-config/scripts/cf-mint-analytics-tokens.py:155-158, beside a working\n * token). Without this field the resource is the only witness, and it says `account`.\n */\n readonly scope?: string;\n}\n\n/** What apply-roles.py wrote to the KV catalog for one role (apply-roles.py:58-62). */\nexport interface CatalogView {\n readonly description: string;\n readonly zone: string | null;\n readonly ttl: string;\n readonly maxTtl: string;\n readonly permissions: readonly string[];\n}\n\nexport interface ExpandedRole {\n readonly account: string;\n readonly accountId: string;\n readonly mount: string;\n readonly surface: string;\n readonly name: string;\n /** Exactly what apply-roles.py:160-161 wrote — the zone suffix included. */\n readonly description: string;\n readonly ttl: string;\n readonly maxTtl: string;\n readonly policies: readonly DeclaredPolicy[];\n readonly catalog: CatalogView;\n}\n\n/** cfroles.py:18-20 — `example.com` → `homeflare-dev`. */\nexport const slug = (name: string) =>\n name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n/**\n * cfroles.py:23-38. ⛔ THE `-internal` SUFFIX IS WHAT KEEPS TWO ZONES OF ONE NAME APART. Slugging\n * both example.com zones alike would leave two roles fighting for one name, and whichever\n * wrote last would silently own it.\n */\nexport const zoneSlug = (zone: CloudflareZone) =>\n `${slug(zone.name)}${zone.internal ? '-internal' : ''}`;\n\n/** cfroles.py:46-47 — one mount, and so one parent token, per (account, surface). */\nexport const mountName = (account: string, surface: string) => `cloudflare-${account}-${surface}`;\n\n/**\n * cfhf.py:151-181. ⛔ ONE ENTRY PER SCOPE, NEVER MERGED: Cloudflare gates a permission at one\n * scope only, so a zone role that also needs account groups gets a SECOND entry on the account\n * resource. ⚠️ `if account_group_ids:` — an empty list emits no second entry (cfhf.py:176).\n */\nconst policiesFor = (\n tpl: RoleTemplate,\n accountId: string,\n zone: CloudflareZone | null,\n accountGroups: readonly string[],\n): DeclaredPolicy[] => {\n /**\n * ⛔ A BUCKET NARROWS THE ACCOUNT RESOURCE; IT NEVER NARROWS A ZONE. A zone role scoped to an R2\n * bucket is not a narrower grant, it is an incoherent one — the groups a zone role carries are\n * gated at the zone and would be refused against a bucket resource. Refusing here is the only\n * place that can tell the difference; roles.yaml cannot express the contradiction as a type.\n */\n if (tpl.bucket !== undefined && zone !== null) {\n throw new Error(`${tpl.name}: a zone role cannot be scoped to R2 bucket ${tpl.bucket}`);\n }\n const accountScoped =\n tpl.bucket === undefined\n ? accountResource(accountId)\n : bucketResource(accountId, tpl.bucketJurisdiction, tpl.bucket);\n const resource = zone === null ? accountScoped : zoneResource(zone.id);\n const first: DeclaredPolicy = {\n effect: 'allow',\n groupOrder: 'declared',\n groups: tpl.groups,\n resource,\n /**\n * ⚠️ `groups_scope:` GOVERNS `groups:` AND NOTHING ELSE. The second entry below exists because\n * `account_groups` are account-scoped BY CONSTRUCTION (cfhf.py:176-180) — overriding its\n * scope from the same key would make one word mean two things in one template.\n * ★ OMITTED, NOT SET TO THE DEFAULT, WHEN THE yaml IS SILENT: an always-present field would\n * rewrite the stored props of all 594 declared roles to say what the resource already said.\n */\n ...(tpl.groupsScope === undefined ? {} : { scope: tpl.groupsScope }),\n };\n if (accountGroups.length === 0) return [first];\n const second: DeclaredPolicy = {\n effect: 'allow',\n groupOrder: 'by-id',\n groups: accountGroups,\n resource: accountResource(accountId),\n };\n return [first, second];\n};\n\nconst build = (\n account: AccountSpec,\n surface: string,\n tpl: RoleTemplate,\n zone: CloudflareZone | null,\n accountGroups: readonly string[],\n): ExpandedRole => ({\n account: account.key,\n accountId: account.id,\n catalog: {\n description: tpl.desc,\n maxTtl: tpl.maxTtl,\n // apply-roles.py:61 — groups then account_groups, names, in file order.\n permissions: [...tpl.groups, ...accountGroups],\n ttl: tpl.ttl,\n zone: zone === null ? null : zone.name,\n },\n /**\n * apply-roles.py:160-161. ⚠️ THE ZONE NAME, NOT ITS SLUG, so a public zone and its internal\n * twin describe alike, and an empty `desc` still gains the suffix after a leading space.\n */\n description: zone === null ? tpl.desc : `${tpl.desc} (zone: ${zone.name})`,\n maxTtl: tpl.maxTtl,\n mount: mountName(account.key, surface),\n // cfroles.py:84 for zone roles, :98 for account roles.\n name: zone === null ? tpl.name : `${zoneSlug(zone)}-${tpl.name}`,\n policies: policiesFor(tpl, account.id, zone, accountGroups),\n surface,\n ttl: tpl.ttl,\n});\n\n/** cfroles.py:50-104 for one account, in the Python's order: per surface, zone roles first. */\nexport const expandAccount = (\n config: RolesConfig,\n account: AccountSpec,\n zones: readonly CloudflareZone[],\n): ExpandedRole[] => {\n const roles: ExpandedRole[] = [];\n for (const surface of account.surfaces) {\n const spec = config.surfaces[surface];\n if (spec === undefined) throw new Error(`surface ${surface} is not defined`);\n for (const tpl of spec.zoneRoles) {\n const only = tpl.zones;\n /**\n * ⛔ INTERNAL ZONES ARE OPT-IN PER TEMPLATE AND THE DEFAULT IS NO (cfroles.py:68-74). Only the\n * word `internal` in zone_types matters; `full` and `secondary` are never checked, so a\n * public zone of any type expands.\n */\n const internalOk = tpl.zoneTypes.includes('internal');\n for (const zone of zones) {\n if (account.zones !== 'all' && !account.zones.includes(zone.name)) continue; // :76\n if (only !== undefined && only.length > 0 && !only.includes(zone.name)) continue; // :78\n if (zone.internal && !internalOk) continue; // :80\n roles.push(build(account, surface, tpl, zone, tpl.accountGroups));\n }\n }\n // cfroles.py:96-103 — `account_groups` is [] on an account role, whatever the yaml says.\n for (const tpl of spec.accountRoles) roles.push(build(account, surface, tpl, null, []));\n }\n return roles;\n};\n\n/**\n * Every account's roles, grouped by mount.\n *\n * ⛔ A DUPLICATE ROLE ON ONE MOUNT IS AN ERROR HERE. apply-roles.py wrote both and the last write\n * won in silence (apply-roles.py:157-162); declared, they are two resources fighting over one\n * object. ⚠️ A MISSING ZONE INVENTORY IS AN ERROR TOO — an empty one is not, because an account\n * with no zones is real, and the Python expanded it to account roles only.\n */\nexport const expandAll = (\n config: RolesConfig,\n zonesByAccount: Readonly<Record<string, readonly CloudflareZone[]>>,\n): ReadonlyMap<string, readonly ExpandedRole[]> => {\n const byMount = new Map<string, ExpandedRole[]>();\n const seen = new Set<string>();\n for (const account of config.accounts) {\n const zones = zonesByAccount[account.key];\n if (zones === undefined) throw new Error(`no zone inventory for account ${account.key}`);\n for (const role of expandAccount(config, account, zones)) {\n const key = `${role.mount}/roles/${role.name}`;\n if (seen.has(key)) throw new Error(`roles.yaml expands ${key} twice`);\n seen.add(key);\n const mount = byMount.get(role.mount) ?? [];\n mount.push(role);\n byMount.set(role.mount, mount);\n }\n }\n return byMount;\n};\n",
20
+ "/**\n * roles.yaml, parsed and checked — the input half of the Cloudflare role expansion. The expansion\n * itself is cloudflare-roles-expand.ts.\n *\n * ★ BUN's OWN PARSER, NO DEPENDENCY. `Bun.YAML.parse` ships in Bun 1.4 — MEASURED on 1.4.0:\n * `typeof Bun.YAML` is `object` with `parse` and `stringify`, typed in bun-types 1.4.2\n * (bun.d.ts:1479). The Python read the same file with PyYAML's `safe_load` (cfroles.py:41-43).\n * ⚠️ THEY ARE DIFFERENT PARSERS, SO THE SHAPE IS CHECKED, NOT TRUSTED. The file leans on flow\n * mappings (`- { name: dns-edit, groups: [DNS Write] }`), and a bare `5m` must stay a string.\n * MEASURED against roles.yaml: both parsers give `ttl` as the string `5m`, and both keep\n * `'Access: Apps and Policies Write'` as one name. parity.ts against the live snapshot is the\n * end-to-end proof; a field of the wrong type fails loudly here instead of expanding to nonsense.\n *\n * ⛔ A MISSING FIELD IS AN ERROR, NEVER A DEFAULT — except exactly where the Python defaulted:\n * `desc` to '' (cfroles.py:86, :100), an account's `zones` to \"all\" (:57), `surfaces`,\n * `zone_roles` and `account_roles` to empty (:59, :62, :96), `zone_types` to empty (:74) and\n * `account_groups` to empty (:90). Everywhere else the Python raised KeyError, and so does this.\n *\n * ⚠️ `consumers:` IS NOT READ HERE. It belongs to apply-consumers.py, and declaring it is the next\n * phase — see the report that came with this file.\n */\nimport { GROUP_SCOPES, groupScopeNamed } from './cloudflare-group-scope.ts';\n\n/** One `zone_roles` or `account_roles` entry. */\nexport interface RoleTemplate {\n readonly name: string;\n readonly groups: readonly string[];\n /** Duration text exactly as written (`5m`), which is what apply-roles.py sent. */\n readonly ttl: string;\n readonly maxTtl: string;\n readonly desc: string;\n /** `zones:` narrowing. Undefined or empty narrows nothing — `if only and …` (cfroles.py:78). */\n readonly zones: readonly string[] | undefined;\n readonly zoneTypes: readonly string[];\n /** Account-scoped groups on a ZONE role. Ignored on account roles, as cfroles.py:101 ignores it. */\n readonly accountGroups: readonly string[];\n /**\n * One R2 bucket NAME, narrowing an account role's resource to that bucket alone.\n *\n * ⛔ BUCKET IS THE FINEST GRAIN R2 HAS — A PREFIX CANNOT BE SCOPED. So one repository per\n * instance in its own bucket is the only least-privilege shape for a backup credential, and\n * this field is what expresses it. Undefined leaves the role account-wide, which is what every\n * role declared before 2026-09-15 is.\n * ⚠️ IT ONLY MEANS ANYTHING WITH THE `Bucket Item` GROUPS. `Workers R2 Storage Write` is gated at\n * the ACCOUNT scope, so pairing it with a bucket resource is a token Cloudflare will mint and\n * that will then be refused on every call. roles.yaml says which pair goes with which.\n */\n readonly bucket: string | undefined;\n /**\n * The bucket's jurisdiction, which is part of its resource id and not cosmetic — a bucket\n * created in `default` is a different resource from the same name under `eu`. Defaults to\n * `default`, which is what every bucket in this estate is (measured: `r2_bucket_get` reports\n * `jurisdiction default` on all 34).\n */\n readonly bucketJurisdiction: string;\n /**\n * roles.yaml `groups_scope:` — the scope this template's `groups:` NAMES resolve at, as a\n * GROUP_SCOPES value. Undefined means the entry's own resource namespace, which is every\n * template written before 2026-09-15.\n *\n * ⛔ IT SAYS WHICH ID, NOT WHICH RESOURCE. `groups_scope: zone` on an ACCOUNT role keeps the\n * account resource and takes the zone-scoped id of each name — Cloudflare's \"all zones from\n * this account\" (cf-mint-analytics-tokens.py:155-158). It is meaningful only for the seven\n * names the engine lists at two scopes; anywhere else the name has one id and answers alike.\n */\n readonly groupsScope: string | undefined;\n}\n\nexport interface SurfaceSpec {\n readonly zoneRoles: readonly RoleTemplate[];\n readonly accountRoles: readonly RoleTemplate[];\n}\n\nexport interface AccountSpec {\n /** The key under `accounts:` — the `<account>` in `cloudflare-<account>-<surface>`. */\n readonly key: string;\n readonly id: string;\n readonly zones: 'all' | readonly string[];\n readonly surfaces: readonly string[];\n}\n\nexport interface RolesConfig {\n readonly namespace: string;\n readonly surfaces: Readonly<Record<string, SurfaceSpec>>;\n /** In file order, which is the order apply-roles.py walked them (apply-roles.py:111). */\n readonly accounts: readonly AccountSpec[];\n}\n\nexport class RolesConfigError extends Error {\n constructor(where: string, problem: string) {\n super(`roles.yaml ${where}: ${problem}`);\n this.name = 'RolesConfigError';\n }\n}\n\ntype Raw = Readonly<Record<string, unknown>>;\n\nconst isRaw = (value: unknown): value is Raw =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst record = (value: unknown, where: string): Raw => {\n if (!isRaw(value)) throw new RolesConfigError(where, 'expected a mapping');\n return value;\n};\n\nconst text = (raw: Raw, key: string, where: string): string => {\n const value = raw[key];\n if (typeof value === 'string') return value;\n /**\n * ⚠️ STRICTER THAN THE PYTHON FOR A NUMBER. `ttl: 300` would have reached `bao write` as `300`\n * and been read as seconds. Every duration in roles.yaml is unit-suffixed, and the comparison\n * in cloudflare-role-form.ts only parses unit-suffixed text, so a bare number is refused here\n * rather than planning an update that can never settle.\n */\n throw new RolesConfigError(`${where}.${key}`, `expected a string, got ${JSON.stringify(value)}`);\n};\n\nconst texts = (raw: Raw, key: string, where: string): readonly string[] | undefined => {\n const value = raw[key];\n if (value === undefined || value === null) return undefined;\n if (Array.isArray(value) && value.every((item): item is string => typeof item === 'string')) {\n return value;\n }\n throw new RolesConfigError(`${where}.${key}`, 'expected a list of strings');\n};\n\nconst entries = (raw: Raw, key: string, where: string): readonly unknown[] => {\n const value = raw[key];\n if (value === undefined || value === null) return [];\n if (!Array.isArray(value)) throw new RolesConfigError(`${where}.${key}`, 'expected a list');\n return value;\n};\n\nconst template = (value: unknown, where: string): RoleTemplate => {\n const raw = record(value, where);\n const groups = texts(raw, 'groups', where);\n if (groups === undefined) throw new RolesConfigError(`${where}.groups`, 'is required');\n /**\n * ⚠️ `bucket` IS OPTIONAL BUT NEVER EMPTY. `bucket: ''` would expand to the resource\n * `…r2.bucket.<acct>_default_`, which is not a bucket and not the account either — a policy\n * that names nothing. A missing key means account-wide; a present one must name a bucket.\n */\n const bucket = raw['bucket'] === undefined ? undefined : text(raw, 'bucket', where);\n if (bucket !== undefined && bucket.length === 0) {\n throw new RolesConfigError(`${where}.bucket`, 'is empty; omit it to stay account-wide');\n }\n /**\n * ⛔ AN UNKNOWN WORD IS AN ERROR, NEVER A PASS-THROUGH. A scope roles.yaml invents matches no\n * group at all, so accepting it would turn a typo into \"unknown group X at scope zonee\" at\n * deploy time — a failure naming the group rather than the line that is wrong.\n */\n const groupsScope =\n raw['groups_scope'] === undefined\n ? undefined\n : groupScopeNamed(text(raw, 'groups_scope', where));\n if (raw['groups_scope'] !== undefined && groupsScope === undefined) {\n throw new RolesConfigError(\n `${where}.groups_scope`,\n `expected one of ${Object.keys(GROUP_SCOPES).join(', ')}`,\n );\n }\n return {\n accountGroups: texts(raw, 'account_groups', where) ?? [],\n bucket,\n bucketJurisdiction:\n raw['bucket_jurisdiction'] === undefined\n ? 'default'\n : text(raw, 'bucket_jurisdiction', where),\n desc: raw['desc'] === undefined ? '' : text(raw, 'desc', where),\n groups,\n groupsScope,\n maxTtl: text(raw, 'max_ttl', where),\n name: text(raw, 'name', where),\n ttl: text(raw, 'ttl', where),\n zoneTypes: texts(raw, 'zone_types', where) ?? [],\n zones: texts(raw, 'zones', where),\n };\n};\n\nconst surface = (name: string, value: unknown): SurfaceSpec => {\n const where = `surfaces.${name}`;\n const raw = record(value, where);\n return {\n accountRoles: entries(raw, 'account_roles', where).map((item, i) =>\n template(item, `${where}.account_roles[${String(i)}]`),\n ),\n zoneRoles: entries(raw, 'zone_roles', where).map((item, i) =>\n template(item, `${where}.zone_roles[${String(i)}]`),\n ),\n };\n};\n\nconst account = (\n key: string,\n value: unknown,\n surfaces: Readonly<Record<string, SurfaceSpec>>,\n): AccountSpec => {\n const where = `accounts.${key}`;\n const raw = record(value, where);\n const names = texts(raw, 'surfaces', where) ?? [];\n for (const name of names) {\n /** ⚠️ cfroles.py:60 would raise KeyError at expansion; this says which account named it. */\n if (surfaces[name] === undefined) {\n throw new RolesConfigError(\n `${where}.surfaces`,\n `names ${name}, which surfaces: never defines`,\n );\n }\n }\n const zones =\n raw['zones'] === undefined || raw['zones'] === 'all' ? 'all' : texts(raw, 'zones', where);\n return { id: text(raw, 'id', where), key, surfaces: names, zones: zones ?? 'all' };\n};\n\n/** Parse and check roles.yaml. Throws RolesConfigError naming the first bad field. */\nexport const parseRolesConfig = (yaml: string): RolesConfig => {\n const root = record(Bun.YAML.parse(yaml), '(document)');\n const surfaces: Record<string, SurfaceSpec> = {};\n for (const [name, spec] of Object.entries(record(root['surfaces'], 'surfaces'))) {\n surfaces[name] = surface(name, spec);\n }\n const accounts = Object.entries(record(root['accounts'], 'accounts')).map(([key, value]) =>\n account(key, value, surfaces),\n );\n return {\n accounts,\n namespace: text(record(root['defaults'], 'defaults'), 'namespace', 'defaults'),\n surfaces,\n };\n};\n",
18
21
  "/**\n * An OpenBao secrets engine mount — path, type, description and lease TTLs.\n *\n * ⛔ NO SECRET IN PROPS OR ATTRIBUTES — see policy.ts for why. This declares mount\n * SHAPE only: names, types, TTL strings and a digest. KV values and CA material live\n * in OpenBao, not Alchemy state.\n *\n * ★ `defaultRemovalPolicy: 'retain'` — disabling a mount destroys every secret under it.\n * Opt in with `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport {\n type BaoMountAttributes,\n type BaoMountProps,\n attributesOf,\n matches,\n mountPath,\n wantsTune,\n} from './mount-form.ts';\nimport { disableMount, enableMount, readMountData, tuneMount } from './mount-wire.ts';\n\nexport type { BaoMountAttributes, BaoMountProps };\n\nexport interface BaoMount extends Resource<\n 'Bao.Mount',\n BaoMountProps,\n BaoMountAttributes,\n never,\n HttpClient.HttpClient\n> {}\n\nexport const BaoMount = Resource<BaoMount>('Bao.Mount', {\n defaultRemovalPolicy: 'retain',\n});\n\nconst readMount = (props: BaoMountProps) =>\n Effect.gen(function* () {\n const live = yield* readMountData(props.path);\n if (live === undefined) return undefined;\n return attributesOf(props, live);\n });\n\nexport const BaoMountProvider = () =>\n Provider.effect(\n BaoMount,\n Effect.succeed(\n BaoMount.Provider.of({\n /**\n * ⛔ `bao secrets list` IS NOT A LIST OF THINGS THIS OWNS. Every mount in the\n * namespace answers, including ones created by hand at bringup. Returning them\n * would invite Alchemy to adopt — and then disable — mounts it never created.\n * ⚠️ mount-wire.ts does read that listing, for one question only: whether a mount a 400\n * named is really absent. It never becomes a list of resources.\n */\n list: () => Effect.succeed([]),\n\n read: Effect.fn(function* ({ olds }) {\n return yield* readMount(olds);\n }),\n\n diff: Effect.fn(function* ({ news, output }) {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readMount(news);\n if (live === undefined) return { action: 'update' } as const;\n /**\n * ⛔ A CHANGED `type` IS A REPLACE, AND THIS FAMILY'S DELETE IS A MOUNT DISABLE — the\n * destruction of every secret under the mount. `kv/` is the estate's entire\n * secret shelf, so the question \"does `retain` guard the delete half of a REPLACE, or\n * only an orphan?\" is the difference between a typo and a catastrophe.\n * ★ IT GUARDS BOTH — VERIFIED IN ALCHEMY'S OWN SOURCE, not assumed. Apply.ts:2164-2173:\n * \"Honor `retain` for the old generation of a replacement, mirroring the orphan-delete\n * path above\", with `retainOldGeneration = node.removalPolicy === 'retain'`, and when\n * it is true the engine logs \"Retaining replaced resource (removal policy: retain)\"\n * and skips the delete entirely. Every mount this package declares carries the retain\n * default (see the ★ on the resource below), so a wrong `type` string cannot disable a\n * live mount. What it CAN do is try to enable a second mount at an occupied path,\n * which OpenBao refuses loudly — a failed deploy, not a lost shelf.\n * ⚠️ THAT SAFETY IS THE DECORATION'S, NOT THIS LINE'S. A caller who opts into\n * `.pipe(RemovalPolicy.destroy())` gets the destructive replace, which is the correct\n * meaning of opting in and is worth knowing before you type it on a mount.\n */\n if (live.type !== news.type) return { action: 'replace' } as const;\n if (matches(live, news)) return { action: 'noop' } as const;\n return { action: 'update' } as const;\n }),\n\n /**\n * ★ A REFUSED ENABLE OR TUNE FAILS THE EFFECT WITH OpenBao's OWN `errors`, naming the\n * method and path — the job the per-command exit-code checks used to do by hand.\n */\n reconcile: Effect.fn(function* ({ news }) {\n let live = yield* readMount(news);\n if (live === undefined) {\n yield* enableMount(news);\n if (wantsTune(news)) yield* tuneMount(news);\n } else if (!matches(live, news)) {\n if (live.type !== news.type) {\n return yield* Effect.die(\n new Error(\n `Bao.Mount ${mountPath(news.path)}: live type ${live.type} != ${news.type}. ` +\n 'Secrets engine type is immutable — replace manually.',\n ),\n );\n }\n yield* tuneMount(news);\n }\n live = yield* readMount(news);\n if (live === undefined) {\n return yield* Effect.die(\n new Error(\n `Bao.Mount ${mountPath(news.path)}: write returned no error but the mount is still absent.`,\n ),\n );\n }\n return live;\n }),\n\n /**\n * ⛔ DISABLING A MOUNT DESTROYS EVERY SECRET UNDER IT. Idempotent as Alchemy\n * requires — already gone is success — but retain is the default for a reason.\n */\n delete: Effect.fn(function* ({ output }) {\n yield* disableMount(output.path);\n return undefined;\n }),\n }),\n ),\n );\n",
19
22
  "/**\n * The OpenBao calls Bao.Mount makes — read one mount, enable, tune, disable. Split from mount.ts so\n * the classification of a MISSING mount can be tested against a fake server.\n *\n * ★ ENDPOINTS, READ FROM openbao v2.6.2 api/sys_mounts.go — the client the CLI used:\n * read GET sys/mounts/<path> (MountInfo, :254) — what `bao read sys/mounts/<path>` hit\n * enable POST sys/mounts/<path> (Mount, :57) — `bao secrets enable`\n * tune POST sys/mounts/<path>/tune (TuneMount, :201) — `bao secrets tune`\n * disable DELETE sys/mounts/<path> (Unmount, :79) — `bao secrets disable`\n */\nimport * as Effect from 'effect/Effect';\nimport { baoDelete, baoRead, baoWrite } from './bao-http.ts';\nimport { BaoError } from './bao-status.ts';\nimport {\n type BaoMountProps,\n enableBody,\n mountPath,\n readPath,\n tuneBody,\n tunePath,\n} from './mount-form.ts';\n\n/**\n * Confirm a mount is absent from the mount table, or give back the error that asked.\n *\n * ⛔ A MISSING MOUNT IS NOT A 404, IT IS A 400 — AND THAT MADE A NEW MOUNT UNCREATABLE, SILENTLY,\n * THE SAME WAY A NEW POLICY WAS (b3c18a33e). `handleReadMount` answers a path with no mount with a\n * bare error response, \"No secret engine mount at <path>\" (vault/logical_system.go:1171-1178), and\n * RespondErrorCommon turns an error response with no coded error into 400\n * (sdk/logical/response_util.go). The CLI therefore exited 2 with that text, which was not\n * `No value found at`, so every read of an undeclared-yet mount FAILED and reconcile never\n * reached `secrets enable`. All four declared mounts already exist, which is the only reason\n * nothing broke. REASONED FROM SOURCE, NOT MEASURED — no read of a missing mount was run.\n * ★ SO A 400 IS SETTLED BY A SECOND, STATUS-CLASSIFIED QUESTION rather than by matching that text:\n * `GET sys/mounts` lists the namespace's mount table, keyed `<path>/`. Only a 200 table WITHOUT\n * the key is absence. A listed mount, a refused listing, or a 404 listing leaves the original 400\n * standing — \"I could not tell\" is an error, never a create.\n * ⚠️ THE LISTING NEEDS `read` ON `sys/mounts`. The admin lane has it\n * (policies/homeflare-admin/live-captured-2026-09-02.hcl:20). A narrower token still fails, which\n * is what it did before.\n */\nconst absentFromTable = (path: string, asked: BaoError) =>\n baoRead('sys/mounts').pipe(\n // ⚠️ A listing that fails keeps the 400, and says why it could not settle it.\n Effect.mapError(\n (listing) =>\n new BaoError(asked.status, asked.method, asked.path, [\n ...asked.errors,\n `sys/mounts could not confirm the mount is absent: ${listing.message}`,\n ]),\n ),\n Effect.flatMap((table) =>\n table !== undefined && !Object.hasOwn(table, `${mountPath(path)}/`)\n ? Effect.succeed(undefined)\n : Effect.fail(asked),\n ),\n );\n\n/** One mount's config (`type`, `description`, `config.*_lease_ttl`), or undefined when absent. */\nexport const readMountData = (path: string) =>\n baoRead(readPath(path)).pipe(\n Effect.catchIf(\n (error) => error.status === 400,\n (error) => absentFromTable(path, error),\n ),\n );\n\nexport const enableMount = (props: BaoMountProps) =>\n baoWrite('POST', readPath(props.path), enableBody(props));\n\nexport const tuneMount = (props: BaoMountProps) =>\n baoWrite('POST', tunePath(props.path), tuneBody(props));\n\n/**\n * ⚠️ THERE IS NO FORCE. The old delete ran `bao secrets disable -force`, and v2.6.2's\n * command/secrets_disable.go defines no `-force` flag, so that argv would have been refused at\n * flag parsing. `Unmount` is a plain DELETE (api/sys_mounts.go:79); nothing else was ever sent.\n */\nexport const disableMount = (path: string) => baoDelete(readPath(path));\n",
20
23
  "/**\n * An OpenBao PKI role — the policy a future issuance is checked against, and nothing else.\n *\n * ⛔ THE ROLE IS THE POLICY, NEVER THE CERTIFICATE. Nothing here touches `pki/issue/*` (which\n * RETURNS a private key) or `pki/root/generate/*` (which CREATES one). Every value this\n * resource stores is a domain name, a flag, a bit count or a TTL — safe to sit in Alchemy's\n * UNENCRYPTED Postgres state. See policy.ts for why that line is load-bearing here.\n *\n * ⛔ `bao write pki/roles/<name>` REPLACES THE WHOLE ROLE — it is not a merge. OpenBao builds\n * a fresh role entry from the request, so every field left out reverts to its SCHEMA\n * DEFAULT. MEASURED 2026-09-13 against the live OpenBao 2.6.2, from its own\n * `sys/internal/specs/openapi` cross-read against all eight live `pki/roles/*`, four of\n * those defaults are WIDER than what this estate actually runs:\n *\n * allow_ip_sans default true — false on 5 of the 8 roles\n * allow_localhost default true — false on 6 of the 8\n * allow_wildcard_certificates default true — false on 6 of the 8\n * cn_validations default [\"email\",\"hostname\"] — [\"hostname\"] on 5 of the 8\n *\n * A resource that managed only the eleven fields the brief named would therefore, on any\n * unrelated TTL edit, silently re-open wildcards and localhost on six production roles.\n * That is why those four are props in pki-role-form.ts though they were not in the brief,\n * and why their default there is the CLOSED value rather than OpenBao's open one.\n *\n * ★ NARROWING IS THE FAIL-SAFE DIRECTION. A default tighter than OpenBao's can only refuse a\n * certificate that should have been issued — loud, and cured by declaring the field. A\n * default looser than OpenBao's issues one that should have been refused, in silence.\n *\n * ⚠️ WHAT WAS NOT MEASURED. Only reads were run against the live engine; no `bao write`\n * happened, so nothing below is a verified round-trip. Two consequences carried into the\n * form file: every live role has `ext_key_usage: []`, so the stored casing of a non-empty\n * list was never observed (the compare folds case because OpenBao matches these\n * case-insensitively at issuance); and every live role has exactly ONE allowed domain, so\n * whether OpenBao preserves list order was never observed either (the compare sorts,\n * because allowed_domains is a set). Both choices can only mask a cosmetic difference,\n * never a policy one — but neither is a measurement.\n *\n * ★ `defaultRemovalPolicy: 'retain'` — see the delete comment below. Opt in with\n * `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { baoDelete, baoRead, baoWrite } from './bao-http.ts';\nimport { mountPath, parseDuration } from './mount-form.ts';\nimport {\n type BaoPkiRoleAttributes,\n type BaoPkiRoleProps,\n attributesOf,\n matches,\n rolePath,\n writeBody,\n} from './pki-role-form.ts';\n\nexport type { BaoPkiRoleAttributes, BaoPkiRoleProps };\n\nexport interface BaoPkiRole extends Resource<\n 'Bao.PkiRole',\n BaoPkiRoleProps,\n BaoPkiRoleAttributes,\n never,\n HttpClient.HttpClient\n> {}\n\nexport const BaoPkiRole = Resource<BaoPkiRole>('Bao.PkiRole', {\n defaultRemovalPolicy: 'retain',\n});\n\nconst readRole = (props: BaoPkiRoleProps) =>\n Effect.gen(function* () {\n const live = yield* baoRead(rolePath(props));\n if (live === undefined) return undefined;\n return attributesOf(props, live);\n });\n\n/** Duration props `bao write` must never see — reconcile turns these into a refusal. */\nconst badDurations = (props: BaoPkiRoleProps) =>\n [['ttl', props.ttl] as const, ['maxTtl', props.maxTtl] as const].filter(\n ([, text]) => parseDuration(text) === undefined,\n );\n\nexport const BaoPkiRoleProvider = () =>\n Provider.effect(\n BaoPkiRole,\n Effect.succeed(\n BaoPkiRole.Provider.of({\n /**\n * ⛔ `bao list pki/roles` IS NOT A LIST OF THINGS THIS OWNS. All eight roles in the\n * live engine answer it, and every one of them predates this resource. Returning\n * them would invite Alchemy to adopt — and then delete — roles it never created.\n */\n list: () => Effect.succeed([]),\n\n read: Effect.fn(function* ({ olds }) {\n return yield* readRole(olds);\n }),\n\n /**\n * ⛔ IT COMPARES A DIGEST OF THE LIVE ROLE, NOT THE STORED ONE. The attributes fed to\n * `matches` are always freshly derived from a live read in this same operation, so\n * a role widened by hand in the OpenBao UI still reads as drift — which is the\n * whole reason the check-* gates exist. Comparing one digest rather than sixteen\n * fields is also what stops a field being added to props and quietly forgotten in\n * the comparison.\n */\n diff: Effect.fn(function* ({ news, output }) {\n if (output === undefined || !isResolved(news)) return undefined;\n /**\n * ⚠️ A ROLE IS IDENTIFIED BY MOUNT **AND** NAME. Moving a declaration to another\n * engine is a different object under a different CA, never an in-place edit —\n * `replace`, so Alchemy creates the new one and retires the old.\n */\n if (mountPath(news.mount ?? 'pki') !== output.mount)\n return { action: 'replace' } as const;\n /**\n * ⚠️ A DECLARATION reconcile WOULD REFUSE MUST NEVER PLAN AS noop. An empty\n * allowedDomains, or a duration OpenBao cannot parse, can compare equal to a\n * live role already in that state — and a noop there hides the refusal behind a\n * clean plan until the next deploy. Route it to reconcile, which says why.\n */\n if (news.allowedDomains.length === 0 || badDurations(news).length > 0) {\n return { action: 'update' } as const;\n }\n const live = yield* readRole(news);\n if (live === undefined) return { action: 'update' } as const;\n return matches(live, news)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: Effect.fn(function* ({ news }) {\n const path = rolePath(news);\n /**\n * ⛔ AN EMPTY allowedDomains IS A REFUSAL, NOT AN EMPTY ROLE. `allow_any_name` is\n * false on every live role, so a role with no allowed domains can issue NOTHING —\n * and an unresolved or mistyped prop reads exactly like an author who meant it.\n * policy.ts refuses an empty fragment directory for the same reason.\n */\n if (news.allowedDomains.length === 0) {\n return yield* Effect.die(\n new Error(\n `Bao.PkiRole ${path}: allowedDomains is empty. With allow_any_name false ` +\n 'that role can issue no certificate at all.',\n ),\n );\n }\n const bad = badDurations(news);\n if (bad.length > 0) {\n return yield* Effect.die(\n new Error(\n `Bao.PkiRole ${path}: ${bad.map(([k, v]) => `${k}=${v}`).join(', ')} ` +\n 'is not a duration OpenBao parses (expect 30m, 720h, 8760h or 0).',\n ),\n );\n }\n const live = yield* readRole(news);\n if (live === undefined || !matches(live, news)) {\n yield* baoWrite('PUT', path, writeBody(news));\n }\n const after = yield* readRole(news);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(`Bao.PkiRole ${path}: write reported success but the role is absent.`),\n );\n }\n /**\n * ⛔ THE WRITE IS NOT TRUSTED, IT IS RE-READ AND RE-COMPARED. A write succeeds (2xx)\n * for a field it accepted but stored differently — the live worry being the\n * comma-joined list values in writeBody, whose splitting is documented for\n * allowed_domains and ext_key_usage but NOT for cn_validations. Without this\n * check a role could land with `cn_validations: [\"email,hostname\"]`, report\n * success, and then refuse every renewal at issuance time instead.\n */\n if (!matches(after, news)) {\n return yield* Effect.die(\n new Error(\n `Bao.PkiRole ${path}: wrote cleanly but the role read back different. ` +\n 'OpenBao stored something other than what was declared — inspect with ' +\n `\\`bao read ${path}\\` before retrying.`,\n ),\n );\n }\n return after;\n }),\n\n /**\n * ⛔ DELETING A ROLE DOES NOT REVOKE THE CERTIFICATES IT ISSUED — they stay valid to\n * their own expiry, so this is quiet now and loud much later: every renewal through\n * the role fails once the current certificate runs out. MEASURED: the live roles\n * carry ttl 604800 to 31536000 seconds, so the fuse on `rpi5-otel-client` is a full\n * year. Idempotent as Alchemy requires — already gone is success — but retain is\n * the default for exactly this reason.\n */\n delete: Effect.fn(function* ({ output }) {\n yield* baoDelete(rolePath(output));\n return undefined;\n }),\n }),\n ),\n );\n",
@@ -27,7 +30,7 @@
27
30
  "/**\n * An OpenBao SSH secrets-engine role — `<mount>/roles/{name}`, `key_type=ca`. METADATA ONLY.\n *\n * ⛔ THE SIGNING KEY IS OUT OF SCOPE AND MUST STAY OUT. `ssh/config/ca` holds (or generates)\n * the CA private key and `ssh/sign/<role>` issues certificates. Neither is declarable\n * here, for the reason policy.ts spells out: Alchemy persists attributes to its state\n * store WITHOUT encrypting them, that store is the `alchemy` Postgres, and pg-backup.sh\n * dumps it nightly to CT100. A CA key there would outlive the vault that guards it. This\n * resource declares the SHAPE a signature must satisfy — principals, extensions, TTLs.\n *\n * ⛔ THE ROLE WRITE IS A FULL REPLACE, NOT A PATCH. OpenBao rebuilds the role entry from the\n * request body, so any field the write omits reverts to its ZERO value. Two things follow:\n * `resolve` in ssh-role-form.ts fills every optional prop with the default the write would\n * produce and `matches` compares all of it (an omitted prop asserts the default, it never\n * means \"don't care\"); and `wouldErase` below names the fields this resource does NOT\n * declare, so reconcile can REFUSE instead of quietly dropping someone's key-length floor.\n *\n * ⛔ `allowEmptyPrincipals: true` WITH AN EMPTY `allowedUsers` IS A SKELETON KEY. OpenBao\n * will sign a certificate carrying no principals, and OpenSSH accepts such a certificate\n * for ANY user on ANY host that trusts the CA. It defaults to false, and all three roles\n * on the live engine carry false (MEASURED). Do not set it true without pinning\n * `defaultCriticalOptions['force-command']` in the same declaration.\n *\n * ⛔ `ttl: '0'` DOES NOT MEAN \"NO EXPIRY\" AND IT DOES NOT MEAN \"SHORT\". It means the mount's\n * `default_lease_ttl`, and the live `ssh` mount leaves that at 0, which means the SYSTEM\n * default — 768h. A 32-day SSH certificate is the opposite of what an SSH CA is for.\n * State the duration. MEASURED: the live `node-admin` and `tim` roles are ttl 14400 /\n * max_ttl 28800 (4h / 8h); `ssh-host/roles/host` is 31536000 (365d), as a host cert should.\n *\n * ★ `defaultRemovalPolicy: 'retain'`. Deleting this role locks every operator out of the\n * estate — the memory note \"operator SSH is homeflare-bot@<host>\" is this CA. Opt in with\n * `.pipe(RemovalPolicy.destroy())`; see resource.ts in house/proxmox.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type * as HttpClient from 'effect/unstable/http/HttpClient';\nimport { baoDelete, baoRead, baoWrite } from './bao-http.ts';\nimport {\n type BaoSshRoleAttributes,\n type BaoSshRoleForm,\n type BaoSshRoleProps,\n attributesOf,\n badDurations,\n extMap,\n matches,\n readPath,\n resolve,\n writeBody,\n} from './ssh-role-form.ts';\n\nexport type { BaoSshRoleAttributes, BaoSshRoleProps };\n\nexport interface BaoSshRole extends Resource<\n 'Bao.SshRole',\n BaoSshRoleProps,\n BaoSshRoleAttributes,\n never,\n HttpClient.HttpClient\n> {}\n\nexport const BaoSshRole = Resource<BaoSshRole>('Bao.SshRole', {\n defaultRemovalPolicy: 'retain',\n});\n\n/** Live role, plus the raw body — reconcile needs the raw half to see what it would erase. */\nconst readRole = (form: BaoSshRoleForm) =>\n Effect.gen(function* () {\n const live = yield* baoRead(readPath(form.mount, form.name));\n if (live === undefined) return undefined;\n return { attributes: attributesOf(form, live), live };\n });\n\n/**\n * Fields this resource deliberately does not model, mapped to the value OpenBao's own write\n * puts there when nobody says otherwise. The templating flags change how a principal is\n * DERIVED at signing time, which is a different kind of decision from which principals\n * exist; the rest are issuance mechanics. MEASURED against all three live roles — every one\n * of them sits on exactly these values, so the guard below fires on nothing that exists.\n */\nconst UNMANAGED_DEFAULTS: Readonly<Record<string, unknown>> = {\n algorithm_signer: 'default',\n allow_commas_in_identity_templates: false,\n allow_user_key_ids: false,\n allowed_domains_template: false,\n allowed_users_template: false,\n default_extensions_template: false,\n default_user_template: false,\n issuer_ref: 'default',\n key_id_format: '',\n not_before_duration: 30,\n};\n\n/**\n * ⚠️ ABSENT AND EMPTY BOTH COUNT AS \"NEVER SET\". A role this resource wrote omits these\n * fields entirely, so a stricter test would refuse on the provider's own output and\n * deadlock the update after next.\n */\nconst isDefault = (live: Record<string, unknown>, field: string) =>\n live[field] === undefined || live[field] === '' || live[field] === UNMANAGED_DEFAULTS[field];\n\n/**\n * ⛔ THE FIELDS A WRITE WOULD SILENTLY DESTROY. Because the write is a full replace, a role\n * someone tuned by hand — `allowed_user_key_lengths` (a minimum RSA size), a\n * `key_id_format` the audit trail is grepped by, a `not_before_duration` widened to\n * survive clock skew, a non-default issuer — loses all of it the moment this resource\n * decides to update. A vanished key-length floor is a security regression that no plan\n * output would ever mention, and a vanished backdating window breaks signing on exactly\n * the skewed host it was added for. So reconcile refuses instead of writing.\n */\nconst wouldErase = (live: Record<string, unknown>): readonly string[] => {\n const lost = Object.keys(UNMANAGED_DEFAULTS).filter((field) => !isDefault(live, field));\n if (Object.keys(extMap(live['allowed_user_key_lengths'])).length > 0) {\n lost.push('allowed_user_key_lengths');\n }\n return lost.sort();\n};\n\nconst refuse = (message: string) => Effect.die(new Error(message));\n\nexport const BaoSshRoleProvider = () =>\n Provider.effect(\n BaoSshRole,\n Effect.succeed(\n BaoSshRole.Provider.of({\n /**\n * ⛔ `bao list ssh/roles` IS NOT A LIST OF THINGS THIS OWNS. Every role on the mount\n * answers, including the break-glass ones cut by hand at bringup. Returning them\n * would invite Alchemy to adopt — and then delete — the role that is the only way\n * back into the estate.\n */\n list: () => Effect.succeed([]),\n\n read: Effect.fn(function* ({ olds }) {\n const found = yield* readRole(resolve(olds));\n return found?.attributes;\n }),\n\n /**\n * ⛔ IT COMPARES THE LIVE ROLE, NOT THE STORED DIGEST. A role widened in the OpenBao\n * UI — one extra principal in `allowed_users` — is exactly the drift the check-*\n * gates exist to catch, and a provider that trusted its own state would report\n * `noop` straight through it.\n *\n * ⚠️ `wouldErase` is deliberately NOT consulted here. Extra hand-set fields are only\n * at risk when something actually writes; if every managed field already matches,\n * the honest answer is `noop` and nothing gets destroyed.\n */\n diff: Effect.fn(function* ({ news, output }) {\n if (output === undefined || !isResolved(news)) return undefined;\n const form = resolve(news);\n /**\n * ⛔ A RENAMED ROLE IS A NEW PATH, NOT AN EDIT. `ssh/roles/x` and `ssh-host/roles/x`\n * are different mounts with different CAs. Without this, changing `name` or\n * `mount` would write the new role and leave the old one signing certificates\n * for as long as anyone remembered its name.\n */\n if (output.mount !== form.mount || output.name !== form.name) {\n return { action: 'replace' } as const;\n }\n const found = yield* readRole(form);\n if (found === undefined) return { action: 'update' } as const;\n return matches(found.attributes, form)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: Effect.fn(function* ({ news }) {\n const form = resolve(news);\n const path = readPath(form.mount, form.name);\n\n const bad = badDurations(form);\n if (bad.length > 0) {\n return yield* refuse(\n `Bao.SshRole ${path}: ${bad.join(', ')} is not a duration parseDuration understands ` +\n '(`0` or `<n>s|m|h|d`). It would write, then report update on every plan forever.',\n );\n }\n /**\n * ⛔ A USER-CERT ROLE WITH NO PRINCIPALS SIGNS NOTHING. It is not dangerous — it\n * fails closed at sign time — but it is never what was meant, and the failure\n * surfaces hours later as \"ssh stopped working\" rather than here. The opposite\n * case, empty principals that are ALLOWED, is the skeleton key in the header.\n */\n if (\n form.allowUserCertificates &&\n form.allowedUsers.length === 0 &&\n !form.allowEmptyPrincipals\n ) {\n return yield* refuse(\n `Bao.SshRole ${path}: allowUserCertificates with an empty allowedUsers and ` +\n 'allowEmptyPrincipals false. Every sign request against it would be rejected.',\n );\n }\n\n const found = yield* readRole(form);\n if (found === undefined || !matches(found.attributes, form)) {\n if (found !== undefined) {\n const lost = wouldErase(found.live);\n if (lost.length > 0) {\n return yield* refuse(\n `Bao.SshRole ${path}: live role carries ${lost.join(', ')}, which this ` +\n 'resource does not declare and the full-replace write would ERASE. ' +\n 'Fold those settings into the declaration, or clear them by hand first.',\n );\n }\n }\n yield* baoWrite('PUT', path, writeBody(form));\n }\n /**\n * ⚠️ RE-READ RATHER THAN ECHO THE DECLARATION. The write is the only place the\n * JSON-string encoding of `default_extensions` could be wrong (see the ⛔ on\n * mapValue), and a provider that returned its own props would record a role it\n * had never confirmed.\n */\n const after = yield* readRole(form);\n if (after === undefined) {\n return yield* refuse(\n `Bao.SshRole ${path}: write returned no error but the role is still absent.`,\n );\n }\n return after.attributes;\n }),\n\n /**\n * ⛔ DELETING THE ROLE DOES NOT REVOKE THE CERTIFICATES IT ALREADY SIGNED. OpenSSH\n * has no CRL here: every outstanding certificate stays valid for the rest of its\n * TTL, on every host trusting the CA, with no way to call it back short of a KRL\n * on each host. On the live `ssh-host` role that TTL is 365 days. Deleting is\n * therefore a change to who gets in NEXT, never a way to lock someone out now.\n * Idempotent as Alchemy requires — already gone is success.\n */\n delete: Effect.fn(function* ({ output }) {\n yield* baoDelete(readPath(output.mount, output.name));\n return undefined;\n }),\n }),\n ),\n );\n",
28
31
  "/**\n * The wire-and-form half of Bao.SshRole: normalisation, argv, and the equality that decides\n * whether a plan says `noop`. Split from ssh-role.ts for the 250-line cap.\n *\n * ⚠️ EVERY FIELD TYPE BELOW WAS MEASURED, not assumed — OpenBao v2.6.2, read from the live\n * engine's own `sys/internal/specs/openapi`, schema `SshWriteRoleRequest`:\n * `allowed_users`, `allowed_extensions`, `allowed_critical_options`, `allowed_domains`\n * → `string`. ONE COMMA-SEPARATED STRING. Not a list, however much it reads like one.\n * `default_extensions`, `default_critical_options`, `allowed_user_key_lengths`\n * → `object`, `format: map`.\n * `ttl`, `max_ttl`, `not_before_duration` → `integer`, SECONDS.\n * A role read echoes exactly those types back, which is why csvList and extMap exist.\n */\nimport { sha256 } from './digest.ts';\nimport { parseDuration, ttlSeconds } from './mount-form.ts';\n\nexport interface BaoSshRoleProps {\n /** Role name, as `<mount>/roles/{name}` takes it. */\n name: string;\n /** Secrets engine mount, no trailing slash. Defaults to `ssh`; `ssh-host` also exists. */\n mount?: string;\n /** Principals a certificate may carry. `['*']` is OpenBao's wildcard. */\n allowedUsers: readonly string[];\n /** Principal used when a sign request does not name one. */\n defaultUser?: string;\n /** Sign user certificates. Defaults to false — OpenBao's own default. */\n allowUserCertificates?: boolean;\n /** Sign host certificates. Defaults to false — OpenBao's own default. */\n allowHostCertificates?: boolean;\n /** Host-cert roles only: the domains a host certificate may claim. */\n allowedDomains?: readonly string[];\n /** Host-cert roles only: allow `host.example.com` under an allowed `example.com`. */\n allowSubdomains?: boolean;\n /** Host-cert roles only: allow the bare allowed domain itself. */\n allowBareDomains?: boolean;\n /**\n * Extensions a REQUESTER may ask for — not the ones that get stamped on. `[]` means none\n * may be requested, which is what all three live roles carry; `['*']` allows any.\n */\n allowedExtensions?: readonly string[];\n /** Extensions stamped on every certificate, e.g. `{ 'permit-pty': '' }`. */\n defaultExtensions?: Readonly<Record<string, string>>;\n /** Critical options a requester may ask for — `force-command`, `source-address`. */\n allowedCriticalOptions?: readonly string[];\n /** Critical options stamped on every certificate. See the ⛔ on erasure in ssh-role.ts. */\n defaultCriticalOptions?: Readonly<Record<string, string>>;\n /** ⛔ Skeleton-key flag — read the ⛔ in ssh-role.ts before setting this true. */\n allowEmptyPrincipals?: boolean;\n /** Certificate lifetime, e.g. `4h`. ⛔ `0` is NOT \"no expiry\" — see ssh-role.ts. */\n ttl: string;\n /** Ceiling on a requested lifetime, e.g. `8h`. */\n maxTtl: string;\n}\n\n/**\n * Every prop resolved to the value the full-replace write will actually produce.\n *\n * ★ Derived rather than retyped: `Required` is the whole difference between the two, and a\n * hand-copied twin is the kind of thing that silently loses a field in review.\n */\nexport type BaoSshRoleForm = Required<BaoSshRoleProps>;\n\n/** ⛔ NO SECRET HERE — names, flags, TTLs and a digest. The CA key is out of scope. */\nexport interface BaoSshRoleAttributes extends Omit<BaoSshRoleForm, 'maxTtl' | 'ttl'> {\n /**\n * ⚠️ SECONDS, NOT A DURATION STRING. OpenBao stores seconds and a plan should show what is\n * stored; `4h` in the props and 14400 here are the same role. Rendering seconds back\n * into `4h` needs a table of unit rules that mount-form.ts and auth-role-form.ts each\n * already carry a private copy of — a third copy is how the three drift apart.\n */\n ttlSeconds: number;\n maxTtlSeconds: number;\n /** Always `ca` on a healthy role. Stored so an otp/dynamic role reads as a mismatch. */\n keyType: string;\n /** SHA-256 of the managed fields — safe to persist; see policy.ts. */\n digest: string;\n}\n\n/** Mount path without a trailing slash; `ssh` when the caller did not say. */\nexport const mountOf = (mount: string | undefined) => (mount ?? 'ssh').replace(/\\/+$/, '');\n\nexport const readPath = (mount: string | undefined, name: string) =>\n `${mountOf(mount)}/roles/${name}`;\n\nconst text = (value: unknown) => (typeof value === 'string' ? value : '');\n\nconst bool = (value: unknown, fallback: boolean) => (typeof value === 'boolean' ? value : fallback);\n\n/**\n * ⚠️ SETS, NOT SEQUENCES. OpenBao stores these as one comma-separated string and promises\n * nothing about the order it hands back. Sorting and de-duplicating on BOTH sides is what\n * stops every plan from reporting an update on a role nobody touched.\n */\nexport const csvList = (value: unknown): readonly string[] => {\n const parts = Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === 'string')\n : text(value).split(',');\n return [\n ...new Set(parts.map((entry) => entry.trim()).filter((entry) => entry.length > 0)),\n ].sort();\n};\n\n/**\n * ⚠️ A MAP WITH NO PROMISED ORDER. Key order also decides the digest and the argv, so it is\n * normalised once here and everything else reads the sorted copy.\n */\nexport const extMap = (value: unknown): Record<string, string> => {\n const out: Record<string, string> = {};\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return out;\n const source = value as Record<string, unknown>;\n for (const key of Object.keys(source).sort()) out[key] = text(source[key]);\n return out;\n};\n\n/** ⛔ Every default here is what the WRITE produces, not what felt sensible. */\nexport const resolve = (props: BaoSshRoleProps): BaoSshRoleForm => ({\n name: props.name,\n mount: mountOf(props.mount),\n allowedUsers: csvList(props.allowedUsers),\n defaultUser: props.defaultUser ?? '',\n allowUserCertificates: props.allowUserCertificates ?? false,\n allowHostCertificates: props.allowHostCertificates ?? false,\n allowedDomains: csvList(props.allowedDomains),\n allowSubdomains: props.allowSubdomains ?? false,\n allowBareDomains: props.allowBareDomains ?? false,\n allowedExtensions: csvList(props.allowedExtensions),\n defaultExtensions: extMap(props.defaultExtensions ?? {}),\n allowedCriticalOptions: csvList(props.allowedCriticalOptions),\n defaultCriticalOptions: extMap(props.defaultCriticalOptions ?? {}),\n allowEmptyPrincipals: props.allowEmptyPrincipals ?? false,\n ttl: props.ttl,\n maxTtl: props.maxTtl,\n});\n\nexport const attributesOf = (\n form: BaoSshRoleForm,\n live: Record<string, unknown>,\n): BaoSshRoleAttributes => {\n const attrs = {\n name: form.name,\n mount: form.mount,\n allowedUsers: csvList(live['allowed_users']),\n defaultUser: text(live['default_user']),\n allowUserCertificates: bool(live['allow_user_certificates'], false),\n allowHostCertificates: bool(live['allow_host_certificates'], false),\n allowedDomains: csvList(live['allowed_domains']),\n allowSubdomains: bool(live['allow_subdomains'], false),\n allowBareDomains: bool(live['allow_bare_domains'], false),\n allowedExtensions: csvList(live['allowed_extensions']),\n defaultExtensions: extMap(live['default_extensions']),\n allowedCriticalOptions: csvList(live['allowed_critical_options']),\n defaultCriticalOptions: extMap(live['default_critical_options']),\n allowEmptyPrincipals: bool(live['allow_empty_principals'], false),\n keyType: text(live['key_type']) || 'ca',\n ttlSeconds: ttlSeconds(live['ttl']) ?? 0,\n maxTtlSeconds: ttlSeconds(live['max_ttl']) ?? 0,\n };\n return { ...attrs, digest: sha256(JSON.stringify(attrs)) };\n};\n\n/**\n * ⛔ THE MAPS CROSS THE WIRE AS A JSON STRING, AND THAT IS THE CORRECT SHAPE. MEASURED with\n * `bao write -output-curl-string` against the live v2.6.2 (no write was sent): the CLI\n * puts every `k=v` value in the body as a string, so `default_extensions` leaves as\n * `\"{\\\"permit-pty\\\":\\\"\\\"}\"` and never as an object. OpenBao's own OpenAPI types that field\n * `object`/`format: map` — a `framework` TypeMap, which JSON-decodes a string value.\n * ⚠️ THAT DECODE IS REASONED, NOT MEASURED: writing to the live engine was out of bounds,\n * so the round trip was never executed. If a first deploy lands a role whose\n * default_extensions came out EMPTY, this is the line that was wrong, and the fix is to\n * send the map as a JSON object in writeBody rather than as this string — the HTTP body\n * can now carry either.\n */\nconst mapValue = (map: Readonly<Record<string, string>>) => JSON.stringify(extMap(map));\n\n/**\n * ⛔ EVERY MANAGED FIELD IS SENT ON EVERY WRITE, INCLUDING THE FALSE ONES. The role write is\n * a full replace (see ssh-role.ts), so an omitted field is not \"left alone\" — it is reset.\n * Sending the resolved form makes the body and the declaration the same statement. All\n * strings, exactly the `k=v` pairs `bao write` sent, for `PUT <mount>/roles/<name>`.\n */\nexport const writeBody = (form: BaoSshRoleForm): Record<string, string> => ({\n key_type: 'ca',\n allowed_users: form.allowedUsers.join(','),\n default_user: form.defaultUser,\n allow_user_certificates: String(form.allowUserCertificates),\n allow_host_certificates: String(form.allowHostCertificates),\n allowed_domains: form.allowedDomains.join(','),\n allow_subdomains: String(form.allowSubdomains),\n allow_bare_domains: String(form.allowBareDomains),\n allowed_extensions: form.allowedExtensions.join(','),\n default_extensions: mapValue(form.defaultExtensions),\n allowed_critical_options: form.allowedCriticalOptions.join(','),\n default_critical_options: mapValue(form.defaultCriticalOptions),\n allow_empty_principals: String(form.allowEmptyPrincipals),\n ttl: form.ttl,\n max_ttl: form.maxTtl,\n});\n\nconst sameList = (want: readonly string[], have: readonly string[]) =>\n want.length === have.length && want.every((entry, index) => entry === have[index]);\n\nconst sameMap = (\n want: Readonly<Record<string, string>>,\n have: Readonly<Record<string, string>>,\n) => {\n const keys = Object.keys(want);\n return keys.length === Object.keys(have).length && keys.every((key) => have[key] === want[key]);\n};\n\n/**\n * Compare in seconds, never as text — `60m` and `1h` are the same role.\n * ⚠️ An unparseable prop yields undefined, which equals no number, so it reports drift\n * rather than a false noop. `badDurations` is what turns that into a readable refusal.\n */\nconst sameTtl = (want: string, have: number) => parseDuration(want) === have;\n\n/**\n * ⛔ AN UNPARSEABLE TTL IS A PLAN THAT NEVER GOES GREEN. parseDuration understands `0` and\n * `<n>[smhd]` and nothing else. A prop like `4h30m` writes fine, reads back as 16200,\n * fails to parse on the want side, and reports `update` forever — and a resource that is\n * always dirty is one nobody reads the plan for any more.\n */\nexport const badDurations = (form: BaoSshRoleForm): readonly string[] =>\n (['ttl', 'maxTtl'] as const).filter((field) => parseDuration(form[field]) === undefined);\n\n/**\n * True when live already matches the declaration on every managed field.\n * ⛔ NOTHING IS SKIPPED FOR BEING UNDEFINED. mount.ts and auth-role.ts can treat an absent\n * prop as \"don't care\" because their writes are partial tunes; this one cannot, because\n * the write resets whatever it omits. Comparing the resolved form is what keeps a\n * hand-edited role from surviving forever behind a green plan.\n */\nexport const matches = (attributes: BaoSshRoleAttributes, form: BaoSshRoleForm) =>\n attributes.keyType === 'ca' &&\n sameList(form.allowedUsers, attributes.allowedUsers) &&\n attributes.defaultUser === form.defaultUser &&\n attributes.allowUserCertificates === form.allowUserCertificates &&\n attributes.allowHostCertificates === form.allowHostCertificates &&\n sameList(form.allowedDomains, attributes.allowedDomains) &&\n attributes.allowSubdomains === form.allowSubdomains &&\n attributes.allowBareDomains === form.allowBareDomains &&\n sameList(form.allowedExtensions, attributes.allowedExtensions) &&\n sameMap(form.defaultExtensions, attributes.defaultExtensions) &&\n sameList(form.allowedCriticalOptions, attributes.allowedCriticalOptions) &&\n sameMap(form.defaultCriticalOptions, attributes.defaultCriticalOptions) &&\n attributes.allowEmptyPrincipals === form.allowEmptyPrincipals &&\n sameTtl(form.ttl, attributes.ttlSeconds) &&\n sameTtl(form.maxTtl, attributes.maxTtlSeconds);\n"
29
32
  ],
30
- "mappings": "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",
31
- "debugId": "72D46173613CE4CB64756E2164756E21",
33
+ "mappings": "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",
34
+ "debugId": "4D8C0F4073136EF664756E2164756E21",
32
35
  "names": []
33
36
  }