@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.
- package/README.md +6 -32
- package/dist/talos/bao-env.d.ts +7 -0
- package/dist/talos/bao-env.d.ts.map +1 -0
- package/dist/talos/cluster-adapter-errors.d.ts +134 -0
- package/dist/talos/cluster-adapter-errors.d.ts.map +1 -0
- package/dist/talos/cluster-adapter.d.ts +115 -0
- package/dist/talos/cluster-adapter.d.ts.map +1 -0
- package/dist/talos/cluster-identity.d.ts +28 -0
- package/dist/talos/cluster-identity.d.ts.map +1 -0
- package/dist/talos/cluster-transport.d.ts +64 -0
- package/dist/talos/cluster-transport.d.ts.map +1 -0
- package/dist/talos/credentials-write.d.ts.map +1 -1
- package/dist/talos/credentials.d.ts +10 -19
- package/dist/talos/credentials.d.ts.map +1 -1
- package/dist/talos/fake-apiserver.d.ts +9 -0
- package/dist/talos/fake-apiserver.d.ts.map +1 -0
- package/dist/talos/index.d.ts +7 -0
- package/dist/talos/index.d.ts.map +1 -1
- package/dist/talos/index.js +669 -167
- package/dist/talos/index.js.map +22 -10
- package/dist/talos/kubeconfig-attrs.d.ts +14 -0
- package/dist/talos/kubeconfig-attrs.d.ts.map +1 -1
- package/dist/talos/kubeconfig-doc.d.ts +23 -0
- package/dist/talos/kubeconfig-doc.d.ts.map +1 -0
- package/dist/talos/kubeconfig.d.ts +0 -12
- package/dist/talos/kubeconfig.d.ts.map +1 -1
- package/dist/talos/literal-connection.d.ts +16 -0
- package/dist/talos/literal-connection.d.ts.map +1 -0
- package/dist/talos/machine-config-read.d.ts +1 -1
- package/dist/talos/machine-config-read.d.ts.map +1 -1
- package/dist/talos/mint-temp-file.d.ts +20 -0
- package/dist/talos/mint-temp-file.d.ts.map +1 -0
- package/dist/talos/node-temp.harness.d.ts +2 -0
- package/dist/talos/node-temp.harness.d.ts.map +1 -0
- package/dist/talos/talos-bootstrap-etcd.d.ts +1 -1
- package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -1
- package/dist/talos/talos-cluster-health.d.ts +15 -15
- package/dist/talos/talos-cluster-health.d.ts.map +1 -1
- package/dist/talos/talos-cluster-identity.d.ts +65 -0
- package/dist/talos/talos-cluster-identity.d.ts.map +1 -0
- package/dist/talos/talosctl-binary.d.ts +43 -0
- package/dist/talos/talosctl-binary.d.ts.map +1 -0
- package/dist/talos/talosctl.d.ts +12 -15
- package/dist/talos/talosctl.d.ts.map +1 -1
- package/dist/talos/trust-boundary.d.ts +8 -0
- package/dist/talos/trust-boundary.d.ts.map +1 -0
- package/dist/talos/values.d.ts.map +1 -1
- package/dist/talos/yaml-parse.d.ts +3 -0
- package/dist/talos/yaml-parse.d.ts.map +1 -0
- package/dist/verify/fake-engine.d.ts +2 -0
- package/dist/verify/fake-engine.d.ts.map +1 -1
- package/docs/peers.md +32 -5
- package/docs/talos-openbao-adapter.md +44 -0
- package/docs/upstream-conformance-bun.md +61 -24
- package/package.json +116 -2
- package/src/talos/bao-env.ts +16 -0
- package/src/talos/bao-vetting.test.ts +97 -0
- package/src/talos/cluster-adapter-deadline.test.ts +110 -0
- package/src/talos/cluster-adapter-errors.ts +192 -0
- package/src/talos/cluster-adapter-move.test.ts +129 -0
- package/src/talos/cluster-adapter-reconcile.test.ts +165 -0
- package/src/talos/cluster-adapter-refusals.test.ts +102 -0
- package/src/talos/cluster-adapter-rename.test.ts +87 -0
- package/src/talos/cluster-adapter-secrecy.test.ts +243 -0
- package/src/talos/cluster-adapter.fixtures.ts +125 -0
- package/src/talos/cluster-adapter.test.ts +240 -0
- package/src/talos/cluster-adapter.ts +249 -0
- package/src/talos/cluster-identity.ts +63 -0
- package/src/talos/cluster-transport.ts +110 -0
- package/src/talos/credentials-write.ts +27 -5
- package/src/talos/credentials.ts +51 -45
- package/src/talos/fake-apiserver.ts +55 -0
- package/src/talos/fake-process.ts +47 -1
- package/src/talos/index.ts +32 -0
- package/src/talos/kubeconfig-adapter.test.ts +37 -0
- package/src/talos/kubeconfig-attrs.ts +12 -28
- package/src/talos/kubeconfig-doc.ts +74 -0
- package/src/talos/kubeconfig.fixtures.ts +52 -0
- package/src/talos/kubeconfig.test.ts +6 -54
- package/src/talos/kubeconfig.ts +18 -34
- package/src/talos/literal-connection.ts +59 -0
- package/src/talos/mint-temp-file.ts +56 -0
- package/src/talos/node-connect.harness.ts +78 -0
- package/src/talos/node-connect.test.ts +27 -0
- package/src/talos/node-temp.harness.ts +40 -0
- package/src/talos/node-temp.test.ts +26 -0
- package/src/talos/talos-cluster-health-declare.test.ts +54 -0
- package/src/talos/talos-cluster-health-literal.test.ts +69 -0
- package/src/talos/talos-cluster-health.test.ts +104 -18
- package/src/talos/talos-cluster-health.ts +46 -14
- package/src/talos/talos-cluster-identity.test.ts +96 -0
- package/src/talos/talos-cluster-identity.ts +130 -0
- package/src/talos/talosctl-binary.ts +150 -0
- package/src/talos/talosctl-vetting.test.ts +212 -0
- package/src/talos/talosctl.test.ts +110 -0
- package/src/talos/talosctl.ts +101 -15
- package/src/talos/trust-boundary.test.ts +17 -0
- package/src/talos/trust-boundary.ts +45 -0
- package/src/talos/values.ts +5 -12
- package/src/talos/yaml-parse.test.ts +41 -0
- package/src/talos/yaml-parse.ts +28 -0
- package/src/verify/fake-engine.ts +10 -0
- package/dist/talos/fake-process.d.ts +0 -56
- package/dist/talos/fake-process.d.ts.map +0 -1
- package/dist/talos/machine-config-fixtures.d.ts +0 -60
- package/dist/talos/machine-config-fixtures.d.ts.map +0 -1
- package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +0 -147
- package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +0 -31
- package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +0 -82
- package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +0 -44
- package/src/postgres/fixtures/pg-REL_18_6-create-database-synopsis.txt +0 -26
- package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +0 -26
- package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +0 -95
- package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +0 -24
- package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +0 -62
- package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +0 -70
- package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +0 -33
- package/src/postgres/fixtures/pg-REL_18_6-pg_database.h.txt +0 -67
- package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +0 -81
- package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +0 -28
- package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +0 -124
- package/src/release/fixtures/openbao/checksums.txt +0 -83
- package/src/release/fixtures/openbao/checksums.txt.gpgsig +0 -0
- package/src/release/fixtures/openbao/darwin-assets.txt +0 -12
- package/src/release/fixtures/openbao/openbao-gpg-pub-20240618.asc +0 -109
- package/src/release/fixtures/victoria/darwin-arm64-assets.txt +0 -22
- package/src/release/fixtures/victoria/victoria-logs-darwin-arm64-v1.52.0_checksums.txt +0 -2
- package/src/release/fixtures/victoria/victoria-metrics-darwin-arm64-v1.151.0_checksums.txt +0 -2
- package/src/release/fixtures/victoria/victoria-traces-darwin-arm64-v0.10.0_checksums.txt +0 -2
- package/src/release/fixtures/victoria/vmutils-darwin-arm64-v1.151.0_checksums.txt +0 -8
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Talos.Kubeconfig`'s attribute builder — split out of kubeconfig.ts (LAND, 2026-09-26, C1/I2
|
|
3
|
+
* fixes) once fixing those findings pushed the file over the 250-line cap. Only `import type`
|
|
4
|
+
* comes back from kubeconfig.ts, so there is no runtime cycle.
|
|
5
|
+
*
|
|
6
|
+
* ⛔ NO `connection` HERE. A connection names the PHYSICAL cluster (`{ kind, uid }`,
|
|
7
|
+
* cluster-adapter.ts's identity rule) and the uid is only knowable from the cluster, which does
|
|
8
|
+
* not exist yet when this resource writes the vault key. Workloads get their connection from the
|
|
9
|
+
* operator's pinned literal (`talosOpenBaoConnection(uid)`) or `Talos.ClusterHealth`'s
|
|
10
|
+
* pass-through; `Talos.ClusterIdentity` publishes `{ uid }` only; a name-only connection
|
|
11
|
+
* (`cluster` present) is refused by the adapter as legacy. Neither the
|
|
12
|
+
* stock `kubeconfig` kind (an absent path falls back to `$KUBECONFIG`) nor `client-cert` (PEM on
|
|
13
|
+
* every workload's attributes, `Connection.ts` v2.0.0-beta.79 lines 12-14) is ever used.
|
|
14
|
+
*/
|
|
1
15
|
import type { KubeconfigAttributes, KubeconfigProps } from './kubeconfig.ts';
|
|
2
16
|
/** Parse `raw` kubeconfig YAML into public, persistable attributes, or `undefined` if it fails to. */
|
|
3
17
|
export declare const buildAttrs: (raw: string, props: KubeconfigProps) => KubeconfigAttributes | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kubeconfig-attrs.d.ts","sourceRoot":"","sources":["../../src/talos/kubeconfig-attrs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"kubeconfig-attrs.d.ts","sourceRoot":"","sources":["../../src/talos/kubeconfig-attrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAU7E,sGAAsG;AACtG,eAAO,MAAM,UAAU,QAChB,MAAM,SACJ,eAAe,KACrB,oBAAoB,GAAG,SAUzB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory kubeconfig parse for `talos-openbao` connect.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ THE RESULT HOLDS PEM. Callers may put it on a `ClusterTransport` for one request.
|
|
5
|
+
* They must not persist it, log it, or copy it onto a `Connection`. Alchemy stores
|
|
6
|
+
* connection attributes in plaintext (`credentials.ts`'s own header).
|
|
7
|
+
* ★ YAML IS `yaml-parse.ts` (runtime-neutral: Bun.YAML does not exist under Node, where the
|
|
8
|
+
* published dist runs). Nothing here touches a filesystem or OpenBao — the caller has already
|
|
9
|
+
* read the bytes.
|
|
10
|
+
*
|
|
11
|
+
* Walked against alchemy 2.0.0-beta.79 `Kubernetes/internal/client.ts`: `certificateAuthorityData`
|
|
12
|
+
* stays base64 (the client decodes it) and `clientCert` is PEM. The document shape is the one
|
|
13
|
+
* `values.ts` parses from the Talos v1.13 kubeconfig reference. Not measured on a live cluster.
|
|
14
|
+
*/
|
|
15
|
+
import type { ClusterTransport } from 'alchemy/Kubernetes/ClusterAdapter';
|
|
16
|
+
export type KubeconfigMaterial = Pick<ClusterTransport, 'certificateAuthorityData' | 'clientCert' | 'endpoint'>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve `contextName` to endpoint, base64 CA, and PEM client cert/key.
|
|
19
|
+
* `undefined` for any shape that is not that context's admin kubeconfig — the caller
|
|
20
|
+
* fails closed without embedding the document in the error.
|
|
21
|
+
*/
|
|
22
|
+
export declare const kubeconfigTransport: (yamlText: string, contextName: string) => KubeconfigMaterial | undefined;
|
|
23
|
+
//# sourceMappingURL=kubeconfig-doc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubeconfig-doc.d.ts","sourceRoot":"","sources":["../../src/talos/kubeconfig-doc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAe1E,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,gBAAgB,EAChB,0BAA0B,GAAG,YAAY,GAAG,UAAU,CACvD,CAAC;AASF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,aACpB,MAAM,eACH,MAAM,KAClB,kBAAkB,GAAG,SAwBvB,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Resource } from 'alchemy';
|
|
2
2
|
import type { Input } from 'alchemy/Input';
|
|
3
|
-
import type { Connection } from 'alchemy/Kubernetes/Connection';
|
|
4
3
|
import * as Provider from 'alchemy/Provider';
|
|
5
4
|
import * as Effect from 'effect/Effect';
|
|
6
5
|
import type { TalosRequirements, WithTarget } from './resource.ts';
|
|
@@ -20,17 +19,6 @@ export interface KubeconfigAttributes {
|
|
|
20
19
|
clientCertificateFingerprint: string;
|
|
21
20
|
/** Digest of endpoint+context+fingerprints — detects credential rotation without storing PEM. */
|
|
22
21
|
credentialGeneration: string;
|
|
23
|
-
/**
|
|
24
|
-
* Serializable `Kubernetes.Connection` for downstream workloads.
|
|
25
|
-
*
|
|
26
|
-
* ★ auth.kind `kubeconfig` is the stock ClusterAdapter — provider-roadmap.md names this seam.
|
|
27
|
-
* `path` is a sentinel that can never resolve (LAND red team I2, `kubeconfig-attrs.ts`'s own
|
|
28
|
-
* `toConnection` header): the content lives in OpenBao, not at a fixed host path, and a real
|
|
29
|
-
* `Kubernetes.ClusterAdapter` wiring is later work, so this must fail rather than silently
|
|
30
|
-
* reach the operator's own kubeconfig. A consumer materializes its own scoped temp file via
|
|
31
|
-
* `credentials.ts`'s `mintKubeconfig` in the meantime.
|
|
32
|
-
*/
|
|
33
|
-
connection: Connection;
|
|
34
22
|
}
|
|
35
23
|
export interface TalosKubeconfig extends Resource<'Talos.Kubeconfig', KubeconfigProps, KubeconfigAttributes, never, TalosRequirements> {
|
|
36
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kubeconfig.d.ts","sourceRoot":"","sources":["../../src/talos/kubeconfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"kubeconfig.d.ts","sourceRoot":"","sources":["../../src/talos/kubeconfig.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AASxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGnE,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B,EAAE,MAAM,CAAC;IACxC,4BAA4B,EAAE,MAAM,CAAC;IACrC,iGAAiG;IACjG,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,KAAK,EACL,iBAAiB,CAClB;CAAG;AAEJ,eAAO,MAAM,eAAe,kDAAgD,CAAC;AAQ7E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,UAAW,eAAe,6HAgBjD,CAAC;AAEL,eAAO,MAAM,cAAc,SACnB,KAAK,CAAC,eAAe,CAAC,UACpB,oBAAoB,GAAG,SAAS;qBAenB,MAAM;;qBAER,QAAQ;uFACzB,CAAC;AAEL;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,UACvB,eAAe,UACd,oBAAoB,GAAG,SAAS,gKA2DvC,CAAC;AAsBJ,eAAO,MAAM,uBAAuB,iJACqD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TalosUidNotLiteral } from './cluster-adapter-errors.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The typed refusal unless `connection` is `{ auth: { kind, uid: literal } }`, else `undefined`.
|
|
4
|
+
* ★ A value, never a throw: a throw inside `Effect.gen` would become a defect, not a failure.
|
|
5
|
+
*/
|
|
6
|
+
export declare const literalConnectionRefusal: (connection: unknown) => TalosUidNotLiteral | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* ⛔ THE `diff` GUARD ALONE IS NOT ENOUGH (round-4 review): alchemy skips `diff` for a FRESH
|
|
9
|
+
* resource whose inputs are unresolved, and reconcile then copies the resolved string downstream
|
|
10
|
+
* — an Output uid slips through on exactly the first deploy. So the same refusal runs when the
|
|
11
|
+
* resource is DECLARED, before any input resolution, by wrapping its constructor.
|
|
12
|
+
* ★ A Proxy over the class (not a new function) keeps `.Provider`, `.Self`, `.ref` and the type.
|
|
13
|
+
* Plain props fail the declaring Effect; a props Effect fails once it yields.
|
|
14
|
+
*/
|
|
15
|
+
export declare const withLiteralConnection: <C extends (...args: never[]) => unknown>(resource: C) => C;
|
|
16
|
+
//# sourceMappingURL=literal-connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literal-connection.d.ts","sourceRoot":"","sources":["../../src/talos/literal-connection.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,eAAgB,OAAO,KAAG,kBAAkB,GAAG,SAYnF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,YAAY,CAAC,KAAG,CAkBzF,CAAC"}
|
|
@@ -13,7 +13,7 @@ import type { MachineConfigAttributes, MachineConfigProps } from './talos-machin
|
|
|
13
13
|
* talosconfig context's own endpoints, which may be a control-plane VIP that only comes up AFTER
|
|
14
14
|
* bootstrap; every pre-bootstrap call in this file targets the node directly instead.
|
|
15
15
|
*/
|
|
16
|
-
export declare const liveSpecDigest: (props: MachineConfigProps, talosconfigPath: string) => Effect.Effect<string, Error | import("effect/PlatformError").PlatformError | import("./talosctl.ts").TalosError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
16
|
+
export declare const liveSpecDigest: (props: MachineConfigProps, talosconfigPath: string) => Effect.Effect<string, Error | import("effect/PlatformError").PlatformError | import("./talosctl-binary.ts").TalosBinaryRefused | import("./talosctl.ts").TalosError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
17
17
|
/**
|
|
18
18
|
* ⛔ NO SWALLOWING. A transport failure here propagates as its own error (TalosError or the
|
|
19
19
|
* shape error above) — never as `converged: false`. A false only means "read succeeded, and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine-config-read.d.ts","sourceRoot":"","sources":["../../src/talos/machine-config-read.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI7F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,UAAW,kBAAkB,mBAAmB,MAAM,
|
|
1
|
+
{"version":3,"file":"machine-config-read.d.ts","sourceRoot":"","sources":["../../src/talos/machine-config-read.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI7F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,UAAW,kBAAkB,mBAAmB,MAAM,2OAiB9E,CAAC;AAuBJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,iBAAiB,UAAW,kBAAkB;;;;;sIAiBxD,CAAC;AAEJ,eAAO,MAAM,iBAAiB,SACtB,KAAK,CAAC,kBAAkB,CAAC,UACvB,uBAAuB,GAAG,SAAS;qBAK4B,MAAM;;qBAC1D,QAAQ;sIACzB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import type * as Scope from 'effect/Scope';
|
|
3
|
+
/**
|
|
4
|
+
* Write `raw` to a session-temp, 0600, exclusively-created file whose lifetime is the CALLER's
|
|
5
|
+
* `Effect.scoped`, not this call's. See the ⛔ C1 FIX note at the top of credentials.ts.
|
|
6
|
+
*
|
|
7
|
+
* ⛔ 0600, CREATED EXCLUSIVELY, AND `Bun.write` CANNOT DO EITHER. This file can hold a cluster
|
|
8
|
+
* admin client certificate or a machine config's bootstrap token. `Bun.write` takes no mode, so
|
|
9
|
+
* it lands at the process umask — world-readable on this estate — for as long as the resource
|
|
10
|
+
* runs. The name is unguessable, and "unguessable" is not a permission.
|
|
11
|
+
* ⚠️ `wx` IS THE OTHER HALF. `O_EXCL` means this cannot be made to write through a path an
|
|
12
|
+
* attacker pre-created (the classic /tmp symlink race), and with a UUID name a collision is a
|
|
13
|
+
* genuine error rather than something to paper over.
|
|
14
|
+
* ⚠️ A HARD KILL (SIGKILL, power loss) skips the finalizer and leaves the file behind. 0600 is
|
|
15
|
+
* what makes that survivable rather than a disclosure.
|
|
16
|
+
*/
|
|
17
|
+
export declare const mintKvTempFile: (raw: string, label: string) => Effect.Effect<{
|
|
18
|
+
readonly path: string;
|
|
19
|
+
}, Error, Scope.Scope>;
|
|
20
|
+
//# sourceMappingURL=mint-temp-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint-temp-file.d.ts","sourceRoot":"","sources":["../../src/talos/mint-temp-file.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,QACpB,MAAM,SACJ,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAyB1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-temp.harness.d.ts","sourceRoot":"","sources":["../../src/talos/node-temp.harness.ts"],"names":[],"mappings":""}
|
|
@@ -15,7 +15,7 @@ import { TalosReBootstrapRefused } from './talos-errors.ts';
|
|
|
15
15
|
* failure here means (talos-bootstrap.ts's `read`/`reconcile`, and `assertNoLivePeers` below), so
|
|
16
16
|
* it is not decided here.
|
|
17
17
|
*/
|
|
18
|
-
export declare const isBootstrapped: (props: BootstrapProps, talosconfigPath: string) => Effect.Effect<boolean, import("effect/PlatformError").PlatformError | import("./talosctl.ts").TalosError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
18
|
+
export declare const isBootstrapped: (props: BootstrapProps, talosconfigPath: string) => Effect.Effect<boolean, import("effect/PlatformError").PlatformError | import("./talosctl-binary.ts").TalosBinaryRefused | import("./talosctl.ts").TalosError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
19
19
|
/**
|
|
20
20
|
* ⛔ I4 FIX (LAND red team, 2026-09-26) — THE CREATE PATH ONLY CHECKED THIS NODE. If the state row
|
|
21
21
|
* is lost (wrong `--stage`, an FQN rename, a wiped state store) while the cluster already lives on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"talos-bootstrap-etcd.d.ts","sourceRoot":"","sources":["../../src/talos/talos-bootstrap-etcd.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAG5D;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,UAAW,cAAc,mBAAmB,MAAM,
|
|
1
|
+
{"version":3,"file":"talos-bootstrap-etcd.d.ts","sourceRoot":"","sources":["../../src/talos/talos-bootstrap-etcd.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAG5D;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,UAAW,cAAc,mBAAmB,MAAM,oOAIM,CAAC;AAEpF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,UAAW,cAAc,mBAAmB,MAAM,mHA2B7E,CAAC"}
|
|
@@ -22,11 +22,16 @@
|
|
|
22
22
|
* rollout would never learn the real problem was vault. Both `read` and `reconcile` now only
|
|
23
23
|
* catch `TalosError` (`talosctl health` itself ran and exited non-zero — the one case this
|
|
24
24
|
* family may honestly call "not healthy"); anything else propagates untouched.
|
|
25
|
+
* ★ `connection` IS A PASS-THROUGH so this resource is `ClusterLike`. Later rows take
|
|
26
|
+
* `cluster: health`. The health check itself still uses `target` and `talosctl`; the field is
|
|
27
|
+
* copied onto attributes and is not a credential. It is required: an optional field would not
|
|
28
|
+
* satisfy `{ connection: Connection }`.
|
|
25
29
|
*/
|
|
26
30
|
import { Resource } from 'alchemy';
|
|
27
31
|
import type { Input } from 'alchemy/Input';
|
|
28
32
|
import * as Provider from 'alchemy/Provider';
|
|
29
33
|
import * as Effect from 'effect/Effect';
|
|
34
|
+
import type { TalosOpenBaoConnection } from './cluster-adapter.ts';
|
|
30
35
|
import type { TalosRequirements, WithTarget } from './resource.ts';
|
|
31
36
|
export interface ClusterHealthProps extends WithTarget {
|
|
32
37
|
/** Control-plane node IPs passed to `--control-plane-nodes`. */
|
|
@@ -45,34 +50,29 @@ export interface ClusterHealthProps extends WithTarget {
|
|
|
45
50
|
* on kube-proxy and CoreDNS, both of which wait on a CNI that does not exist yet at bootstrap.
|
|
46
51
|
*/
|
|
47
52
|
after?: readonly unknown[];
|
|
53
|
+
/**
|
|
54
|
+
* Kubernetes connection copied onto attributes so a later row can take `cluster: this`.
|
|
55
|
+
* Not read by the health check. Persist only a secret-free connection (`talos-openbao`).
|
|
56
|
+
*/
|
|
57
|
+
connection: TalosOpenBaoConnection;
|
|
48
58
|
}
|
|
49
59
|
export interface ClusterHealthAttributes {
|
|
50
60
|
healthy: boolean;
|
|
51
61
|
controlPlaneNodes: string;
|
|
52
62
|
workerNodes: string;
|
|
63
|
+
/** Same object as the prop. Makes these attributes `ClusterLike`. */
|
|
64
|
+
connection: TalosOpenBaoConnection;
|
|
53
65
|
}
|
|
54
66
|
export interface TalosClusterHealth extends Resource<'Talos.ClusterHealth', ClusterHealthProps, ClusterHealthAttributes, never, TalosRequirements> {
|
|
55
67
|
}
|
|
56
68
|
export declare const TalosClusterHealth: import("alchemy").ResourceClass<TalosClusterHealth>;
|
|
57
69
|
/** ★ EXPORTED for talos-cluster-health.test.ts — see talos-bootstrap.ts's own note on the pattern. */
|
|
58
|
-
export declare const readClusterHealth: (props: ClusterHealthProps) => Effect.Effect<
|
|
59
|
-
controlPlaneNodes: string;
|
|
60
|
-
healthy: boolean;
|
|
61
|
-
workerNodes: string;
|
|
62
|
-
} | {
|
|
63
|
-
controlPlaneNodes: string;
|
|
64
|
-
healthy: boolean;
|
|
65
|
-
workerNodes: string;
|
|
66
|
-
}, Error | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
70
|
+
export declare const readClusterHealth: (props: ClusterHealthProps) => Effect.Effect<ClusterHealthAttributes, Error | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
67
71
|
export declare const diffClusterHealth: (news: Input<ClusterHealthProps>, output: ClusterHealthAttributes | undefined) => Effect.Effect<{
|
|
68
72
|
readonly action: 'noop';
|
|
69
73
|
} | {
|
|
70
74
|
readonly action: 'update';
|
|
71
|
-
} | undefined, Error | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
72
|
-
export declare const reconcileClusterHealth: (props: ClusterHealthProps) => Effect.Effect<
|
|
73
|
-
controlPlaneNodes: string;
|
|
74
|
-
healthy: boolean;
|
|
75
|
-
workerNodes: string;
|
|
76
|
-
}, Error | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
75
|
+
} | undefined, Error | import("effect/PlatformError").PlatformError | import("./cluster-adapter-errors.ts").TalosUidNotLiteral, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
76
|
+
export declare const reconcileClusterHealth: (props: ClusterHealthProps) => Effect.Effect<ClusterHealthAttributes, Error | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
77
77
|
export declare const TalosClusterHealthProvider: () => import("effect/Layer").Layer<Provider.Provider<TalosClusterHealth>, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
78
78
|
//# sourceMappingURL=talos-cluster-health.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"talos-cluster-health.d.ts","sourceRoot":"","sources":["../../src/talos/talos-cluster-health.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"talos-cluster-health.d.ts","sourceRoot":"","sources":["../../src/talos/talos-cluster-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGnE,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,gEAAgE;IAChE,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kDAAkD;IAClD,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC3B;;;OAGG;IACH,UAAU,EAAE,sBAAsB,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,UAAU,EAAE,sBAAsB,CAAC;CACpC;AAED,MAAM,WAAW,kBAAmB,SAAQ,QAAQ,CAClD,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,EACL,iBAAiB,CAClB;CAAG;AAGJ,eAAO,MAAM,kBAAkB,qDAE9B,CAAC;AAgFF,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,UAAW,kBAAkB,mKAGxD,CAAC;AAEJ,eAAO,MAAM,iBAAiB,SACtB,KAAK,CAAC,kBAAkB,CAAC,UACvB,uBAAuB,GAAG,SAAS;qBAUtB,MAAM;;qBAER,QAAQ;iMACzB,CAAC;AAEL,eAAO,MAAM,sBAAsB,UAAW,kBAAkB,mKAU7D,CAAC;AAgBJ,eAAO,MAAM,0BAA0B,oJACwD,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Talos.ClusterIdentity` — a read-only resource that reports WHICH physical cluster a name means.
|
|
3
|
+
*
|
|
4
|
+
* ★ It reads the vault kubeconfig and GETs the kube-system Namespace once (`cluster-identity.ts`),
|
|
5
|
+
* and publishes `{ uid }`. That is the BOOTSTRAP-THEN-PIN step (cluster-adapter.ts header): the
|
|
6
|
+
* first deploy creates the cluster and this row with no workloads, the operator copies the
|
|
7
|
+
* printed uid into the adapter config, and workloads take `talosOpenBaoConnection(<literal>)`.
|
|
8
|
+
* ⛔ It publishes NO `connection`: an Output uid in a workload's auth is unresolved at plan time
|
|
9
|
+
* and hides a cluster change from the plan (`talosOpenBaoConnection` explains the DELETE on B).
|
|
10
|
+
* ⛔ DRIFT REPAIR CANNOT LAUNDER A MOVE: `read` receives the persisted output and compares it, so
|
|
11
|
+
* `Drift.repair` fails with `TalosClusterMoved` instead of reconciling B against B.
|
|
12
|
+
* ⛔ IT MUTATES NOTHING: no vault write, no cluster write, `delete` is a no-op. Its only effect is
|
|
13
|
+
* the value it reports. `after` must reach past Cilium/CNI only if the apiserver needs it; the
|
|
14
|
+
* kube-system namespace exists as soon as the apiserver answers.
|
|
15
|
+
* ⛔ A CHANGED UID IS REFUSED, NEVER AN UPDATE (`TalosClusterMoved`, in diff AND reconcile). This
|
|
16
|
+
* resource declares no `stables`, so downstream the engine sees an unresolved Output, every
|
|
17
|
+
* workload `diff` returns undefined and the engine plans an UPDATE, not a replace (Plan.ts
|
|
18
|
+
* resourceExpr, `isResolved(news)` in Manifest.ts and HelmChart.ts). Reconcile would then
|
|
19
|
+
* connect with the NEW uid and force-apply onto the new cluster while the old cluster's objects
|
|
20
|
+
* are orphaned (an earlier comment here claimed a replace and a refusal at cleanup: it cannot
|
|
21
|
+
* happen). A real move is a NEW identity resource per physical cluster.
|
|
22
|
+
*/
|
|
23
|
+
import { Resource } from 'alchemy';
|
|
24
|
+
import type { Input } from 'alchemy/Input';
|
|
25
|
+
import * as Provider from 'alchemy/Provider';
|
|
26
|
+
import * as Effect from 'effect/Effect';
|
|
27
|
+
import { TalosClusterMoved } from './cluster-adapter-errors.ts';
|
|
28
|
+
import type { KubeconfigProps } from './kubeconfig.ts';
|
|
29
|
+
import type { TalosRequirements } from './resource.ts';
|
|
30
|
+
type KubeconfigSource = Pick<KubeconfigProps, 'context' | 'kubeconfigKey' | 'target'>;
|
|
31
|
+
export interface ClusterIdentityProps extends KubeconfigSource {
|
|
32
|
+
/** Ordering edge: after `Talos.Kubeconfig` (the vault key must exist) and the apiserver is up. */
|
|
33
|
+
after?: readonly unknown[];
|
|
34
|
+
}
|
|
35
|
+
export interface ClusterIdentityAttributes {
|
|
36
|
+
/**
|
|
37
|
+
* The cluster's kube-system `metadata.uid`. Public. ⛔ NOT A `connection`: these attributes are
|
|
38
|
+
* deliberately not `ClusterLike`. Pin this value as a literal in `TalosOpenBaoAdapter` and build
|
|
39
|
+
* workloads' connection from that literal (bootstrap-then-pin, cluster-adapter.ts header).
|
|
40
|
+
*/
|
|
41
|
+
uid: string;
|
|
42
|
+
}
|
|
43
|
+
export interface TalosClusterIdentity extends Resource<'Talos.ClusterIdentity', ClusterIdentityProps, ClusterIdentityAttributes, never, TalosRequirements> {
|
|
44
|
+
}
|
|
45
|
+
export declare const TalosClusterIdentity: import("alchemy").ResourceClass<TalosClusterIdentity>;
|
|
46
|
+
/**
|
|
47
|
+
* ★ EXPORTED for talos-cluster-identity.test.ts — see talos-bootstrap.ts's note on the pattern.
|
|
48
|
+
* ⛔ A PERSISTED OUTPUT IS COMPARED HERE TOO, not only in reconcile: `Drift.repair` hands `read`
|
|
49
|
+
* the persisted attributes, then reconciles `news: old.props, output: <what read returned>`.
|
|
50
|
+
* A read that ignored the output returned the NEW uid, so the reconcile guard compared B with B
|
|
51
|
+
* and saved it. Failing in read stops that path with `TalosClusterMoved`.
|
|
52
|
+
*/
|
|
53
|
+
export declare const readClusterIdentity: (props: ClusterIdentityProps, output?: ClusterIdentityAttributes) => Effect.Effect<{
|
|
54
|
+
uid: string;
|
|
55
|
+
}, Error | import("alchemy/Kubernetes/internal/client").KubernetesApiError | import("./cluster-adapter-errors.ts").TalosClusterIdentityTimeout | import("./cluster-adapter-errors.ts").TalosClusterIdentityUnreadable | TalosClusterMoved | import("./cluster-adapter-errors.ts").TalosKubeconfigUnreadable | import("./cluster-adapter-errors.ts").TalosOpenBaoConnectTimeout | import("./cluster-adapter-errors.ts").TalosVaultKeyMissing, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
56
|
+
/** ⛔ Fails closed when a saved uid exists and the live one differs. See the header. */
|
|
57
|
+
export declare const reconcileClusterIdentity: (props: ClusterIdentityProps, output: ClusterIdentityAttributes | undefined) => Effect.Effect<{
|
|
58
|
+
uid: string;
|
|
59
|
+
}, Error | import("alchemy/Kubernetes/internal/client").KubernetesApiError | import("./cluster-adapter-errors.ts").TalosClusterIdentityTimeout | import("./cluster-adapter-errors.ts").TalosClusterIdentityUnreadable | TalosClusterMoved | import("./cluster-adapter-errors.ts").TalosKubeconfigUnreadable | import("./cluster-adapter-errors.ts").TalosOpenBaoConnectTimeout | import("./cluster-adapter-errors.ts").TalosVaultKeyMissing, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
60
|
+
export declare const diffClusterIdentity: (news: Input<ClusterIdentityProps>, output: ClusterIdentityAttributes | undefined) => Effect.Effect<{
|
|
61
|
+
readonly action: 'noop';
|
|
62
|
+
} | undefined, Error | import("alchemy/Kubernetes/internal/client").KubernetesApiError | import("./cluster-adapter-errors.ts").TalosClusterIdentityTimeout | import("./cluster-adapter-errors.ts").TalosClusterIdentityUnreadable | TalosClusterMoved | import("./cluster-adapter-errors.ts").TalosKubeconfigUnreadable | import("./cluster-adapter-errors.ts").TalosOpenBaoConnectTimeout | import("./cluster-adapter-errors.ts").TalosVaultKeyMissing, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
63
|
+
export declare const TalosClusterIdentityProvider: () => import("effect/Layer").Layer<Provider.Provider<TalosClusterIdentity>, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=talos-cluster-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"talos-cluster-identity.d.ts","sourceRoot":"","sources":["../../src/talos/talos-cluster-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,KAAK,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,eAAe,GAAG,QAAQ,CAAC,CAAC;AAEtF,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,kGAAkG;IAClG,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAqB,SAAQ,QAAQ,CACpD,uBAAuB,EACvB,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,EACL,iBAAiB,CAClB;CAAG;AAEJ,eAAO,MAAM,oBAAoB,uDAA0D,CAAC;AAE5F;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,UACvB,oBAAoB,WAClB,yBAAyB;;8eAgBhC,CAAC;AAEL,uFAAuF;AACvF,eAAO,MAAM,wBAAwB,UAC5B,oBAAoB,UACnB,yBAAyB,GAAG,SAAS;;8eACR,CAAC;AAExC,eAAO,MAAM,mBAAmB,SACxB,KAAK,CAAC,oBAAoB,CAAC,UACzB,yBAAyB,GAAG,SAAS;qBAK1B,MAAM;0fACvB,CAAC;AA4BL,eAAO,MAAM,4BAA4B,sJAC0D,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
/** `talosctl` on `PATH`. A lane pins another build with {@link TALOSCTL_BINARY_ENV} or `binary`. */
|
|
3
|
+
export declare const DEFAULT_TALOSCTL_BINARY = "talosctl";
|
|
4
|
+
/**
|
|
5
|
+
* Executable override, read at call time. The Mac PATH measured 2026-10-05 has v1.13.8; the
|
|
6
|
+
* cluster is v1.14.2. Set this to the v1.14.2 binary. A per-call `binary` option wins.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TALOSCTL_BINARY_ENV = "HF_TALOSCTL";
|
|
9
|
+
/** `bao` on `PATH` — the OpenBao CLI that fetches the cluster credentials at connect time. */
|
|
10
|
+
export declare const DEFAULT_BAO_BINARY = "bao";
|
|
11
|
+
/** `bao` executable override, read at call time and vetted exactly like {@link TALOSCTL_BINARY_ENV}. */
|
|
12
|
+
export declare const BAO_BINARY_ENV = "HF_BAO";
|
|
13
|
+
export declare class TalosBinaryRefused extends Error {
|
|
14
|
+
readonly command: string;
|
|
15
|
+
readonly binary: string;
|
|
16
|
+
constructor(command: string, detail: string, binary?: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* ⛔ THE DEFAULT IS VETTED TOO (hunt round 5): a bare `talosctl` is resolved against `PATH` here
|
|
20
|
+
* (not `Bun.which` — the published dist runs on Node, where that global is missing), symlinks are
|
|
21
|
+
* followed, and the REAL file is vetted, version-checked and executed by absolute path.
|
|
22
|
+
*/
|
|
23
|
+
export declare const resolveDefault: (binary: string) => Effect.Effect<string, TalosBinaryRefused, never>;
|
|
24
|
+
/**
|
|
25
|
+
* ⛔ THE BINARY GETS THE VAULT-MINTED TALOSCONFIG: absolute, owned, not writable, executable, trusted
|
|
26
|
+
* path. ⛔ RETURNS THE CANONICAL PATH (round 7): the override's directory is resolved ONCE
|
|
27
|
+
* (realpath), that path and every ancestor of it are vetted, and the caller must launch exactly
|
|
28
|
+
* the returned path for the version probe AND the credential-bearing call. Vetting the given path
|
|
29
|
+
* and executing it again let a symlinked ancestor be repointed between the two launches. The leaf
|
|
30
|
+
* itself is still lstat'd, so a symlink leaf is refused rather than followed.
|
|
31
|
+
*/
|
|
32
|
+
export declare const checkBinaryPath: (binary: string, source: string) => Effect.Effect<string, TalosBinaryRefused, never>;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve and vet the `bao` binary: {@link BAO_BINARY_ENV} wins over `bao` on `PATH`, and either is
|
|
35
|
+
* checked exactly like talosctl (absolute, owned, not writable, executable, not a symlink, every
|
|
36
|
+
* ancestor trusted). Returns the canonical path to launch.
|
|
37
|
+
*
|
|
38
|
+
* ⛔ `bao` FETCHES THE CLUSTER CREDENTIALS (`readKvValue` / `writeKvValue`), so an un-vetted `bao`
|
|
39
|
+
* on a group/world-writable PATH folder (umask 002, the round-10 incident) could answer with an
|
|
40
|
+
* attacker's kubeconfig. The same walk that vets `talosctl` must gate every `bao` launch.
|
|
41
|
+
*/
|
|
42
|
+
export declare const resolveBao: () => Effect.Effect<string, TalosBinaryRefused>;
|
|
43
|
+
//# sourceMappingURL=talosctl-binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"talosctl-binary.d.ts","sourceRoot":"","sources":["../../src/talos/talosctl-binary.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,oGAAoG;AACpG,eAAO,MAAM,uBAAuB,aAAa,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,8FAA8F;AAC9F,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,wGAAwG;AACxG,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAA0B,EAK5E;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,WAAY,MAAM,qDAgBzC,CAAC;AA6BL;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,WAAY,MAAM,UAAU,MAAM,qDAgC7D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,QAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAOrE,CAAC"}
|
package/dist/talos/talosctl.d.ts
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One `talosctl` invocation — stdout/stderr captured, secrets never echoed.
|
|
3
|
-
*
|
|
4
|
-
* ★ SHELL OUT LIKE ALCHEMY'S DOCKER PROVIDER (ChildProcessSpawner), NOT A SECOND SDK. Talos speaks
|
|
5
|
-
* gRPC; the published, stable surface for operators is `talosctl`. No Talos npm package is added.
|
|
6
|
-
*
|
|
7
|
-
* ⚠️ REASONED FROM docs.siderolabs.com/talos/v1.13/reference/cli — nothing here was measured on a
|
|
8
|
-
* live cluster in this session.
|
|
9
|
-
*
|
|
10
|
-
* ⛔ DO NOT LOG STDOUT ON FAILURE. `talosctl kubeconfig` and error paths have been observed in the
|
|
11
|
-
* wild to include credential material; stderr is the safe diagnostic channel.
|
|
12
|
-
*/
|
|
13
1
|
import * as Effect from 'effect/Effect';
|
|
14
2
|
import * as ChildProcessSpawner from 'effect/process/ChildProcessSpawner';
|
|
3
|
+
import { DEFAULT_TALOSCTL_BINARY, TALOSCTL_BINARY_ENV, TalosBinaryRefused } from './talosctl-binary.ts';
|
|
4
|
+
export { DEFAULT_TALOSCTL_BINARY, TALOSCTL_BINARY_ENV, TalosBinaryRefused };
|
|
15
5
|
export declare class TalosError extends Error {
|
|
16
6
|
readonly command: string;
|
|
17
7
|
readonly exitCode: number;
|
|
18
|
-
constructor(command: string, exitCode: number, detail: string);
|
|
8
|
+
constructor(command: string, exitCode: number, detail: string, binary?: string);
|
|
19
9
|
}
|
|
10
|
+
/** The Talos client version this family is written against (`--client` of the pinned binary). */
|
|
11
|
+
export declare const TALOSCTL_PINNED_VERSION = "v1.14.2";
|
|
20
12
|
export type TalosRunOptions = {
|
|
21
13
|
readonly talosconfigPath: string;
|
|
14
|
+
/**
|
|
15
|
+
* `talosctl` executable. Wins over {@link TALOSCTL_BINARY_ENV}.
|
|
16
|
+
* @default `talosctl` on `PATH`, or `HF_TALOSCTL` when that variable is set.
|
|
17
|
+
*/
|
|
18
|
+
readonly binary?: string;
|
|
22
19
|
readonly nodes?: readonly string[];
|
|
23
20
|
readonly endpoints?: readonly string[];
|
|
24
21
|
/**
|
|
@@ -30,7 +27,7 @@ export type TalosRunOptions = {
|
|
|
30
27
|
readonly insecure?: boolean;
|
|
31
28
|
};
|
|
32
29
|
/** Run `talosctl <args…>`. Returns trimmed stdout, or '' when empty. */
|
|
33
|
-
export declare const talosctl: (args: readonly string[], options: TalosRunOptions) => Effect.Effect<string, import("effect/PlatformError").PlatformError | TalosError, ChildProcessSpawner.ChildProcessSpawner>;
|
|
30
|
+
export declare const talosctl: (args: readonly string[], options: TalosRunOptions) => Effect.Effect<string, import("effect/PlatformError").PlatformError | TalosBinaryRefused | TalosError, ChildProcessSpawner.ChildProcessSpawner>;
|
|
34
31
|
/** Like `talosctl`, but exit code 1 with "already" in stderr is treated as success. */
|
|
35
|
-
export declare const talosctlOrAlready: (args: readonly string[], options: TalosRunOptions) => Effect.Effect<string, import("effect/PlatformError").PlatformError, ChildProcessSpawner.ChildProcessSpawner>;
|
|
32
|
+
export declare const talosctlOrAlready: (args: readonly string[], options: TalosRunOptions) => Effect.Effect<string, import("effect/PlatformError").PlatformError | TalosBinaryRefused, ChildProcessSpawner.ChildProcessSpawner>;
|
|
36
33
|
//# sourceMappingURL=talosctl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"talosctl.d.ts","sourceRoot":"","sources":["../../src/talos/talosctl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"talosctl.d.ts","sourceRoot":"","sources":["../../src/talos/talosctl.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,mBAAmB,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAGnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;AAE5E,qBAAa,UAAW,SAAQ,KAAK;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAF3B,YACW,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,MAAM,SAA0B,EAIjC;CACF;AAED,iGAAiG;AACjG,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAwBjD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AA8DF,wEAAwE;AACxE,eAAO,MAAM,QAAQ,SAAU,SAAS,MAAM,EAAE,WAAW,eAAe,mJAgCtE,CAAC;AAEL,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,SAAU,SAAS,MAAM,EAAE,WAAW,eAAe,sIAShF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical compare: the walk hands over a real path, but the boundary is a security decision —
|
|
3
|
+
* resolving again makes it independent of what a caller (now or future) cached. ⛔ A directory
|
|
4
|
+
* that cannot be resolved is answered FALSE, never thrown: it is certainly not a registered
|
|
5
|
+
* boundary, and the walk must treat "no boundary" as "vet everything" (fail closed).
|
|
6
|
+
*/
|
|
7
|
+
export declare const isTrustedBoundary: (dir: string) => boolean;
|
|
8
|
+
//# sourceMappingURL=trust-boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust-boundary.d.ts","sourceRoot":"","sources":["../../src/talos/trust-boundary.ts"],"names":[],"mappings":"AAoBA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAS,MAAM,KAAG,OAM/C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/talos/values.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/talos/values.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,eAAO,MAAM,aAAa,SAAU,MAAM,WAAmB,CAAC;AAE9D,iGAAiG;AACjG,eAAO,MAAM,MAAM,SAAU,MAAM,WAC6B,CAAC;AAEjE,oFAAoF;AACpF,eAAO,MAAM,YAAY,SAAU,MAAM,WAAiB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,wBAAwB,gBAAiB,MAAM,KAAG,MAAM,GAAG,SASvE,CAAC;AAeF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,aACnB,MAAM,eACH,MAAM,KAClB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAAG,SAsB3E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parse.d.ts","sourceRoot":"","sources":["../../src/talos/yaml-parse.ts"],"names":[],"mappings":"AAcA,+EAA+E;AAC/E,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,OAYxC,CAAC"}
|
|
@@ -67,6 +67,8 @@ export interface FakeEngine {
|
|
|
67
67
|
* `verify.ts`'s `readWithState`, which already wraps that same call in `Effect.catchCause`.
|
|
68
68
|
*/
|
|
69
69
|
readonly drift: (body: Body) => Promise<Record<string, DriftRow>>;
|
|
70
|
+
/** `alchemy drift --repair` (`Alchemy.Drift.repair`): read, then reconcile what drifted. */
|
|
71
|
+
readonly repair: (body: Body) => Promise<Record<string, DriftRow>>;
|
|
70
72
|
/**
|
|
71
73
|
* Every state row the store holds, as JSON — what a Postgres store would persist. ★ For tests
|
|
72
74
|
* that must prove a value NEVER reaches state (proxmox/pbs-notification-target-state.test.ts).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/E;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,EAAE,GAAG,SAC9B,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,YACvB;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KACpC,
|
|
1
|
+
{"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/E;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,EAAE,GAAG,SAC9B,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,YACvB;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KACpC,UA2DF,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,UAA+C,CAAC"}
|
package/docs/peers.md
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
|
-
# Peers — and
|
|
2
|
-
|
|
3
|
-
The install line for `@homeflare/alchemy`, and why every peer on it and every entry in the
|
|
4
|
-
`overrides` block is required. The block itself, which every consumer copies, is in the
|
|
5
|
-
[README](../README.md#peers--and-one-override-you-need).
|
|
1
|
+
# Peers — and one override you need
|
|
6
2
|
|
|
7
3
|
```sh
|
|
8
4
|
bun add @homeflare/alchemy alchemy@2.0.0-beta.81 effect@4.0.1 \
|
|
9
5
|
@effect/platform-node@4.0.1 mime@4.1.0 \
|
|
10
6
|
@distilled.cloud/cloudflare@1.0.0-rc.13 @distilled.cloud/forgejo@1.0.0-rc.13 \
|
|
7
|
+
@distilled.cloud/discord@1.0.0-rc.13 @distilled.cloud/google-workspace@1.0.0-rc.13 \
|
|
8
|
+
@distilled.cloud/argocd@1.0.0-rc.13 \
|
|
11
9
|
@effect/sql-pg@4.0.1
|
|
12
10
|
```
|
|
13
11
|
|
|
12
|
+
⛔ **Every one of those is required, and you also need an `overrides` block** — see
|
|
13
|
+
below. The install succeeds without them and the import throws.
|
|
14
|
+
|
|
15
|
+
★ **The machine-readable source of truth** lives in this package's `package.json` under the
|
|
16
|
+
`homeflare.consumer` field. It carries the exact pins, the overrides below, and the import
|
|
17
|
+
moves for `effect/unstable/*` as an ordered **array of `{"from", "to"}` pairs** — not an
|
|
18
|
+
object keyed by the old path. Order is load-bearing: the most specific path comes first
|
|
19
|
+
(`httpapi` before its parent `http`), because consumers apply the moves in published order.
|
|
20
|
+
The install line, the overrides block in this doc, and the smoke test install are all
|
|
21
|
+
asserted against that field; change the field first, then copy its `overrides` block here.
|
|
22
|
+
|
|
23
|
+
⛔ **Add this to your `package.json`, or the install works and the import throws:**
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"overrides": {
|
|
28
|
+
"effect": "4.0.1",
|
|
29
|
+
"@effect/platform-node": "4.0.1",
|
|
30
|
+
"@effect/platform-node-shared": "4.0.1",
|
|
31
|
+
"@effect/platform-bun": "4.0.1",
|
|
32
|
+
"rolldown": "1.2.8",
|
|
33
|
+
"redis": "6.3.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Why each peer is required and each pin exists — the measurements, and the error a missing one
|
|
39
|
+
produces — is below.
|
|
40
|
+
|
|
14
41
|
🔴 **Why, measured 2026-09-16 on 0.1.0 and re-checked 2026-09-17 against Alchemy 78.**
|
|
15
42
|
Effect's `rc` line is not semver-compatible with itself. Alchemy 78's peer is
|
|
16
43
|
`effect >= 4.0.0-rc.115`; an unlocked `@effect/platform-node-shared` still floats to the
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# `Kubernetes.ClusterAdapter` kind `talos-openbao`
|
|
2
|
+
|
|
3
|
+
Reads the cluster admin kubeconfig from OpenBao KV (`bao kv get`, in memory, nothing on disk)
|
|
4
|
+
when a `Kubernetes.Manifest` / `HelmChart` connects, and proves the answering cluster is the
|
|
5
|
+
pinned one by its kube-system `metadata.uid`. The persisted connection is `{ kind, uid }` only.
|
|
6
|
+
The design, the identity rule and the failure modes are in the header of
|
|
7
|
+
`src/talos/cluster-adapter.ts`; this page is what an operator must do differently.
|
|
8
|
+
|
|
9
|
+
## Connect deadline
|
|
10
|
+
|
|
11
|
+
Vault read and uid GET share one 10 s deadline. A hung `bao` or a silent apiserver fails closed
|
|
12
|
+
with `TalosOpenBaoConnectTimeout` (the `bao` child is killed with its process group). The HTTPS
|
|
13
|
+
GET itself cannot be cancelled: upstream `readObject` takes no abort signal, so the request may
|
|
14
|
+
linger until the OS gives up. That is an upstream ask, not something to re-implement here.
|
|
15
|
+
|
|
16
|
+
## Literal connections only
|
|
17
|
+
|
|
18
|
+
`talosOpenBaoConnection(uid)` throws `TalosUidNotLiteral` for an Output, and
|
|
19
|
+
`Talos.ClusterHealth` refuses an Output connection in `diff` for the same reason: `cluster: health`
|
|
20
|
+
passes that connection to workloads, and an unresolved connection hides a cluster change from the
|
|
21
|
+
plan.
|
|
22
|
+
|
|
23
|
+
## Usage rules
|
|
24
|
+
|
|
25
|
+
Upstream Alchemy behaviour the adapter cannot fix. Follow these or risk deleting objects on the
|
|
26
|
+
wrong cluster.
|
|
27
|
+
|
|
28
|
+
1. **Move a workload to another cluster only by new logical IDs** (destroy the old, create the new).
|
|
29
|
+
Never change a live workload's `connection` in place: upstream skips the identity comparison
|
|
30
|
+
when any input is unresolved (`HelmChart.ts:246`), so the old generation's cleanup can run
|
|
31
|
+
against the new cluster.
|
|
32
|
+
2. **Manage namespaces as separate `Manifest`s**, never `HelmChart` `createNamespace`. A replacement
|
|
33
|
+
cleanup deletes a shared `createNamespace` namespace (`HelmChart.ts:257`, `:344`) and everything
|
|
34
|
+
else in it.
|
|
35
|
+
3. **Never rename a `HelmChart` `releaseName` in place.** It is replaced, and cleanup removes the
|
|
36
|
+
release the new one just took over.
|
|
37
|
+
|
|
38
|
+
## Upstream asks (alchemy 2.0.0-beta.79)
|
|
39
|
+
|
|
40
|
+
- `HelmChart`/`Manifest` diff skips identity comparison when any input is unresolved.
|
|
41
|
+
- Replacement cleanup deletes a shared `createNamespace` namespace.
|
|
42
|
+
- `readObject` cannot be cancelled (`internal/client.ts:75`).
|
|
43
|
+
- `deleteObject` has no uid precondition.
|
|
44
|
+
- Refresh replaces the saved uids.
|