@homeflare/alchemy 0.47.0 → 0.48.0

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.
Files changed (130) hide show
  1. package/README.md +6 -32
  2. package/dist/talos/bao-env.d.ts +7 -0
  3. package/dist/talos/bao-env.d.ts.map +1 -0
  4. package/dist/talos/cluster-adapter-errors.d.ts +134 -0
  5. package/dist/talos/cluster-adapter-errors.d.ts.map +1 -0
  6. package/dist/talos/cluster-adapter.d.ts +115 -0
  7. package/dist/talos/cluster-adapter.d.ts.map +1 -0
  8. package/dist/talos/cluster-identity.d.ts +28 -0
  9. package/dist/talos/cluster-identity.d.ts.map +1 -0
  10. package/dist/talos/cluster-transport.d.ts +64 -0
  11. package/dist/talos/cluster-transport.d.ts.map +1 -0
  12. package/dist/talos/credentials-write.d.ts.map +1 -1
  13. package/dist/talos/credentials.d.ts +10 -19
  14. package/dist/talos/credentials.d.ts.map +1 -1
  15. package/dist/talos/fake-apiserver.d.ts +9 -0
  16. package/dist/talos/fake-apiserver.d.ts.map +1 -0
  17. package/dist/talos/index.d.ts +7 -0
  18. package/dist/talos/index.d.ts.map +1 -1
  19. package/dist/talos/index.js +669 -167
  20. package/dist/talos/index.js.map +22 -10
  21. package/dist/talos/kubeconfig-attrs.d.ts +14 -0
  22. package/dist/talos/kubeconfig-attrs.d.ts.map +1 -1
  23. package/dist/talos/kubeconfig-doc.d.ts +23 -0
  24. package/dist/talos/kubeconfig-doc.d.ts.map +1 -0
  25. package/dist/talos/kubeconfig.d.ts +0 -12
  26. package/dist/talos/kubeconfig.d.ts.map +1 -1
  27. package/dist/talos/literal-connection.d.ts +16 -0
  28. package/dist/talos/literal-connection.d.ts.map +1 -0
  29. package/dist/talos/machine-config-read.d.ts +1 -1
  30. package/dist/talos/machine-config-read.d.ts.map +1 -1
  31. package/dist/talos/mint-temp-file.d.ts +20 -0
  32. package/dist/talos/mint-temp-file.d.ts.map +1 -0
  33. package/dist/talos/node-temp.harness.d.ts +2 -0
  34. package/dist/talos/node-temp.harness.d.ts.map +1 -0
  35. package/dist/talos/talos-bootstrap-etcd.d.ts +1 -1
  36. package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -1
  37. package/dist/talos/talos-cluster-health.d.ts +15 -15
  38. package/dist/talos/talos-cluster-health.d.ts.map +1 -1
  39. package/dist/talos/talos-cluster-identity.d.ts +65 -0
  40. package/dist/talos/talos-cluster-identity.d.ts.map +1 -0
  41. package/dist/talos/talosctl-binary.d.ts +43 -0
  42. package/dist/talos/talosctl-binary.d.ts.map +1 -0
  43. package/dist/talos/talosctl.d.ts +12 -15
  44. package/dist/talos/talosctl.d.ts.map +1 -1
  45. package/dist/talos/trust-boundary.d.ts +8 -0
  46. package/dist/talos/trust-boundary.d.ts.map +1 -0
  47. package/dist/talos/values.d.ts.map +1 -1
  48. package/dist/talos/yaml-parse.d.ts +3 -0
  49. package/dist/talos/yaml-parse.d.ts.map +1 -0
  50. package/dist/verify/fake-engine.d.ts +2 -0
  51. package/dist/verify/fake-engine.d.ts.map +1 -1
  52. package/docs/peers.md +32 -5
  53. package/docs/talos-openbao-adapter.md +44 -0
  54. package/docs/upstream-conformance-bun.md +61 -24
  55. package/package.json +116 -2
  56. package/src/talos/bao-env.ts +16 -0
  57. package/src/talos/bao-vetting.test.ts +97 -0
  58. package/src/talos/cluster-adapter-deadline.test.ts +110 -0
  59. package/src/talos/cluster-adapter-errors.ts +192 -0
  60. package/src/talos/cluster-adapter-move.test.ts +129 -0
  61. package/src/talos/cluster-adapter-reconcile.test.ts +165 -0
  62. package/src/talos/cluster-adapter-refusals.test.ts +102 -0
  63. package/src/talos/cluster-adapter-rename.test.ts +87 -0
  64. package/src/talos/cluster-adapter-secrecy.test.ts +243 -0
  65. package/src/talos/cluster-adapter.fixtures.ts +125 -0
  66. package/src/talos/cluster-adapter.test.ts +240 -0
  67. package/src/talos/cluster-adapter.ts +249 -0
  68. package/src/talos/cluster-identity.ts +63 -0
  69. package/src/talos/cluster-transport.ts +110 -0
  70. package/src/talos/credentials-write.ts +27 -5
  71. package/src/talos/credentials.ts +51 -45
  72. package/src/talos/fake-apiserver.ts +55 -0
  73. package/src/talos/fake-process.ts +47 -1
  74. package/src/talos/index.ts +32 -0
  75. package/src/talos/kubeconfig-adapter.test.ts +37 -0
  76. package/src/talos/kubeconfig-attrs.ts +12 -28
  77. package/src/talos/kubeconfig-doc.ts +74 -0
  78. package/src/talos/kubeconfig.fixtures.ts +52 -0
  79. package/src/talos/kubeconfig.test.ts +6 -54
  80. package/src/talos/kubeconfig.ts +18 -34
  81. package/src/talos/literal-connection.ts +59 -0
  82. package/src/talos/mint-temp-file.ts +56 -0
  83. package/src/talos/node-connect.harness.ts +78 -0
  84. package/src/talos/node-connect.test.ts +27 -0
  85. package/src/talos/node-temp.harness.ts +40 -0
  86. package/src/talos/node-temp.test.ts +26 -0
  87. package/src/talos/talos-cluster-health-declare.test.ts +54 -0
  88. package/src/talos/talos-cluster-health-literal.test.ts +69 -0
  89. package/src/talos/talos-cluster-health.test.ts +104 -18
  90. package/src/talos/talos-cluster-health.ts +46 -14
  91. package/src/talos/talos-cluster-identity.test.ts +96 -0
  92. package/src/talos/talos-cluster-identity.ts +130 -0
  93. package/src/talos/talosctl-binary.ts +150 -0
  94. package/src/talos/talosctl-vetting.test.ts +212 -0
  95. package/src/talos/talosctl.test.ts +110 -0
  96. package/src/talos/talosctl.ts +101 -15
  97. package/src/talos/trust-boundary.test.ts +17 -0
  98. package/src/talos/trust-boundary.ts +45 -0
  99. package/src/talos/values.ts +5 -12
  100. package/src/talos/yaml-parse.test.ts +41 -0
  101. package/src/talos/yaml-parse.ts +28 -0
  102. package/src/verify/fake-engine.ts +10 -0
  103. package/dist/talos/fake-process.d.ts +0 -56
  104. package/dist/talos/fake-process.d.ts.map +0 -1
  105. package/dist/talos/machine-config-fixtures.d.ts +0 -60
  106. package/dist/talos/machine-config-fixtures.d.ts.map +0 -1
  107. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +0 -147
  108. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +0 -31
  109. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +0 -82
  110. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +0 -44
  111. package/src/postgres/fixtures/pg-REL_18_6-create-database-synopsis.txt +0 -26
  112. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +0 -26
  113. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +0 -95
  114. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +0 -24
  115. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +0 -62
  116. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +0 -70
  117. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +0 -33
  118. package/src/postgres/fixtures/pg-REL_18_6-pg_database.h.txt +0 -67
  119. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +0 -81
  120. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +0 -28
  121. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +0 -124
  122. package/src/release/fixtures/openbao/checksums.txt +0 -83
  123. package/src/release/fixtures/openbao/checksums.txt.gpgsig +0 -0
  124. package/src/release/fixtures/openbao/darwin-assets.txt +0 -12
  125. package/src/release/fixtures/openbao/openbao-gpg-pub-20240618.asc +0 -109
  126. package/src/release/fixtures/victoria/darwin-arm64-assets.txt +0 -22
  127. package/src/release/fixtures/victoria/victoria-logs-darwin-arm64-v1.52.0_checksums.txt +0 -2
  128. package/src/release/fixtures/victoria/victoria-metrics-darwin-arm64-v1.151.0_checksums.txt +0 -2
  129. package/src/release/fixtures/victoria/victoria-traces-darwin-arm64-v0.10.0_checksums.txt +0 -2
  130. package/src/release/fixtures/victoria/vmutils-darwin-arm64-v1.151.0_checksums.txt +0 -8
@@ -1,22 +1,34 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/talos/kubeconfig.ts", "../src/talos/credentials.ts", "../src/talos/credentials-write.ts", "../src/talos/values.ts", "../src/talos/kubeconfig-attrs.ts", "../src/talos/talosctl.ts", "../src/talos/talos-bootstrap.ts", "../src/talos/talos-bootstrap-etcd.ts", "../src/talos/talos-errors.ts", "../src/talos/talos-cluster-health.ts", "../src/talos/talos-machine-config.ts", "../src/talos/machine-config-read.ts", "../src/talos/machine-config-poll.ts"],
3
+ "sources": ["../src/talos/cluster-adapter.ts", "../src/talos/cluster-adapter-errors.ts", "../src/talos/cluster-identity.ts", "../src/talos/cluster-transport.ts", "../src/talos/credentials.ts", "../src/talos/bao-env.ts", "../src/talos/talosctl-binary.ts", "../src/talos/trust-boundary.ts", "../src/talos/mint-temp-file.ts", "../src/talos/yaml-parse.ts", "../src/talos/kubeconfig-doc.ts", "../src/talos/kubeconfig.ts", "../src/talos/credentials-write.ts", "../src/talos/values.ts", "../src/talos/kubeconfig-attrs.ts", "../src/talos/talosctl.ts", "../src/talos/talos-bootstrap.ts", "../src/talos/talos-bootstrap-etcd.ts", "../src/talos/talos-errors.ts", "../src/talos/talos-cluster-identity.ts", "../src/talos/talos-cluster-health.ts", "../src/talos/literal-connection.ts", "../src/talos/talos-machine-config.ts", "../src/talos/machine-config-read.ts", "../src/talos/machine-config-poll.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * `Talos.Kubeconfig` — fetch admin kubeconfig so `Kubernetes.*` workloads can connect.\n *\n * ★ REASONED FROM talosctl kubeconfig (Talos v1.13 CLI reference): writes a kubeconfig file;\n * `--merge=false` keeps it isolated; `-f/--force` overwrites an existing file.\n *\n * ⛔ THE KUBECONFIG FILE CONTAINS A CLIENT CERTIFICATE — IT MUST NOT BE AN ATTRIBUTE. Alchemy\n * persists attributes unencrypted. This resource persists ONLY public metadata + fingerprints,\n * never the file's own bytes.\n *\n * ⛔ LANDS IN OPENBAO, NOT A HOST `runtimePath` (K-talos-first-boot, 2026-09-26). The shipped shape\n * wrote a cluster-admin kubeconfig to un-vaulted host disk and never removed it — the exact class\n * of exposure `talos/credentials.ts`'s own header exists to prevent — and its own `read` depended\n * on that file's continued presence, so verifying from any other host planned `update` forever\n * (docs/plans/2026-09-26-talos-secrets-flow.md's \"Measured today\" section). Fixed:\n * - CREATE (`output === undefined`) runs `talosctl kubeconfig` into a throwaway, unguessable\n * temp path (this file's own `reservedTempPath`), reads it back, and writes its bytes into\n * OpenBao at `target.mount`/`kubeconfigKey` via stdin (`credentials-write.ts`'s\n * `writeKvValue` — ⛔ never argv) — never to any path a caller could depend on.\n * - ⛔ WRITTEN ONCE, NOT RE-MINTED EVERY DEPLOY. `talosctl kubeconfig` always issues a FRESH\n * admin client certificate; re-running it every reconcile would rotate credentials for no\n * reason and violate O1's write-once-at-bring-up grant on this one key\n * (docs/plans/2026-09-26-talos-secrets-flow.md, O1). Once `output` is defined, reconcile only\n * reads the vault copy back to confirm it — the same \"once\" shape `talos-bootstrap.ts` uses\n * for a boolean, here for a value.\n * - The persisted `connection` carries no usable host path — a consumer materializes its own\n * temp file via `credentials.ts`'s `mintKubeconfig`, the same pattern `mintTalosconfig`\n * already established. Wiring `Kubernetes.ClusterAdapter` to call it is separate, later work\n * (named, not built, in the secrets-flow doc); this only makes the vault-backed read+mint\n * step exist for it to call. ⛔ Until that wiring lands, `connection.auth.path` is a sentinel\n * that can never resolve to a real file (LAND red team I2, `kubeconfig-attrs.ts`'s own\n * header) — an ABSENT path here would let the stock `Kubernetes.KubeConfigAdapter` silently\n * fall back to `$KUBECONFIG`/`~/.kube/config` instead of failing loudly.\n */\nimport { chmodSync } from 'node:fs';\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport type { Connection } from 'alchemy/Kubernetes/Connection';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { DEFAULT_KUBECONFIG_KEY, mintTalosconfig, readKvValue } from './credentials.ts';\nimport { reservedTempPath, writeKvValue } from './credentials-write.ts';\nimport { buildAttrs } from './kubeconfig-attrs.ts';\nimport type { TalosRequirements, WithTarget } from './resource.ts';\nimport { talosctl } from './talosctl.ts';\n\nexport interface KubeconfigProps extends WithTarget {\n /** Node that serves `talosctl kubeconfig`. */\n node: string;\n /** Context name inside the generated kubeconfig — not secret. */\n context: string;\n /** OpenBao KV path under `target.mount` for the written kubeconfig. Default `'kubeconfig'`. */\n kubeconfigKey?: string;\n after?: readonly unknown[];\n}\n\nexport interface KubeconfigAttributes {\n context: string;\n endpoint: string;\n certificateAuthorityFingerprint: string;\n clientCertificateFingerprint: string;\n /** Digest of endpoint+context+fingerprints — detects credential rotation without storing PEM. */\n credentialGeneration: string;\n /**\n * Serializable `Kubernetes.Connection` for downstream workloads.\n *\n * ★ auth.kind `kubeconfig` is the stock ClusterAdapter — provider-roadmap.md names this seam.\n * `path` is a sentinel that can never resolve (LAND red team I2, `kubeconfig-attrs.ts`'s own\n * `toConnection` header): the content lives in OpenBao, not at a fixed host path, and a real\n * `Kubernetes.ClusterAdapter` wiring is later work, so this must fail rather than silently\n * reach the operator's own kubeconfig. A consumer materializes its own scoped temp file via\n * `credentials.ts`'s `mintKubeconfig` in the meantime.\n */\n connection: Connection;\n}\n\nexport interface TalosKubeconfig extends Resource<\n 'Talos.Kubeconfig',\n KubeconfigProps,\n KubeconfigAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosKubeconfig = Resource<TalosKubeconfig>('Talos.Kubeconfig');\n\n/**\n * ★ MEASURED AGAINST OPENBAO v2.6.2 (C1 fix, LAND red team, 2026-09-26 — isolated in-memory dev\n * server, `env -i`, scratch HOME, no estate credentials; server removed after): `bao kv get` on a\n * genuinely unwritten KV-v2 key exits 2 with stderr exactly `No value found at <mount>/data/<key>`\n * — `readKvValue`'s Error message embeds that text verbatim. This is the ONLY signal this file\n * trusts as \"not written yet\"; every other failure (a wrong exit code, a different stderr such as\n * a permission denial or a network failure) propagates as a real error instead of being read as\n * absence.\n */\nconst isVaultKeyAbsent = (error: unknown): boolean =>\n error instanceof Error && /no value found at/i.test(error.message);\n\nconst readVaultMeta = (props: KubeconfigProps, key: string) =>\n readKvValue(props.target.mount, key, ['kubeconfig', 'config']).pipe(\n Effect.catchIf(isVaultKeyAbsent, () => Effect.succeed(undefined)),\n );\n\n/**\n * ★ EXPORTED for kubeconfig.test.ts — see talos-bootstrap.ts's own note on the pattern.\n *\n * ⛔ C1 FIX (LAND red team, 2026-09-26) — `undefined` NOW MEANS ONLY \"the key has never been\n * written\", NEVER \"some read failed\". The shipped `Effect.orElseSucceed` folded EVERY failure —\n * including a vault outage or wrong mount — into a defined, empty-fingerprint object. Alchemy's\n * engine always adopts a defined cold-start `read` result and forces `update` (alchemy beta.79\n * `Plan.ts:1303-1352`), so `reconcileKubeconfig`'s write-once branch (`output !== undefined`)\n * then tried to CONFIRM a key that had never actually been written, and failed every time —\n * `Talos.Kubeconfig` could never be created. Vault content that EXISTS but does not parse as a\n * kubeconfig is a different, fail-closed case (below), never treated as absence.\n */\nexport const readKubeconfig = (props: KubeconfigProps) =>\n Effect.gen(function* () {\n const key = props.kubeconfigKey ?? DEFAULT_KUBECONFIG_KEY;\n const raw = yield* readVaultMeta(props, key);\n if (raw === undefined) return undefined;\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.fail(\n new Error(\n `${props.target.mount}/${key}: vault content exists but does not parse as a kubeconfig ` +\n `for context ${props.context} — not a cold start. Fix the KV entry or the pinned ` +\n 'context rather than trusting an empty read.',\n ),\n );\n }\n return meta;\n });\n\nexport const diffKubeconfig = (\n news: Input<KubeconfigProps>,\n output: KubeconfigAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readKubeconfig(news);\n if (\n live !== undefined &&\n live.credentialGeneration === output.credentialGeneration &&\n live.context === output.context &&\n live.endpoint === output.endpoint\n ) {\n return { action: 'noop' } as const;\n }\n return { action: 'update' } as const;\n });\n\n/**\n * ⛔ WRAPPED IN `Effect.scoped` — same C1-lifetime reasoning as every other Talos resource file:\n * `mintTalosconfig` and `reservedTempPath` both contribute `Scope.Scope`, and this is the caller\n * that owns their lifetime for the whole reconcile.\n * ⛔ WRITE-ONCE — see this file's own header. A bring-up already ran; this branch never spawns\n * `talosctl kubeconfig` or writes to the vault again.\n * ⛔ GATED ON `credentialGeneration`, NOT JUST `output !== undefined` (C1 fix, LAND red team,\n * belt-and-suspenders alongside the `read` fix above) — `output`'s own type still allows a\n * defined-but-empty value (state persisted by a pre-fix build's `emptyAttrs()`, or any future\n * caller that hands this function a stale row). Treat that exactly like `undefined` — mint and\n * write once — rather than take the confirm-only branch and fail trying to read back a key that\n * was never actually written.\n */\nexport const reconcileKubeconfig = (\n props: KubeconfigProps,\n output: KubeconfigAttributes | undefined,\n) =>\n Effect.scoped(\n Effect.gen(function* () {\n const key = props.kubeconfigKey ?? DEFAULT_KUBECONFIG_KEY;\n\n if (output !== undefined && output.credentialGeneration !== '') {\n const raw = yield* readKvValue(props.target.mount, key, ['kubeconfig', 'config']);\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.die(\n new Error(\n `${props.target.mount}/${key}: vault content no longer parses as a kubeconfig for ` +\n `context ${props.context}. Read back rather than trusting the write once.`,\n ),\n );\n }\n return meta;\n }\n\n const credential = yield* mintTalosconfig(props.target);\n const { path: outPath } = yield* reservedTempPath(\n `${props.target.cluster}-${props.node}-kubeconfig-out`,\n );\n yield* talosctl(\n ['kubeconfig', outPath, '--merge=false', '--force', '--force-context-name', props.context],\n { nodes: [props.node], talosconfigPath: credential.talosconfigPath },\n );\n const raw = yield* Effect.tryPromise({\n catch: (cause) => new Error(`${outPath}: reading generated kubeconfig: ${String(cause)}`),\n try: () => Bun.file(outPath).text(),\n });\n if (raw.trim() === '') {\n return yield* Effect.die(\n new Error(\n `${props.node}: talosctl kubeconfig returned no error but wrote an empty file. Read ` +\n 'back rather than trusting the exit code alone.',\n ),\n );\n }\n // ⚠️ REASONED, not measured: talosctl's own writer likely already uses 0600 like most Go\n // credential writers, but this chmods defensively regardless — same posture as\n // credentials.ts's mintKvTempFile.\n yield* Effect.try({\n catch: (cause) => new Error(`${outPath}: chmod 0600: ${String(cause)}`),\n try: () => chmodSync(outPath, 0o600),\n });\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.die(\n new Error(\n `${props.node}: talosctl kubeconfig wrote a file that does not parse for context ` +\n `${props.context}.`,\n ),\n );\n }\n yield* writeKvValue(props.target.mount, key, 'kubeconfig', raw);\n return meta;\n }),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<KubeconfigProps>;\n output: KubeconfigAttributes | undefined;\n }) => diffKubeconfig(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: KubeconfigProps }) => readKubeconfig(olds),\n reconcile: ({\n news,\n output,\n }: {\n news: KubeconfigProps;\n output: KubeconfigAttributes | undefined;\n }) => reconcileKubeconfig(news, output),\n};\n\nexport const TalosKubeconfigProvider = () =>\n Provider.effect(TalosKubeconfig, Effect.succeed(TalosKubeconfig.Provider.of(handlers)));\n",
6
- "/**\n * Talos client material minted from OpenBao, written to a session-temp file whose lifetime the\n * CALLER owns — never this module.\n *\n * ⛔ TALOSCONFIG, MACHINE CONFIG AND secrets.yaml CAN ALL HOLD CLIENT CERTIFICATES AND CLUSTER CA\n * PRIVATE KEYS. Alchemy persists resource attributes WITHOUT encryption — `StateEncoding.ts`\n * tags a `Redacted` value as `{ __redacted__: <plaintext> }` (`REDACTED_MARKER`), it does not\n * encrypt it — and this estate's state store is the shared Cloudflare HTTP state store, not a\n * database anyone forgets is world-legible. None of these three may ever be a prop, an\n * attribute or a log line; see docs/plans/2026-09-26-talos-secrets-flow.md for why the OLD\n * header here (Postgres, `{\"@redacted\": …}`) was wrong on both counts — the RULE survives the\n * correction either way.\n *\n * ★ MODELED ON proxmox/credentials.ts + proxmox/mint.ts: mint at call time, use the material, drop\n * it when the scope ends. The difference is Talos wants a FILE (`--talosconfig` / `-f`), so\n * minting here writes a temp path and registers its own delete finalizer instead of just\n * building a header.\n *\n * ⛔ C1 FIX (2026-09-26, K-A3) — THE SHIPPED `mintTalosconfig` DELETED ITS OWN FILE BEFORE ANY\n * CALLER COULD USE IT. It wrapped its whole body in `Effect.scoped(...)` and registered the\n * delete finalizer inside that same scope, so the scope — and the file — closed the instant\n * `mintTalosconfig` RETURNED, before the caller ever got to pass the path to `talosctl`. Fixed\n * by `Effect.acquireRelease`: it still deletes on every exit path, but contributes `Scope.Scope`\n * to this module's own return type instead of discharging it, so the file survives until\n * whichever `Effect.scoped(...)` the CALLER wraps around its own use of the path (every\n * talos-*.ts resource file wraps its `read`/`reconcile` bodies for exactly this reason now).\n *\n * ⚠️ REASONED FROM THE PUBLISHED TALOS WORKFLOW, NOT MEASURED ON THIS ESTATE. There is no Talos\n * cluster here yet; KV paths below follow the `mount/<key>` shape O1 (the secrets-flow doc)\n * assigns, and `bao kv get` inserts the KV-v2 `data/` API segment itself — a key already\n * prefixed `data/` reads `<mount>/data/data/<key>`, which the OLD default did.\n */\nimport { closeSync, openSync, writeFileSync } from 'node:fs';\nimport * as Effect from 'effect/Effect';\nimport type * as Scope from 'effect/Scope';\nimport * as Stream from 'effect/Stream';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\n\n/** Where credentials come from. HomeFlare-specific mount names live in the stack, not here. */\nexport type TalosTarget = {\n /** OpenBao KV mount holding Talos material, e.g. `talos-c1`. */\n readonly mount: string;\n /** Logical cluster name — safe to persist and log. */\n readonly cluster: string;\n /**\n * Path under the mount for the talosconfig YAML. Default `'talosconfig'` — FIXED 2026-09-26;\n * the shipped default was `'data/talosconfig'`, which `bao kv get` turned into\n * `<mount>/data/data/talosconfig` (see the ⚠️ above). It failed closed rather than reading an\n * empty talosconfig, but it would have blocked the very first deploy.\n */\n readonly talosconfigKey?: string;\n};\n\nexport type TalosCredential = {\n /** Absolute path to a temp talosconfig. ⛔ NEVER PERSIST, NEVER LOG CONTENTS. */\n readonly talosconfigPath: string;\n};\n\nconst DEFAULT_TALOSCONFIG_KEY = 'talosconfig';\n\n/**\n * Default OpenBao KV path (under `target.mount`) for the admin kubeconfig `Talos.Kubeconfig`\n * writes once at cluster bring-up. See kubeconfig.ts's own header (K-talos-first-boot, 2026-09-26)\n * and docs/plans/2026-09-26-talos-secrets-flow.md's O1 key list.\n */\nexport const DEFAULT_KUBECONFIG_KEY = 'kubeconfig';\n\n/**\n * Read one OpenBao KV-v2 value and return the first of `fields` that is a non-empty string.\n *\n * ★ THE ONE PLACE THIS PACKAGE SHELLS TO `bao` — talosconfig, per-node machine config and any\n * future KV-backed Talos material (secrets.yaml, ceph entity keys) all read through this,\n * so there is exactly one spot that must never echo a KV value on failure.\n * ⛔ stderr ONLY ON FAILURE. stdout may hold the very secret this call exists to fetch.\n */\nexport const readKvValue = (\n mount: string,\n key: string,\n fields: readonly string[],\n): Effect.Effect<string, Error, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n const result = yield* ChildProcess.make(\n 'bao',\n ['kv', 'get', '-format=json', `${mount}/${key}`],\n { detached: false, extendEnv: true, stderr: 'pipe', stdin: 'ignore', stdout: 'pipe' },\n ).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n stdout: child.stdout.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new Error(`bao kv get ${mount}/${key} exited ${String(result.exitCode)}: ${result.stderr}`),\n );\n }\n\n const parsed = JSON.parse(result.stdout) as { data?: { data?: Record<string, unknown> } };\n const data = parsed.data?.data;\n for (const field of fields) {\n const raw = data?.[field];\n if (typeof raw === 'string' && raw.trim() !== '') return raw;\n }\n return yield* Effect.fail(\n new Error(\n `${mount}/${key} returned no ${fields.join('/')} field. Never store the value itself in ` +\n 'an Alchemy prop or attribute — fix the KV entry, not the caller.',\n ),\n );\n });\n\n/**\n * Write `raw` to a session-temp, 0600, exclusively-created file whose lifetime is the CALLER's\n * `Effect.scoped`, not this call's. See the ⛔ C1 FIX note at the top of this file.\n *\n * ⛔ 0600, CREATED EXCLUSIVELY, AND `Bun.write` CANNOT DO EITHER. This file can hold a cluster\n * admin client certificate or a machine config's bootstrap token. `Bun.write` takes no mode, so\n * it lands at the process umask — world-readable on this estate — for as long as the resource\n * runs. The name is unguessable, and \"unguessable\" is not a permission.\n * ⚠️ `wx` IS THE OTHER HALF. `O_EXCL` means this cannot be made to write through a path an\n * attacker pre-created (the classic /tmp symlink race), and with a UUIDv7 name a collision is a\n * genuine error rather than something to paper over.\n * ⚠️ A HARD KILL (SIGKILL, power loss) skips the finalizer and leaves the file behind. 0600 is\n * what makes that survivable rather than a disclosure.\n */\nexport const mintKvTempFile = (\n raw: string,\n label: string,\n): Effect.Effect<{ readonly path: string }, Error, Scope.Scope> =>\n Effect.gen(function* () {\n const path = `${Bun.env['TMPDIR'] ?? '/tmp'}/hf-talos-${label}-${Bun.randomUUIDv7()}.yaml`;\n yield* Effect.acquireRelease(\n Effect.try({\n try: () => {\n const fd = openSync(path, 'wx', 0o600);\n try {\n writeFileSync(fd, raw);\n } finally {\n closeSync(fd);\n }\n },\n catch: (cause) => new Error(`writing ${label} temp file: ${String(cause)}`),\n }),\n () =>\n Effect.tryPromise({ try: () => Bun.file(path).delete(), catch: () => undefined }).pipe(\n Effect.orElseSucceed(() => undefined),\n ),\n );\n return { path };\n });\n\n/**\n * Mint one talosconfig file for `target`.\n *\n * ⛔ CALLERS MUST WRAP THEIR WHOLE USE OF `credential.talosconfigPath` — not just this call — in\n * `Effect.scoped(...)`. This function's own `Scope.Scope` requirement is what makes that the\n * caller's job instead of a lie this function tells itself; see the header above.\n */\nexport const mintTalosconfig = (\n target: TalosTarget,\n): Effect.Effect<TalosCredential, Error, ChildProcessSpawner.ChildProcessSpawner | Scope.Scope> =>\n readKvValue(target.mount, target.talosconfigKey ?? DEFAULT_TALOSCONFIG_KEY, [\n 'talosconfig',\n 'config',\n ]).pipe(\n Effect.flatMap((raw) => mintKvTempFile(raw, `${target.cluster}-talosconfig`)),\n Effect.map(({ path }): TalosCredential => ({ talosconfigPath: path })),\n );\n\n/**\n * Mint one temp kubeconfig file from the vault copy `Talos.Kubeconfig` writes at bring-up\n * (K-talos-first-boot, 2026-09-26) — the consumer-side counterpart to {@link mintTalosconfig},\n * named as the future seam for `Kubernetes.ClusterAdapter` in\n * docs/plans/2026-09-26-talos-secrets-flow.md (\"consumers mint it the way the talosconfig is\n * minted\"). Not yet wired to that adapter — this only makes the read+materialize step exist.\n */\nexport const mintKubeconfig = (\n target: TalosTarget,\n key = DEFAULT_KUBECONFIG_KEY,\n): Effect.Effect<\n { readonly path: string },\n Error,\n ChildProcessSpawner.ChildProcessSpawner | Scope.Scope\n> =>\n readKvValue(target.mount, key, ['kubeconfig', 'config']).pipe(\n Effect.flatMap((raw) => mintKvTempFile(raw, `${target.cluster}-kubeconfig`)),\n );\n",
7
- "/**\n * The write half of Talos's OpenBao KV access — split out of credentials.ts (2026-09-26,\n * K-talos-first-boot) once it needed its own header, the same reason machine-config-read.ts,\n * machine-config-poll.ts and talos-errors.ts were split out of talos-machine-config.ts before it.\n * `credentials.ts` stays the read side (mint a talosconfig, read a KV value); this file is the one\n * place anything in this package ever writes TO OpenBao.\n *\n * ★ FIRST CALLER: `Talos.Kubeconfig` (kubeconfig.ts) writing the admin kubeconfig it generates at\n * cluster bring-up into the vault instead of an un-vaulted host `runtimePath` — see that file's\n * own header. `Ceph.AuthEntity` (K-A4, a separate design/PR) is expected to need the same shape\n * for its own vault-written entity keys; this is not yet shared with it on purpose — two callers\n * is the point at which sharing stops being speculative.\n */\nimport * as Effect from 'effect/Effect';\nimport type * as Scope from 'effect/Scope';\nimport * as Stream from 'effect/Stream';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\n\n/**\n * A fresh, unguessable temp path for SOME OTHER PROCESS (talosctl) to create — unlike\n * `credentials.ts`'s `mintKvTempFile`, this does NOT pre-create the file with `wx`, because the\n * caller here is capturing a command's OWN output rather than writing known content itself. The\n * random UUIDv7 name is the only pre-fabrication guard (an attacker cannot pre-plant a symlink at a\n * path it cannot predict) — first used by `kubeconfig.ts` to capture `talosctl kubeconfig`'s\n * generated file before reading it back and writing it into the vault.\n */\nexport const reservedTempPath = (\n label: string,\n): Effect.Effect<{ readonly path: string }, never, Scope.Scope> =>\n Effect.gen(function* () {\n const path = `${Bun.env['TMPDIR'] ?? '/tmp'}/hf-talos-${label}-${Bun.randomUUIDv7()}.yaml`;\n yield* Effect.addFinalizer(() =>\n Effect.tryPromise({ try: () => Bun.file(path).delete(), catch: () => undefined }).pipe(\n Effect.orElseSucceed(() => undefined),\n ),\n );\n return { path };\n });\n\n/**\n * Write one field of an OpenBao KV-v2 value from `value` — never argv, the mirror image of\n * `credentials.ts`'s `readKvValue`.\n *\n * ⛔ C2 FIX (LAND red team, 2026-09-26) — `field=@-` IS WRONG AND WAS NEVER MEASURED. `@value` means\n * \"read a file at this path\"; a literal path of `-` is not the stdin convention for `@` — it is\n * just a file named `-`. MEASURED against the estate's OpenBao v2.6.2 binary (isolated in-memory\n * dev server, `env -i`, scratch HOME, no estate credentials involved; server removed after):\n * `field=@-` exits 1 with `invalid key/value pair \"field=@-\": error reading file: open -: no\n * such file or directory`, and if a file literally named `-` exists in the working directory it\n * silently stores THAT file's bytes instead. `field=-` (no `@`) is Vault/OpenBao's own stdin\n * convention and was confirmed against the same binary to read the piped bytes correctly. Every\n * `Talos.Kubeconfig` create failed here — AFTER `talosctl kubeconfig` had already issued a fresh\n * admin client certificate, which cannot be revoked.\n * ⛔ stderr ONLY ON FAILURE — same rule as `readKvValue`: never echo what was being written, on\n * success or failure.\n */\nexport const writeKvValue = (\n mount: string,\n key: string,\n field: string,\n value: string,\n): Effect.Effect<void, Error, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n const result = yield* ChildProcess.make('bao', ['kv', 'put', `${mount}/${key}`, `${field}=-`], {\n detached: false,\n extendEnv: true,\n stderr: 'pipe',\n stdin: Stream.fromIterable([new TextEncoder().encode(value)]),\n stdout: 'pipe',\n }).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new Error(`bao kv put ${mount}/${key} exited ${String(result.exitCode)}: ${result.stderr}`),\n );\n }\n });\n",
8
- "/**\n * Coercions and digests for Talos resources — every function here exists because a trap does.\n *\n * ⚠️ NOTHING IN THIS FILE TOUCHES A LIVE CLUSTER OR OpenBao. Digests are computed from KV content\n * or talosctl output already fetched by the caller, and kubeconfig YAML already on disk at\n * reconcile time; tests use fixtures only.\n */\nimport { createHash } from 'node:crypto';\n\n/** Trim trailing whitespace only — leading space in YAML is meaningful. */\nexport const canonicalText = (text: string) => text.trimEnd();\n\n/** SHA-256 hex digest of canonical text. Safe to persist — it is not reversible to the input. */\nexport const sha256 = (text: string) =>\n createHash('sha256').update(canonicalText(text)).digest('hex');\n\n/** Digest of a machine config's canonical text. ⛔ Never persist the text itself. */\nexport const configDigest = (text: string) => sha256(text);\n\n/**\n * Extract the raw config text under `spec` from `talosctl get machineconfig -o yaml`'s wrapper.\n *\n * ⛔ THE WHOLE WRAPPER CAN NEVER MATCH THE PINNED DIGEST, AND HASHING IT WAS THE SHIPPED BUG.\n * REASONED from talosctl source (`cmd/talosctl/.../output/yaml.go:63`,\n * `resources/config/machine_config.go:40-50`): the resource envelope nests a `node:` line and\n * resource metadata (version, timestamps) around the config, which is itself a raw YAML STRING\n * under `spec`. Metadata changes on every observation, so `configDigest(wrapper)` never equals\n * `configDigest(seededConfigText)` even when nothing changed — every reconcile would die, every\n * diff would plan `update`, verify would never go quiet (all three MEASURED against the shipped\n * code's shape, docs/plans/2026-09-26-talos-stack-first-boot.md).\n * ⚠️ Returns `undefined` for any shape without a string `spec`, so a caller cannot mistake\n * \"unparsable wrapper\" for \"empty config\" — those must fail differently (the caller's job).\n * ⛔ MORE THAN ONE DOCUMENT IS REFUSED, NEVER `doc[0]` (fix-first #2, PR 307 red team). An unfiltered\n * `get machineconfig` lists BOTH the `persistent` and `v1alpha1` resources, sorted by id\n * (REASONED, cosi-project/runtime `inmem/collection.go:122-124`), so a bare `doc[0]` is always\n * `persistent` — never the config this package applies. The caller (machine-config-read.ts) now\n * always requests the single named resource (`get machineconfig v1alpha1`); a second document\n * showing up here means that request shape changed without this guard changing with it, and\n * silently picking one would repeat the exact shipped bug.\n */\nexport const extractMachineConfigSpec = (wrapperYaml: string): string | undefined => {\n let doc: unknown;\n try {\n doc = Bun.YAML.parse(wrapperYaml);\n } catch {\n return undefined;\n }\n if (Array.isArray(doc)) {\n if (doc.length !== 1) return undefined;\n doc = doc[0];\n }\n if (doc === null || typeof doc !== 'object') return undefined;\n const spec = (doc as { spec?: unknown }).spec;\n return typeof spec === 'string' ? spec : undefined;\n};\n\ntype KubeconfigDoc = {\n clusters?: {\n cluster?: { server?: string; 'certificate-authority-data'?: string };\n name?: string;\n }[];\n contexts?: { context?: { cluster?: string; user?: string }; name?: string }[];\n users?: {\n name?: string;\n user?: { 'client-certificate-data'?: string; 'client-key-data'?: string };\n }[];\n 'current-context'?: string;\n};\n\n/**\n * Public metadata extracted from a kubeconfig file on disk.\n *\n * ⛔ RETURNS FINGERPRINTS ONLY. The admin kubeconfig contains a client certificate; Alchemy state\n * may hold the API server URL and CA/client cert digests, never the PEM bytes.\n */\nexport const kubeconfigMetadata = (\n yamlText: string,\n contextName: string,\n): { endpoint: string; caFingerprint: string; clientFingerprint: string } | undefined => {\n let doc: KubeconfigDoc;\n try {\n doc = Bun.YAML.parse(yamlText) as KubeconfigDoc;\n } catch {\n return undefined;\n }\n\n const ctx = doc.contexts?.find((row) => row.name === contextName)?.context;\n const clusterName = ctx?.cluster;\n const userName = ctx?.user;\n if (clusterName === undefined || userName === undefined) return undefined;\n\n const cluster = doc.clusters?.find((row) => row.name === clusterName)?.cluster;\n const user = doc.users?.find((row) => row.name === userName)?.user;\n const endpoint = cluster?.server;\n const ca = cluster?.['certificate-authority-data'];\n const cert = user?.['client-certificate-data'] ?? user?.['client-key-data'];\n if (endpoint === undefined || ca === undefined || cert === undefined) return undefined;\n\n return {\n caFingerprint: sha256(ca),\n clientFingerprint: sha256(cert),\n endpoint,\n };\n};\n",
9
- "/**\n * `Talos.Kubeconfig`'s attribute builder and its `Kubernetes.Connection` — split out of\n * kubeconfig.ts (LAND, 2026-09-26, C1/I2 fixes) once fixing those findings pushed the file over the\n * 250-line cap, the same reason machine-config-read.ts/machine-config-poll.ts/talos-errors.ts were\n * split out of talos-machine-config.ts before it. Only `import type` comes back from kubeconfig.ts,\n * so there is no runtime cycle between the two files.\n */\nimport type { Connection } from 'alchemy/Kubernetes/Connection';\nimport type { KubeconfigAttributes, KubeconfigProps } from './kubeconfig.ts';\nimport { kubeconfigMetadata, sha256 } from './values.ts';\n\nconst generation = (meta: {\n endpoint: string;\n caFingerprint: string;\n clientFingerprint: string;\n context: string;\n}) => sha256(`${meta.context}\\n${meta.endpoint}\\n${meta.caFingerprint}\\n${meta.clientFingerprint}`);\n\n/**\n * ⛔ I2 FIX (LAND red team, 2026-09-26) — NEVER LEAVE `path` UNDEFINED. An undefined `path` here\n * made the stock `Kubernetes.KubeConfigAdapter` fall back to `$KUBECONFIG`/`~/.kube/config`\n * (alchemy `Kubernetes/internal/kubeconfig.ts`'s `resolveKubeConfigPath`, wired in\n * `BuiltinAdapters.ts`) — exactly the un-vaulted, possibly-stale-context exposure this whole\n * family exists to remove. A consumer wiring `Kubernetes.*` to `kube.connection` (this\n * attribute's own doc invites exactly that) would silently connect through whatever\n * `admin@<cluster>` context happens to be on the operator's machine. `Kubernetes.ClusterAdapter`\n * is not yet wired to `mintKubeconfig` (kubeconfig.ts's own header) — no real path exists for\n * this connection to use — so it must fail LOUDLY instead of silently succeeding against a\n * stranger's cluster. A path that can never resolve does that: `resolveKubeContext` fails at\n * `fs.readFileString` naming this exact sentinel, instead of reading whatever real file happens\n * to be on `$KUBECONFIG`.\n */\nconst UNWIRED_KUBECONFIG_PATH =\n '/talos-first-boot-unwired/wire-Kubernetes.ClusterAdapter-to-mintKubeconfig';\n\nconst toConnection = (props: KubeconfigProps): Connection => ({\n auth: { context: props.context, kind: 'kubeconfig', path: UNWIRED_KUBECONFIG_PATH },\n});\n\n/** Parse `raw` kubeconfig YAML into public, persistable attributes, or `undefined` if it fails to. */\nexport const buildAttrs = (\n raw: string,\n props: KubeconfigProps,\n): KubeconfigAttributes | undefined => {\n const meta = kubeconfigMetadata(raw, props.context);\n if (meta === undefined) return undefined;\n return {\n certificateAuthorityFingerprint: meta.caFingerprint,\n clientCertificateFingerprint: meta.clientFingerprint,\n connection: toConnection(props),\n context: props.context,\n credentialGeneration: generation({ ...meta, context: props.context }),\n endpoint: meta.endpoint,\n };\n};\n",
10
- "/**\n * One `talosctl` invocation — stdout/stderr captured, secrets never echoed.\n *\n * ★ SHELL OUT LIKE ALCHEMY'S DOCKER PROVIDER (ChildProcessSpawner), NOT A SECOND SDK. Talos speaks\n * gRPC; the published, stable surface for operators is `talosctl`. No Talos npm package is added.\n *\n * ⚠️ REASONED FROM docs.siderolabs.com/talos/v1.13/reference/cli — nothing here was measured on a\n * live cluster in this session.\n *\n * ⛔ DO NOT LOG STDOUT ON FAILURE. `talosctl kubeconfig` and error paths have been observed in the\n * wild to include credential material; stderr is the safe diagnostic channel.\n */\nimport * as Effect from 'effect/Effect';\nimport * as Stream from 'effect/Stream';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\n\nexport class TalosError extends Error {\n constructor(\n readonly command: string,\n readonly exitCode: number,\n detail: string,\n ) {\n super(`talosctl ${command} -> ${String(exitCode)}: ${detail}`);\n this.name = 'TalosError';\n }\n}\n\nexport type TalosRunOptions = {\n readonly talosconfigPath: string;\n readonly nodes?: readonly string[];\n readonly endpoints?: readonly string[];\n /**\n * `-i/--insecure` — a maintenance-mode node has no established PKI yet. Used by the CREATE apply\n * (resource.ts's own header) and by talos-machine-config.ts's maintenance-mode probe (fix-first\n * #1, PR 307 red team): `--talosconfig` is still passed alongside it, matching the CREATE path,\n * since insecure mode ignores the file's certs rather than requiring their absence.\n */\n readonly insecure?: boolean;\n};\n\n/** Run `talosctl <args…>`. Returns trimmed stdout, or '' when empty. */\nexport const talosctl = (args: readonly string[], options: TalosRunOptions) =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n const argv = [\n ...args,\n '--talosconfig',\n options.talosconfigPath,\n ...(options.nodes === undefined ? [] : ['--nodes', options.nodes.join(',')]),\n ...(options.endpoints === undefined ? [] : ['--endpoints', options.endpoints.join(',')]),\n ...(options.insecure === true ? ['--insecure'] : []),\n ];\n const result = yield* ChildProcess.make('talosctl', argv, {\n detached: false,\n extendEnv: true,\n stderr: 'pipe',\n stdin: 'ignore',\n stdout: 'pipe',\n }).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n stdout: child.stdout.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n\n const command = args.join(' ');\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new TalosError(command, result.exitCode, result.stderr.slice(0, 300)),\n );\n }\n return result.stdout;\n });\n\n/** Like `talosctl`, but exit code 1 with \"already\" in stderr is treated as success. */\nexport const talosctlOrAlready = (args: readonly string[], options: TalosRunOptions) =>\n talosctl(args, options).pipe(\n Effect.catchIf(\n (cause): cause is TalosError =>\n cause instanceof TalosError &&\n cause.exitCode !== 0 &&\n /already|exists|bootstrapped/i.test(cause.message),\n () => Effect.succeed(''),\n ),\n );\n",
5
+ "/**\n * `Kubernetes.ClusterAdapter` kind `talos-openbao`.\n *\n * Reads `mount/key` from OpenBao at connect time (`credentials.ts`'s `readKvValue`, which\n * shells to `bao` with BAO_ADDR/BAO_TOKEN) and returns a `ClusterTransport`.\n * ⛔ NOTHING IS WRITTEN TO DISK. ⛔ THE PERSISTED CONNECTION IS `{ kind, uid }` ONLY.\n * alchemy `Kubernetes/Connection.ts` (v2.0.0-beta.79, lines 12-14) stores the Connection on\n * every workload's attributes, so the upstream `client-cert` kind would put the admin PEM in\n * the shared state store. The stock `kubeconfig` kind is also refused: an empty path falls\n * back to `$KUBECONFIG`.\n * ⛔ mount/key/context LIVE IN THE ADAPTER'S CONFIGURATION, NOT IN THE AUTH BLOCK. Upstream\n * compares clusters by the auth block (`internal/workload.ts:91-96` `connectionIdentity`) and\n * HelmChart/Manifest answer `replace` when it changes (`HelmChart.ts:248-258`,\n * `Manifest.ts:194-209`); a replace creates first, then cleanup deletes the SAME-named objects.\n * Renaming a vault key would silently delete Cilium, External Secrets and Gatekeeper.\n * ⛔ THE IDENTITY RULE: THE AUTH BLOCK NAMES THE PHYSICAL CLUSTER. `uid` is the kube-system\n * Namespace `metadata.uid` (public, stable across CA rotation). read/update/delete all\n * reconnect from the SAVED auth block (`Manifest.ts:214` and `:267`, `HelmChart.ts:322` and\n * `:335`, via `connectionOfOutput`, `internal/workload.ts:104-108`). A cluster NAME resolved\n * through today's MUTABLE config would let a repointed `c1` PATCH one cluster and DELETE on\n * another (reproduced through ManifestProvider). So the auth block carries the uid and NOTHING\n * else: the config entry is looked up BY uid (no probing walk), `connect` fails closed BEFORE\n * any vault read when the uid is absent or the row is legacy (`auth.cluster`), then GETs\n * kube-system and compares before returning a transport. Missing, unreadable, unknown or\n * different uid is a typed error — never `ClusterNotFoundError` (except a `retired` entry's\n * absent key), which upstream turns into a silent no-op. Cost: one extra GET per connect.\n * ⛔ BOOTSTRAP-THEN-PIN. A brand-new cluster has no uid until it exists, and an Output uid is\n * forbidden (`talosOpenBaoConnection`). So: (1) the first deploy creates the cluster and\n * `Talos.ClusterIdentity` (which reads and outputs the uid) with NO workloads; (2) the operator\n * pins that printed uid literal in this adapter's config; (3) workloads deploy afterwards with\n * `talosOpenBaoConnection(<that literal>)`. A uid that is not pinned is refused at connect.\n * ⚠️ A REAL MOVE IS NOT AN AUTOMATIC REPLACE. `Talos.ClusterIdentity` refuses a changed uid\n * (`TalosClusterMoved`); a move is a NEW identity resource per physical cluster, so the old\n * rows keep their old uid and their cleanup reaches only the old cluster.\n * ⛔ ONE 10 s DEADLINE covers the vault read AND the uid GET (`withConnectDeadline`): a hung `bao`\n * or silent apiserver fails with `TalosOpenBaoConnectTimeout` and the `bao` child is killed.\n * ⚠️ The in-flight HTTPS GET is NOT aborted: upstream `readObject` takes no signal\n * (`internal/client.ts:75`), so the socket lives until the OS gives up. Left for the upstream ask.\n *\n * USAGE RULES (upstream behaviour this adapter cannot fix; full text in\n * `docs/talos-openbao-adapter.md`):\n * 1. Move a workload to another cluster ONLY by new logical IDs (destroy + create), never by\n * changing its connection in place.\n * 2. Manage namespaces as separate `Manifest`s, never HelmChart `createNamespace`.\n * 3. Never rename a HelmChart `releaseName` in place.\n *\n * Walked against alchemy 2.0.0-beta.79 `ClusterAdapter.ts` / `BuiltinAdapters.ts` and the OpenBao\n * v2.6.2 absence string in `isVaultKeyAbsent`. Fake `bao` and fake apiserver only.\n */\nimport {\n ClusterAdapter,\n type ClusterAdapterService,\n ClusterNotFoundError,\n type ClusterTransport,\n} from 'alchemy/Kubernetes/ClusterAdapter';\nimport type { Connection } from 'alchemy/Kubernetes/Connection';\nimport type * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport type * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\nimport {\n type TalosClusterIdentityMismatch,\n TalosClusterIdentityMissing,\n type TalosClusterIdentityTimeout,\n type TalosClusterIdentityUnreadable,\n type TalosKubeconfigUnreadable,\n TalosOpenBaoAmbiguousUid,\n TalosOpenBaoAuthKind,\n type TalosOpenBaoConnectTimeout,\n TalosOpenBaoLegacyAuth,\n TalosOpenBaoUnknownCluster,\n TalosUidNotLiteral,\n type TalosVaultKeyMissing,\n} from './cluster-adapter-errors.ts';\nimport { assertClusterUid } from './cluster-identity.ts';\nimport {\n CONNECT_TIMEOUT,\n type TalosOpenBaoCluster,\n openTransport,\n withConnectDeadline,\n} from './cluster-transport.ts';\n\nexport {\n TalosClusterIdentityMismatch,\n TalosClusterIdentityMissing,\n TalosClusterIdentityTimeout,\n TalosClusterIdentityUnreadable,\n TalosClusterMoved,\n TalosKubeconfigUnreadable,\n TalosOpenBaoAmbiguousUid,\n TalosOpenBaoAuthKind,\n TalosOpenBaoConnectTimeout,\n TalosOpenBaoLegacyAuth,\n TalosOpenBaoUnknownCluster,\n TalosUidNotLiteral,\n TalosVaultKeyMissing,\n} from './cluster-adapter-errors.ts';\nexport { type TalosOpenBaoCluster, talosOpenBaoCluster } from './cluster-transport.ts';\n\ndeclare module 'alchemy/Kubernetes/Connection' {\n interface AuthRegistry {\n /**\n * Admin kubeconfig in OpenBao KV, read when a workload connects. Contributed by\n * {@link TalosOpenBaoAdapter}, which holds the mount, key and context.\n */\n 'talos-openbao': {\n /**\n * The cluster's kube-system `metadata.uid`: the ONLY identity, a LITERAL string known at\n * plan time (never an Output, see {@link talosOpenBaoConnection}). A row saved before it\n * existed has none at runtime and is refused at connect.\n */\n uid: string;\n };\n }\n}\n\n/**\n * ⛔ KEYED BY ALIAS, BUT THE ALIAS IS NEVER PERSISTED OR LOOKED UP BY. `connect` finds the entry\n * whose pinned `uid` equals the saved auth block's, so renaming an alias changes nothing upstream\n * hashes. Unknown uid is {@link TalosOpenBaoUnknownCluster}: refused, not another cluster's key.\n */\nexport type TalosOpenBaoConfig = Readonly<Record<string, TalosOpenBaoCluster>>;\n\n/** A `Connection` narrowed to this kind, so a PEM-bearing connection cannot be stored by type. */\nexport type TalosOpenBaoConnection = Connection & {\n readonly auth: { readonly kind: 'talos-openbao'; readonly uid: string };\n};\n\n/**\n * Serializable connection: kind and uid. No alias, vault path, endpoint, CA or cert.\n * ⛔ THE UID MUST BE A LITERAL. An Output (a resource attribute such as `Talos.ClusterIdentity`'s)\n * is unresolved at plan time, so `isResolved(news)` is false, upstream plans an UPDATE (Plan.ts)\n * and reconcile replays the OLD cluster's `previousObjects` as deletes on the NEW cluster\n * (reproduced: DELETE on B). Take the uid from the pinned adapter entry: a changed literal is a\n * changed auth block, which upstream answers with `replace`. Anything else throws\n * {@link TalosUidNotLiteral} while the stack is being declared.\n */\nexport const talosOpenBaoConnection = (uid: string): TalosOpenBaoConnection => {\n if (typeof uid !== 'string' || uid === '') throw new TalosUidNotLiteral({});\n return { auth: { kind: 'talos-openbao', uid } };\n};\n\n/**\n * Resolve one `talos-openbao` connection to a transport. Requires `ChildProcessSpawner`\n * because the vault read shells to `bao`, and reaches the apiserver once for the identity check.\n *\n * ⚠️ A key the vault reports absent is `ClusterNotFoundError` ONLY for a cluster configured\n * `retired: true` (upstream `read`/`delete` treat that as \"everything in-cluster is already\n * gone\", so tearing down a destroyed cluster is not stuck). Otherwise it is the typed\n * `TalosVaultKeyMissing`. Neither message names document bytes.\n */\nexport const connectTalosOpenBao = (\n configs: TalosOpenBaoConfig,\n connection: Connection,\n timeout: Duration.Duration = CONNECT_TIMEOUT,\n): Effect.Effect<\n ClusterTransport,\n | TalosOpenBaoAuthKind\n | TalosOpenBaoUnknownCluster\n | TalosOpenBaoAmbiguousUid\n | TalosOpenBaoLegacyAuth\n | TalosClusterIdentityMissing\n | TalosClusterIdentityMismatch\n | TalosClusterIdentityUnreadable\n | TalosClusterIdentityTimeout\n | TalosOpenBaoConnectTimeout\n | TalosVaultKeyMissing\n | ClusterNotFoundError\n | TalosKubeconfigUnreadable\n | Error,\n ChildProcessSpawner.ChildProcessSpawner\n> =>\n Effect.gen(function* () {\n // ⛔ FAIL CLOSED BEFORE ANY DESTRUCTURING: a saved row missing its whole connection, or just\n // its auth block, names no physical cluster — a typed refusal, never a raw TypeError.\n if (connection === undefined || connection === null) {\n return yield* Effect.fail(new TalosClusterIdentityMissing({}));\n }\n const { auth } = connection;\n if (auth === undefined || auth === null) {\n return yield* Effect.fail(new TalosClusterIdentityMissing({}));\n }\n if (auth.kind !== 'talos-openbao') {\n return yield* Effect.fail(new TalosOpenBaoAuthKind({ kind: auth.kind }));\n }\n // ⛔ Before the vault is touched. A row saved with an alias is refused even if it also has a\n // uid: no silent migration, the saved state is edited deliberately (the error says how).\n if (Object.hasOwn(auth, 'cluster')) {\n return yield* Effect.fail(new TalosOpenBaoLegacyAuth({}));\n }\n const { uid } = auth;\n if (typeof uid !== 'string' || uid === '') {\n return yield* Effect.fail(new TalosClusterIdentityMissing({}));\n }\n const matches = Object.entries(configs).filter(([, entry]) => entry.uid === uid);\n const [match] = matches;\n if (match === undefined) {\n return yield* Effect.fail(\n new TalosOpenBaoUnknownCluster({\n known: Object.values(configs).map((entry) => entry.uid),\n uid,\n }),\n );\n }\n // ⛔ Two entries claiming one uid is a configuration error: refuse, never pick one.\n if (matches.length > 1) {\n return yield* Effect.fail(\n new TalosOpenBaoAmbiguousUid({ aliases: matches.map(([alias]) => alias), uid }),\n );\n }\n const [alias, config] = match;\n // ⛔ A retired pin means the cluster is gone: no vault read, so destroying its rows completes.\n if (config.retired === true) {\n return yield* Effect.fail(\n new ClusterNotFoundError({ message: `talos-openbao cluster '${alias}' is retired` }),\n );\n }\n // ⛔ One deadline over the vault read AND the uid GET (`withConnectDeadline`).\n return yield* withConnectDeadline(\n alias,\n Effect.gen(function* () {\n const transport = yield* openTransport(config);\n yield* assertClusterUid(alias, uid, transport);\n return transport;\n }),\n timeout,\n );\n });\n\n/**\n * Register kind `talos-openbao`. Merge with `Kubernetes.providers()`:\n * `Layer.mergeAll(Kubernetes.providers(), TalosOpenBaoAdapter({ c1: talosOpenBaoCluster(kc1) }))`\n * where `kc1` is the props object handed to `Talos.Kubeconfig`.\n */\nexport const TalosOpenBaoAdapter = (\n config: TalosOpenBaoConfig,\n): Layer.Layer<ClusterAdapterService, never, ChildProcessSpawner.ChildProcessSpawner> =>\n Layer.effect(\n ClusterAdapter('talos-openbao'),\n Effect.gen(function* () {\n const context = yield* Effect.context<ChildProcessSpawner.ChildProcessSpawner>();\n const service: ClusterAdapterService = {\n kind: 'Kubernetes.ClusterAdapter',\n connect: (connection) =>\n connectTalosOpenBao(config, connection).pipe(Effect.provideContext(context)),\n };\n return service;\n }),\n );\n",
6
+ "/**\n * Typed failures of the `talos-openbao` adapter — split out of cluster-adapter.ts to keep each\n * class's own header out of that file's 250-line budget. No message names document bytes.\n */\nimport * as Data from 'effect/Data';\n\n/** The connection's uid matches no adapter entry. Uids are public. */\nexport class TalosOpenBaoUnknownCluster extends Data.TaggedError('TalosOpenBaoUnknownCluster')<{\n readonly uid: string;\n readonly known: readonly string[];\n}> {\n override get message(): string {\n return (\n `talos-openbao adapter has no entry pinned to cluster uid ${this.uid} ` +\n `(configured uids: ${this.known.join(', ') || 'none'}). Refused rather than reading ` +\n \"another cluster's kubeconfig. If the cluster was retired, keep its entry with \" +\n '`retired: true` and its uid until its rows are destroyed.'\n );\n }\n}\n\n/** Two adapter entries pin the same uid, so which vault key to read is ambiguous. */\nexport class TalosOpenBaoAmbiguousUid extends Data.TaggedError('TalosOpenBaoAmbiguousUid')<{\n readonly uid: string;\n readonly aliases: readonly string[];\n}> {\n override get message(): string {\n return (\n `talos-openbao adapter entries ${this.aliases.join(', ')} are all pinned to uid ` +\n `${this.uid}. Refused instead of picking one: a uid names exactly one entry.`\n );\n }\n}\n\n/** The saved auth block still carries the alias an earlier build of this branch persisted. */\nexport class TalosOpenBaoLegacyAuth extends Data.TaggedError('TalosOpenBaoLegacyAuth')<{\n readonly _?: never;\n}> {\n override get message(): string {\n return (\n 'talos-openbao connection carries a legacy `cluster` alias in its auth block. Refused ' +\n 'before any vault read or request, with no silent migration (old and new auth differ, so ' +\n 'upstream would PATCH then DELETE the same object). Remedy: edit the saved state ONCE so ' +\n \"each such row's `connection.auth` is `{ kind: 'talos-openbao', uid }` (drop `cluster`), \" +\n 'then redeploy.'\n );\n }\n}\n\n/** `Talos.ClusterIdentity` read a different uid than the one it published. Never an update. */\nexport class TalosClusterMoved extends Data.TaggedError('TalosClusterMoved')<{\n readonly cluster: string;\n readonly saved: string;\n readonly live: string;\n}> {\n override get message(): string {\n return (\n `Talos.ClusterIdentity '${this.cluster}' published uid ${this.saved} but the vault key now ` +\n `answers as ${this.live}. Refused, not updated: an update cannot become a replace for the ` +\n 'workloads downstream, so the new cluster would be force-applied and the old one orphaned. ' +\n 'A move is explicit: declare a NEW Talos.ClusterIdentity for the new cluster and leave this ' +\n 'one pointing at the old cluster until its workloads are destroyed.'\n );\n }\n}\n\n/** `bao kv get` reported the key unwritten. The message names `mount/key` and no document bytes. */\nexport class TalosVaultKeyMissing extends Data.TaggedError('TalosVaultKeyMissing')<{\n readonly mount: string;\n readonly key: string;\n}> {\n override get message(): string {\n return (\n `${this.mount}/${this.key}: OpenBao has no value at this key. Talos.Kubeconfig writes it ` +\n 'once at bring-up. Connect refused instead of reading a kubeconfig from disk.'\n );\n }\n}\n\n/** Vault bytes exist but are not a kubeconfig for the pinned context. The document is not echoed. */\nexport class TalosKubeconfigUnreadable extends Data.TaggedError('TalosKubeconfigUnreadable')<{\n readonly mount: string;\n readonly key: string;\n readonly context: string;\n}> {\n override get message(): string {\n return (\n `${this.mount}/${this.key}: OpenBao kubeconfig does not parse for context ${this.context}. ` +\n 'The document stayed in the vault. Connect wrote nothing to disk and nothing to state.'\n );\n }\n}\n\n/** The layer was asked to connect a different auth kind. */\nexport class TalosOpenBaoAuthKind extends Data.TaggedError('TalosOpenBaoAuthKind')<{\n readonly kind: string;\n}> {\n override get message(): string {\n return (\n `talos-openbao adapter received auth kind '${this.kind}'. This adapter only connects ` +\n '`talos-openbao`.'\n );\n }\n}\n\n/** The saved auth block carries no `uid`, so nothing says WHICH physical cluster it meant. */\nexport class TalosClusterIdentityMissing extends Data.TaggedError('TalosClusterIdentityMissing')<{\n readonly _?: never;\n}> {\n override get message(): string {\n return (\n 'talos-openbao connection carries no uid, so it cannot say which physical cluster it ' +\n 'targets. Refused before any vault read or request: pin the uid ' +\n 'printed by `Talos.ClusterIdentity` as a literal in `TalosOpenBaoAdapter` and build ' +\n 'workloads from `talosOpenBaoConnection(<that literal>)`.'\n );\n }\n}\n\n/** The cluster that answered is not the one the saved auth block named. Uids are public. */\nexport class TalosClusterIdentityMismatch extends Data.TaggedError('TalosClusterIdentityMismatch')<{\n readonly cluster: string;\n readonly expected: string;\n readonly got: string;\n}> {\n override get message(): string {\n return (\n `talos-openbao cluster '${this.cluster}' answered as kube-system uid ${this.got}, but the ` +\n `saved connection expects ${this.expected}. Refused before any apply or delete: the name ` +\n 'now resolves to a different physical cluster. If the original cluster is gone for good, ' +\n 'remove its rows from state deliberately.'\n );\n }\n}\n\n/** `GET /api/v1/namespaces/kube-system` answered without a usable `metadata.uid`. */\nexport class TalosClusterIdentityUnreadable extends Data.TaggedError(\n 'TalosClusterIdentityUnreadable',\n)<{\n readonly cluster: string;\n}> {\n override get message(): string {\n return (\n `talos-openbao cluster '${this.cluster}': kube-system has no readable metadata.uid. ` +\n 'Refused rather than assuming the cluster is the expected one.'\n );\n }\n}\n\n/** The kube-system GET got no answer in time: a silent apiserver must not hang connect or plan. */\nexport class TalosClusterIdentityTimeout extends Data.TaggedError('TalosClusterIdentityTimeout')<{\n readonly cluster: string;\n readonly seconds: number;\n}> {\n override get message(): string {\n return (\n `talos-openbao cluster '${this.cluster}': no answer to the kube-system uid read within ` +\n `${this.seconds}s. Refused (failed closed) rather than waiting on a silent apiserver.`\n );\n }\n}\n\n/**\n * The whole connect path (vault read, parse, kube-system uid read) did not finish in time. One\n * deadline covers `bao` and the apiserver together: a hung `bao` or a silent apiserver must not\n * hang connect or a plan. The `bao` child is killed when the deadline interrupts the read.\n */\nexport class TalosOpenBaoConnectTimeout extends Data.TaggedError('TalosOpenBaoConnectTimeout')<{\n readonly cluster: string;\n readonly seconds: number;\n}> {\n override get message(): string {\n return (\n `talos-openbao cluster '${this.cluster}': vault read and identity check did not finish ` +\n `within ${this.seconds}s. Refused (failed closed); the bao child was killed.`\n );\n }\n}\n\n/** A connection was built from a uid that is not a plain string known at plan time. */\nexport class TalosUidNotLiteral extends Data.TaggedError('TalosUidNotLiteral')<{\n readonly _?: never;\n}> {\n override get message(): string {\n return (\n 'talos-openbao connection uid must be a literal string taken from the adapter config, not ' +\n 'an Output (for example a Talos.ClusterIdentity attribute). An unresolved uid hides a ' +\n \"cluster change from the plan: upstream would plan an UPDATE and reconcile the old cluster's \" +\n 'objects on the new one. Pin the uid in `TalosOpenBaoAdapter` and take it from there.'\n );\n }\n}\n",
7
+ "/**\n * Which PHYSICAL cluster answers — the kube-system Namespace's `metadata.uid`.\n *\n * ★ WHY THE UID. It is public, assigned once at cluster creation and stable across CA and\n * admin-cert rotation (a CA fingerprint is not: rotation would read as \"a different cluster\").\n * Every cluster has the namespace, and the admin kubeconfig can read it.\n * ★ The GET goes through alchemy's own `readObject` (`Kubernetes/internal/client.ts`, reached\n * through the package's `./*` export) so TLS, CA and client-cert handling stay upstream's.\n */\nimport type { ClusterTransport } from 'alchemy/Kubernetes/ClusterAdapter';\nimport { readObject } from 'alchemy/Kubernetes/internal/client';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport {\n TalosClusterIdentityMismatch,\n TalosClusterIdentityTimeout,\n TalosClusterIdentityUnreadable,\n} from './cluster-adapter-errors.ts';\n\nconst KUBE_SYSTEM = { apiVersion: 'v1', kind: 'Namespace', name: 'kube-system' } as const;\n\n/**\n * ⛔ upstream `readObject` (`internal/client.ts`) sets no request timeout, so a silent apiserver\n * would hang connect and every plan. Bounded here; the failure is typed and closed.\n * ⛔ SHORTER THAN `CONNECT_TIMEOUT` (10 s, cluster-transport.ts): the outer deadline wraps the vault\n * read AND this uid GET together, so an equal inner deadline could never fire first and\n * `TalosClusterIdentityTimeout` was unreachable through `connectTalosOpenBao` (red team, PR 355).\n * A silent apiserver now fails with the identity timeout while a slow `bao` still gets the full\n * outer budget.\n */\nexport const UID_READ_TIMEOUT = Duration.seconds(5);\n\n/** The cluster's kube-system uid. Request failures propagate: nothing here fails open. */\nexport const readClusterUid = (\n cluster: string,\n transport: ClusterTransport,\n timeout: Duration.Duration = UID_READ_TIMEOUT,\n) =>\n readObject({ object: KUBE_SYSTEM, transport }).pipe(\n Effect.timeoutOrElse({\n duration: timeout,\n orElse: () =>\n Effect.fail(\n new TalosClusterIdentityTimeout({ cluster, seconds: Duration.toSeconds(timeout) }),\n ),\n }),\n Effect.flatMap((body) => {\n const uid = (body as { metadata?: { uid?: unknown } } | undefined)?.metadata?.uid;\n return typeof uid === 'string' && uid !== ''\n ? Effect.succeed(uid)\n : Effect.fail(new TalosClusterIdentityUnreadable({ cluster }));\n }),\n );\n\n/** Succeeds only when the answering cluster is the one `expected` names. */\nexport const assertClusterUid = (cluster: string, expected: string, transport: ClusterTransport) =>\n readClusterUid(cluster, transport).pipe(\n Effect.flatMap((got) =>\n got === expected\n ? Effect.void\n : Effect.fail(new TalosClusterIdentityMismatch({ cluster, expected, got })),\n ),\n );\n",
8
+ "/**\n * One cluster's vault location and the in-memory read of its admin kubeconfig, shared by the\n * `talos-openbao` adapter (which then verifies identity) and `Talos.ClusterIdentity` (which\n * reads the uid the adapter will later demand).\n */\nimport type { ClusterTransport } from 'alchemy/Kubernetes/ClusterAdapter';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport {\n TalosKubeconfigUnreadable,\n TalosOpenBaoConnectTimeout,\n TalosVaultKeyMissing,\n} from './cluster-adapter-errors.ts';\nimport { DEFAULT_KUBECONFIG_KEY, isVaultKeyAbsent, readKvValue } from './credentials.ts';\nimport { kubeconfigTransport } from './kubeconfig-doc.ts';\nimport type { KubeconfigProps } from './kubeconfig.ts';\n\n/** Where one cluster's admin kubeconfig lives in the vault. Configuration; never persisted. */\nexport type TalosVaultLocation = {\n /** OpenBao KV mount, e.g. `talos-c1`. */\n readonly mount: string;\n /** Path under the mount. `Talos.Kubeconfig` writes `kubeconfig` unless `kubeconfigKey` is set. */\n readonly key: string;\n /** Context name inside the kubeconfig. Not secret. */\n readonly context: string;\n};\n\n/**\n * One adapter entry: a vault location PINNED to the physical cluster it must answer as.\n * ⛔ `uid` is the kube-system `metadata.uid`. The persisted auth block carries only this, and\n * connect looks the entry up BY it, so renaming the alias, vault key, mount or context changes\n * nothing upstream hashes (`internal/workload.ts:91-96` `connectionIdentity`). Connect still\n * proves the answering cluster has this uid before it returns a transport.\n */\nexport type TalosOpenBaoCluster = TalosVaultLocation & {\n readonly uid: string;\n /**\n * ⛔ ONLY `true` MAKES THIS UID MEAN \"THE CLUSTER IS GONE\": connect answers `ClusterNotFoundError`\n * (upstream read/delete treat it as \"everything in-cluster is already gone\") WITHOUT a vault\n * read, so destroying a dead cluster's rows completes. Otherwise an absent key is the loud\n * `TalosVaultKeyMissing`: a typo in mount/key must not make `destroy` a silent no-op.\n */\n readonly retired?: boolean;\n};\n\n/**\n * ★ ONE SOURCE OF TRUTH FOR mount/key/context: build the location from the SAME props the\n * `Talos.Kubeconfig` resource writes with (`target.mount`, `kubeconfigKey`, `context`), so the\n * writer and the reader cannot disagree.\n */\nexport const talosVaultLocation = (\n props: Pick<KubeconfigProps, 'context' | 'kubeconfigKey' | 'target'>,\n): TalosVaultLocation => ({\n context: props.context,\n key: props.kubeconfigKey ?? DEFAULT_KUBECONFIG_KEY,\n mount: props.target.mount,\n});\n\n/** An adapter entry: {@link talosVaultLocation} plus the uid it is pinned to. */\nexport const talosOpenBaoCluster = (\n props: Pick<KubeconfigProps, 'context' | 'kubeconfigKey' | 'target'>,\n pin: { readonly uid: string; readonly retired?: boolean },\n): TalosOpenBaoCluster => ({\n ...talosVaultLocation(props),\n uid: pin.uid,\n ...(pin.retired === true ? { retired: true } : {}),\n});\n\n/**\n * ⛔ ONE DEADLINE FOR THE WHOLE CONNECT PATH. `bao kv get` has no timeout of its own, and the\n * uid GET's bound (`cluster-identity.ts`) only starts after the vault read returns, so a hung\n * `bao` hung connect and every plan. Interrupting the effect closes the spawn scope, which\n * signals the child's process group (`NodeChildProcessSpawner` `terminateProcessGroup`).\n */\nexport const CONNECT_TIMEOUT = Duration.seconds(10);\n\nexport const withConnectDeadline = <A, E, R>(\n cluster: string,\n effect: Effect.Effect<A, E, R>,\n timeout: Duration.Duration = CONNECT_TIMEOUT,\n) =>\n effect.pipe(\n Effect.timeoutOrElse({\n duration: timeout,\n orElse: () =>\n Effect.fail(\n new TalosOpenBaoConnectTimeout({ cluster, seconds: Duration.toSeconds(timeout) }),\n ),\n }),\n );\n\n/**\n * Vault read and parse, in memory. ⛔ No identity check here: callers decide what to trust.\n * ⚠️ Only a document that does not parse is `TalosKubeconfigUnreadable`; a parser or runtime\n * failure (a missing global, a broken import) is a defect and propagates as one.\n */\nexport const openTransport = (config: TalosVaultLocation) =>\n Effect.gen(function* () {\n const { context, key, mount } = config;\n const raw = yield* readKvValue(mount, key, ['kubeconfig', 'config']).pipe(\n Effect.mapError((error) =>\n isVaultKeyAbsent(error) ? new TalosVaultKeyMissing({ key, mount }) : error,\n ),\n );\n const material = yield* Effect.sync(() => kubeconfigTransport(raw, context));\n if (material === undefined) {\n return yield* Effect.fail(new TalosKubeconfigUnreadable({ context, key, mount }));\n }\n return { ...material, headers: Effect.succeed({}) } satisfies ClusterTransport;\n });\n",
9
+ "/**\n * Talos client material minted from OpenBao, written to a session-temp file whose lifetime the\n * CALLER owns — never this module.\n *\n * ⛔ TALOSCONFIG, MACHINE CONFIG AND secrets.yaml CAN ALL HOLD CLIENT CERTIFICATES AND CLUSTER CA\n * PRIVATE KEYS. Alchemy persists resource attributes WITHOUT encryption — `StateEncoding.ts`\n * tags a `Redacted` value as `{ __redacted__: <plaintext> }` (`REDACTED_MARKER`), it does not\n * encrypt it — and this estate's state store is the shared Cloudflare HTTP state store, not a\n * database anyone forgets is world-legible. None of these three may ever be a prop, an\n * attribute or a log line; see docs/plans/2026-09-26-talos-secrets-flow.md for why the OLD\n * header here (Postgres, `{\"@redacted\": …}`) was wrong on both counts — the RULE survives the\n * correction either way.\n *\n * ★ MODELED ON proxmox/credentials.ts + proxmox/mint.ts: mint at call time, use the material, drop\n * it when the scope ends. The difference is Talos wants a FILE (`--talosconfig` / `-f`), so\n * minting here writes a temp path and registers its own delete finalizer instead of just\n * building a header.\n *\n * ⛔ C1 FIX (2026-09-26, K-A3) — THE SHIPPED `mintTalosconfig` DELETED ITS OWN FILE BEFORE ANY\n * CALLER COULD USE IT. It wrapped its whole body in `Effect.scoped(...)` and registered the\n * delete finalizer inside that same scope, so the scope — and the file — closed the instant\n * `mintTalosconfig` RETURNED, before the caller ever got to pass the path to `talosctl`. Fixed\n * by `Effect.acquireRelease`: it still deletes on every exit path, but contributes `Scope.Scope`\n * to this module's own return type instead of discharging it, so the file survives until\n * whichever `Effect.scoped(...)` the CALLER wraps around its own use of the path (every\n * talos-*.ts resource file wraps its `read`/`reconcile` bodies for exactly this reason now).\n *\n * ⚠️ REASONED FROM THE PUBLISHED TALOS WORKFLOW, NOT MEASURED ON THIS ESTATE. There is no Talos\n * cluster here yet; KV paths below follow the `mount/<key>` shape O1 (the secrets-flow doc)\n * assigns, and `bao kv get` inserts the KV-v2 `data/` API segment itself — a key already\n * prefixed `data/` reads `<mount>/data/data/<key>`, which the OLD default did.\n */\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport type * as Scope from 'effect/Scope';\nimport * as Stream from 'effect/Stream';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\nimport { baoEnv } from './bao-env.ts';\nimport { resolveBao } from './talosctl-binary.ts';\nimport { mintKvTempFile } from './mint-temp-file.ts';\n\nexport { mintKvTempFile } from './mint-temp-file.ts';\n\n/** Where credentials come from. HomeFlare-specific mount names live in the stack, not here. */\nexport type TalosTarget = {\n /** OpenBao KV mount holding Talos material, e.g. `talos-c1`. */\n readonly mount: string;\n /** Logical cluster name — safe to persist and log. */\n readonly cluster: string;\n /**\n * Path under the mount for the talosconfig YAML. Default `'talosconfig'` — FIXED 2026-09-26;\n * the shipped default was `'data/talosconfig'`, which `bao kv get` turned into\n * `<mount>/data/data/talosconfig` (see the ⚠️ above). It failed closed rather than reading an\n * empty talosconfig, but it would have blocked the very first deploy.\n */\n readonly talosconfigKey?: string;\n};\n\nexport type TalosCredential = {\n /** Absolute path to a temp talosconfig. ⛔ NEVER PERSIST, NEVER LOG CONTENTS. */\n readonly talosconfigPath: string;\n};\n\nconst DEFAULT_TALOSCONFIG_KEY = 'talosconfig';\n\n/**\n * Default OpenBao KV path (under `target.mount`) for the admin kubeconfig `Talos.Kubeconfig`\n * writes once at cluster bring-up. See kubeconfig.ts's own header (K-talos-first-boot, 2026-09-26)\n * and docs/plans/2026-09-26-talos-secrets-flow.md's O1 key list.\n */\nexport const DEFAULT_KUBECONFIG_KEY = 'kubeconfig';\n\n/**\n * Read one OpenBao KV-v2 value and return the first of `fields` that is a non-empty string.\n *\n * ★ THE ONE PLACE THIS PACKAGE SHELLS TO `bao` — talosconfig, per-node machine config and any\n * future KV-backed Talos material (secrets.yaml, ceph entity keys) all read through this,\n * so there is exactly one spot that must never echo a KV value on failure.\n * ⛔ stderr ONLY ON FAILURE. stdout may hold the very secret this call exists to fetch.\n */\nexport const readKvValue = (\n mount: string,\n key: string,\n fields: readonly string[],\n): Effect.Effect<string, Error, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n // ⛔ `bao` fetches the cluster credentials, so it is resolved and VETTED before any env is built\n // or passed: a fake `bao` in a group/world-writable PATH folder is refused here, never launched.\n const bao = yield* resolveBao();\n const env = baoEnv();\n if (env === undefined) {\n return yield* Effect.fail(\n new Error(\n `bao kv get ${mount}/${key} refused: BAO_ADDR and BAO_TOKEN must both be set. ` +\n \"Without them bao would fall back to a cached login in the operator's home.\",\n ),\n );\n }\n const result = yield* ChildProcess.make(\n bao,\n ['kv', 'get', '-format=json', `${mount}/${key}`],\n // ⛔ NO `detached: false`, AND `forceKillAfter` IS SET (round-4 review). Effect detaches on\n // Unix so `bao` leads its own process group, and the scope finalizer signals the WHOLE group\n // (`NodeChildProcessSpawner`: `kill(-pid)`). With `detached: false` a `bao` that forked a\n // sleeper left the grandchild alive, and without `forceKillAfter` a `bao` that ignores\n // SIGTERM kept connect blocked past its deadline. 1 s after SIGTERM the group gets SIGKILL.\n {\n env,\n extendEnv: false,\n forceKillAfter: Duration.seconds(1),\n stderr: 'pipe',\n stdin: 'ignore',\n stdout: 'pipe',\n },\n ).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n stdout: child.stdout.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new Error(`bao kv get ${mount}/${key} exited ${String(result.exitCode)}: ${result.stderr}`),\n );\n }\n\n // ⛔ A V8 SyntaxError quotes the offending input; this stdout may hold the secret itself.\n let parsed: { data?: { data?: Record<string, unknown> } };\n try {\n parsed = JSON.parse(result.stdout) as typeof parsed;\n } catch {\n return yield* Effect.fail(\n new Error(`bao kv get ${mount}/${key} returned output that is not JSON (not echoed).`),\n );\n }\n const data = parsed.data?.data;\n for (const field of fields) {\n const raw = data?.[field];\n if (typeof raw === 'string' && raw.trim() !== '') return raw;\n }\n return yield* Effect.fail(\n new Error(\n `${mount}/${key} returned no ${fields.join('/')} field. Never store the value itself in ` +\n 'an Alchemy prop or attribute — fix the KV entry, not the caller.',\n ),\n );\n });\n\n/**\n * ★ MEASURED AGAINST OPENBAO v2.6.2 (C1 fix, LAND red team, 2026-09-26 — isolated in-memory\n * dev server): `bao kv get` on an unwritten KV-v2 key exits 2 with stderr exactly\n * `No value found at <mount>/data/<key>`. `readKvValue`'s Error embeds that text. It is the\n * only signal treated as \"not written yet\"; a permission denial or a transport failure is not.\n */\nexport const isVaultKeyAbsent = (error: unknown): boolean =>\n error instanceof Error && /no value found at/i.test(error.message);\n\n/**\n * Mint one talosconfig file for `target`.\n *\n * ⛔ CALLERS MUST WRAP THEIR WHOLE USE OF `credential.talosconfigPath` — not just this call — in\n * `Effect.scoped(...)`. This function's own `Scope.Scope` requirement is what makes that the\n * caller's job instead of a lie this function tells itself; see the header above.\n */\nexport const mintTalosconfig = (\n target: TalosTarget,\n): Effect.Effect<TalosCredential, Error, ChildProcessSpawner.ChildProcessSpawner | Scope.Scope> =>\n readKvValue(target.mount, target.talosconfigKey ?? DEFAULT_TALOSCONFIG_KEY, [\n 'talosconfig',\n 'config',\n ]).pipe(\n Effect.flatMap((raw) => mintKvTempFile(raw, `${target.cluster}-talosconfig`)),\n Effect.map(({ path }): TalosCredential => ({ talosconfigPath: path })),\n );\n\n/**\n * Mint one temp kubeconfig file from the vault copy `Talos.Kubeconfig` writes at bring-up\n * (K-talos-first-boot, 2026-09-26) — the file-shaped counterpart to {@link mintTalosconfig}.\n * `Kubernetes.ClusterAdapter` `talos-openbao` does not use it: connect reads the bytes with\n * {@link readKvValue} and keeps them in memory. This remains for a caller that must hand a\n * path to a process.\n */\nexport const mintKubeconfig = (\n target: TalosTarget,\n key = DEFAULT_KUBECONFIG_KEY,\n): Effect.Effect<\n { readonly path: string },\n Error,\n ChildProcessSpawner.ChildProcessSpawner | Scope.Scope\n> =>\n readKvValue(target.mount, key, ['kubeconfig', 'config']).pipe(\n Effect.flatMap((raw) => mintKvTempFile(raw, `${target.cluster}-kubeconfig`)),\n );\n",
10
+ "/**\n * ⛔ THE CHILD GETS A MINIMAL ENV, NOT `process.env`: `PATH` to find `bao`, the vault address and\n * token, and the optional namespace / CA. `undefined` when BAO_ADDR or BAO_TOKEN is missing —\n * `bao` would then read a cached `~/.vault-token` login and act as whoever last logged in.\n */\nexport const baoEnv = (): Record<string, string> | undefined => {\n const addr = process.env['BAO_ADDR'];\n const token = process.env['BAO_TOKEN'];\n if (addr === undefined || addr === '' || token === undefined || token === '') return undefined;\n const env: Record<string, string> = { BAO_ADDR: addr, BAO_TOKEN: token };\n for (const name of ['PATH', 'BAO_NAMESPACE', 'BAO_CACERT']) {\n const value = process.env[name];\n if (value !== undefined && value !== '') env[name] = value;\n }\n return env;\n};\n",
11
+ "/**\n * Which `talosctl` runs, and whether that file may be trusted with the vault-minted talosconfig.\n * Extracted from talosctl.ts (250-line cap).\n *\n * ⛔ A VETTING REFUSAL IS NOT A TalosError. `TalosError` means a `talosctl` run completed and\n * exited non-zero — the one outcome `Talos.ClusterHealth` may call \"not healthy\", and the one\n * `talosctlOrAlready` pattern-matches. A refused binary never ran, so it is its own class and\n * propagates through both untouched (hunt round 6: it read as `healthy: false`).\n */\nimport { accessSync, constants, lstatSync, realpathSync } from 'node:fs';\nimport { basename, delimiter, dirname, isAbsolute, join } from 'node:path';\nimport * as Effect from 'effect/Effect';\nimport { isTrustedBoundary } from './trust-boundary.ts';\n\n/** `talosctl` on `PATH`. A lane pins another build with {@link TALOSCTL_BINARY_ENV} or `binary`. */\nexport const DEFAULT_TALOSCTL_BINARY = 'talosctl';\n\n/**\n * Executable override, read at call time. The Mac PATH measured 2026-10-05 has v1.13.8; the\n * cluster is v1.14.2. Set this to the v1.14.2 binary. A per-call `binary` option wins.\n */\nexport const TALOSCTL_BINARY_ENV = 'HF_TALOSCTL';\n\n/** `bao` on `PATH` — the OpenBao CLI that fetches the cluster credentials at connect time. */\nexport const DEFAULT_BAO_BINARY = 'bao';\n\n/** `bao` executable override, read at call time and vetted exactly like {@link TALOSCTL_BINARY_ENV}. */\nexport const BAO_BINARY_ENV = 'HF_BAO';\n\nexport class TalosBinaryRefused extends Error {\n readonly command: string;\n readonly binary: string;\n\n constructor(command: string, detail: string, binary = DEFAULT_TALOSCTL_BINARY) {\n super(`${binary} ${command} refused: ${detail}`);\n this.name = 'TalosBinaryRefused';\n this.command = command;\n this.binary = binary;\n }\n}\n\n/**\n * ⛔ THE DEFAULT IS VETTED TOO (hunt round 5): a bare `talosctl` is resolved against `PATH` here\n * (not `Bun.which` — the published dist runs on Node, where that global is missing), symlinks are\n * followed, and the REAL file is vetted, version-checked and executed by absolute path.\n */\nexport const resolveDefault = (binary: string) =>\n Effect.try({\n try: () => {\n for (const entry of (process.env['PATH'] ?? '').split(delimiter)) {\n if (!isAbsolute(entry)) continue;\n try {\n const candidate = join(entry, binary);\n accessSync(candidate, constants.X_OK);\n return realpathSync(candidate);\n } catch {\n // not in this PATH entry — try the next\n }\n }\n throw new Error('not found');\n },\n catch: () => new TalosBinaryRefused('binary check', `${binary} was not found on PATH`, binary),\n });\n\n/**\n * ⛔ EVERY DIRECTORY ON THE CANONICAL PATH must belong to the current user or root and must not be\n * group/world-writable (unless sticky: a sticky directory's entries cannot be renamed by others).\n * Round 5 checked only the immediate parent's mode, so an attacker-owned 0755 parent, or a\n * writable ancestor, could swap the file after the check. Returns the refusal reason, or\n * undefined when the whole chain is trusted.\n */\nconst untrustedAncestor = (file: string, uid: number | undefined): string | undefined => {\n let dir = realpathSync(dirname(file));\n for (;;) {\n const stat = lstatSync(dir);\n // The boundary directory itself is still vetted; only what lies ABOVE it is not (test seam,\n // trust-boundary.seam.ts, which the published tarball does not carry).\n const isBoundary = isTrustedBoundary(dir);\n if (uid !== undefined && stat.uid !== uid && stat.uid !== 0) {\n return `lives under a directory owned by another user (${dir})`;\n }\n const sticky = (stat.mode & 0o1000) !== 0;\n if ((stat.mode & 0o022) !== 0 && !sticky) {\n return `lives in a group- or world-writable directory (${dir})`;\n }\n const up = dirname(dir);\n if (up === dir || isBoundary) return undefined;\n dir = up;\n }\n};\n\n/**\n * ⛔ THE BINARY GETS THE VAULT-MINTED TALOSCONFIG: absolute, owned, not writable, executable, trusted\n * path. ⛔ RETURNS THE CANONICAL PATH (round 7): the override's directory is resolved ONCE\n * (realpath), that path and every ancestor of it are vetted, and the caller must launch exactly\n * the returned path for the version probe AND the credential-bearing call. Vetting the given path\n * and executing it again let a symlinked ancestor be repointed between the two launches. The leaf\n * itself is still lstat'd, so a symlink leaf is refused rather than followed.\n */\nexport const checkBinaryPath = (binary: string, source: string) => {\n const refuse = (why: string) =>\n Effect.fail(new TalosBinaryRefused('binary check', `${source} ${why}`, binary));\n if (!isAbsolute(binary)) return refuse('must be an absolute path');\n return Effect.try({\n try: () => {\n const canonical = join(realpathSync(dirname(binary)), basename(binary));\n const file = lstatSync(canonical);\n const uid = process.getuid?.();\n return { canonical, file, uid, ancestor: untrustedAncestor(canonical, uid) };\n },\n catch: () => new TalosBinaryRefused('binary check', `${source} is not a readable file`, binary),\n }).pipe(\n Effect.flatMap(({ canonical, file, uid, ancestor }) => {\n // ★ lstat, not stat: a symlink can be re-pointed by whoever owns the link, so none is accepted.\n if (file.isSymbolicLink()) return refuse('must not be a symlink');\n if (!file.isFile()) return refuse('is not a regular file');\n // ⛔ FAIL CLOSED: with no process uid (a platform lacking getuid) ownership cannot be checked.\n if (uid === undefined) return refuse('cannot be vetted: no process uid to check ownership');\n if (ancestor !== undefined) return refuse(ancestor);\n if (uid !== undefined && file.uid !== uid && file.uid !== 0) {\n return refuse('must be owned by the current user or root');\n }\n if ((file.mode & 0o022) !== 0) return refuse('is group- or world-writable');\n try {\n accessSync(canonical, constants.X_OK);\n } catch {\n return refuse('is not executable');\n }\n return Effect.succeed(canonical);\n }),\n );\n};\n\n/**\n * Resolve and vet the `bao` binary: {@link BAO_BINARY_ENV} wins over `bao` on `PATH`, and either is\n * checked exactly like talosctl (absolute, owned, not writable, executable, not a symlink, every\n * ancestor trusted). Returns the canonical path to launch.\n *\n * ⛔ `bao` FETCHES THE CLUSTER CREDENTIALS (`readKvValue` / `writeKvValue`), so an un-vetted `bao`\n * on a group/world-writable PATH folder (umask 002, the round-10 incident) could answer with an\n * attacker's kubeconfig. The same walk that vets `talosctl` must gate every `bao` launch.\n */\nexport const resolveBao = (): Effect.Effect<string, TalosBinaryRefused> => {\n const override = process.env[BAO_BINARY_ENV]?.trim();\n const requested = override !== undefined && override !== '' ? override : DEFAULT_BAO_BINARY;\n const source = requested === DEFAULT_BAO_BINARY ? 'bao on PATH' : BAO_BINARY_ENV;\n const resolved =\n requested === DEFAULT_BAO_BINARY ? resolveDefault(requested) : Effect.succeed(requested);\n return Effect.flatMap(resolved, (path) => checkBinaryPath(path, source));\n};\n",
12
+ "/**\n * Which directories the talosctl ancestor walk (talosctl-binary.ts) may stop above.\n *\n * ⛔ READ-ONLY SHIPPED SURFACE, TEST-ONLY BY CONSTRUCTION. This is the only module the walk\n * consults, and its only export is the query below — the register function lives in\n * `trust-boundary.seam.ts`, which the published tarball does not contain (package.json `files`\n * excludes it; scripts/smoke.ts asserts that). A non-test import of this module therefore\n * cannot stop the walk early: `trustBoundaryForTests` is unreachable, the set it feeds is not\n * exported, and in a consumer install the dynamic pull below finds no seam, keeps the empty\n * set and every ancestor of a binary is vetted (fail closed). The seam is pulled with a\n * COMPUTED specifier so no bundler inlines it into the shipped module.\n *\n * Plain syntax on purpose: fake-process.ts's graph is loaded under Node's strip-only\n * TypeScript (node-connect.harness.ts), which cannot load talosctl-binary.ts (parameter\n * properties). Not exported from the subpath index.\n */\nimport { realpathSync } from 'node:fs';\n\nlet boundaries: ReadonlySet<string> = new Set<string>();\n\n/**\n * Canonical compare: the walk hands over a real path, but the boundary is a security decision —\n * resolving again makes it independent of what a caller (now or future) cached. ⛔ A directory\n * that cannot be resolved is answered FALSE, never thrown: it is certainly not a registered\n * boundary, and the walk must treat \"no boundary\" as \"vet everything\" (fail closed).\n */\nexport const isTrustedBoundary = (dir: string): boolean => {\n try {\n return boundaries.has(realpathSync(dir));\n } catch {\n return false;\n }\n};\n\nconst seamSpecifier = './trust-boundary' + '.seam.ts';\nvoid import(seamSpecifier).then(\n (seam: { boundaries: ReadonlySet<string> }) => {\n boundaries = seam.boundaries;\n },\n () => {\n // Published package: no seam in the tarball — the set stays empty and the walk is never\n // shortened. In-repo this only fires if the seam file was deleted; boundary-dependent tests\n // then fail loudly instead of passing short-handed.\n },\n);\n",
13
+ "/**\n * `mintKvTempFile` — the 0600 session-temp file `readKvValue`'s material lands in. Extracted from\n * credentials.ts (2026-10-06, red team PR 355) once the Node-runtime fix pushed that file past the\n * 250-line cap; the split mirrors credentials-write.ts, which was split out for its own header.\n */\nimport { closeSync, openSync, writeFileSync } from 'node:fs';\nimport { unlink } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport * as Effect from 'effect/Effect';\nimport type * as Scope from 'effect/Scope';\n\n/**\n * Write `raw` to a session-temp, 0600, exclusively-created file whose lifetime is the CALLER's\n * `Effect.scoped`, not this call's. See the ⛔ C1 FIX note at the top of credentials.ts.\n *\n * ⛔ 0600, CREATED EXCLUSIVELY, AND `Bun.write` CANNOT DO EITHER. This file can hold a cluster\n * admin client certificate or a machine config's bootstrap token. `Bun.write` takes no mode, so\n * it lands at the process umask — world-readable on this estate — for as long as the resource\n * runs. The name is unguessable, and \"unguessable\" is not a permission.\n * ⚠️ `wx` IS THE OTHER HALF. `O_EXCL` means this cannot be made to write through a path an\n * attacker pre-created (the classic /tmp symlink race), and with a UUID name a collision is a\n * genuine error rather than something to paper over.\n * ⚠️ A HARD KILL (SIGKILL, power loss) skips the finalizer and leaves the file behind. 0600 is\n * what makes that survivable rather than a disclosure.\n */\nexport const mintKvTempFile = (\n raw: string,\n label: string,\n): Effect.Effect<{ readonly path: string }, Error, Scope.Scope> =>\n Effect.gen(function* () {\n // ⛔ NODE, NOT BUN (red team, PR 355): the published dist runs on Node, where `Bun.env` and\n // `Bun.randomUUIDv7` are missing globals — a `Talos.ClusterHealth` check would hit a\n // `ReferenceError` before `talosctl` ever ran. `os.tmpdir()` and `node:crypto` `randomUUID`\n // are the portable equivalents.\n const path = join(tmpdir(), `hf-talos-${label}-${randomUUID()}.yaml`);\n yield* Effect.acquireRelease(\n Effect.try({\n try: () => {\n const fd = openSync(path, 'wx', 0o600);\n try {\n writeFileSync(fd, raw);\n } finally {\n closeSync(fd);\n }\n },\n catch: (cause) => new Error(`writing ${label} temp file: ${String(cause)}`),\n }),\n () =>\n Effect.tryPromise({ try: () => unlink(path), catch: () => undefined }).pipe(\n Effect.orElseSucceed(() => undefined),\n ),\n );\n return { path };\n });\n",
14
+ "/**\n * The one YAML parser of the Talos family — runtime-neutral, so it runs under Bun AND Node.\n *\n * ⛔ NOT `Bun.YAML`. The published `dist/` runs on Node for consumers (AGENTS.md: Bun is the\n * toolchain, not the runtime). `Bun.YAML` is a missing global there: the old code swallowed that\n * ReferenceError and reported every kubeconfig as unreadable (reproduced on Node 22: the adapter\n * returned no transport). ★ `yaml` is the parser alchemy itself depends on (`yaml ^2.9.0`), so no\n * new package enters a consumer's tree.\n * ⚠️ ONLY a YAML syntax error is `undefined` (\"this is not a document\"). Anything else — a broken\n * import, a runtime fault — propagates, so a parser/runtime defect is never dressed up as bad\n * vault content.\n */\nimport { YAMLParseError, parse } from 'yaml';\n\n/** Parse one YAML document, or `undefined` when the text is not valid YAML. */\nexport const parseYaml = (text: string): unknown => {\n try {\n // ⛔ yaml reports unresolved tags etc. via process.emitWarning with the SOURCE TEXT in the\n // message (reproduced, hunt round 5: a kubeconfig with an unknown tag beside client-key-data\n // put the whole key on stderr). `logLevel: 'error'` silences warnings (yaml options.d.ts:\n // LogLevelId; doc.warnings are never emitted) and `prettyErrors: false` keeps source excerpts\n // out of any thrown error's message; syntax errors still throw YAMLParseError.\n return parse(text, { logLevel: 'error', prettyErrors: false });\n } catch (error) {\n if (error instanceof YAMLParseError) return undefined;\n throw error;\n }\n};\n",
15
+ "/**\n * In-memory kubeconfig parse for `talos-openbao` connect.\n *\n * ⛔ THE RESULT HOLDS PEM. Callers may put it on a `ClusterTransport` for one request.\n * They must not persist it, log it, or copy it onto a `Connection`. Alchemy stores\n * connection attributes in plaintext (`credentials.ts`'s own header).\n * ★ YAML IS `yaml-parse.ts` (runtime-neutral: Bun.YAML does not exist under Node, where the\n * published dist runs). Nothing here touches a filesystem or OpenBao — the caller has already\n * read the bytes.\n *\n * Walked against alchemy 2.0.0-beta.79 `Kubernetes/internal/client.ts`: `certificateAuthorityData`\n * stays base64 (the client decodes it) and `clientCert` is PEM. The document shape is the one\n * `values.ts` parses from the Talos v1.13 kubeconfig reference. Not measured on a live cluster.\n */\nimport type { ClusterTransport } from 'alchemy/Kubernetes/ClusterAdapter';\nimport { parseYaml } from './yaml-parse.ts';\n\ntype KubeconfigDoc = {\n clusters?: {\n cluster?: { server?: string; 'certificate-authority-data'?: string };\n name?: string;\n }[];\n contexts?: { context?: { cluster?: string; user?: string }; name?: string }[];\n users?: {\n name?: string;\n user?: { 'client-certificate-data'?: string; 'client-key-data'?: string };\n }[];\n};\n\nexport type KubeconfigMaterial = Pick<\n ClusterTransport,\n 'certificateAuthorityData' | 'clientCert' | 'endpoint'\n>;\n\n/** Base64 kubeconfig field → PEM, or `undefined` when it is not a PEM payload. */\nconst pem = (data: string | undefined): string | undefined => {\n if (data === undefined || data.trim() === '') return undefined;\n const decoded = Buffer.from(data, 'base64').toString('utf8');\n return decoded.includes('BEGIN ') ? decoded : undefined;\n};\n\n/**\n * Resolve `contextName` to endpoint, base64 CA, and PEM client cert/key.\n * `undefined` for any shape that is not that context's admin kubeconfig — the caller\n * fails closed without embedding the document in the error.\n */\nexport const kubeconfigTransport = (\n yamlText: string,\n contextName: string,\n): KubeconfigMaterial | undefined => {\n const parsed = parseYaml(yamlText);\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;\n const doc = parsed as KubeconfigDoc;\n const ctx = doc.contexts?.find((row) => row.name === contextName)?.context;\n const clusterName = ctx?.cluster;\n const userName = ctx?.user;\n if (clusterName === undefined || userName === undefined) return undefined;\n const cluster = doc.clusters?.find((row) => row.name === clusterName)?.cluster;\n const user = doc.users?.find((row) => row.name === userName)?.user;\n const endpoint = cluster?.server;\n const certificateAuthorityData = cluster?.['certificate-authority-data'];\n const certificate = pem(user?.['client-certificate-data']);\n const key = pem(user?.['client-key-data']);\n if (\n endpoint === undefined ||\n certificateAuthorityData === undefined ||\n pem(certificateAuthorityData) === undefined ||\n certificate === undefined ||\n key === undefined\n ) {\n return undefined;\n }\n return { certificateAuthorityData, clientCert: { certificate, key }, endpoint };\n};\n",
16
+ "/**\n * `Talos.Kubeconfig` — fetch admin kubeconfig so `Kubernetes.*` workloads can connect.\n *\n * ★ REASONED FROM talosctl kubeconfig (Talos v1.13 CLI reference): writes a kubeconfig file;\n * `--merge=false` keeps it isolated; `-f/--force` overwrites an existing file.\n *\n * ⛔ THE KUBECONFIG FILE CONTAINS A CLIENT CERTIFICATE — IT MUST NOT BE AN ATTRIBUTE. Alchemy\n * persists attributes unencrypted. This resource persists ONLY public metadata + fingerprints,\n * never the file's own bytes.\n *\n * ⛔ LANDS IN OPENBAO, NOT A HOST `runtimePath` (K-talos-first-boot, 2026-09-26). The shipped shape\n * wrote a cluster-admin kubeconfig to un-vaulted host disk and never removed it — the exact class\n * of exposure `talos/credentials.ts`'s own header exists to prevent — and its own `read` depended\n * on that file's continued presence, so verifying from any other host planned `update` forever\n * (docs/plans/2026-09-26-talos-secrets-flow.md's \"Measured today\" section). Fixed:\n * - CREATE (`output === undefined`) runs `talosctl kubeconfig` into a throwaway, unguessable\n * temp path (this file's own `reservedTempPath`), reads it back, and writes its bytes into\n * OpenBao at `target.mount`/`kubeconfigKey` via stdin (`credentials-write.ts`'s\n * `writeKvValue` — ⛔ never argv) — never to any path a caller could depend on.\n * - ⛔ WRITTEN ONCE, NOT RE-MINTED EVERY DEPLOY. `talosctl kubeconfig` always issues a FRESH\n * admin client certificate; re-running it every reconcile would rotate credentials for no\n * reason and violate O1's write-once-at-bring-up grant on this one key\n * (docs/plans/2026-09-26-talos-secrets-flow.md, O1). Once `output` is defined, reconcile only\n * reads the vault copy back to confirm it — the same \"once\" shape `talos-bootstrap.ts` uses\n * for a boolean, here for a value.\n * - NO `connection` is persisted here: a connection names the physical cluster by its\n * kube-system uid, which only `Talos.ClusterIdentity` can read (cluster-adapter.ts, the\n * identity rule). The adapter reads the vault at connect time. ⛔ Never the stock\n * `kubeconfig` kind (absent path falls back to `$KUBECONFIG`) nor `client-cert` (PEM on\n * every workload's attributes, alchemy `Connection.ts`).\n */\nimport { readFile } from 'node:fs/promises';\nimport { chmodSync } from 'node:fs';\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport {\n DEFAULT_KUBECONFIG_KEY,\n isVaultKeyAbsent,\n mintTalosconfig,\n readKvValue,\n} from './credentials.ts';\nimport { reservedTempPath, writeKvValue } from './credentials-write.ts';\nimport { buildAttrs } from './kubeconfig-attrs.ts';\nimport type { TalosRequirements, WithTarget } from './resource.ts';\nimport { talosctl } from './talosctl.ts';\n\nexport interface KubeconfigProps extends WithTarget {\n /** Node that serves `talosctl kubeconfig`. */\n node: string;\n /** Context name inside the generated kubeconfig — not secret. */\n context: string;\n /** OpenBao KV path under `target.mount` for the written kubeconfig. Default `'kubeconfig'`. */\n kubeconfigKey?: string;\n after?: readonly unknown[];\n}\n\nexport interface KubeconfigAttributes {\n context: string;\n endpoint: string;\n certificateAuthorityFingerprint: string;\n clientCertificateFingerprint: string;\n /** Digest of endpoint+context+fingerprints — detects credential rotation without storing PEM. */\n credentialGeneration: string;\n}\n\nexport interface TalosKubeconfig extends Resource<\n 'Talos.Kubeconfig',\n KubeconfigProps,\n KubeconfigAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosKubeconfig = Resource<TalosKubeconfig>('Talos.Kubeconfig');\n\n/** Absence is {@link isVaultKeyAbsent} — measured OpenBao v2.6.2 text, not every bao failure. */\nconst readVaultMeta = (props: KubeconfigProps, key: string) =>\n readKvValue(props.target.mount, key, ['kubeconfig', 'config']).pipe(\n Effect.catchIf(isVaultKeyAbsent, () => Effect.succeed(undefined)),\n );\n\n/**\n * ★ EXPORTED for kubeconfig.test.ts — see talos-bootstrap.ts's own note on the pattern.\n *\n * ⛔ C1 FIX (LAND red team, 2026-09-26) — `undefined` NOW MEANS ONLY \"the key has never been\n * written\", NEVER \"some read failed\". The shipped `Effect.orElseSucceed` folded EVERY failure —\n * including a vault outage or wrong mount — into a defined, empty-fingerprint object. Alchemy's\n * engine always adopts a defined cold-start `read` result and forces `update` (alchemy beta.79\n * `Plan.ts:1303-1352`), so `reconcileKubeconfig`'s write-once branch (`output !== undefined`)\n * then tried to CONFIRM a key that had never actually been written, and failed every time —\n * `Talos.Kubeconfig` could never be created. Vault content that EXISTS but does not parse as a\n * kubeconfig is a different, fail-closed case (below), never treated as absence.\n */\nexport const readKubeconfig = (props: KubeconfigProps) =>\n Effect.gen(function* () {\n const key = props.kubeconfigKey ?? DEFAULT_KUBECONFIG_KEY;\n const raw = yield* readVaultMeta(props, key);\n if (raw === undefined) return undefined;\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.fail(\n new Error(\n `${props.target.mount}/${key}: vault content exists but does not parse as a kubeconfig ` +\n `for context ${props.context} — not a cold start. Fix the KV entry or the pinned ` +\n 'context rather than trusting an empty read.',\n ),\n );\n }\n return meta;\n });\n\nexport const diffKubeconfig = (\n news: Input<KubeconfigProps>,\n output: KubeconfigAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readKubeconfig(news);\n if (\n live !== undefined &&\n live.credentialGeneration === output.credentialGeneration &&\n live.context === output.context &&\n // ⚠️ A row saved by an earlier build still carries a `connection` (a name-only or dead\n // placeholder one). It must update so the stale connection leaves state: a workload wired\n // to this resource would otherwise keep an auth block that names no physical cluster.\n !('connection' in output) &&\n live.endpoint === output.endpoint\n ) {\n return { action: 'noop' } as const;\n }\n return { action: 'update' } as const;\n });\n\n/**\n * ⛔ WRAPPED IN `Effect.scoped` — same C1-lifetime reasoning as every other Talos resource file:\n * `mintTalosconfig` and `reservedTempPath` both contribute `Scope.Scope`, and this is the caller\n * that owns their lifetime for the whole reconcile.\n * ⛔ WRITE-ONCE — see this file's own header. A bring-up already ran; this branch never spawns\n * `talosctl kubeconfig` or writes to the vault again.\n * ⛔ GATED ON `credentialGeneration`, NOT JUST `output !== undefined` (C1 fix, LAND red team,\n * belt-and-suspenders alongside the `read` fix above) — `output`'s own type still allows a\n * defined-but-empty value (state persisted by a pre-fix build's `emptyAttrs()`, or any future\n * caller that hands this function a stale row). Treat that exactly like `undefined` — mint and\n * write once — rather than take the confirm-only branch and fail trying to read back a key that\n * was never actually written.\n */\nexport const reconcileKubeconfig = (\n props: KubeconfigProps,\n output: KubeconfigAttributes | undefined,\n) =>\n Effect.scoped(\n Effect.gen(function* () {\n const key = props.kubeconfigKey ?? DEFAULT_KUBECONFIG_KEY;\n\n if (output !== undefined && output.credentialGeneration !== '') {\n const raw = yield* readKvValue(props.target.mount, key, ['kubeconfig', 'config']);\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.die(\n new Error(\n `${props.target.mount}/${key}: vault content no longer parses as a kubeconfig for ` +\n `context ${props.context}. Read back rather than trusting the write once.`,\n ),\n );\n }\n return meta;\n }\n\n const credential = yield* mintTalosconfig(props.target);\n const { path: outPath } = yield* reservedTempPath(\n `${props.target.cluster}-${props.node}-kubeconfig-out`,\n );\n yield* talosctl(\n ['kubeconfig', outPath, '--merge=false', '--force', '--force-context-name', props.context],\n { nodes: [props.node], talosconfigPath: credential.talosconfigPath },\n );\n const raw = yield* Effect.tryPromise({\n catch: (cause) => new Error(`${outPath}: reading generated kubeconfig: ${String(cause)}`),\n try: () => readFile(outPath, 'utf8'),\n });\n if (raw.trim() === '') {\n return yield* Effect.die(\n new Error(\n `${props.node}: talosctl kubeconfig returned no error but wrote an empty file. Read ` +\n 'back rather than trusting the exit code alone.',\n ),\n );\n }\n // ⚠️ REASONED, not measured: talosctl's own writer likely already uses 0600 like most Go\n // credential writers, but this chmods defensively regardless — same posture as\n // credentials.ts's mintKvTempFile.\n yield* Effect.try({\n catch: (cause) => new Error(`${outPath}: chmod 0600: ${String(cause)}`),\n try: () => chmodSync(outPath, 0o600),\n });\n const meta = buildAttrs(raw, props);\n if (meta === undefined) {\n return yield* Effect.die(\n new Error(\n `${props.node}: talosctl kubeconfig wrote a file that does not parse for context ` +\n `${props.context}.`,\n ),\n );\n }\n yield* writeKvValue(props.target.mount, key, 'kubeconfig', raw);\n return meta;\n }),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<KubeconfigProps>;\n output: KubeconfigAttributes | undefined;\n }) => diffKubeconfig(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: KubeconfigProps }) => readKubeconfig(olds),\n reconcile: ({\n news,\n output,\n }: {\n news: KubeconfigProps;\n output: KubeconfigAttributes | undefined;\n }) => reconcileKubeconfig(news, output),\n};\n\nexport const TalosKubeconfigProvider = () =>\n Provider.effect(TalosKubeconfig, Effect.succeed(TalosKubeconfig.Provider.of(handlers)));\n",
17
+ "/**\n * The write half of Talos's OpenBao KV access — split out of credentials.ts (2026-09-26,\n * K-talos-first-boot) once it needed its own header, the same reason machine-config-read.ts,\n * machine-config-poll.ts and talos-errors.ts were split out of talos-machine-config.ts before it.\n * `credentials.ts` stays the read side (mint a talosconfig, read a KV value); this file is the one\n * place anything in this package ever writes TO OpenBao.\n *\n * ★ FIRST CALLER: `Talos.Kubeconfig` (kubeconfig.ts) writing the admin kubeconfig it generates at\n * cluster bring-up into the vault instead of an un-vaulted host `runtimePath` — see that file's\n * own header. `Ceph.AuthEntity` (K-A4, a separate design/PR) is expected to need the same shape\n * for its own vault-written entity keys; this is not yet shared with it on purpose — two callers\n * is the point at which sharing stops being speculative.\n */\nimport * as Effect from 'effect/Effect';\nimport type * as Scope from 'effect/Scope';\nimport * as Duration from 'effect/Duration';\nimport * as Stream from 'effect/Stream';\nimport { unlink } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\nimport { baoEnv } from './bao-env.ts';\nimport { resolveBao } from './talosctl-binary.ts';\n\n/**\n * A fresh, unguessable temp path for SOME OTHER PROCESS (talosctl) to create — unlike\n * `credentials.ts`'s `mintKvTempFile`, this does NOT pre-create the file with `wx`, because the\n * caller here is capturing a command's OWN output rather than writing known content itself. The\n * random UUIDv7 name is the only pre-fabrication guard (an attacker cannot pre-plant a symlink at a\n * path it cannot predict) — first used by `kubeconfig.ts` to capture `talosctl kubeconfig`'s\n * generated file before reading it back and writing it into the vault.\n */\nexport const reservedTempPath = (\n label: string,\n): Effect.Effect<{ readonly path: string }, never, Scope.Scope> =>\n Effect.gen(function* () {\n const path = join(tmpdir(), `hf-talos-${label}-${randomUUID()}.yaml`);\n yield* Effect.addFinalizer(() =>\n Effect.tryPromise({ try: () => unlink(path), catch: () => undefined }).pipe(\n Effect.orElseSucceed(() => undefined),\n ),\n );\n return { path };\n });\n\n/**\n * Write one field of an OpenBao KV-v2 value from `value` — never argv, the mirror image of\n * `credentials.ts`'s `readKvValue`.\n *\n * ⛔ C2 FIX (LAND red team, 2026-09-26) — `field=@-` IS WRONG AND WAS NEVER MEASURED. `@value` means\n * \"read a file at this path\"; a literal path of `-` is not the stdin convention for `@` — it is\n * just a file named `-`. MEASURED against the estate's OpenBao v2.6.2 binary (isolated in-memory\n * dev server, `env -i`, scratch HOME, no estate credentials involved; server removed after):\n * `field=@-` exits 1 with `invalid key/value pair \"field=@-\": error reading file: open -: no\n * such file or directory`, and if a file literally named `-` exists in the working directory it\n * silently stores THAT file's bytes instead. `field=-` (no `@`) is Vault/OpenBao's own stdin\n * convention and was confirmed against the same binary to read the piped bytes correctly. Every\n * `Talos.Kubeconfig` create failed here — AFTER `talosctl kubeconfig` had already issued a fresh\n * admin client certificate, which cannot be revoked.\n * ⛔ stderr ONLY ON FAILURE — same rule as `readKvValue`: never echo what was being written, on\n * success or failure.\n */\nexport const writeKvValue = (\n mount: string,\n key: string,\n field: string,\n value: string,\n): Effect.Effect<void, Error, ChildProcessSpawner.ChildProcessSpawner> =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n // ⛔ Same vetting as `readKvValue`: `bao` writes credentials, so it is resolved and vetted before\n // any env is built or passed — a fake `bao` in a writable PATH folder is refused, never launched.\n const bao = yield* resolveBao();\n const env = baoEnv();\n if (env === undefined) {\n return yield* Effect.fail(\n new Error(\n `bao kv put ${mount}/${key} refused: BAO_ADDR and BAO_TOKEN must both be set. ` +\n \"Without them bao would fall back to a cached login in the operator's home.\",\n ),\n );\n }\n const result = yield* ChildProcess.make(bao, ['kv', 'put', `${mount}/${key}`, `${field}=-`], {\n env,\n extendEnv: false,\n // ⛔ Mirror readKvValue's spawn: `bao` leads its own process group (killed whole on interrupt)\n // and a SIGTERM-ignoring `bao` is SIGKILLed 1 s later instead of blocking the plan.\n forceKillAfter: Duration.seconds(1),\n stderr: 'pipe',\n stdin: Stream.fromIterable([new TextEncoder().encode(value)]),\n stdout: 'pipe',\n }).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new Error(`bao kv put ${mount}/${key} exited ${String(result.exitCode)}: ${result.stderr}`),\n );\n }\n });\n",
18
+ "/**\n * Coercions and digests for Talos resources — every function here exists because a trap does.\n *\n * ⚠️ NOTHING IN THIS FILE TOUCHES A LIVE CLUSTER OR OpenBao. Digests are computed from KV content\n * or talosctl output already fetched by the caller, and kubeconfig YAML already on disk at\n * reconcile time; tests use fixtures only.\n */\nimport { createHash } from 'node:crypto';\nimport { parseYaml } from './yaml-parse.ts';\n\n/** Trim trailing whitespace only — leading space in YAML is meaningful. */\nexport const canonicalText = (text: string) => text.trimEnd();\n\n/** SHA-256 hex digest of canonical text. Safe to persist — it is not reversible to the input. */\nexport const sha256 = (text: string) =>\n createHash('sha256').update(canonicalText(text)).digest('hex');\n\n/** Digest of a machine config's canonical text. ⛔ Never persist the text itself. */\nexport const configDigest = (text: string) => sha256(text);\n\n/**\n * Extract the raw config text under `spec` from `talosctl get machineconfig -o yaml`'s wrapper.\n *\n * ⛔ THE WHOLE WRAPPER CAN NEVER MATCH THE PINNED DIGEST, AND HASHING IT WAS THE SHIPPED BUG.\n * REASONED from talosctl source (`cmd/talosctl/.../output/yaml.go:63`,\n * `resources/config/machine_config.go:40-50`): the resource envelope nests a `node:` line and\n * resource metadata (version, timestamps) around the config, which is itself a raw YAML STRING\n * under `spec`. Metadata changes on every observation, so `configDigest(wrapper)` never equals\n * `configDigest(seededConfigText)` even when nothing changed — every reconcile would die, every\n * diff would plan `update`, verify would never go quiet (all three MEASURED against the shipped\n * code's shape, docs/plans/2026-09-26-talos-stack-first-boot.md).\n * ⚠️ Returns `undefined` for any shape without a string `spec`, so a caller cannot mistake\n * \"unparsable wrapper\" for \"empty config\" — those must fail differently (the caller's job).\n * ⛔ MORE THAN ONE DOCUMENT IS REFUSED, NEVER `doc[0]` (fix-first #2, PR 307 red team). An unfiltered\n * `get machineconfig` lists BOTH the `persistent` and `v1alpha1` resources, sorted by id\n * (REASONED, cosi-project/runtime `inmem/collection.go:122-124`), so a bare `doc[0]` is always\n * `persistent` — never the config this package applies. The caller (machine-config-read.ts) now\n * always requests the single named resource (`get machineconfig v1alpha1`); a second document\n * showing up here means that request shape changed without this guard changing with it, and\n * silently picking one would repeat the exact shipped bug.\n */\nexport const extractMachineConfigSpec = (wrapperYaml: string): string | undefined => {\n let doc = parseYaml(wrapperYaml);\n if (Array.isArray(doc)) {\n if (doc.length !== 1) return undefined;\n doc = doc[0];\n }\n if (doc === null || typeof doc !== 'object') return undefined;\n const spec = (doc as { spec?: unknown }).spec;\n return typeof spec === 'string' ? spec : undefined;\n};\n\ntype KubeconfigDoc = {\n clusters?: {\n cluster?: { server?: string; 'certificate-authority-data'?: string };\n name?: string;\n }[];\n contexts?: { context?: { cluster?: string; user?: string }; name?: string }[];\n users?: {\n name?: string;\n user?: { 'client-certificate-data'?: string; 'client-key-data'?: string };\n }[];\n 'current-context'?: string;\n};\n\n/**\n * Public metadata extracted from a kubeconfig file on disk.\n *\n * ⛔ RETURNS FINGERPRINTS ONLY. The admin kubeconfig contains a client certificate; Alchemy state\n * may hold the API server URL and CA/client cert digests, never the PEM bytes.\n */\nexport const kubeconfigMetadata = (\n yamlText: string,\n contextName: string,\n): { endpoint: string; caFingerprint: string; clientFingerprint: string } | undefined => {\n const parsed = parseYaml(yamlText);\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;\n const doc = parsed as KubeconfigDoc;\n\n const ctx = doc.contexts?.find((row) => row.name === contextName)?.context;\n const clusterName = ctx?.cluster;\n const userName = ctx?.user;\n if (clusterName === undefined || userName === undefined) return undefined;\n\n const cluster = doc.clusters?.find((row) => row.name === clusterName)?.cluster;\n const user = doc.users?.find((row) => row.name === userName)?.user;\n const endpoint = cluster?.server;\n const ca = cluster?.['certificate-authority-data'];\n const cert = user?.['client-certificate-data'] ?? user?.['client-key-data'];\n if (endpoint === undefined || ca === undefined || cert === undefined) return undefined;\n\n return {\n caFingerprint: sha256(ca),\n clientFingerprint: sha256(cert),\n endpoint,\n };\n};\n",
19
+ "/**\n * `Talos.Kubeconfig`'s attribute builder — split out of kubeconfig.ts (LAND, 2026-09-26, C1/I2\n * fixes) once fixing those findings pushed the file over the 250-line cap. Only `import type`\n * comes back from kubeconfig.ts, so there is no runtime cycle.\n *\n * ⛔ NO `connection` HERE. A connection names the PHYSICAL cluster (`{ kind, uid }`,\n * cluster-adapter.ts's identity rule) and the uid is only knowable from the cluster, which does\n * not exist yet when this resource writes the vault key. Workloads get their connection from the\n * operator's pinned literal (`talosOpenBaoConnection(uid)`) or `Talos.ClusterHealth`'s\n * pass-through; `Talos.ClusterIdentity` publishes `{ uid }` only; a name-only connection\n * (`cluster` present) is refused by the adapter as legacy. Neither the\n * stock `kubeconfig` kind (an absent path falls back to `$KUBECONFIG`) nor `client-cert` (PEM on\n * every workload's attributes, `Connection.ts` v2.0.0-beta.79 lines 12-14) is ever used.\n */\nimport type { KubeconfigAttributes, KubeconfigProps } from './kubeconfig.ts';\nimport { kubeconfigMetadata, sha256 } from './values.ts';\n\nconst generation = (meta: {\n endpoint: string;\n caFingerprint: string;\n clientFingerprint: string;\n context: string;\n}) => sha256(`${meta.context}\\n${meta.endpoint}\\n${meta.caFingerprint}\\n${meta.clientFingerprint}`);\n\n/** Parse `raw` kubeconfig YAML into public, persistable attributes, or `undefined` if it fails to. */\nexport const buildAttrs = (\n raw: string,\n props: KubeconfigProps,\n): KubeconfigAttributes | undefined => {\n const meta = kubeconfigMetadata(raw, props.context);\n if (meta === undefined) return undefined;\n return {\n certificateAuthorityFingerprint: meta.caFingerprint,\n clientCertificateFingerprint: meta.clientFingerprint,\n context: props.context,\n credentialGeneration: generation({ ...meta, context: props.context }),\n endpoint: meta.endpoint,\n };\n};\n",
20
+ "/**\n * One `talosctl` invocation — stdout/stderr captured, secrets never echoed.\n *\n * ★ SHELL OUT LIKE ALCHEMY'S DOCKER PROVIDER (ChildProcessSpawner), NOT A SECOND SDK. Talos speaks\n * gRPC; the published, stable surface for operators is `talosctl`. No Talos npm package is added.\n *\n * ⚠️ REASONED FROM docs.siderolabs.com/talos/v1.13/reference/cli — nothing here was measured on a\n * live cluster in this session.\n *\n * ⛔ DO NOT LOG STDOUT ON FAILURE. `talosctl kubeconfig` and error paths have been observed in the\n * wild to include credential material; stderr is the safe diagnostic channel.\n */\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Stream from 'effect/Stream';\nimport * as ChildProcess from 'effect/process/ChildProcess';\nimport * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';\nimport {\n DEFAULT_TALOSCTL_BINARY,\n TALOSCTL_BINARY_ENV,\n TalosBinaryRefused,\n checkBinaryPath,\n resolveDefault,\n} from './talosctl-binary.ts';\n\nexport { DEFAULT_TALOSCTL_BINARY, TALOSCTL_BINARY_ENV, TalosBinaryRefused };\n\nexport class TalosError extends Error {\n constructor(\n readonly command: string,\n readonly exitCode: number,\n detail: string,\n binary = DEFAULT_TALOSCTL_BINARY,\n ) {\n super(`${binary} ${command} -> ${String(exitCode)}: ${detail}`);\n this.name = 'TalosError';\n }\n}\n\n/** The Talos client version this family is written against (`--client` of the pinned binary). */\nexport const TALOSCTL_PINNED_VERSION = 'v1.14.2';\n\nconst talosctlBinary = (override: string | undefined): string => {\n const fromOption = override?.trim();\n if (fromOption !== undefined && fromOption !== '') return fromOption;\n const fromEnv = process.env[TALOSCTL_BINARY_ENV]?.trim();\n if (fromEnv !== undefined && fromEnv !== '') return fromEnv;\n return DEFAULT_TALOSCTL_BINARY;\n};\n\n/**\n * ⛔ THE CHILD GETS A MINIMAL ENV, NOT `process.env`: BAO_TOKEN and every other credential in the\n * caller's environment stay out of an override that is only vetted by path and version. The\n * talosconfig travels as a file argument, so the binary needs nothing else but `PATH`/`HOME`.\n */\nconst talosctlEnv = (): Record<string, string> => {\n const env: Record<string, string> = {};\n for (const name of ['PATH', 'HOME', 'TMPDIR']) {\n const value = process.env[name];\n if (value !== undefined && value !== '') env[name] = value;\n }\n return env;\n};\n\nexport type TalosRunOptions = {\n readonly talosconfigPath: string;\n /**\n * `talosctl` executable. Wins over {@link TALOSCTL_BINARY_ENV}.\n * @default `talosctl` on `PATH`, or `HF_TALOSCTL` when that variable is set.\n */\n readonly binary?: string;\n readonly nodes?: readonly string[];\n readonly endpoints?: readonly string[];\n /**\n * `-i/--insecure` — a maintenance-mode node has no established PKI yet. Used by the CREATE apply\n * (resource.ts's own header) and by talos-machine-config.ts's maintenance-mode probe (fix-first\n * #1, PR 307 red team): `--talosconfig` is still passed alongside it, matching the CREATE path,\n * since insecure mode ignores the file's certs rather than requiring their absence.\n */\n readonly insecure?: boolean;\n};\n\nconst capture = (binary: string, argv: readonly string[]) =>\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n return yield* ChildProcess.make(binary, argv, {\n // ⛔ No `detached: false`, plus `forceKillAfter`, as credentials.ts's bao spawn: the child\n // leads its own process group (killed whole on interrupt) and a SIGTERM-ignoring talosctl\n // is SIGKILLed 1 s later instead of blocking interruption.\n env: talosctlEnv(),\n extendEnv: false,\n forceKillAfter: Duration.seconds(1),\n stderr: 'pipe',\n stdin: 'ignore',\n stdout: 'pipe',\n }).pipe(\n spawner.spawn,\n Effect.flatMap((child) =>\n Effect.all(\n {\n exitCode: child.exitCode,\n stderr: child.stderr.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n stdout: child.stdout.pipe(\n Stream.decodeText,\n Stream.mkString,\n Effect.map((text) => text.trim()),\n ),\n },\n { concurrency: 'unbounded' },\n ),\n ),\n Effect.scoped,\n );\n });\n\n/** ⚠️ EXACT TOKEN MATCH: `includes` would accept v1.14.20 for v1.14.2. */\nconst reportsPinnedVersion = (stdout: string) =>\n stdout.split(/[^\\w.+-]+/).includes(TALOSCTL_PINNED_VERSION);\n\n/**\n * ⛔ AN OVERRIDE MUST REPORT THE PINNED CLIENT VERSION (`version --client`, no talosconfig, so\n * nothing secret reaches an untrusted binary before it is vetted).\n */\nconst checkOverrideVersion = (binary: string, source: string) =>\n capture(binary, ['version', '--client']).pipe(\n Effect.flatMap((out) =>\n out.exitCode === 0 && reportsPinnedVersion(out.stdout)\n ? Effect.void\n : Effect.fail(\n new TalosBinaryRefused(\n 'version --client',\n `${source} is not talosctl ${TALOSCTL_PINNED_VERSION} (exit ${String(out.exitCode)})`,\n binary,\n ),\n ),\n ),\n );\n\n/** Run `talosctl <args…>`. Returns trimmed stdout, or '' when empty. */\nexport const talosctl = (args: readonly string[], options: TalosRunOptions) =>\n Effect.gen(function* () {\n const requested = talosctlBinary(options.binary);\n const resolved =\n requested === DEFAULT_TALOSCTL_BINARY ? yield* resolveDefault(requested) : requested;\n const fromOption = options.binary?.trim();\n const source =\n requested === DEFAULT_TALOSCTL_BINARY\n ? 'talosctl on PATH'\n : fromOption !== undefined && fromOption !== ''\n ? 'the `binary` option'\n : TALOSCTL_BINARY_ENV;\n // ⛔ Launch exactly the vetted canonical path, for the probe and the credentialed call alike.\n const binary = yield* checkBinaryPath(resolved, source);\n yield* checkOverrideVersion(binary, source);\n const argv = [\n ...args,\n '--talosconfig',\n options.talosconfigPath,\n ...(options.nodes === undefined ? [] : ['--nodes', options.nodes.join(',')]),\n ...(options.endpoints === undefined ? [] : ['--endpoints', options.endpoints.join(',')]),\n ...(options.insecure === true ? ['--insecure'] : []),\n ];\n const result = yield* capture(binary, argv);\n\n const command = args.join(' ');\n if (result.exitCode !== 0) {\n return yield* Effect.fail(\n new TalosError(command, result.exitCode, result.stderr.slice(0, 300), binary),\n );\n }\n return result.stdout;\n });\n\n/** Like `talosctl`, but exit code 1 with \"already\" in stderr is treated as success. */\nexport const talosctlOrAlready = (args: readonly string[], options: TalosRunOptions) =>\n talosctl(args, options).pipe(\n Effect.catchIf(\n (cause): cause is TalosError =>\n cause instanceof TalosError &&\n cause.exitCode !== 0 &&\n /already|exists|bootstrapped/i.test(cause.message),\n () => Effect.succeed(''),\n ),\n );\n",
11
21
  "/**\n * `Talos.Bootstrap` — initialize etcd once on ONE control-plane node.\n *\n * ★ REASONED FROM talosctl bootstrap (Talos v1.13 CLI reference): one node aborts the etcd join\n * loop and forms the initial cluster; other control-plane nodes join after Kubernetes starts on\n * the bootstrap node. This command must run exactly once per cluster.\n *\n * ⛔ NOT A FACTORY RESOURCE — bootstrap cannot be deleted or updated in place; `delete` is a no-op.\n *\n * ⛔ ONCE MEANS ONCE (K-talos-first-boot, 2026-09-26) — THE SHIPPED SHAPE COULD BOOTSTRAP A SECOND\n * etcd CLUSTER. The original `isBootstrapped` turned every read failure into `false`\n * (`Effect.orElseSucceed`), `diff` then planned `update`, and `reconcile` re-ran `talosctl\n * bootstrap` — Talos's only server-side guard is a non-empty etcd data directory (REASONED,\n * `v1alpha1_server.go:441`), so a reinstalled or reset bootstrap node re-bootstrapped a fresh,\n * isolated single-member cluster: split brain. Fixed per\n * docs/plans/2026-09-26-talos-stack-first-boot.md's \"Bootstrap — once means once\" section:\n * - `read` now answers presence/absence correctly instead of always returning a defined\n * object — `undefined` only from a SUCCESSFUL read that finds no members (cold-start\n * absence); a failing read propagates its error instead of being reinterpreted as absence.\n * - `diff` trusts `output.bootstrapped` once it is `true` and reports `noop` without touching\n * the live cluster at all — confirmation is `reconcile`'s job now, not plan's.\n * - `reconcile` checks `output?.bootstrapped` FIRST: once true, it NEVER calls `talosctl\n * bootstrap` again, no matter what a live read says. A live read that fails OR comes back\n * empty both raise the same `TalosReBootstrapRefused` — re-bootstrap is a human decision.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { mintTalosconfig } from './credentials.ts';\nimport type { TalosRequirements, WithTarget } from './resource.ts';\nimport { assertNoLivePeers, isBootstrapped } from './talos-bootstrap-etcd.ts';\nimport { TalosReBootstrapRefused } from './talos-errors.ts';\nimport { talosctlOrAlready } from './talosctl.ts';\n\nexport interface BootstrapProps extends WithTarget {\n /** The ONE control-plane node that receives `talosctl bootstrap`. */\n node: string;\n /**\n * The OTHER declared control-plane nodes — never `node` itself. Optional, but a multi-control-\n * plane cluster (decision 66: 3, one per TB4 node) SHOULD set it: `reconcileBootstrap`'s CREATE\n * path (I4 fix, LAND red team, 2026-09-26) requires every one of these to show a successful,\n * EMPTY etcd-members read before it will bootstrap `node` — the guard against re-bootstrapping a\n * split-brain second cluster when this row's own state was lost. See talos-bootstrap-etcd.ts's\n * `assertNoLivePeers`.\n */\n peers?: readonly string[];\n /** Machine configs for this node (and peers) must be applied first. */\n after?: readonly unknown[];\n}\n\nexport interface BootstrapAttributes {\n node: string;\n bootstrapped: boolean;\n}\n\nexport interface TalosBootstrap extends Resource<\n 'Talos.Bootstrap',\n BootstrapProps,\n BootstrapAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosBootstrap = Resource<TalosBootstrap>('Talos.Bootstrap', {\n /** etcd data is irreplaceable — opt into destroy explicitly if Talos ever adds an undo. */\n defaultRemovalPolicy: 'retain',\n});\n\n/**\n * ⛔ WRAPPED IN `Effect.scoped` (K-A3, 2026-09-26) — `mintTalosconfig` contributes `Scope.Scope`\n * to its own return type rather than closing its scope internally (the C1 fix, credentials.ts's\n * own header); this is the caller that owns the temp talosconfig's lifetime for the read.\n *\n * ⛔ ANSWERS PRESENCE/ABSENCE, NOT \"attrs-or-error\" (K-talos-first-boot, fixes the shipped shape).\n * `undefined` only when a read SUCCEEDS and finds no members — the honest \"not created yet\"\n * Alchemy's engine expects from a cold-start adoption probe. A failing read propagates instead\n * of being reinterpreted as absence — this is the fix `isBootstrapped` no longer hides.\n *\n * ★ EXPORTED (like proxmox/ceph-daemon.ts's `reconcileDaemon`, machine-config-read.ts's\n * `readMachineConfig`) so talos-bootstrap.test.ts calls it directly with a fake spawner instead\n * of driving it through the full Alchemy engine.\n */\nexport const readBootstrap = (props: BootstrapProps) =>\n Effect.scoped(\n Effect.gen(function* () {\n const credential = yield* mintTalosconfig(props.target);\n const bootstrapped = yield* isBootstrapped(props, credential.talosconfigPath);\n return bootstrapped ? ({ bootstrapped: true, node: props.node } as const) : undefined;\n }),\n );\n\n/**\n * ⛔ TRUSTS STATE, NEVER TOUCHES THE LIVE CLUSTER (K-talos-first-boot) — once `output.bootstrapped`\n * is `true` this always reports `noop`, unconditionally, with zero live calls.\n *\n * ⛔ I3 CORRECTION (LAND red team, 2026-09-26) — THE OLD COMMENT HERE CLAIMED \"confirming the\n * invariant against etcd is reconcile's job (every deploy calls it)\". THAT IS FALSE, VERIFIED\n * against the pinned alchemy beta.79 source: Apply never reconciles a node whose diff came back\n * `noop` (`Apply.ts`'s `noop` branch just refreshes row metadata and signals ready — it does not\n * call `provider.reconcile` at all). This file's own `noop` above IS what skips it. So\n * `reconcileBootstrap`'s re-confirm branch (the one that raises `TalosReBootstrapRefused` on a\n * failed or empty read) never runs on an ordinary `plan`/`deploy` once `bootstrapped: true` is\n * recorded — only `--force` reaches it, by forcing a reconcile regardless of the plan action.\n * Safety still holds — `talosctl bootstrap` genuinely never re-runs while state exists — but a\n * reset control-plane node (etcd wiped, VM replaced) stays silently invisible to `plan` and\n * `deploy` alike until an operator runs `--force` or a verify pass.\n * ⚠️ NOT FIXED BY HAVING `diff` READ HERE TOO (the finding's other offered fix) — that would touch\n * the live cluster (and mint a talosconfig) on EVERY plan for an already-bootstrapped node, for a\n * scenario (a reset node) that a `configDigest`-style pinned check can't distinguish from a merely\n * slow/unreachable read; a single transient failure would then abort every future plan for a\n * healthy node, for no benefit — the exact cost the original (correct) half of this comment\n * already named. `MachineConfig`/`ClusterHealth`'s diffs DO mint and read live on every plan\n * (D2 puts that on the admin/operator lane, not agent), so this isn't a lane-access limit; it is\n * this resource's own choice to trust a `true` boolean forever rather than re-derive it from a\n * live signal that cannot yet tell \"reset\" apart from \"briefly unreachable\". Recorded as an open\n * gap for whoever builds the operator verify pass, not silently fixed here.\n */\nexport const diffBootstrap = (\n news: Input<BootstrapProps>,\n output: BootstrapAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n if (output.bootstrapped) return { action: 'noop' } as const;\n const live = yield* readBootstrap(news);\n return live?.bootstrapped === true\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n });\n\n/**\n * ⛔ ONCE MEANS ONCE — see this file's own header. `output?.bootstrapped === true` is checked\n * BEFORE anything else, and that branch never builds a `talosctl bootstrap` argv at all — the\n * confirmation read below can fail, or succeed and say \"absent\", and EITHER way this raises\n * `TalosReBootstrapRefused` rather than treating \"absent\" as licence to bootstrap again.\n */\nexport const reconcileBootstrap = (\n props: BootstrapProps,\n output: BootstrapAttributes | undefined,\n) =>\n Effect.scoped(\n Effect.gen(function* () {\n const credential = yield* mintTalosconfig(props.target);\n\n if (output?.bootstrapped === true) {\n const stillBootstrapped = yield* isBootstrapped(props, credential.talosconfigPath).pipe(\n Effect.catchIf(\n (): boolean => true,\n (cause) =>\n Effect.fail(\n new TalosReBootstrapRefused({\n detail: `live read failed: ${String(cause)}`,\n node: props.node,\n }),\n ),\n ),\n );\n if (!stillBootstrapped) {\n return yield* Effect.fail(\n new TalosReBootstrapRefused({\n detail: 'etcd members are absent on a live read against already-bootstrapped state',\n node: props.node,\n }),\n );\n }\n return { bootstrapped: true, node: props.node };\n }\n\n const before = yield* isBootstrapped(props, credential.talosconfigPath);\n if (!before) {\n // ⛔ I4 FIX (LAND red team) — see BootstrapProps.peers's own doc and\n // talos-bootstrap-etcd.ts's assertNoLivePeers header.\n yield* assertNoLivePeers(props, credential.talosconfigPath);\n yield* talosctlOrAlready(['bootstrap'], {\n nodes: [props.node],\n talosconfigPath: credential.talosconfigPath,\n });\n }\n const after = yield* isBootstrapped(props, credential.talosconfigPath);\n if (!after) {\n return yield* Effect.die(\n new Error(\n `${props.node}: bootstrap returned no error but etcd members are still absent. ` +\n 'Read back rather than trusting the exit code alone.',\n ),\n );\n }\n return { bootstrapped: true, node: props.node };\n }),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<BootstrapProps>;\n output: BootstrapAttributes | undefined;\n }) => diffBootstrap(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: BootstrapProps }) => readBootstrap(olds),\n reconcile: ({\n news,\n output,\n }: {\n news: BootstrapProps;\n output: BootstrapAttributes | undefined;\n }) => reconcileBootstrap(news, output),\n};\n\nexport const TalosBootstrapProvider = () =>\n Provider.effect(TalosBootstrap, Effect.succeed(TalosBootstrap.Provider.of(handlers)));\n",
12
22
  "/**\n * `Talos.Bootstrap`'s etcd-members probe and split-brain guard — split out of talos-bootstrap.ts\n * (LAND, 2026-09-26, I4 fix) once adding the guard pushed that file over the 250-line cap, the same\n * reason machine-config-read.ts was split out of talos-machine-config.ts before it. Only\n * `import type` comes back from talos-bootstrap.ts, so there is no runtime cycle between the files.\n */\nimport * as Effect from 'effect/Effect';\nimport type { BootstrapProps } from './talos-bootstrap.ts';\nimport { TalosReBootstrapRefused } from './talos-errors.ts';\nimport { talosctl } from './talosctl.ts';\n\n/**\n * REASONED: `talosctl get etcdmembers -o json` should list members after bootstrap.\n * ⚠️ NOT MEASURED — first live deploy confirms the resource type name.\n * ⛔ NO SWALLOWING (K-talos-first-boot) — a transport failure propagates as its own error; only a\n * SUCCESSFUL read may conclude presence or absence. Every caller decides for itself what a\n * failure here means (talos-bootstrap.ts's `read`/`reconcile`, and `assertNoLivePeers` below), so\n * it is not decided here.\n */\nexport const isBootstrapped = (props: BootstrapProps, talosconfigPath: string) =>\n talosctl(['get', 'etcdmembers', '-o', 'json'], {\n nodes: [props.node],\n talosconfigPath,\n }).pipe(Effect.map((text) => text.includes('\"id\"') || text.includes('\"member\"')));\n\n/**\n * ⛔ I4 FIX (LAND red team, 2026-09-26) — THE CREATE PATH ONLY CHECKED THIS NODE. If the state row\n * is lost (wrong `--stage`, an FQN rename, a wiped state store) while the cluster already lives on\n * OTHER control-plane nodes, the cold-start adoption read on THIS node comes back empty, plan\n * calls `create`, and `talosctl bootstrap` runs here too — a SECOND, isolated etcd cluster: split\n * brain. Before bootstrapping, every OTHER declared control-plane node (`props.peers`) must show a\n * successful, EMPTY etcd-members read — proof no cluster already exists anywhere this row knows\n * about. A peer that already has members, or a peer whose read fails, refuses bootstrap exactly\n * like an already-bootstrapped confirmation failure does (same typed error, same \"hand it to a\n * human\" posture) — a genuinely fresh cluster has no peers with members yet, so this never blocks\n * a real first boot.\n * ⚠️ `peers` IS OPTIONAL, SO THIS GUARD IS OPT-IN — an existing single-control-plane declaration\n * keeps working unguarded; a consuming stack with more than one control-plane node (decision 66:\n * 3, one per TB4 node) SHOULD list the other two here to get the protection.\n * ★ `Effect.all` over a mapped array, not `Effect.forEach` — oxlint's unicorn/no-array-for-each\n * matches the method NAME and cannot tell Effect's from Array's (same pattern as\n * openbao/cloudflare-permission-groups.ts).\n */\nexport const assertNoLivePeers = (props: BootstrapProps, talosconfigPath: string) =>\n Effect.all(\n (props.peers ?? []).map((peer) =>\n isBootstrapped({ ...props, node: peer }, talosconfigPath).pipe(\n Effect.matchEffect({\n onFailure: (cause) =>\n Effect.fail(\n new TalosReBootstrapRefused({\n detail: `peer ${peer}: live read failed before bootstrap: ${String(cause)}`,\n node: props.node,\n }),\n ),\n onSuccess: (hasMembers) =>\n hasMembers\n ? Effect.fail(\n new TalosReBootstrapRefused({\n detail:\n `peer ${peer} already reports etcd members — a cluster may already exist; ` +\n 'refusing to bootstrap a second one',\n node: props.node,\n }),\n )\n : Effect.void,\n }),\n ),\n ),\n { discard: true },\n );\n",
13
23
  "/**\n * `Talos.MachineConfig`'s typed failures — split out of talos-machine-config.ts (2026-09-26,\n * K-A3) for the same reason proxmox/credential-errors.ts gives: keep a class's own header out of\n * the 250-line budget of the file that raises it.\n */\nimport * as Data from 'effect/Data';\nimport type { ApplyMode } from './resource.ts';\n\n/**\n * The OpenBao KV content at `mount/key` does not hash to the pinned `configDigest`.\n *\n * ★ FAIL CLOSED, NO SPAWN — docs/plans/2026-09-26-talos-secrets-flow.md's O-A: \"a poisoned or\n * fat-fingered KV write cannot silently reach a node\". Raised BEFORE any talosctl process\n * starts, so a mismatch never sends an unpinned config anywhere — see reconcile() in\n * talos-machine-config.ts, which checks this ahead of minting the talosconfig credential too.\n * ⛔ NEITHER DIGEST IN THIS MESSAGE IS THE CONFIG. Both are sha256 hex digests — safe to log,\n * safe to persist — never the KV content itself.\n */\nexport class TalosConfigDigestMismatch extends Data.TaggedError('TalosConfigDigestMismatch')<{\n readonly mount: string;\n readonly key: string;\n readonly expected: string;\n readonly got: string;\n}> {\n override get message(): string {\n return (\n `${this.mount}/${this.key}: live content digest ${this.got} does not match the pinned ` +\n `configDigest ${this.expected}. Fail closed — nothing was sent to talosctl. Either the KV ` +\n 'value was rewritten without a matching PR, or the pinned digest is stale; check which one ' +\n 'moved before re-pinning either side.'\n );\n }\n}\n\n/**\n * `apply-config` returned success but the live machineconfig digest never matched the pin within\n * the bounded poll (machine-config-poll.ts). See\n * docs/plans/2026-09-26-talos-stack-first-boot.md's \"Converged\" section.\n *\n * ⛔ THIS IS THE REPLACEMENT FOR A SILENT `converged: false`. The shipped code let a read\n * failure during convergence checking disguise itself as \"not converged yet\" forever\n * (`orElseSucceed`); this type makes cap expiry a refusal an operator sees, not a plan that\n * quietly retries the same apply on every future run.\n */\nexport class TalosConvergenceTimeout extends Data.TaggedError('TalosConvergenceTimeout')<{\n readonly node: string;\n readonly mode: ApplyMode;\n readonly attempts: number;\n}> {\n override get message(): string {\n return (\n `${this.node}: apply-config (--mode ${this.mode}) was accepted but the live machineconfig ` +\n `digest never matched the pin within ${this.attempts} bounded poll attempts. Refusing to ` +\n 'report converged — hand this node to the operator rather than silently pass.'\n );\n }\n}\n\n/**\n * `Talos.Bootstrap` reconcile found state already recording `bootstrapped: true`, and a live\n * check against etcd could not reconfirm it — either the read itself failed (`detail` carries the\n * propagated cause), or it succeeded and came back with no members.\n *\n * ★ K-talos-first-boot's \"once means once\" — docs/plans/2026-09-26-talos-stack-first-boot.md's own\n * section of that name. EITHER cause raises this SAME typed error, and both ways `talosctl\n * bootstrap` is never spawned a second time: re-running it against a node that lost its etcd\n * data (a VM replace, a reset) forms a second, isolated single-member etcd cluster instead of\n * rejoining the existing one (REASONED, `v1alpha1_server.go:441` — Talos's only server-side\n * guard is a non-empty data directory, not \"did this cluster already bootstrap\"). That is split\n * brain, and nothing here can tell a genuinely reset node (needs its own operator-run recovery)\n * apart from a merely slow or unreachable read (needs a retry) — so both refuse alike and hand\n * the node to a human instead of guessing.\n */\nexport class TalosReBootstrapRefused extends Data.TaggedError('TalosReBootstrapRefused')<{\n readonly node: string;\n readonly detail: string;\n}> {\n override get message(): string {\n return (\n `${this.node}: state already recorded a successful bootstrap, and a live check could not ` +\n `reconfirm it (${this.detail}). Refusing to run 'talosctl bootstrap' again — that risks a ` +\n 'second, isolated etcd cluster on a reset node. This needs an operator, not a reconcile.'\n );\n }\n}\n",
14
- "/**\n * `Talos.ClusterHealth` — readiness gate other resources can depend on via `after`.\n *\n * ★ REASONED FROM talosctl health (Talos v1.13 CLI reference): checks Talos services, etcd, and\n * Kubernetes component health; `--wait-timeout` defaults to 20m0s.\n *\n * ⚠️ PLAN READS USE A SHORT TIMEOUT SO `plan` DOES NOT BLOCK TWENTY MINUTES. Reconcile uses the\n * declared timeout — that is the deploy gate, not the plan gate.\n *\n * ⛔ THIS RESOURCE ASSUMES A CNI IS ALREADY RUNNING (K-talos-first-boot, 2026-09-26). The default\n * `talosctl health` suite checks nodes Ready, kube-proxy and CoreDNS, and Talos's own source\n * comment says these wait on the CNI (REASONED, `pkg/cluster/check/default.go:28-60,89-91`;\n * docs/plans/2026-09-26-talos-stack-first-boot.md's \"CNI ordering\" section). A consuming stack's\n * `after` MUST include the Cilium install step, not just `Talos.Bootstrap`/`Talos.Kubeconfig` —\n * declaring this row directly after bootstrap deadlocks into the `--wait-timeout` on every first\n * deploy, because Argo CD itself needs pod networking before it can install Cilium. Row order:\n * Bootstrap → Kubeconfig → Cilium (inline manifests in the seeded machine config, D-S2) →\n * `Talos.ClusterHealth`.\n * ⛔ NO SWALLOWED TRANSPORT ERRORS (K-talos-first-boot) — the shipped `read` caught EVERY error\n * from `check()`, including a `mintTalosconfig`/`bao` failure, into a plain `healthy: false`. A\n * vault outage would then read as \"cluster not healthy yet\" — an operator chasing a Cilium\n * rollout would never learn the real problem was vault. Both `read` and `reconcile` now only\n * catch `TalosError` (`talosctl health` itself ran and exited non-zero — the one case this\n * family may honestly call \"not healthy\"); anything else propagates untouched.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { mintTalosconfig } from './credentials.ts';\nimport type { TalosRequirements, WithTarget } from './resource.ts';\nimport { TalosError, talosctl } from './talosctl.ts';\n\nexport interface ClusterHealthProps extends WithTarget {\n /** Control-plane node IPs passed to `--control-plane-nodes`. */\n controlPlaneNodes: readonly string[];\n /** Worker node IPs passed to `--worker-nodes`. */\n workerNodes?: readonly string[];\n /**\n * Reconcile wait (`--wait-timeout`), e.g. `20m0s`. Default from published CLI.\n *\n * ⚠️ REASONED default — not measured here.\n */\n waitTimeout?: string;\n /**\n * Ordering edge. ⛔ MUST reach past `Talos.Bootstrap`/`Talos.Kubeconfig` all the way through the\n * Cilium CNI install (this file's own header, \"CNI ordering\") — the default health checks wait\n * on kube-proxy and CoreDNS, both of which wait on a CNI that does not exist yet at bootstrap.\n */\n after?: readonly unknown[];\n}\n\nexport interface ClusterHealthAttributes {\n healthy: boolean;\n controlPlaneNodes: string;\n workerNodes: string;\n}\n\nexport interface TalosClusterHealth extends Resource<\n 'Talos.ClusterHealth',\n ClusterHealthProps,\n ClusterHealthAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosClusterHealth = Resource<TalosClusterHealth>('Talos.ClusterHealth');\n\nconst nodeCsv = (nodes: readonly string[] | undefined) =>\n nodes === undefined || nodes.length === 0 ? '' : nodes.join(',');\n\nconst healthArgs = (props: ClusterHealthProps, waitTimeout: string) => {\n const args = ['health', '--wait-timeout', waitTimeout];\n const cp = nodeCsv(props.controlPlaneNodes);\n const workers = nodeCsv(props.workerNodes);\n if (cp !== '') args.push('--control-plane-nodes', cp);\n if (workers !== '') args.push('--worker-nodes', workers);\n return args;\n};\n\n/**\n * ⛔ WRAPPED IN `Effect.scoped` (K-A3, 2026-09-26) — `mintTalosconfig` contributes `Scope.Scope`\n * to its own return type rather than closing its scope internally (the C1 fix, credentials.ts's\n * own header); both `read` and `reconcile` call this one function, so wrapping it here covers\n * both callers.\n * ⛔ I1 FIX (LAND red team, 2026-09-26) — `--nodes` NAMES ONE CONTACT NODE, NOT THE WHOLE CLUSTER.\n * MEASURED against local talosctl v1.13.8 (unroutable TEST-NET addresses): `talosctl health\n * --nodes <ip1>,<ip2>` fails with `command \"health\" is not supported with multiple nodes` — the\n * shipped code passed EVERY control-plane node as `--nodes`, so with decision 66's 3-node layout\n * this command could never succeed even against a genuinely healthy cluster: `read` always\n * reported `healthy:false`, `diff` always planned `update`, and `reconcile` always failed with a\n * misleading \"not healthy within Nm\". Fixed: the first control-plane node is the sole `--nodes`/\n * `--endpoints` contact point (talosctl proxies the actual check through it); the FULL node lists\n * still go to `--control-plane-nodes`/`--worker-nodes` via `healthArgs`, which is what `talosctl\n * health` actually checks the health OF.\n */\nconst check = (props: ClusterHealthProps, waitTimeout: string) =>\n Effect.scoped(\n Effect.gen(function* () {\n const credential = yield* mintTalosconfig(props.target);\n const contact = props.controlPlaneNodes[0];\n if (contact === undefined) {\n return yield* Effect.fail(\n new Error(\n `Talos.ClusterHealth ${props.target.cluster}: controlPlaneNodes is empty — need at ` +\n 'least one node to contact.',\n ),\n );\n }\n yield* talosctl(healthArgs(props, waitTimeout), {\n endpoints: [contact],\n nodes: [contact],\n talosconfigPath: credential.talosconfigPath,\n });\n return {\n controlPlaneNodes: nodeCsv(props.controlPlaneNodes),\n healthy: true,\n workerNodes: nodeCsv(props.workerNodes),\n };\n }),\n );\n\n/**\n * ⛔ CATCHES ONLY `TalosError` (K-talos-first-boot) — a run of `talosctl health` that itself\n * completed and exited non-zero, which is the only outcome this family may honestly call \"not\n * healthy yet\". Anything else (a `mintTalosconfig`/`bao` failure, a JS defect) propagates instead\n * of masquerading as an unhealthy cluster — see this file's own header.\n */\nconst isTalosError = (cause: unknown): cause is TalosError => cause instanceof TalosError;\n\n/** ★ EXPORTED for talos-cluster-health.test.ts — see talos-bootstrap.ts's own note on the pattern. */\nexport const readClusterHealth = (props: ClusterHealthProps) =>\n check(props, '5s').pipe(\n Effect.catchIf(isTalosError, () =>\n Effect.succeed({\n controlPlaneNodes: nodeCsv(props.controlPlaneNodes),\n healthy: false,\n workerNodes: nodeCsv(props.workerNodes),\n }),\n ),\n );\n\nexport const diffClusterHealth = (\n news: Input<ClusterHealthProps>,\n output: ClusterHealthAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readClusterHealth(news);\n if (live.healthy) return { action: 'noop' } as const;\n return { action: 'update' } as const;\n });\n\nexport const reconcileClusterHealth = (props: ClusterHealthProps) =>\n check(props, props.waitTimeout ?? '20m0s').pipe(\n Effect.catchIf(isTalosError, (cause) =>\n Effect.fail(\n new Error(\n `Talos.ClusterHealth ${props.target.cluster}: cluster not healthy within ` +\n `${props.waitTimeout ?? '20m0s'} — ${String(cause)}`,\n ),\n ),\n ),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<ClusterHealthProps>;\n output: ClusterHealthAttributes | undefined;\n }) => diffClusterHealth(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: ClusterHealthProps }) => readClusterHealth(olds),\n reconcile: ({ news }: { news: ClusterHealthProps }) => reconcileClusterHealth(news),\n};\n\nexport const TalosClusterHealthProvider = () =>\n Provider.effect(TalosClusterHealth, Effect.succeed(TalosClusterHealth.Provider.of(handlers)));\n",
24
+ "/**\n * `Talos.ClusterIdentity` — a read-only resource that reports WHICH physical cluster a name means.\n *\n * ★ It reads the vault kubeconfig and GETs the kube-system Namespace once (`cluster-identity.ts`),\n * and publishes `{ uid }`. That is the BOOTSTRAP-THEN-PIN step (cluster-adapter.ts header): the\n * first deploy creates the cluster and this row with no workloads, the operator copies the\n * printed uid into the adapter config, and workloads take `talosOpenBaoConnection(<literal>)`.\n * ⛔ It publishes NO `connection`: an Output uid in a workload's auth is unresolved at plan time\n * and hides a cluster change from the plan (`talosOpenBaoConnection` explains the DELETE on B).\n * ⛔ DRIFT REPAIR CANNOT LAUNDER A MOVE: `read` receives the persisted output and compares it, so\n * `Drift.repair` fails with `TalosClusterMoved` instead of reconciling B against B.\n * ⛔ IT MUTATES NOTHING: no vault write, no cluster write, `delete` is a no-op. Its only effect is\n * the value it reports. `after` must reach past Cilium/CNI only if the apiserver needs it; the\n * kube-system namespace exists as soon as the apiserver answers.\n * ⛔ A CHANGED UID IS REFUSED, NEVER AN UPDATE (`TalosClusterMoved`, in diff AND reconcile). This\n * resource declares no `stables`, so downstream the engine sees an unresolved Output, every\n * workload `diff` returns undefined and the engine plans an UPDATE, not a replace (Plan.ts\n * resourceExpr, `isResolved(news)` in Manifest.ts and HelmChart.ts). Reconcile would then\n * connect with the NEW uid and force-apply onto the new cluster while the old cluster's objects\n * are orphaned (an earlier comment here claimed a replace and a refusal at cleanup: it cannot\n * happen). A real move is a NEW identity resource per physical cluster.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { TalosClusterMoved } from './cluster-adapter-errors.ts';\nimport { readClusterUid } from './cluster-identity.ts';\nimport { openTransport, talosVaultLocation, withConnectDeadline } from './cluster-transport.ts';\nimport type { KubeconfigProps } from './kubeconfig.ts';\nimport type { TalosRequirements } from './resource.ts';\n\ntype KubeconfigSource = Pick<KubeconfigProps, 'context' | 'kubeconfigKey' | 'target'>;\n\nexport interface ClusterIdentityProps extends KubeconfigSource {\n /** Ordering edge: after `Talos.Kubeconfig` (the vault key must exist) and the apiserver is up. */\n after?: readonly unknown[];\n}\n\nexport interface ClusterIdentityAttributes {\n /**\n * The cluster's kube-system `metadata.uid`. Public. ⛔ NOT A `connection`: these attributes are\n * deliberately not `ClusterLike`. Pin this value as a literal in `TalosOpenBaoAdapter` and build\n * workloads' connection from that literal (bootstrap-then-pin, cluster-adapter.ts header).\n */\n uid: string;\n}\n\nexport interface TalosClusterIdentity extends Resource<\n 'Talos.ClusterIdentity',\n ClusterIdentityProps,\n ClusterIdentityAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosClusterIdentity = Resource<TalosClusterIdentity>('Talos.ClusterIdentity');\n\n/**\n * ★ EXPORTED for talos-cluster-identity.test.ts — see talos-bootstrap.ts's note on the pattern.\n * ⛔ A PERSISTED OUTPUT IS COMPARED HERE TOO, not only in reconcile: `Drift.repair` hands `read`\n * the persisted attributes, then reconciles `news: old.props, output: <what read returned>`.\n * A read that ignored the output returned the NEW uid, so the reconcile guard compared B with B\n * and saved it. Failing in read stops that path with `TalosClusterMoved`.\n */\nexport const readClusterIdentity = (\n props: ClusterIdentityProps,\n output?: ClusterIdentityAttributes,\n) =>\n Effect.gen(function* () {\n const cluster = props.target.cluster;\n // ⛔ Same single deadline as connect: a hung `bao` must not hang the plan.\n const uid = yield* withConnectDeadline(\n cluster,\n Effect.gen(function* () {\n const transport = yield* openTransport(talosVaultLocation(props));\n return yield* readClusterUid(cluster, transport);\n }),\n );\n if (output !== undefined && uid !== output.uid) {\n return yield* Effect.fail(new TalosClusterMoved({ cluster, live: uid, saved: output.uid }));\n }\n return { uid };\n });\n\n/** ⛔ Fails closed when a saved uid exists and the live one differs. See the header. */\nexport const reconcileClusterIdentity = (\n props: ClusterIdentityProps,\n output: ClusterIdentityAttributes | undefined,\n) => readClusterIdentity(props, output);\n\nexport const diffClusterIdentity = (\n news: Input<ClusterIdentityProps>,\n output: ClusterIdentityAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n yield* reconcileClusterIdentity(news, output);\n return { action: 'noop' } as const;\n });\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<ClusterIdentityProps>;\n output: ClusterIdentityAttributes | undefined;\n }) => diffClusterIdentity(news, output),\n list: () => Effect.succeed([]),\n read: ({\n olds,\n output,\n }: {\n olds: ClusterIdentityProps;\n output: ClusterIdentityAttributes | undefined;\n }) => readClusterIdentity(olds, output),\n reconcile: ({\n news,\n output,\n }: {\n news: ClusterIdentityProps;\n output: ClusterIdentityAttributes | undefined;\n }) => reconcileClusterIdentity(news, output),\n};\n\nexport const TalosClusterIdentityProvider = () =>\n Provider.effect(TalosClusterIdentity, Effect.succeed(TalosClusterIdentity.Provider.of(handlers)));\n",
25
+ "/**\n * `Talos.ClusterHealth` — readiness gate other resources can depend on via `after`.\n *\n * ★ REASONED FROM talosctl health (Talos v1.13 CLI reference): checks Talos services, etcd, and\n * Kubernetes component health; `--wait-timeout` defaults to 20m0s.\n *\n * ⚠️ PLAN READS USE A SHORT TIMEOUT SO `plan` DOES NOT BLOCK TWENTY MINUTES. Reconcile uses the\n * declared timeout — that is the deploy gate, not the plan gate.\n *\n * ⛔ THIS RESOURCE ASSUMES A CNI IS ALREADY RUNNING (K-talos-first-boot, 2026-09-26). The default\n * `talosctl health` suite checks nodes Ready, kube-proxy and CoreDNS, and Talos's own source\n * comment says these wait on the CNI (REASONED, `pkg/cluster/check/default.go:28-60,89-91`;\n * docs/plans/2026-09-26-talos-stack-first-boot.md's \"CNI ordering\" section). A consuming stack's\n * `after` MUST include the Cilium install step, not just `Talos.Bootstrap`/`Talos.Kubeconfig` —\n * declaring this row directly after bootstrap deadlocks into the `--wait-timeout` on every first\n * deploy, because Argo CD itself needs pod networking before it can install Cilium. Row order:\n * Bootstrap → Kubeconfig → Cilium (inline manifests in the seeded machine config, D-S2) →\n * `Talos.ClusterHealth`.\n * ⛔ NO SWALLOWED TRANSPORT ERRORS (K-talos-first-boot) — the shipped `read` caught EVERY error\n * from `check()`, including a `mintTalosconfig`/`bao` failure, into a plain `healthy: false`. A\n * vault outage would then read as \"cluster not healthy yet\" — an operator chasing a Cilium\n * rollout would never learn the real problem was vault. Both `read` and `reconcile` now only\n * catch `TalosError` (`talosctl health` itself ran and exited non-zero — the one case this\n * family may honestly call \"not healthy\"); anything else propagates untouched.\n * ★ `connection` IS A PASS-THROUGH so this resource is `ClusterLike`. Later rows take\n * `cluster: health`. The health check itself still uses `target` and `talosctl`; the field is\n * copied onto attributes and is not a credential. It is required: an optional field would not\n * satisfy `{ connection: Connection }`.\n */\nimport { Resource } from 'alchemy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport type { TalosOpenBaoConnection } from './cluster-adapter.ts';\nimport { mintTalosconfig } from './credentials.ts';\nimport { literalConnectionRefusal, withLiteralConnection } from './literal-connection.ts';\nimport type { TalosRequirements, WithTarget } from './resource.ts';\nimport { TalosError, talosctl } from './talosctl.ts';\n\nexport interface ClusterHealthProps extends WithTarget {\n /** Control-plane node IPs passed to `--control-plane-nodes`. */\n controlPlaneNodes: readonly string[];\n /** Worker node IPs passed to `--worker-nodes`. */\n workerNodes?: readonly string[];\n /**\n * Reconcile wait (`--wait-timeout`), e.g. `20m0s`. Default from published CLI.\n *\n * ⚠️ REASONED default — not measured here.\n */\n waitTimeout?: string;\n /**\n * Ordering edge. ⛔ MUST reach past `Talos.Bootstrap`/`Talos.Kubeconfig` all the way through the\n * Cilium CNI install (this file's own header, \"CNI ordering\") — the default health checks wait\n * on kube-proxy and CoreDNS, both of which wait on a CNI that does not exist yet at bootstrap.\n */\n after?: readonly unknown[];\n /**\n * Kubernetes connection copied onto attributes so a later row can take `cluster: this`.\n * Not read by the health check. Persist only a secret-free connection (`talos-openbao`).\n */\n connection: TalosOpenBaoConnection;\n}\n\nexport interface ClusterHealthAttributes {\n healthy: boolean;\n controlPlaneNodes: string;\n workerNodes: string;\n /** Same object as the prop. Makes these attributes `ClusterLike`. */\n connection: TalosOpenBaoConnection;\n}\n\nexport interface TalosClusterHealth extends Resource<\n 'Talos.ClusterHealth',\n ClusterHealthProps,\n ClusterHealthAttributes,\n never,\n TalosRequirements\n> {}\n\n// ⛔ Declaration-time literal guard: a fresh resource skips `diff` (see `withLiteralConnection`).\nexport const TalosClusterHealth = withLiteralConnection(\n Resource<TalosClusterHealth>('Talos.ClusterHealth'),\n);\n\nconst nodeCsv = (nodes: readonly string[] | undefined) =>\n nodes === undefined || nodes.length === 0 ? '' : nodes.join(',');\n\nconst attributes = (props: ClusterHealthProps, healthy: boolean): ClusterHealthAttributes => ({\n connection: props.connection,\n controlPlaneNodes: nodeCsv(props.controlPlaneNodes),\n healthy,\n workerNodes: nodeCsv(props.workerNodes),\n});\n\n/**\n * ⚠️ A ROW SAVED BEFORE `connection` EXISTED HAS NONE — `right` is `undefined` at runtime despite\n * the type, and reading `right.auth` threw on a healthy cluster. Missing means \"update\".\n */\nconst sameConnection = (\n left: TalosOpenBaoConnection,\n right: TalosOpenBaoConnection | undefined,\n): boolean =>\n right?.auth?.kind === left.auth.kind &&\n right.auth.uid === left.auth.uid &&\n // ⚠️ A row that still carries the legacy `auth.cluster` alias must update, so it leaves state.\n !Object.hasOwn(right.auth, 'cluster');\n\nconst healthArgs = (props: ClusterHealthProps, waitTimeout: string) => {\n const args = ['health', '--wait-timeout', waitTimeout];\n const cp = nodeCsv(props.controlPlaneNodes);\n const workers = nodeCsv(props.workerNodes);\n if (cp !== '') args.push('--control-plane-nodes', cp);\n if (workers !== '') args.push('--worker-nodes', workers);\n return args;\n};\n\n/**\n * ⛔ WRAPPED IN `Effect.scoped` (K-A3, 2026-09-26) — `mintTalosconfig` contributes `Scope.Scope`\n * to its own return type rather than closing its scope internally (the C1 fix, credentials.ts's\n * own header); both `read` and `reconcile` call this one function, so wrapping it here covers\n * both callers.\n * ⛔ I1 FIX (LAND red team, 2026-09-26) — `--nodes` NAMES ONE CONTACT NODE, NOT THE WHOLE CLUSTER.\n * MEASURED against local talosctl v1.13.8 (unroutable TEST-NET addresses): `talosctl health\n * --nodes <ip1>,<ip2>` fails with `command \"health\" is not supported with multiple nodes` — the\n * shipped code passed EVERY control-plane node as `--nodes`, so with decision 66's 3-node layout\n * this command could never succeed even against a genuinely healthy cluster: `read` always\n * reported `healthy:false`, `diff` always planned `update`, and `reconcile` always failed with a\n * misleading \"not healthy within Nm\". Fixed: the first control-plane node is the sole `--nodes`/\n * `--endpoints` contact point (talosctl proxies the actual check through it); the FULL node lists\n * still go to `--control-plane-nodes`/`--worker-nodes` via `healthArgs`, which is what `talosctl\n * health` actually checks the health OF.\n */\nconst check = (props: ClusterHealthProps, waitTimeout: string) =>\n Effect.scoped(\n Effect.gen(function* () {\n const credential = yield* mintTalosconfig(props.target);\n const contact = props.controlPlaneNodes[0];\n if (contact === undefined) {\n return yield* Effect.fail(\n new Error(\n `Talos.ClusterHealth ${props.target.cluster}: controlPlaneNodes is empty — need at ` +\n 'least one node to contact.',\n ),\n );\n }\n yield* talosctl(healthArgs(props, waitTimeout), {\n endpoints: [contact],\n nodes: [contact],\n talosconfigPath: credential.talosconfigPath,\n });\n return attributes(props, true);\n }),\n );\n\n/**\n * ⛔ CATCHES ONLY `TalosError` (K-talos-first-boot) — a run of `talosctl health` that itself\n * completed and exited non-zero, which is the only outcome this family may honestly call \"not\n * healthy yet\". Anything else (a `mintTalosconfig`/`bao` failure, a JS defect) propagates instead\n * of masquerading as an unhealthy cluster — see this file's own header.\n */\nconst isTalosError = (cause: unknown): cause is TalosError => cause instanceof TalosError;\n\n/** ★ EXPORTED for talos-cluster-health.test.ts — see talos-bootstrap.ts's own note on the pattern. */\nexport const readClusterHealth = (props: ClusterHealthProps) =>\n check(props, '5s').pipe(\n Effect.catchIf(isTalosError, () => Effect.succeed(attributes(props, false))),\n );\n\nexport const diffClusterHealth = (\n news: Input<ClusterHealthProps>,\n output: ClusterHealthAttributes | undefined,\n) =>\n Effect.gen(function* () {\n // ⛔ `cluster: health` hands this connection to workloads: refuse an Output here, while it is\n // still an Input (`literal-connection.ts`).\n const refused = literalConnectionRefusal((news as { connection?: unknown }).connection);\n if (refused !== undefined) return yield* Effect.fail(refused);\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readClusterHealth(news);\n if (live.healthy && sameConnection(live.connection, output.connection)) {\n return { action: 'noop' } as const;\n }\n return { action: 'update' } as const;\n });\n\nexport const reconcileClusterHealth = (props: ClusterHealthProps) =>\n check(props, props.waitTimeout ?? '20m0s').pipe(\n Effect.catchIf(isTalosError, (cause) =>\n Effect.fail(\n new Error(\n `Talos.ClusterHealth ${props.target.cluster}: cluster not healthy within ` +\n `${props.waitTimeout ?? '20m0s'} — ${String(cause)}`,\n ),\n ),\n ),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<ClusterHealthProps>;\n output: ClusterHealthAttributes | undefined;\n }) => diffClusterHealth(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: ClusterHealthProps }) => readClusterHealth(olds),\n reconcile: ({ news }: { news: ClusterHealthProps }) => reconcileClusterHealth(news),\n};\n\nexport const TalosClusterHealthProvider = () =>\n Provider.effect(TalosClusterHealth, Effect.succeed(TalosClusterHealth.Provider.of(handlers)));\n",
26
+ "/**\n * Runtime refusal of a `talos-openbao` connection that is not a plain literal.\n *\n * ⛔ A RESOURCE THAT TAKES A `connection` PROP MUST CALL THIS IN `diff`, WHERE THE PROP IS STILL\n * AN `Input`. By `read`/`reconcile` the engine has resolved an Output to its current string, so\n * the same check there can no longer tell a literal from an Output: the refusal only works\n * before resolution. An Output in the connection is unresolved at plan time, upstream plans an\n * UPDATE for every workload on it, and reconcile replays the old cluster's deletes on the new\n * one (`talosOpenBaoConnection` in cluster-adapter.ts).\n */\nimport { hasUnresolvedInputs } from 'alchemy/Diff';\nimport * as Effect from 'effect/Effect';\nimport { TalosUidNotLiteral } from './cluster-adapter-errors.ts';\n\n/**\n * The typed refusal unless `connection` is `{ auth: { kind, uid: literal } }`, else `undefined`.\n * ★ A value, never a throw: a throw inside `Effect.gen` would become a defect, not a failure.\n */\nexport const literalConnectionRefusal = (connection: unknown): TalosUidNotLiteral | undefined => {\n const auth = (connection as { auth?: { kind?: unknown; uid?: unknown } } | undefined)?.auth;\n // ⛔ A stock `kubeconfig` connection has no uid and would pass the checks below by failing the\n // `uid` test as \"not a string\" — but it must be refused here, at declaration/diff time, because\n // connect would only refuse it later, after the engine has resolved it (and its empty path has\n // already fallen back to `$KUBECONFIG`). Only `talos-openbao` carries a literal uid.\n return hasUnresolvedInputs(connection) ||\n auth?.kind !== 'talos-openbao' ||\n typeof auth?.uid !== 'string' ||\n auth.uid === ''\n ? new TalosUidNotLiteral({})\n : undefined;\n};\n\n/**\n * ⛔ THE `diff` GUARD ALONE IS NOT ENOUGH (round-4 review): alchemy skips `diff` for a FRESH\n * resource whose inputs are unresolved, and reconcile then copies the resolved string downstream\n * — an Output uid slips through on exactly the first deploy. So the same refusal runs when the\n * resource is DECLARED, before any input resolution, by wrapping its constructor.\n * ★ A Proxy over the class (not a new function) keeps `.Provider`, `.Self`, `.ref` and the type.\n * Plain props fail the declaring Effect; a props Effect fails once it yields.\n */\nexport const withLiteralConnection = <C extends (...args: never[]) => unknown>(resource: C): C =>\n new Proxy(resource, {\n apply: (target, thisArg, args: unknown[]) => {\n const refusal = (given: unknown) =>\n literalConnectionRefusal((given as { connection?: unknown } | undefined)?.connection);\n const props = args[1];\n if (Effect.isEffect(props)) {\n const checked = props.pipe(\n Effect.flatMap((resolved) => {\n const refused = refusal(resolved);\n return refused === undefined ? Effect.succeed(resolved) : Effect.fail(refused);\n }),\n );\n return Reflect.apply(target, thisArg, [args[0], checked, ...args.slice(2)]);\n }\n const refused = refusal(props);\n return refused === undefined ? Reflect.apply(target, thisArg, args) : Effect.fail(refused);\n },\n });\n",
15
27
  "/**\n * `Talos.MachineConfig` — apply one machine configuration document to one node.\n *\n * ★ REASONED FROM talosctl apply-config (Talos v1.13 CLI reference): `-f/--file`, `-n/--nodes`,\n * `-m/--mode`, `-i/--insecure` for maintenance mode.\n *\n * ⛔ THE CONFIG BODY IS NEVER AN ATTRIBUTE, A PROP, OR ARGV — ONLY ITS DIGEST. K-A3\n * (docs/plans/2026-09-26-talos-secrets-flow.md, option O-A) moved the source of truth from a\n * repo file (the shipped `configFile` + `STACK_DIR`, gone with this rewrite) to OpenBao: props\n * carry a `configKey` (a vault path) and a `configDigest` PINNED IN GIT, never the bytes. The\n * source is write-only from Alchemy's point of view — content is read once per reconcile,\n * verified against the pin, written to a session-temp file, and never returned from any\n * handler.\n * ⛔ NEVER `--dry-run`. Talos's dry-run prints a full, unredacted old/new config diff — with an\n * empty old config (the first apply) that diff IS the whole config, CA private key and\n * bootstrap token included (REASONED, `internal/app/machined/.../v1alpha1_server.go:258-272` +\n * `configdiff.go`; docs/plans/2026-09-26-talos-stack-first-boot.md). This file never builds\n * that flag.\n * ⛔ `insecure` IS NOT A PROP. A fixed value fails in both directions — `true` breaks every later\n * update, `false` breaks the very first apply against a node with no talosconfig auth yet — so\n * CREATE (`output === undefined`) applies `--insecure` and UPDATE never does (resource.ts).\n */\nimport { Resource } from 'alchemy';\nimport type { Input } from 'alchemy/Input';\nimport * as Provider from 'alchemy/Provider';\nimport * as Effect from 'effect/Effect';\nimport { mintKvTempFile, mintTalosconfig, readKvValue } from './credentials.ts';\nimport { diffMachineConfig, liveSpecDigest, readMachineConfig } from './machine-config-read.ts';\nimport { type PollPolicy, confirmConverged } from './machine-config-poll.ts';\nimport type { ApplyMode, TalosRequirements, WithTarget } from './resource.ts';\nimport { TalosConfigDigestMismatch } from './talos-errors.ts';\nimport { talosctl } from './talosctl.ts';\nimport { configDigest } from './values.ts';\n\nexport type { ApplyMode } from './resource.ts';\n\nexport interface MachineConfigProps extends WithTarget {\n /** Node IP or hostname — the `-n` target. */\n node: string;\n /** OpenBao KV path under `target.mount` holding this node's rendered config, e.g. `nodes/10001`. */\n configKey: string;\n /**\n * sha256(canonicalText(content)) of the seeded KV value (values.ts `configDigest`), pinned in\n * git by the operator. ⛔ Verified against the live KV content before ANY talosctl spawn — a\n * mismatch fails closed (`TalosConfigDigestMismatch`), nothing is applied.\n */\n configDigest: string;\n /** talosctl `-m` mode. Default `auto` per published CLI. */\n mode?: ApplyMode;\n /** Ordering edge — e.g. wait for Proxmox.Vm. */\n after?: readonly unknown[];\n}\n\nexport interface MachineConfigAttributes {\n node: string;\n configDigest: string;\n mode: ApplyMode;\n /**\n * Which convergence claim was made. `'read-back'`/`'accepted'` only come from `reconcile` (see\n * machine-config-poll.ts); `false` only comes from `read`, meaning a live digest was\n * successfully fetched and genuinely differs — never a stand-in for a failed read, which\n * propagates as its own error instead (docs/plans/2026-09-26-talos-stack-first-boot.md).\n */\n converged: 'read-back' | 'accepted' | false;\n}\n\nexport interface TalosMachineConfig extends Resource<\n 'Talos.MachineConfig',\n MachineConfigProps,\n MachineConfigAttributes,\n never,\n TalosRequirements\n> {}\n\nexport const TalosMachineConfig = Resource<TalosMachineConfig>('Talos.MachineConfig');\n\n/**\n * The read path (`readMachineConfig`, `diffMachineConfig`, `liveSpecDigest`) lives in\n * machine-config-read.ts — see that file's own header for the ownership-aware three-way answer\n * `read` now gives (fix-first #1/#2, PR 307 red team).\n */\n\n/** `pollPolicies` is a test seam only — see machine-config-poll.ts's `confirmConverged`. */\nexport const reconcileMachineConfig = (\n props: MachineConfigProps,\n output: MachineConfigAttributes | undefined,\n pollPolicies?: { readonly immediate: PollPolicy; readonly rebootish: PollPolicy },\n) =>\n Effect.scoped(\n Effect.gen(function* () {\n const mode = props.mode ?? 'auto';\n\n // ⛔ VERIFY BEFORE ANY talosctl SPAWN. A mismatch fails closed — see talos-errors.ts.\n const raw = yield* readKvValue(props.target.mount, props.configKey, ['config']);\n const gotDigest = configDigest(raw);\n if (gotDigest !== props.configDigest) {\n return yield* Effect.fail(\n new TalosConfigDigestMismatch({\n expected: props.configDigest,\n got: gotDigest,\n key: props.configKey,\n mount: props.target.mount,\n }),\n );\n }\n\n const credential = yield* mintTalosconfig(props.target);\n const { path } = yield* mintKvTempFile(raw, `${props.target.cluster}-${props.node}-config`);\n\n const isCreate = output === undefined;\n const args = [\n 'apply-config',\n '--file',\n path,\n '--mode',\n mode,\n ...(isCreate ? ['--insecure'] : []),\n ];\n yield* talosctl(args, { nodes: [props.node], talosconfigPath: credential.talosconfigPath });\n\n const converged = yield* confirmConverged(\n props.node,\n mode,\n liveSpecDigest(props, credential.talosconfigPath).pipe(\n Effect.map((live) => live === props.configDigest),\n ),\n pollPolicies,\n );\n\n return {\n configDigest: props.configDigest,\n converged,\n mode,\n node: props.node,\n } satisfies MachineConfigAttributes;\n }),\n );\n\nconst handlers = {\n delete: () => Effect.void,\n diff: ({\n news,\n output,\n }: {\n news: Input<MachineConfigProps>;\n output: MachineConfigAttributes | undefined;\n }) => diffMachineConfig(news, output),\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: MachineConfigProps }) => readMachineConfig(olds),\n reconcile: ({\n news,\n output,\n }: {\n news: MachineConfigProps;\n output: MachineConfigAttributes | undefined;\n }) => reconcileMachineConfig(news, output),\n};\n\nexport const TalosMachineConfigProvider = () =>\n Provider.effect(TalosMachineConfig, Effect.succeed(TalosMachineConfig.Provider.of(handlers)));\n",
16
28
  "/**\n * `Talos.MachineConfig`'s read path — split out of talos-machine-config.ts (2026-09-26, fix-first\n * #1/#2 on PR 307's red team) once the ownership-aware read needed its own header, the same reason\n * machine-config-poll.ts and talos-errors.ts were split out before it. Only `import type` comes\n * back from talos-machine-config.ts, so there is no runtime cycle between the two files.\n */\nimport { Unowned } from 'alchemy/AdoptPolicy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport * as Effect from 'effect/Effect';\nimport * as Result from 'effect/Result';\nimport { mintTalosconfig } from './credentials.ts';\nimport type { MachineConfigAttributes, MachineConfigProps } from './talos-machine-config.ts';\nimport { talosctl } from './talosctl.ts';\nimport { configDigest, extractMachineConfigSpec } from './values.ts';\n\n/**\n * Single live read: `talosctl get machineconfig v1alpha1`, extract `spec`, hash it. No retry, no\n * swallow.\n *\n * ⛔ THE ID IS NEVER OMITTED (fix-first #2, PR 307 red team). An unfiltered `get machineconfig`\n * lists `persistent` AND `v1alpha1`, sorted by id — `persistent` first — so a caller that does not\n * name `v1alpha1` gets whichever the SDK's `doc[0]` happens to be, never provably the applied\n * config (values.ts's own multi-document guard is the second half of this fix).\n * ★ `endpoints: [props.node]` (fix-first #5, same review) — without it talosctl falls back to the\n * talosconfig context's own endpoints, which may be a control-plane VIP that only comes up AFTER\n * bootstrap; every pre-bootstrap call in this file targets the node directly instead.\n */\nexport const liveSpecDigest = (props: MachineConfigProps, talosconfigPath: string) =>\n talosctl(['get', 'machineconfig', 'v1alpha1', '-o', 'yaml'], {\n endpoints: [props.node],\n nodes: [props.node],\n talosconfigPath,\n }).pipe(\n Effect.flatMap((wrapperYaml) => {\n const spec = extractMachineConfigSpec(wrapperYaml);\n return spec === undefined\n ? Effect.fail(\n new Error(\n `${props.node}: get machineconfig v1alpha1 returned no string 'spec' field — see ` +\n 'values.ts extractMachineConfigSpec for the expected shape.',\n ),\n )\n : Effect.succeed(configDigest(spec));\n }),\n );\n\n/**\n * ★ MAINTENANCE-MODE PROBE (fix-first #1, PR 307 red team). A freshly booted node has no\n * talosconfig auth yet, so the AUTHENTICATED read above fails there exactly the same way it would\n * against a genuinely unreachable node — the two must not be confused (a real transport failure\n * silently read as \"not created\" would let a cold-start plan skip straight past a broken node).\n * `--insecure` distinguishes them: REASONED from the published Talos quickstart\n * (`talosctl -n <ip> version --insecure` is the documented way to confirm a maintenance-mode node\n * before its first apply) — not measured on a live cluster. Success here means \"nothing applied\n * yet\", never \"converged\", and never returns config content.\n */\nconst probeMaintenanceMode = (props: MachineConfigProps, talosconfigPath: string) =>\n talosctl(['version'], {\n endpoints: [props.node],\n insecure: true,\n nodes: [props.node],\n talosconfigPath,\n }).pipe(\n Effect.as(true),\n Effect.orElseSucceed(() => false),\n );\n\n/**\n * ⛔ NO SWALLOWING. A transport failure here propagates as its own error (TalosError or the\n * shape error above) — never as `converged: false`. A false only means \"read succeeded, and\n * genuinely differs\" (docs/plans/2026-09-26-talos-stack-first-boot.md, acceptance test 3).\n * ⛔ THREE-WAY COLD-START ANSWER, NOT TWO (fix-first #1). Alchemy's engine calls this exact\n * function as its adoption probe with no prior state (alchemy beta.79 Plan.ts:1302-1318) and\n * again to recover an interrupted create (`:1413-1450`) — both hand it nothing to distinguish\n * \"not created\" from \"already configured\". Answering only \"attrs or error\" (the shipped shape)\n * meant a maintenance-mode node's expected auth failure aborted the plan instead of reaching\n * CREATE, and a genuinely different node's matching-cluster-CA-but-wrong-content read landed as a\n * plain, unbranded attrs object — a silent adopt with no `adopt()`, breaking first-boot acceptance\n * test 1 (\"zero adopts\"). Now: authenticated read fails but the maintenance probe succeeds →\n * `undefined` (not created); authenticated read succeeds and the digest matches → plain attrs\n * (ours); succeeds and differs → `Unowned` (exists, not proven ours — the digest match IS this\n * family's ownership proof, not a state-row lookup like `ownership/probe.ts`'s generic\n * `ownedRead`, which answers a different question: \"did OUR state row create this name\", not\n * \"does this node hold OUR pinned content\"); both reads fail → the authenticated error propagates.\n *\n * ★ EXPORTED (like proxmox/ceph-daemon.ts's `reconcileDaemon`) so tests call it directly with a\n * fake `ChildProcessSpawner` instead of driving it through the full Alchemy engine.\n */\nexport const readMachineConfig = (props: MachineConfigProps) =>\n Effect.scoped(\n Effect.gen(function* () {\n const credential = yield* mintTalosconfig(props.target);\n const outcome = yield* Effect.result(liveSpecDigest(props, credential.talosconfigPath));\n if (Result.isFailure(outcome)) {\n const reachable = yield* probeMaintenanceMode(props, credential.talosconfigPath);\n return reachable ? undefined : yield* Effect.fail(outcome.failure);\n }\n const attrs = {\n configDigest: props.configDigest,\n converged: outcome.success === props.configDigest ? ('read-back' as const) : false,\n mode: props.mode ?? 'auto',\n node: props.node,\n } satisfies MachineConfigAttributes;\n return attrs.converged === false ? Unowned(attrs) : attrs;\n }),\n );\n\nexport const diffMachineConfig = (\n news: Input<MachineConfigProps>,\n output: MachineConfigAttributes | undefined,\n) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* readMachineConfig(news);\n if (live !== undefined && live.converged !== false) return { action: 'noop' } as const;\n return { action: 'update' } as const;\n });\n",
17
29
  "/**\n * Post-apply convergence for `Talos.MachineConfig` — split out of talos-machine-config.ts\n * (2026-09-26, K-A3) once the bounded-poll logic needed its own header. See\n * docs/plans/2026-09-26-talos-stack-first-boot.md, \"Converged\" and \"Bootstrap\" sections.\n *\n * ⛔ NO SILENT `converged: false` HERE. A single attempt's own transport failure is swallowed\n * ONLY inside the bounded loop below — a rebooting node's API is legitimately unreachable for a\n * while — but the loop AS A WHOLE never swallows: running out of attempts always raises\n * `TalosConvergenceTimeout`, never a quiet `false`. That distinction is read()'s job, not\n * reconcile's — see talos-machine-config.ts.\n * ⚠️ SHORT INTERVALS, A LOW CAP, NEVER ONE LONG SLEEP — the house timeout rule, and the specific\n * reason talosctl's own `health` gate has a 20-minute `--wait-timeout`: a single blocking wait\n * that long would hide whether THIS process is still alive from anything watching it.\n */\nimport * as Effect from 'effect/Effect';\nimport type { ApplyMode } from './resource.ts';\nimport { TalosConvergenceTimeout } from './talos-errors.ts';\n\n/**\n * Modes whose apply can trigger a full install + reboot. REASONED, Talos v1.13 CLI reference.\n * ⛔ `'staged'` is deliberately absent — resource.ts's own header explains why (fix-first #2).\n */\nconst isRebootish = (mode: ApplyMode) => mode === 'reboot' || mode === 'auto';\n\n/**\n * ★ TWO POLICIES, ONE PER MODE CLASS — REASONED, no live cluster to time this against yet.\n * `no-reboot` never drops the API, so a handful of quick retries covers only ordinary\n * config-propagation lag. `reboot`/`auto` can drop the API for a full boot cycle, so the cap is\n * longer and the interval coarser. Both stay well inside the house rule above.\n */\nexport type PollPolicy = { readonly intervalMs: number; readonly maxAttempts: number };\n\nconst POLICY: { readonly immediate: PollPolicy; readonly rebootish: PollPolicy } = {\n immediate: { intervalMs: 2_000, maxAttempts: 5 }, // ~10s cap\n rebootish: { intervalMs: 5_000, maxAttempts: 24 }, // ~2m cap\n};\n\n/**\n * Run `check` until it reports `true` or `maxAttempts` is spent, sleeping `intervalMs` between\n * attempts. A per-attempt failure counts as \"not yet\" and does not end the loop early.\n */\nconst pollUntilMatch = <E, R>(\n check: Effect.Effect<boolean, E, R>,\n policy: { readonly intervalMs: number; readonly maxAttempts: number },\n): Effect.Effect<boolean, never, R> =>\n Effect.gen(function* () {\n for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {\n const matched = yield* check.pipe(Effect.orElseSucceed(() => false));\n if (matched) return true;\n if (attempt < policy.maxAttempts) yield* Effect.sleep(policy.intervalMs);\n }\n return false;\n });\n\n/**\n * Confirm convergence per `mode`'s policy, or fail with `TalosConvergenceTimeout`.\n *\n * Returns which CLAIM was proven, never a boolean — `'read-back'` for the immediate policy\n * (no-reboot), `'accepted'` for the reboot-tolerant one (reboot/auto): state records which kind of\n * confirmation actually happened, per the design doc's `converged` field.\n *\n * ⚠️ `policies` IS A TEST SEAM, NOT A PROP. `talos-machine-config.ts` never passes it, so\n * production always runs the REASONED defaults above; tests pass tiny intervals so a bounded\n * poll test finishes in milliseconds instead of the real ~10s/~2m caps.\n */\nexport const confirmConverged = <E, R>(\n node: string,\n mode: ApplyMode,\n check: Effect.Effect<boolean, E, R>,\n policies: { readonly immediate: PollPolicy; readonly rebootish: PollPolicy } = POLICY,\n): Effect.Effect<'read-back' | 'accepted', TalosConvergenceTimeout, R> =>\n Effect.gen(function* () {\n const rebootish = isRebootish(mode);\n const policy = rebootish ? policies.rebootish : policies.immediate;\n const matched = yield* pollUntilMatch(check, policy);\n if (!matched) {\n return yield* Effect.fail(\n new TalosConvergenceTimeout({ attempts: policy.maxAttempts, mode, node }),\n );\n }\n return rebootish ? 'accepted' : 'read-back';\n });\n"
18
30
  ],
19
- "mappings": ";AAkCA;AACA;AACA;AAGA;AACA;;;ACRA;AACA;AAEA;AACA;AACA;AAsBA,IAAM,0BAA0B;AAOzB,IAAM,yBAAyB;AAU/B,IAAM,cAAc,CACzB,OACA,KACA,WAEO,WAAI,UAAU,GAAG;AAAA,EACtB,MAAM,UAAU,OAA2B;AAAA,EAC3C,MAAM,SAAS,OAAoB,kBACjC,OACA,CAAC,MAAM,OAAO,gBAAgB,GAAG,SAAS,KAAK,GAC/C,EAAE,UAAU,OAAO,WAAW,MAAM,QAAQ,QAAQ,OAAO,UAAU,QAAQ,OAAO,CACtF,EAAE,KACA,QAAQ,OACD,eAAQ,CAAC,UACP,WACL;AAAA,IACE,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,OAAO,KACZ,mBACA,iBACA,WAAI,CAAC,SAAS,KAAK,KAAK,CAAC,CAClC;AAAA,IACA,QAAQ,MAAM,OAAO,KACZ,mBACA,iBACA,WAAI,CAAC,SAAS,KAAK,KAAK,CAAC,CAClC;AAAA,EACF,GACA,EAAE,aAAa,YAAY,CAC7B,CACF,GACO,aACT;AAAA,EAEA,IAAI,OAAO,aAAa,GAAG;AAAA,IACzB,OAAO,OAAc,YACnB,IAAI,MAAM,cAAc,SAAS,cAAc,OAAO,OAAO,QAAQ,MAAM,OAAO,QAAQ,CAC5F;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,KAAK,MAAM,OAAO,MAAM;AAAA,EACvC,MAAM,OAAO,OAAO,MAAM;AAAA,EAC1B,WAAW,SAAS,QAAQ;AAAA,IAC1B,MAAM,MAAM,OAAO;AAAA,IACnB,IAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM;AAAA,MAAI,OAAO;AAAA,EAC3D;AAAA,EACA,OAAO,OAAc,YACnB,IAAI,MACF,GAAG,SAAS,mBAAmB,OAAO,KAAK,GAAG,8CAC5C,kEACJ,CACF;AAAA,CACD;AAgBI,IAAM,iBAAiB,CAC5B,KACA,UAEO,WAAI,UAAU,GAAG;AAAA,EACtB,MAAM,OAAO,GAAG,IAAI,IAAI,aAAa,mBAAmB,SAAS,IAAI,aAAa;AAAA,EAClF,OAAc,sBACL,WAAI;AAAA,IACT,KAAK,MAAM;AAAA,MACT,MAAM,KAAK,SAAS,MAAM,MAAM,GAAK;AAAA,MACrC,IAAI;AAAA,QACF,cAAc,IAAI,GAAG;AAAA,gBACrB;AAAA,QACA,UAAU,EAAE;AAAA;AAAA;AAAA,IAGhB,OAAO,CAAC,UAAU,IAAI,MAAM,WAAW,oBAAoB,OAAO,KAAK,GAAG;AAAA,EAC5E,CAAC,GACD,MACS,kBAAW,EAAE,KAAK,MAAM,IAAI,KAAK,IAAI,EAAE,OAAO,GAAG,OAAO,MAAG;AAAA,IAAG;AAAA,IAAU,CAAC,EAAE,KACzE,qBAAc,MAAG;AAAA,IAAG;AAAA,GAAS,CACtC,CACJ;AAAA,EACA,OAAO,EAAE,KAAK;AAAA,CACf;AASI,IAAM,kBAAkB,CAC7B,WAEA,YAAY,OAAO,OAAO,OAAO,kBAAkB,yBAAyB;AAAA,EAC1E;AAAA,EACA;AACF,CAAC,EAAE,KACM,eAAQ,CAAC,QAAQ,eAAe,KAAK,GAAG,OAAO,qBAAqB,CAAC,GACrE,WAAI,GAAG,YAA6B,EAAE,iBAAiB,KAAK,EAAE,CACvE;;;AC7KF;AAEA;AACA;AACA;AAUO,IAAM,mBAAmB,CAC9B,UAEO,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,OAAO,GAAG,IAAI,IAAI,aAAa,mBAAmB,SAAS,IAAI,aAAa;AAAA,EAClF,OAAc,qBAAa,MAClB,mBAAW,EAAE,KAAK,MAAM,IAAI,KAAK,IAAI,EAAE,OAAO,GAAG,OAAO,MAAG;AAAA,IAAG;AAAA,IAAU,CAAC,EAAE,KACzE,sBAAc,MAAG;AAAA,IAAG;AAAA,GAAS,CACtC,CACF;AAAA,EACA,OAAO,EAAE,KAAK;AAAA,CACf;AAmBI,IAAM,eAAe,CAC1B,OACA,KACA,OACA,UAEO,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,UAAU,OAA2B;AAAA,EAC3C,MAAM,SAAS,OAAoB,mBAAK,OAAO,CAAC,MAAM,OAAO,GAAG,SAAS,OAAO,GAAG,SAAS,GAAG;AAAA,IAC7F,UAAU;AAAA,IACV,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAc,qBAAa,CAAC,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC,CAAC;AAAA,IAC5D,QAAQ;AAAA,EACV,CAAC,EAAE,KACD,QAAQ,OACD,gBAAQ,CAAC,UACP,YACL;AAAA,IACE,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,OAAO,KACZ,oBACA,kBACA,YAAI,CAAC,SAAS,KAAK,KAAK,CAAC,CAClC;AAAA,EACF,GACA,EAAE,aAAa,YAAY,CAC7B,CACF,GACO,cACT;AAAA,EAEA,IAAI,OAAO,aAAa,GAAG;AAAA,IACzB,OAAO,OAAc,aACnB,IAAI,MAAM,cAAc,SAAS,cAAc,OAAO,OAAO,QAAQ,MAAM,OAAO,QAAQ,CAC5F;AAAA,EACF;AAAA,CACD;;;ACvFH;AAGO,IAAM,gBAAgB,CAAC,SAAiB,KAAK,QAAQ;AAGrD,IAAM,SAAS,CAAC,SACrB,WAAW,QAAQ,EAAE,OAAO,cAAc,IAAI,CAAC,EAAE,OAAO,KAAK;AAGxD,IAAM,eAAe,CAAC,SAAiB,OAAO,IAAI;AAuBlD,IAAM,2BAA2B,CAAC,gBAA4C;AAAA,EACnF,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,MAAM,IAAI,KAAK,MAAM,WAAW;AAAA,IAChC,MAAM;AAAA,IACN;AAAA;AAAA,EAEF,IAAI,MAAM,QAAQ,GAAG,GAAG;AAAA,IACtB,IAAI,IAAI,WAAW;AAAA,MAAG;AAAA,IACtB,MAAM,IAAI;AAAA,EACZ;AAAA,EACA,IAAI,QAAQ,QAAQ,OAAO,QAAQ;AAAA,IAAU;AAAA,EAC7C,MAAM,OAAQ,IAA2B;AAAA,EACzC,OAAO,OAAO,SAAS,WAAW,OAAO;AAAA;AAsBpC,IAAM,qBAAqB,CAChC,UACA,gBACuF;AAAA,EACvF,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,MAAM,IAAI,KAAK,MAAM,QAAQ;AAAA,IAC7B,MAAM;AAAA,IACN;AAAA;AAAA,EAGF,MAAM,MAAM,IAAI,UAAU,KAAK,CAAC,QAAQ,IAAI,SAAS,WAAW,GAAG;AAAA,EACnE,MAAM,cAAc,KAAK;AAAA,EACzB,MAAM,WAAW,KAAK;AAAA,EACtB,IAAI,gBAAgB,aAAa,aAAa;AAAA,IAAW;AAAA,EAEzD,MAAM,UAAU,IAAI,UAAU,KAAK,CAAC,QAAQ,IAAI,SAAS,WAAW,GAAG;AAAA,EACvE,MAAM,OAAO,IAAI,OAAO,KAAK,CAAC,QAAQ,IAAI,SAAS,QAAQ,GAAG;AAAA,EAC9D,MAAM,WAAW,SAAS;AAAA,EAC1B,MAAM,KAAK,UAAU;AAAA,EACrB,MAAM,OAAO,OAAO,8BAA8B,OAAO;AAAA,EACzD,IAAI,aAAa,aAAa,OAAO,aAAa,SAAS;AAAA,IAAW;AAAA,EAEtE,OAAO;AAAA,IACL,eAAe,OAAO,EAAE;AAAA,IACxB,mBAAmB,OAAO,IAAI;AAAA,IAC9B;AAAA,EACF;AAAA;;;AC3FF,IAAM,aAAa,CAAC,SAKd,OAAO,GAAG,KAAK;AAAA,EAAY,KAAK;AAAA,EAAa,KAAK;AAAA,EAAkB,KAAK,mBAAmB;AAgBlG,IAAM,0BACJ;AAEF,IAAM,eAAe,CAAC,WAAwC;AAAA,EAC5D,MAAM,EAAE,SAAS,MAAM,SAAS,MAAM,cAAc,MAAM,wBAAwB;AACpF;AAGO,IAAM,aAAa,CACxB,KACA,UACqC;AAAA,EACrC,MAAM,OAAO,mBAAmB,KAAK,MAAM,OAAO;AAAA,EAClD,IAAI,SAAS;AAAA,IAAW;AAAA,EACxB,OAAO;AAAA,IACL,iCAAiC,KAAK;AAAA,IACtC,8BAA8B,KAAK;AAAA,IACnC,YAAY,aAAa,KAAK;AAAA,IAC9B,SAAS,MAAM;AAAA,IACf,sBAAsB,WAAW,KAAK,MAAM,SAAS,MAAM,QAAQ,CAAC;AAAA,IACpE,UAAU,KAAK;AAAA,EACjB;AAAA;;;ACzCF;AACA;AACA;AACA;AAAA;AAEO,MAAM,mBAAmB,MAAM;AAAA,EAEzB;AAAA,EACA;AAAA,EAFX,WAAW,CACA,SACA,UACT,QACA;AAAA,IACA,MAAM,YAAY,cAAc,OAAO,QAAQ,MAAM,QAAQ;AAAA,IAJpD;AAAA,IACA;AAAA,IAIT,KAAK,OAAO;AAAA;AAEhB;AAgBO,IAAM,WAAW,CAAC,MAAyB,YACzC,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,UAAU,OAA2B;AAAA,EAC3C,MAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH;AAAA,IACA,QAAQ;AAAA,IACR,GAAI,QAAQ,UAAU,YAAY,CAAC,IAAI,CAAC,WAAW,QAAQ,MAAM,KAAK,GAAG,CAAC;AAAA,IAC1E,GAAI,QAAQ,cAAc,YAAY,CAAC,IAAI,CAAC,eAAe,QAAQ,UAAU,KAAK,GAAG,CAAC;AAAA,IACtF,GAAI,QAAQ,aAAa,OAAO,CAAC,YAAY,IAAI,CAAC;AAAA,EACpD;AAAA,EACA,MAAM,SAAS,OAAoB,mBAAK,YAAY,MAAM;AAAA,IACxD,UAAU;AAAA,IACV,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,EACV,CAAC,EAAE,KACD,QAAQ,OACD,gBAAQ,CAAC,UACP,YACL;AAAA,IACE,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,OAAO,KACZ,oBACA,kBACA,YAAI,CAAC,SAAS,KAAK,KAAK,CAAC,CAClC;AAAA,IACA,QAAQ,MAAM,OAAO,KACZ,oBACA,kBACA,YAAI,CAAC,SAAS,KAAK,KAAK,CAAC,CAClC;AAAA,EACF,GACA,EAAE,aAAa,YAAY,CAC7B,CACF,GACO,cACT;AAAA,EAEA,MAAM,UAAU,KAAK,KAAK,GAAG;AAAA,EAC7B,IAAI,OAAO,aAAa,GAAG;AAAA,IACzB,OAAO,OAAc,aACnB,IAAI,WAAW,SAAS,OAAO,UAAU,OAAO,OAAO,MAAM,GAAG,GAAG,CAAC,CACtE;AAAA,EACF;AAAA,EACA,OAAO,OAAO;AAAA,CACf;AAGI,IAAM,oBAAoB,CAAC,MAAyB,YACzD,SAAS,MAAM,OAAO,EAAE,KACf,gBACL,CAAC,UACC,iBAAiB,cACjB,MAAM,aAAa,KACnB,+BAA+B,KAAK,MAAM,OAAO,GACnD,MAAa,gBAAQ,EAAE,CACzB,CACF;;;ALhBK,IAAM,kBAAkB,SAA0B,kBAAkB;AAW3E,IAAM,mBAAmB,CAAC,UACxB,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO;AAEnE,IAAM,gBAAgB,CAAC,OAAwB,QAC7C,YAAY,MAAM,OAAO,OAAO,KAAK,CAAC,cAAc,QAAQ,CAAC,EAAE,KACtD,gBAAQ,kBAAkB,MAAa,gBAAQ,SAAS,CAAC,CAClE;AAcK,IAAM,iBAAiB,CAAC,UACtB,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,MAAM,MAAM,iBAAiB;AAAA,EACnC,MAAM,MAAM,OAAO,cAAc,OAAO,GAAG;AAAA,EAC3C,IAAI,QAAQ;AAAA,IAAW;AAAA,EACvB,MAAM,OAAO,WAAW,KAAK,KAAK;AAAA,EAClC,IAAI,SAAS,WAAW;AAAA,IACtB,OAAO,OAAc,aACnB,IAAI,MACF,GAAG,MAAM,OAAO,SAAS,kEACvB,eAAe,MAAM,gEACrB,6CACJ,CACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA,CACR;AAEI,IAAM,iBAAiB,CAC5B,MACA,WAEO,YAAI,UAAU,GAAG;AAAA,EACtB,IAAI,WAAW,aAAa,CAAC,WAAW,IAAI;AAAA,IAAG;AAAA,EAC/C,MAAM,OAAO,OAAO,eAAe,IAAI;AAAA,EACvC,IACE,SAAS,aACT,KAAK,yBAAyB,OAAO,wBACrC,KAAK,YAAY,OAAO,WACxB,KAAK,aAAa,OAAO,UACzB;AAAA,IACA,OAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAAA,EACA,OAAO,EAAE,QAAQ,SAAS;AAAA,CAC3B;AAeI,IAAM,sBAAsB,CACjC,OACA,WAEO,eACE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,MAAM,MAAM,iBAAiB;AAAA,EAEnC,IAAI,WAAW,aAAa,OAAO,yBAAyB,IAAI;AAAA,IAC9D,MAAM,OAAM,OAAO,YAAY,MAAM,OAAO,OAAO,KAAK,CAAC,cAAc,QAAQ,CAAC;AAAA,IAChF,MAAM,QAAO,WAAW,MAAK,KAAK;AAAA,IAClC,IAAI,UAAS,WAAW;AAAA,MACtB,OAAO,OAAc,YACnB,IAAI,MACF,GAAG,MAAM,OAAO,SAAS,6DACvB,WAAW,MAAM,yDACrB,CACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EACtD,QAAQ,MAAM,YAAY,OAAO,iBAC/B,GAAG,MAAM,OAAO,WAAW,MAAM,qBACnC;AAAA,EACA,OAAO,SACL,CAAC,cAAc,SAAS,iBAAiB,WAAW,wBAAwB,MAAM,OAAO,GACzF,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,iBAAiB,WAAW,gBAAgB,CACrE;AAAA,EACA,MAAM,MAAM,OAAc,mBAAW;AAAA,IACnC,OAAO,CAAC,UAAU,IAAI,MAAM,GAAG,0CAA0C,OAAO,KAAK,GAAG;AAAA,IACxF,KAAK,MAAM,IAAI,KAAK,OAAO,EAAE,KAAK;AAAA,EACpC,CAAC;AAAA,EACD,IAAI,IAAI,KAAK,MAAM,IAAI;AAAA,IACrB,OAAO,OAAc,YACnB,IAAI,MACF,GAAG,MAAM,+EACP,gDACJ,CACF;AAAA,EACF;AAAA,EAIA,OAAc,YAAI;AAAA,IAChB,OAAO,CAAC,UAAU,IAAI,MAAM,GAAG,wBAAwB,OAAO,KAAK,GAAG;AAAA,IACtE,KAAK,MAAM,UAAU,SAAS,GAAK;AAAA,EACrC,CAAC;AAAA,EACD,MAAM,OAAO,WAAW,KAAK,KAAK;AAAA,EAClC,IAAI,SAAS,WAAW;AAAA,IACtB,OAAO,OAAc,YACnB,IAAI,MACF,GAAG,MAAM,4EACP,GAAG,MAAM,UACb,CACF;AAAA,EACF;AAAA,EACA,OAAO,aAAa,MAAM,OAAO,OAAO,KAAK,cAAc,GAAG;AAAA,EAC9D,OAAO;AAAA,CACR,CACH;AAEF,IAAM,WAAW;AAAA,EACf,QAAQ,MAAa;AAAA,EACrB,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,QAII,eAAe,MAAM,MAAM;AAAA,EACjC,MAAM,MAAa,gBAAQ,CAAC,CAAC;AAAA,EAC7B,MAAM,GAAG,WAAsC,eAAe,IAAI;AAAA,EAClE,WAAW;AAAA,IACT;AAAA,IACA;AAAA,QAII,oBAAoB,MAAM,MAAM;AACxC;AAEO,IAAM,0BAA0B,MAC5B,gBAAO,iBAAwB,gBAAQ,gBAAgB,SAAS,GAAG,QAAQ,CAAC,CAAC;;AMhOxF,qBAAS;AACT,uBAAS;AAET;AACA;;;ACvBA;;;ACDA;AAAA;AAaO,MAAM,kCAAuC,iBAAY,2BAA2B,EAKxF;AAAA,MACY,OAAO,GAAW;AAAA,IAC7B,OACE,GAAG,KAAK,SAAS,KAAK,4BAA4B,KAAK,mCACvD,gBAAgB,KAAK,yEACrB,+FACA;AAAA;AAGN;AAAA;AAYO,MAAM,gCAAqC,iBAAY,yBAAyB,EAIpF;AAAA,MACY,OAAO,GAAW;AAAA,IAC7B,OACE,GAAG,KAAK,8BAA8B,KAAK,mDAC3C,uCAAuC,KAAK,iDAC5C;AAAA;AAGN;AAAA;AAiBO,MAAM,gCAAqC,iBAAY,yBAAyB,EAGpF;AAAA,MACY,OAAO,GAAW;AAAA,IAC7B,OACE,GAAG,KAAK,qFACR,iBAAiB,KAAK,wEACtB;AAAA;AAGN;;;ADjEO,IAAM,iBAAiB,CAAC,OAAuB,oBACpD,SAAS,CAAC,OAAO,eAAe,MAAM,MAAM,GAAG;AAAA,EAC7C,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB;AACF,CAAC,EAAE,KAAY,YAAI,CAAC,SAAS,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,CAAC,CAAC;AAoB3E,IAAM,oBAAoB,CAAC,OAAuB,oBAChD,aACJ,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,SACvB,eAAe,KAAK,OAAO,MAAM,KAAK,GAAG,eAAe,EAAE,KACjD,oBAAY;AAAA,EACjB,WAAW,CAAC,UACH,aACL,IAAI,wBAAwB;AAAA,IAC1B,QAAQ,QAAQ,4CAA4C,OAAO,KAAK;AAAA,IACxE,MAAM,MAAM;AAAA,EACd,CAAC,CACH;AAAA,EACF,WAAW,CAAC,eACV,aACW,aACL,IAAI,wBAAwB;AAAA,IAC1B,QACE,QAAQ,sEACR;AAAA,IACF,MAAM,MAAM;AAAA,EACd,CAAC,CACH,IACO;AACf,CAAC,CACH,CACF,GACA,EAAE,SAAS,KAAK,CAClB;;;ADLK,IAAM,iBAAiB,UAAyB,mBAAmB;AAAA,EAExE,sBAAsB;AACxB,CAAC;AAgBM,IAAM,gBAAgB,CAAC,UACrB,eACE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EACtD,MAAM,eAAe,OAAO,eAAe,OAAO,WAAW,eAAe;AAAA,EAC5E,OAAO,eAAgB,EAAE,cAAc,MAAM,MAAM,MAAM,KAAK,IAAc;AAAA,CAC7E,CACH;AA4BK,IAAM,gBAAgB,CAC3B,MACA,WAEO,YAAI,UAAU,GAAG;AAAA,EACtB,IAAI,WAAW,aAAa,CAAC,YAAW,IAAI;AAAA,IAAG;AAAA,EAC/C,IAAI,OAAO;AAAA,IAAc,OAAO,EAAE,QAAQ,OAAO;AAAA,EACjD,MAAM,OAAO,OAAO,cAAc,IAAI;AAAA,EACtC,OAAO,MAAM,iBAAiB,OACzB,EAAE,QAAQ,OAAO,IACjB,EAAE,QAAQ,SAAS;AAAA,CACzB;AAQI,IAAM,qBAAqB,CAChC,OACA,WAEO,eACE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EAEtD,IAAI,QAAQ,iBAAiB,MAAM;AAAA,IACjC,MAAM,oBAAoB,OAAO,eAAe,OAAO,WAAW,eAAe,EAAE,KAC1E,gBACL,MAAe,MACf,CAAC,UACQ,aACL,IAAI,wBAAwB;AAAA,MAC1B,QAAQ,qBAAqB,OAAO,KAAK;AAAA,MACzC,MAAM,MAAM;AAAA,IACd,CAAC,CACH,CACJ,CACF;AAAA,IACA,IAAI,CAAC,mBAAmB;AAAA,MACtB,OAAO,OAAc,aACnB,IAAI,wBAAwB;AAAA,QAC1B,QAAQ;AAAA,QACR,MAAM,MAAM;AAAA,MACd,CAAC,CACH;AAAA,IACF;AAAA,IACA,OAAO,EAAE,cAAc,MAAM,MAAM,MAAM,KAAK;AAAA,EAChD;AAAA,EAEA,MAAM,SAAS,OAAO,eAAe,OAAO,WAAW,eAAe;AAAA,EACtE,IAAI,CAAC,QAAQ;AAAA,IAGX,OAAO,kBAAkB,OAAO,WAAW,eAAe;AAAA,IAC1D,OAAO,kBAAkB,CAAC,WAAW,GAAG;AAAA,MACtC,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,iBAAiB,WAAW;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,EACA,MAAM,QAAQ,OAAO,eAAe,OAAO,WAAW,eAAe;AAAA,EACrE,IAAI,CAAC,OAAO;AAAA,IACV,OAAO,OAAc,YACnB,IAAI,MACF,GAAG,MAAM,0EACP,qDACJ,CACF;AAAA,EACF;AAAA,EACA,OAAO,EAAE,cAAc,MAAM,MAAM,MAAM,KAAK;AAAA,CAC/C,CACH;AAEF,IAAM,YAAW;AAAA,EACf,QAAQ,MAAa;AAAA,EACrB,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,QAII,cAAc,MAAM,MAAM;AAAA,EAChC,MAAM,MAAa,gBAAQ,CAAC,CAAC;AAAA,EAC7B,MAAM,GAAG,WAAqC,cAAc,IAAI;AAAA,EAChE,WAAW;AAAA,IACT;AAAA,IACA;AAAA,QAII,mBAAmB,MAAM,MAAM;AACvC;AAEO,IAAM,yBAAyB,MAC3B,iBAAO,gBAAuB,gBAAQ,eAAe,SAAS,GAAG,SAAQ,CAAC,CAAC;;AG7LtF,qBAAS;AACT,uBAAS;AAET;AACA;AAsCO,IAAM,qBAAqB,UAA6B,qBAAqB;AAEpF,IAAM,UAAU,CAAC,UACf,UAAU,aAAa,MAAM,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG;AAEjE,IAAM,aAAa,CAAC,OAA2B,gBAAwB;AAAA,EACrE,MAAM,OAAO,CAAC,UAAU,kBAAkB,WAAW;AAAA,EACrD,MAAM,KAAK,QAAQ,MAAM,iBAAiB;AAAA,EAC1C,MAAM,UAAU,QAAQ,MAAM,WAAW;AAAA,EACzC,IAAI,OAAO;AAAA,IAAI,KAAK,KAAK,yBAAyB,EAAE;AAAA,EACpD,IAAI,YAAY;AAAA,IAAI,KAAK,KAAK,kBAAkB,OAAO;AAAA,EACvD,OAAO;AAAA;AAmBT,IAAM,QAAQ,CAAC,OAA2B,gBACjC,eACE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EACtD,MAAM,UAAU,MAAM,kBAAkB;AAAA,EACxC,IAAI,YAAY,WAAW;AAAA,IACzB,OAAO,OAAc,aACnB,IAAI,MACF,uBAAuB,MAAM,OAAO,mDAClC,4BACJ,CACF;AAAA,EACF;AAAA,EACA,OAAO,SAAS,WAAW,OAAO,WAAW,GAAG;AAAA,IAC9C,WAAW,CAAC,OAAO;AAAA,IACnB,OAAO,CAAC,OAAO;AAAA,IACf,iBAAiB,WAAW;AAAA,EAC9B,CAAC;AAAA,EACD,OAAO;AAAA,IACL,mBAAmB,QAAQ,MAAM,iBAAiB;AAAA,IAClD,SAAS;AAAA,IACT,aAAa,QAAQ,MAAM,WAAW;AAAA,EACxC;AAAA,CACD,CACH;AAQF,IAAM,eAAe,CAAC,UAAwC,iBAAiB;AAGxE,IAAM,oBAAoB,CAAC,UAChC,MAAM,OAAO,IAAI,EAAE,KACV,gBAAQ,cAAc,MACpB,gBAAQ;AAAA,EACb,mBAAmB,QAAQ,MAAM,iBAAiB;AAAA,EAClD,SAAS;AAAA,EACT,aAAa,QAAQ,MAAM,WAAW;AACxC,CAAC,CACH,CACF;AAEK,IAAM,oBAAoB,CAC/B,MACA,WAEO,YAAI,UAAU,GAAG;AAAA,EACtB,IAAI,WAAW,aAAa,CAAC,YAAW,IAAI;AAAA,IAAG;AAAA,EAC/C,MAAM,OAAO,OAAO,kBAAkB,IAAI;AAAA,EAC1C,IAAI,KAAK;AAAA,IAAS,OAAO,EAAE,QAAQ,OAAO;AAAA,EAC1C,OAAO,EAAE,QAAQ,SAAS;AAAA,CAC3B;AAEI,IAAM,yBAAyB,CAAC,UACrC,MAAM,OAAO,MAAM,eAAe,OAAO,EAAE,KAClC,gBAAQ,cAAc,CAAC,UACrB,aACL,IAAI,MACF,uBAAuB,MAAM,OAAO,yCAClC,GAAG,MAAM,eAAe,aAAa,OAAO,KAAK,GACrD,CACF,CACF,CACF;AAEF,IAAM,YAAW;AAAA,EACf,QAAQ,MAAa;AAAA,EACrB,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,QAII,kBAAkB,MAAM,MAAM;AAAA,EACpC,MAAM,MAAa,gBAAQ,CAAC,CAAC;AAAA,EAC7B,MAAM,GAAG,WAAyC,kBAAkB,IAAI;AAAA,EACxE,WAAW,GAAG,WAAyC,uBAAuB,IAAI;AACpF;AAEO,IAAM,6BAA6B,MAC/B,iBAAO,oBAA2B,gBAAQ,mBAAmB,SAAS,GAAG,SAAQ,CAAC,CAAC;;AC/J9F,qBAAS;AAET;AACA;;;ACnBA;AACA,uBAAS;AAET;AACA;AAkBO,IAAM,iBAAiB,CAAC,OAA2B,oBACxD,SAAS,CAAC,OAAO,iBAAiB,YAAY,MAAM,MAAM,GAAG;AAAA,EAC3D,WAAW,CAAC,MAAM,IAAI;AAAA,EACtB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB;AACF,CAAC,EAAE,KACM,gBAAQ,CAAC,gBAAgB;AAAA,EAC9B,MAAM,OAAO,yBAAyB,WAAW;AAAA,EACjD,OAAO,SAAS,YACL,aACL,IAAI,MACF,GAAG,MAAM,4EACP,4DACJ,CACF,IACO,gBAAQ,aAAa,IAAI,CAAC;AAAA,CACtC,CACH;AAYF,IAAM,uBAAuB,CAAC,OAA2B,oBACvD,SAAS,CAAC,SAAS,GAAG;AAAA,EACpB,WAAW,CAAC,MAAM,IAAI;AAAA,EACtB,UAAU;AAAA,EACV,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB;AACF,CAAC,EAAE,KACM,WAAG,IAAI,GACP,sBAAc,MAAM,KAAK,CAClC;AAuBK,IAAM,oBAAoB,CAAC,UACzB,eACE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EACtD,MAAM,UAAU,OAAc,eAAO,eAAe,OAAO,WAAW,eAAe,CAAC;AAAA,EACtF,IAAW,iBAAU,OAAO,GAAG;AAAA,IAC7B,MAAM,YAAY,OAAO,qBAAqB,OAAO,WAAW,eAAe;AAAA,IAC/E,OAAO,YAAY,YAAY,OAAc,aAAK,QAAQ,OAAO;AAAA,EACnE;AAAA,EACA,MAAM,QAAQ;AAAA,IACZ,cAAc,MAAM;AAAA,IACpB,WAAW,QAAQ,YAAY,MAAM,eAAgB,cAAwB;AAAA,IAC7E,MAAM,MAAM,QAAQ;AAAA,IACpB,MAAM,MAAM;AAAA,EACd;AAAA,EACA,OAAO,MAAM,cAAc,QAAQ,QAAQ,KAAK,IAAI;AAAA,CACrD,CACH;AAEK,IAAM,oBAAoB,CAC/B,MACA,WAEO,YAAI,UAAU,GAAG;AAAA,EACtB,IAAI,WAAW,aAAa,CAAC,YAAW,IAAI;AAAA,IAAG;AAAA,EAC/C,MAAM,OAAO,OAAO,kBAAkB,IAAI;AAAA,EAC1C,IAAI,SAAS,aAAa,KAAK,cAAc;AAAA,IAAO,OAAO,EAAE,QAAQ,OAAO;AAAA,EAC5E,OAAO,EAAE,QAAQ,SAAS;AAAA,CAC3B;;;ACvGH;AAQA,IAAM,cAAc,CAAC,SAAoB,SAAS,YAAY,SAAS;AAUvE,IAAM,SAA6E;AAAA,EACjF,WAAW,EAAE,YAAY,MAAO,aAAa,EAAE;AAAA,EAC/C,WAAW,EAAE,YAAY,MAAO,aAAa,GAAG;AAClD;AAMA,IAAM,iBAAiB,CACrB,QACA,WAEO,YAAI,UAAU,GAAG;AAAA,EACtB,SAAS,UAAU,EAAG,WAAW,OAAO,aAAa,WAAW;AAAA,IAC9D,MAAM,UAAU,OAAO,OAAM,KAAY,sBAAc,MAAM,KAAK,CAAC;AAAA,IACnE,IAAI;AAAA,MAAS,OAAO;AAAA,IACpB,IAAI,UAAU,OAAO;AAAA,MAAa,OAAc,cAAM,OAAO,UAAU;AAAA,EACzE;AAAA,EACA,OAAO;AAAA,CACR;AAaI,IAAM,mBAAmB,CAC9B,MACA,MACA,QACA,WAA+E,WAExE,YAAI,UAAU,GAAG;AAAA,EACtB,MAAM,YAAY,YAAY,IAAI;AAAA,EAClC,MAAM,SAAS,YAAY,SAAS,YAAY,SAAS;AAAA,EACzD,MAAM,UAAU,OAAO,eAAe,QAAO,MAAM;AAAA,EACnD,IAAI,CAAC,SAAS;AAAA,IACZ,OAAO,OAAc,aACnB,IAAI,wBAAwB,EAAE,UAAU,OAAO,aAAa,MAAM,KAAK,CAAC,CAC1E;AAAA,EACF;AAAA,EACA,OAAO,YAAY,aAAa;AAAA,CACjC;;;AFPI,IAAM,qBAAqB,UAA6B,qBAAqB;AAS7E,IAAM,yBAAyB,CACpC,OACA,QACA,iBAEO,gBACE,aAAI,UAAU,GAAG;AAAA,EACtB,MAAM,OAAO,MAAM,QAAQ;AAAA,EAG3B,MAAM,MAAM,OAAO,YAAY,MAAM,OAAO,OAAO,MAAM,WAAW,CAAC,QAAQ,CAAC;AAAA,EAC9E,MAAM,YAAY,aAAa,GAAG;AAAA,EAClC,IAAI,cAAc,MAAM,cAAc;AAAA,IACpC,OAAO,OAAc,cACnB,IAAI,0BAA0B;AAAA,MAC5B,UAAU,MAAM;AAAA,MAChB,KAAK;AAAA,MACL,KAAK,MAAM;AAAA,MACX,OAAO,MAAM,OAAO;AAAA,IACtB,CAAC,CACH;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,OAAO,gBAAgB,MAAM,MAAM;AAAA,EACtD,QAAQ,SAAS,OAAO,eAAe,KAAK,GAAG,MAAM,OAAO,WAAW,MAAM,aAAa;AAAA,EAE1F,MAAM,WAAW,WAAW;AAAA,EAC5B,MAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,WAAW,CAAC,YAAY,IAAI,CAAC;AAAA,EACnC;AAAA,EACA,OAAO,SAAS,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,iBAAiB,WAAW,gBAAgB,CAAC;AAAA,EAE1F,MAAM,YAAY,OAAO,iBACvB,MAAM,MACN,MACA,eAAe,OAAO,WAAW,eAAe,EAAE,KACzC,aAAI,CAAC,SAAS,SAAS,MAAM,YAAY,CAClD,GACA,YACF;AAAA,EAEA,OAAO;AAAA,IACL,cAAc,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA,MAAM,MAAM;AAAA,EACd;AAAA,CACD,CACH;AAEF,IAAM,YAAW;AAAA,EACf,QAAQ,MAAa;AAAA,EACrB,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,QAII,kBAAkB,MAAM,MAAM;AAAA,EACpC,MAAM,MAAa,iBAAQ,CAAC,CAAC;AAAA,EAC7B,MAAM,GAAG,WAAyC,kBAAkB,IAAI;AAAA,EACxE,WAAW;AAAA,IACT;AAAA,IACA;AAAA,QAII,uBAAuB,MAAM,MAAM;AAC3C;AAEO,IAAM,6BAA6B,MAC/B,iBAAO,oBAA2B,iBAAQ,mBAAmB,SAAS,GAAG,SAAQ,CAAC,CAAC;",
20
- "debugId": "33FF194E493FB6EF64756E2164756E21",
31
+ "mappings": "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",
32
+ "debugId": "0069C805BB1B149764756E2164756E21",
21
33
  "names": []
22
34
  }