@intentius/chant-lexicon-k8s 0.30.0 → 0.32.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 (137) hide show
  1. package/dist/api/classify.d.ts +65 -0
  2. package/dist/api/classify.d.ts.map +1 -0
  3. package/dist/api/connect.d.ts +58 -0
  4. package/dist/api/connect.d.ts.map +1 -0
  5. package/dist/api/fake-cluster.d.ts +55 -0
  6. package/dist/api/fake-cluster.d.ts.map +1 -0
  7. package/dist/api/operation-surface.d.ts +64 -0
  8. package/dist/api/operation-surface.d.ts.map +1 -0
  9. package/dist/api/owner-chain.d.ts +46 -0
  10. package/dist/api/owner-chain.d.ts.map +1 -0
  11. package/dist/api/sweep-types.d.ts +17 -0
  12. package/dist/api/sweep-types.d.ts.map +1 -0
  13. package/dist/codegen/generate-operations.d.ts +29 -0
  14. package/dist/codegen/generate-operations.d.ts.map +1 -0
  15. package/dist/codegen/generate.d.ts.map +1 -1
  16. package/dist/config.d.ts +17 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/crd/parser.d.ts.map +1 -1
  19. package/dist/crd/types.d.ts +7 -0
  20. package/dist/crd/types.d.ts.map +1 -1
  21. package/dist/deep-observe-hooks.d.ts +86 -0
  22. package/dist/deep-observe-hooks.d.ts.map +1 -0
  23. package/dist/deep-observe.d.ts +146 -0
  24. package/dist/deep-observe.d.ts.map +1 -0
  25. package/dist/describe-resources.d.ts +58 -26
  26. package/dist/describe-resources.d.ts.map +1 -1
  27. package/dist/export-resources.d.ts +31 -1
  28. package/dist/export-resources.d.ts.map +1 -1
  29. package/dist/integrity.json +2 -2
  30. package/dist/kube/apply.d.ts +26 -0
  31. package/dist/kube/apply.d.ts.map +1 -0
  32. package/dist/kube/connect.d.ts +30 -0
  33. package/dist/kube/connect.d.ts.map +1 -0
  34. package/dist/kube/delete.d.ts +27 -0
  35. package/dist/kube/delete.d.ts.map +1 -0
  36. package/dist/kube/describe.d.ts +19 -0
  37. package/dist/kube/describe.d.ts.map +1 -0
  38. package/dist/kube/events.d.ts +34 -0
  39. package/dist/kube/events.d.ts.map +1 -0
  40. package/dist/kube/flags.d.ts +40 -0
  41. package/dist/kube/flags.d.ts.map +1 -0
  42. package/dist/kube/get.d.ts +21 -0
  43. package/dist/kube/get.d.ts.map +1 -0
  44. package/dist/kube/group.d.ts +19 -0
  45. package/dist/kube/group.d.ts.map +1 -0
  46. package/dist/kube/logs.d.ts +16 -0
  47. package/dist/kube/logs.d.ts.map +1 -0
  48. package/dist/kube/project.d.ts +59 -0
  49. package/dist/kube/project.d.ts.map +1 -0
  50. package/dist/kube/render.d.ts +75 -0
  51. package/dist/kube/render.d.ts.map +1 -0
  52. package/dist/kube/source.d.ts +19 -0
  53. package/dist/kube/source.d.ts.map +1 -0
  54. package/dist/kube/target.d.ts +52 -0
  55. package/dist/kube/target.d.ts.map +1 -0
  56. package/dist/kube/testing.d.ts +21 -0
  57. package/dist/kube/testing.d.ts.map +1 -0
  58. package/dist/kube/top.d.ts +23 -0
  59. package/dist/kube/top.d.ts.map +1 -0
  60. package/dist/kube/verdict.d.ts +45 -0
  61. package/dist/kube/verdict.d.ts.map +1 -0
  62. package/dist/kube/wait.d.ts +23 -0
  63. package/dist/kube/wait.d.ts.map +1 -0
  64. package/dist/manifest.json +1 -1
  65. package/dist/op/activities/index.d.ts +7 -4
  66. package/dist/op/activities/index.d.ts.map +1 -1
  67. package/dist/op/activities/kubectl.d.ts +120 -2
  68. package/dist/op/activities/kubectl.d.ts.map +1 -1
  69. package/dist/op/activities/wait-for-ready.d.ts +30 -3
  70. package/dist/op/activities/wait-for-ready.d.ts.map +1 -1
  71. package/dist/plugin.d.ts.map +1 -1
  72. package/dist/spec/parse.d.ts +42 -0
  73. package/dist/spec/parse.d.ts.map +1 -1
  74. package/package.json +5 -2
  75. package/src/api/classify.test.ts +133 -0
  76. package/src/api/classify.ts +144 -0
  77. package/src/api/connect.ts +104 -0
  78. package/src/api/fake-cluster.ts +218 -0
  79. package/src/api/operation-surface.test.ts +116 -0
  80. package/src/api/operation-surface.ts +129 -0
  81. package/src/api/owner-chain.test.ts +171 -0
  82. package/src/api/owner-chain.ts +144 -0
  83. package/src/api/sweep-types.ts +36 -0
  84. package/src/codegen/generate-operations.ts +56 -0
  85. package/src/codegen/generate.ts +9 -0
  86. package/src/config.ts +17 -0
  87. package/src/crd/parser.ts +8 -0
  88. package/src/crd/types.ts +7 -0
  89. package/src/deep-observe-hooks.ts +125 -0
  90. package/src/deep-observe.test.ts +668 -0
  91. package/src/deep-observe.ts +299 -0
  92. package/src/describe-resources.test.ts +619 -191
  93. package/src/describe-resources.ts +218 -117
  94. package/src/export-resources-io.test.ts +76 -51
  95. package/src/export-resources.ts +47 -35
  96. package/src/generated/operations.json +2156 -0
  97. package/src/kube/apply.test.ts +105 -0
  98. package/src/kube/apply.ts +101 -0
  99. package/src/kube/connect.ts +54 -0
  100. package/src/kube/delete.test.ts +123 -0
  101. package/src/kube/delete.ts +174 -0
  102. package/src/kube/describe.test.ts +106 -0
  103. package/src/kube/describe.ts +195 -0
  104. package/src/kube/events.test.ts +115 -0
  105. package/src/kube/events.ts +160 -0
  106. package/src/kube/flags.test.ts +65 -0
  107. package/src/kube/flags.ts +114 -0
  108. package/src/kube/get.test.ts +195 -0
  109. package/src/kube/get.ts +190 -0
  110. package/src/kube/group.test.ts +33 -0
  111. package/src/kube/group.ts +125 -0
  112. package/src/kube/logs.test.ts +126 -0
  113. package/src/kube/logs.ts +96 -0
  114. package/src/kube/project.test.ts +57 -0
  115. package/src/kube/project.ts +106 -0
  116. package/src/kube/render.test.ts +142 -0
  117. package/src/kube/render.ts +252 -0
  118. package/src/kube/source.test.ts +138 -0
  119. package/src/kube/source.ts +139 -0
  120. package/src/kube/target.test.ts +67 -0
  121. package/src/kube/target.ts +89 -0
  122. package/src/kube/testing.ts +42 -0
  123. package/src/kube/top.test.ts +149 -0
  124. package/src/kube/top.ts +120 -0
  125. package/src/kube/verdict.test.ts +48 -0
  126. package/src/kube/verdict.ts +77 -0
  127. package/src/kube/wait.test.ts +125 -0
  128. package/src/kube/wait.ts +160 -0
  129. package/src/lifecycle-integration.test.ts +132 -92
  130. package/src/op/activities/index.ts +7 -3
  131. package/src/op/activities/kubectl.test.ts +420 -0
  132. package/src/op/activities/kubectl.ts +379 -13
  133. package/src/op/activities/wait-for-ready.test.ts +94 -0
  134. package/src/op/activities/wait-for-ready.ts +66 -15
  135. package/src/plugin.test.ts +58 -1
  136. package/src/plugin.ts +29 -0
  137. package/src/spec/parse.ts +93 -1
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Typed API failure → the observation tri-state (chant #1089, #1074).
3
+ *
4
+ * `classifyKubectlFailure` in core does this by matching English on stderr,
5
+ * because that was all `kubectl` gave it. The API server has always sent a
6
+ * `Status` object with a numeric code and a `reason` enum; the typed client
7
+ * carries it through, so classification here reads fields rather than
8
+ * searching for substrings. The verdicts are deliberately the same ones the
9
+ * kubectl path produced — this replaces the evidence, not the contract.
10
+ *
11
+ * The one that reads as a surprise, and is not: **a kind the cluster does not
12
+ * serve is an absence, not a hole.** No instance of an unserved kind can exist
13
+ * there, and the usual cause is a CRD the very plan being computed has not
14
+ * applied yet. Calling it NOT-OBSERVED would suppress the create that is
15
+ * genuinely needed. That is core's existing rule (`classifyKubectlFailure`
16
+ * treats "the server doesn't have a resource type" as absent) and it survives
17
+ * the move intact.
18
+ *
19
+ * Errors are discriminated by `name`, not `instanceof`. The client is an
20
+ * optional dependency reached through a dynamic import, so this module must
21
+ * not carry a static value import of it — and `name` is set explicitly by
22
+ * every one of its error classes, which also makes the classification survive
23
+ * a duplicated copy of the package in a consumer's tree.
24
+ */
25
+ import type { UnobservedReason } from "@intentius/chant/lexicon";
26
+ /** What a failed read actually proved. Mirrors core's `KubectlReadOutcome`. */
27
+ export type K8sReadOutcome =
28
+ /** The API server answered and the object is not there. Safe to plan a create. */
29
+ {
30
+ kind: "absent";
31
+ }
32
+ /** The read proved nothing about the object's existence. */
33
+ | {
34
+ kind: "unobserved";
35
+ reason: UnobservedReason;
36
+ detail: string;
37
+ };
38
+ /** Classify a failure from the typed client into the observation tri-state. */
39
+ export declare function classifyApiFailure(err: unknown): K8sReadOutcome;
40
+ /**
41
+ * The cluster's own discovery reports no such kind at all — distinct from a
42
+ * kind that exists but currently has zero live instances. `classifyApiFailure`
43
+ * folds both into `absent` for the declared-entity read path, where "no
44
+ * instance can exist" is exactly the signal a `create` needs. `chant kube get`
45
+ * (chant #1079) needs the finer distinction: an ad hoc `chant kube get
46
+ * widgets` against a kind the cluster has never heard of should say so, not
47
+ * print "No resources found." as if `widgets` were a real, empty kind.
48
+ */
49
+ export declare function isUnknownResource(err: unknown): boolean;
50
+ /**
51
+ * Whether a failure kills the whole observation rather than one entity. A
52
+ * refused binding, a missing client package and a rejected credential plugin
53
+ * are all true of every entity, so they propagate and core marks the lot
54
+ * NOT-OBSERVED with one reason instead of repeating the same failure N times.
55
+ */
56
+ export declare function isWholeLexiconFailure(err: unknown): boolean;
57
+ /**
58
+ * A dynamic import of the optional client package that failed to resolve looks
59
+ * like an ordinary module error. Recognizing it lets `describeResources` report
60
+ * a missing dependency as a missing dependency rather than as a broken cluster.
61
+ */
62
+ export declare function isMissingClientPackage(err: unknown): boolean;
63
+ /** The message a missing client package should produce. */
64
+ export declare const MISSING_CLIENT_DETAIL: string;
65
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/api/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,MAAM,cAAc;AACxB,kFAAkF;AAChF;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,4DAA4D;GAC1D;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAuBrE,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAwC/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK5D;AAED,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,QAEuE,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Getting from a chant environment to a live API client — chant #1074.
3
+ *
4
+ * The cluster binding (chant #1100, landed in #1155) is unchanged by the move
5
+ * off `kubectl`, and deliberately so: `resolveClusterTarget` in core stays the
6
+ * single resolver, shared with the GCP lexicon's Config Connector observation,
7
+ * and the refusal it throws on a bound-but-mismatched context still aborts
8
+ * before any resource is touched. What changes is only *how the ambient
9
+ * context is read*: the typed client parses the kubeconfig it is about to use
10
+ * rather than shelling `kubectl config current-context`, so a worker image with
11
+ * no `kubectl` in it can still check the binding. Same question, same three
12
+ * outcomes:
13
+ *
14
+ * - **Bound and ambient agrees** — the bound context is passed explicitly to
15
+ * the client, never left to the ambient default.
16
+ * - **Bound and ambient disagrees** — `ClusterBindingMismatchError`, thrown
17
+ * before the first request. Core turns the throw into NOT-OBSERVED for every
18
+ * declared entity (chant #1089), which is what stops a wrong-cluster read
19
+ * becoming a confident list of creates.
20
+ * - **Unbound** — the kubeconfig's own current-context, with the same visible
21
+ * warning naming the environment and the missing binding.
22
+ */
23
+ import { type ResolvedClusterTarget } from "@intentius/chant/kubectl-context";
24
+ import type { K8sClient, K8sClientOptions } from "@intentius/chant-k8s-client";
25
+ /**
26
+ * Build a client for an environment. Injectable so tests drive the real client
27
+ * against a fake request layer, and so `describeResources` and the Op
28
+ * activities share one connection story rather than each inventing one.
29
+ */
30
+ export type K8sConnector = (options: ConnectOptions) => Promise<ConnectedClient>;
31
+ export interface ConnectOptions {
32
+ /**
33
+ * chant environment being observed or applied to. Omitting it skips the
34
+ * config lookup and the binding check — which is what an Op activity called
35
+ * with no environment and no explicit context has always done: use whatever
36
+ * the kubeconfig selects.
37
+ */
38
+ environment?: string;
39
+ /** Directory whose `chant.config.ts` carries `k8s.profiles`. Defaults to cwd. */
40
+ cwd?: string;
41
+ /**
42
+ * An explicit context, for the Op write path whose activity contract has
43
+ * always taken one. Skips the config lookup and the binding check entirely.
44
+ */
45
+ context?: string;
46
+ /** Extra client options — the request-layer seam, concurrency. */
47
+ client?: Partial<K8sClientOptions>;
48
+ }
49
+ export interface ConnectedClient {
50
+ client: K8sClient;
51
+ target: ResolvedClusterTarget;
52
+ }
53
+ /**
54
+ * The production connector: read the project's config, resolve the binding,
55
+ * build a client honoring it.
56
+ */
57
+ export declare const defaultK8sConnector: K8sConnector;
58
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/api/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/E;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAEjF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAwCjC,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * A fake cluster to point the k8s lexicon at, for tests (chant #1074).
3
+ *
4
+ * It builds a **real** `@intentius/chant-k8s-client` over a literal kubeconfig
5
+ * with `@kubernetes/client-node`'s HTTP send replaced. So kubeconfig parsing,
6
+ * context selection, the credential policy, API discovery, path construction
7
+ * and the auth path all run for real; the only thing that does not happen is
8
+ * the socket. Nothing reads `~/.kube/config` or `$KUBECONFIG`, and nothing can
9
+ * reach a cluster the developer happens to have a context for.
10
+ *
11
+ * Shipped rather than kept in a test file because the lexicon's own tests, the
12
+ * cross-lexicon lifecycle suite and a consumer wiring chant into their harness
13
+ * all need the same thing.
14
+ */
15
+ import type { K8sObject } from "@intentius/chant-k8s-client";
16
+ import type { FakeRequestLayer, RecordedRequest } from "@intentius/chant-k8s-client/testing";
17
+ import type { ConnectOptions, K8sConnector } from "./connect.js";
18
+ export interface FakeClusterOptions {
19
+ /**
20
+ * Objects the cluster holds, keyed by
21
+ * `<apiVersion>/<Kind>/<namespace|_>/<name>`, e.g.
22
+ * `apps/v1/Deployment/prod/web`. Build keys with {@link objectKey}.
23
+ */
24
+ objects?: Record<string, K8sObject>;
25
+ /**
26
+ * Entity types (or `<apiVersion> <Kind>` pairs) this cluster serves. Defaults
27
+ * to every type in the generated operation surface, which is what makes a
28
+ * CRD resolvable in a test without registering anything.
29
+ */
30
+ serves?: readonly string[];
31
+ /** Full control: return a response for a request, or undefined to fall through. */
32
+ respond?: (request: RecordedRequest) => {
33
+ status?: number;
34
+ body?: unknown;
35
+ } | undefined;
36
+ /** Kubeconfig to hand the client. Defaults to a single-context one. */
37
+ kubeconfig?: string;
38
+ }
39
+ export interface FakeCluster {
40
+ connector: K8sConnector;
41
+ layer: FakeRequestLayer;
42
+ /** Connect options every call received, for asserting the binding path. */
43
+ connects: ConnectOptions[];
44
+ }
45
+ /** Key an object the way {@link fakeCluster} indexes them. */
46
+ export declare function objectKey(apiVersion: string, kind: string, name: string, namespace?: string): string;
47
+ /** Build a live object with chant's ownership marker already on it. */
48
+ export declare function ownedObject(apiVersion: string, kind: string, name: string, namespace: string | undefined, extra?: Partial<K8sObject>): K8sObject;
49
+ /**
50
+ * A cluster that answers discovery for the kinds it serves and holds the
51
+ * objects it was given. Anything else 404s with a real `Status` body, which is
52
+ * how a test drives the absent branch of the observation tri-state.
53
+ */
54
+ export declare function fakeCluster(options?: FakeClusterOptions): FakeCluster;
55
+ //# sourceMappingURL=fake-cluster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-cluster.d.ts","sourceRoot":"","sources":["../../src/api/fake-cluster.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE7F,OAAO,KAAK,EAAmB,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG/E,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACxF,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpG;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,GAAE,OAAO,CAAC,SAAS,CAAM,GAC7B,SAAS,CAcX;AAwBD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA+FzE"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Reading the generated operation surface — chant #1074.
3
+ *
4
+ * The table itself is written by `chant generate` (see
5
+ * `../codegen/generate-operations.ts`); this is the runtime side, and it is
6
+ * deliberately the only place in the lexicon that knows how an entity type
7
+ * becomes an API address.
8
+ *
9
+ * Loading mirrors the serializer's handling of `lexicon-k8s.json`: a `require`
10
+ * behind a try/catch, so a checkout that has not run `chant generate` yet
11
+ * degrades to derivation rather than failing to import. Nothing here touches
12
+ * the filesystem at module load (chant #1081) — the first call does, and caches.
13
+ */
14
+ /** One resource's addressing information, as `chant generate` emits it. */
15
+ export interface K8sOperationDescriptor {
16
+ /** chant entity type, e.g. `K8s::Apps::Deployment`. */
17
+ entityType: string;
18
+ /** `v1`, `apps/v1`, `ray.io/v1` — what goes in a manifest. */
19
+ apiVersion: string;
20
+ /** `Deployment`, `RayCluster`. */
21
+ kind: string;
22
+ /** Plural path segment the schema documents, e.g. `deployments`. */
23
+ plural: string;
24
+ scope: "Namespaced" | "Cluster";
25
+ /** Verbs the schema documents for the named-object path. */
26
+ verbs: string[];
27
+ }
28
+ /** The generated file's shape: entity type → descriptor. */
29
+ export type K8sOperationTable = Record<string, K8sOperationDescriptor>;
30
+ /**
31
+ * Fallback plural for a kind whose schema documented no named-object path.
32
+ *
33
+ * Kubernetes' own pluralization for resource names is the lowercased kind with
34
+ * English plural rules applied — the three cases `kubectl` implements. It only
35
+ * fires for kinds the OpenAPI paths do not cover, and the live client overrides
36
+ * it from the cluster's discovery regardless, so it is a placeholder rather
37
+ * than a second table to maintain.
38
+ */
39
+ export declare function pluralizeKind(kind: string): string;
40
+ /** The generated table, loaded once. Empty when nothing has been generated. */
41
+ export declare function operationTable(): K8sOperationTable;
42
+ /** Reset the memoized table. Tests only. */
43
+ export declare function resetOperationTableForTests(): void;
44
+ /**
45
+ * How to address a declared entity type over the API.
46
+ *
47
+ * Returns undefined only for a type the generated surface does not carry and
48
+ * whose `K8s::<Group>::<Kind>` shape yields no known group — which is the one
49
+ * case where chant genuinely does not know what to ask for. Every generated
50
+ * resource type, including every CRD baked in at generation time, is in the
51
+ * table; that is the difference between this and the twenty-entry map it
52
+ * replaces.
53
+ */
54
+ export declare function operationFor(entityType: string): K8sOperationDescriptor | undefined;
55
+ /**
56
+ * Last-resort derivation from the entity type's own shape, for a lexicon
57
+ * running without generated artifacts. It cannot invent an API group it has
58
+ * never seen, so an unknown group returns undefined rather than a guess that
59
+ * would address the wrong thing.
60
+ */
61
+ export declare function deriveOperation(entityType: string): K8sOperationDescriptor | undefined;
62
+ /** Every entity type the generated surface can address. */
63
+ export declare function addressableEntityTypes(): string[];
64
+ //# sourceMappingURL=operation-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-surface.d.ts","sourceRoot":"","sources":["../../src/api/operation-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;AAEvE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlD;AAqBD,+EAA+E;AAC/E,wBAAgB,cAAc,IAAI,iBAAiB,CAQlD;AAED,4CAA4C;AAC5C,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAKnF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAatF;AAED,2DAA2D;AAC3D,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Resolving a live Kubernetes object's `ownerReferences` chain up to a
3
+ * declared, chant-observed entity (chant #1077).
4
+ *
5
+ * There is no server-side "who ultimately owns this object" query — Kubernetes'
6
+ * own garbage collector does not have one either; it walks the same chain one
7
+ * hop at a time, reading each intermediate owner. A Pod's `ownerReferences`
8
+ * names its ReplicaSet, which chant never declared; the ReplicaSet's own
9
+ * `ownerReferences` names the Deployment, which is declared. Reaching that
10
+ * declared entity takes reading the ReplicaSet in between.
11
+ *
12
+ * This module's only job is assembling that chain — fetching each hop through
13
+ * the typed client, bounded and cycle-guarded so a corrupt or adversarial
14
+ * chain cannot hang an observation. The bounded/cycle-safe *interpretation* of
15
+ * the assembled chain (declared / unowned / foreign / unknown) is core's
16
+ * `classifyOwnerChain` (`@intentius/chant/owner-chain`) — the issue's own
17
+ * division of labor: core owns the category, the lexicon supplies the chain.
18
+ */
19
+ import type { K8sClient, K8sObject } from "@intentius/chant-k8s-client";
20
+ import { type OwnerChainVerdict } from "@intentius/chant/owner-chain";
21
+ /** The client surface this module needs — a single object read, addressed by
22
+ * an owner reference's own coordinates. */
23
+ export type OwnerChainReader = Pick<K8sClient, "readIfPresent">;
24
+ export interface ResolveOwnerChainOptions {
25
+ /** uid → declared chant entity name, from this observation's own resolved entities. */
26
+ declaredByUid: ReadonlyMap<string, string>;
27
+ /** Reads each intermediate owner. */
28
+ reader: OwnerChainReader;
29
+ /**
30
+ * Namespace the starting object lives in. Owner references are same-namespace
31
+ * only — a namespaced object cannot be owned by an object in another
32
+ * namespace, the same rule Kubernetes' own garbage collector enforces —so
33
+ * every hop is read in this namespace.
34
+ */
35
+ namespace: string | undefined;
36
+ maxDepth?: number;
37
+ }
38
+ /**
39
+ * Walk `obj`'s owner-reference chain up to a declared entity, a foreign root,
40
+ * or a bound (#1077). Fetches at most `maxDepth + 1` objects (the starting
41
+ * object plus up to `maxDepth` ancestors) — the same bound `classifyOwnerChain`
42
+ * enforces when interpreting the result, so nothing is fetched that the
43
+ * interpretation would not have used anyway.
44
+ */
45
+ export declare function resolveK8sOwnerChain(obj: K8sObject, options: ResolveOwnerChainOptions): Promise<OwnerChainVerdict>;
46
+ //# sourceMappingURL=owner-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-chain.d.ts","sourceRoot":"","sources":["../../src/api/owner-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AA2BtC;2CAC2C;AAC3C,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACvC,uFAAuF;IACvF,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,qCAAqC;IACrC,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA8D5B"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The kinds chant sweeps when nothing narrows the question.
3
+ *
4
+ * A *product* decision — what a bare `chant import` should pull back, and
5
+ * (chant #1075) which kinds an ownership-scoped prune has to look at to notice
6
+ * that a whole kind was removed from source. Not an addressing limit: since
7
+ * chant #1074 removed `KUBECTL_RESOURCE`, a `--selector type=<entity type>`
8
+ * import can name any of the ~180 types the generated operation surface
9
+ * carries, CRDs included.
10
+ *
11
+ * It lives in its own module, with no imports of its own, because both
12
+ * consumers reach it from different directions — `../export-resources.ts`
13
+ * pulls in the whole import parser, and a Temporal worker loading the apply
14
+ * activity should not.
15
+ */
16
+ export declare const DEFAULT_IMPORT_TYPES: readonly string[];
17
+ //# sourceMappingURL=sweep-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep-types.d.ts","sourceRoot":"","sources":["../../src/api/sweep-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAoBjD,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The generated operation surface — chant #1074.
3
+ *
4
+ * `describeResources` used to reach the cluster through a hand-written
5
+ * `entityType → kubectl resource` map with twenty entries in it. Every one of
6
+ * the other ~180 generated resource types, and every CRD, fell off the end of
7
+ * it. The map was hand-maintained precisely because nothing derived it, and
8
+ * nothing derived it because the codegen pass that produces the types never
9
+ * emitted the addressing half.
10
+ *
11
+ * It does now. This artifact is written by the same `generate()` run that
12
+ * writes `lexicon-k8s.json` and `index.d.ts`, out of the same parsed results,
13
+ * so a resource that has a declarable class necessarily has an operation entry
14
+ * with the same apiVersion and kind. `operation-surface.test.ts` asserts that
15
+ * correspondence rather than trusting it.
16
+ *
17
+ * What it is not: an authority on what a given cluster serves. `plural` and
18
+ * `scope` are what the schema says; the live client confirms both against the
19
+ * cluster's own discovery before addressing anything, because a cluster can
20
+ * serve a different version of a CRD than the one chant generated from.
21
+ */
22
+ import type { K8sParseResult } from "../spec/parse.js";
23
+ import { type K8sOperationDescriptor, type K8sOperationTable } from "../api/operation-surface.js";
24
+ export type { K8sOperationDescriptor, K8sOperationTable };
25
+ /** Build the operation table from the same parsed results the types come from. */
26
+ export declare function buildOperationTable(results: K8sParseResult[]): K8sOperationTable;
27
+ /** Serialize the table, key-sorted so regeneration produces a stable diff. */
28
+ export declare function generateOperationsJSON(results: K8sParseResult[]): string;
29
+ //# sourceMappingURL=generate-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-operations.d.ts","sourceRoot":"","sources":["../../src/codegen/generate-operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAiB,KAAK,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE9G,YAAY,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;AAE1D,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,iBAAiB,CAkBhF;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAKxE"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/codegen/generate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,mCAAmC,CAAC;AAc3C,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC,CAmErF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAUjF"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/codegen/generate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,mCAAmC,CAAC;AAe3C,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0ErF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAWjF"}
package/dist/config.d.ts CHANGED
@@ -58,5 +58,22 @@ export interface K8sClusterProfile {
58
58
  export interface K8sChantConfig {
59
59
  /** Named environment → cluster bindings, keyed by environment name. */
60
60
  profiles?: Record<string, K8sClusterProfile>;
61
+ /**
62
+ * Exec credential-plugin commands chant may execute (chant #1074).
63
+ *
64
+ * On EKS, AKS and GKE, kubeconfig authentication is a subprocess:
65
+ * `aws eks get-token`, `kubelogin`, `gke-gcloud-auth-plugin`. Those three
66
+ * plus `kubectl` are allowed by default. Anything else the kubeconfig names
67
+ * is refused, because an exec plugin is an arbitrary binary named in a file
68
+ * chant did not write. Setting this **replaces** the default list.
69
+ *
70
+ * ```ts
71
+ * k8s: {
72
+ * profiles: { prod: { context: "prod-eks" } },
73
+ * execCredentialPlugins: ["aws", "my-org-oidc-helper"],
74
+ * } satisfies K8sChantConfig
75
+ * ```
76
+ */
77
+ execCredentialPlugins?: string[];
61
78
  }
62
79
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC9C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC7C;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/crd/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAwD,MAAM,eAAe,CAAC;AAC1G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA4CvC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAqB1D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,EAAE,CA4C5D"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/crd/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAwD,MAAM,eAAe,CAAC;AAC1G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA4CvC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAqB1D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,EAAE,CAoD5D"}
@@ -32,6 +32,13 @@ export interface CRDSource {
32
32
  export interface CRDSpec {
33
33
  /** API group (e.g. "cert-manager.io") */
34
34
  group: string;
35
+ /**
36
+ * Whether instances are namespaced. Declared by the CRD itself, so it is the
37
+ * authoritative source for a custom resource's scope — the equivalent of what
38
+ * the OpenAPI `paths` say for built-in kinds (chant #1074). Defaults to
39
+ * `Namespaced`, matching the API server's own default.
40
+ */
41
+ scope?: "Namespaced" | "Cluster";
35
42
  /** Name variants for the CRD */
36
43
  names: {
37
44
  kind: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/crd/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IACjC,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,sCAAsC;IACtC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,0BAA0B,CAAC;IACjC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACnD,IAAI,EAAE,OAAO,CAAC;CACf"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/crd/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IACjC,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACjC,gCAAgC;IAChC,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,sCAAsC;IACtC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,0BAA0B,CAAC;IACjC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACnD,IAAI,EAAE,OAAO,CAAC;CACf"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The k8s lexicon's *static* deep-observation noise rules (#1076, epic #1073).
3
+ *
4
+ * Split out from `./deep-observe.ts` for one reason: this file must be safe
5
+ * to import from `plugin.ts` at module load time, because
6
+ * `LexiconPlugin.deepNormalizationHooks` is plain data core reads to
7
+ * normalize the *declared* tree — the half of the contract that runs whether
8
+ * or not a cluster is ever touched (`lifecycle diff` without `--live`,
9
+ * `chant build`, tests that only exercise normalization). `./deep-observe.ts`
10
+ * itself imports `@intentius/chant-k8s-client` for the live read, and chant
11
+ * #1074 made that package's reachability from the build path a structural
12
+ * property (`examples/k8s-client-boundary.test.ts`) rather than a lint rule —
13
+ * so nothing this file exports may pull that package in, directly or
14
+ * transitively. It imports nothing but the core contract's own types.
15
+ *
16
+ * What lives here is deliberately the *entityType-keyed, resource-agnostic*
17
+ * half of the rules: which fields the API server always populates regardless
18
+ * of what a manager wrote (`status`, `metadata.uid`, …), which fields
19
+ * Kubernetes defaults when a manifest is silent about them, and which arrays
20
+ * are sets addressed by a well-known identity (containers by name, ports by
21
+ * containerPort+protocol). None of that needs a live object in hand.
22
+ *
23
+ * What does *not* live here is the managed-fields prune — whether one
24
+ * specific field on one specific live object is chant-owned, foreign-owned,
25
+ * or contested. That is inherently per-object (it depends on *that* object's
26
+ * `metadata.managedFields`, which the declared tree never carries and which
27
+ * differs between two Deployments of the same type), so it cannot be
28
+ * expressed as a fixed rule keyed only by entity type and path — the shape
29
+ * every other hook in this file takes. `./deep-observe.ts` computes it once
30
+ * per resource and layers it on top of the rules below.
31
+ *
32
+ * The *entity-type-agnostic* half of these rules — which fields every
33
+ * Kubernetes API object carries regardless of kind, and the well-known
34
+ * list-map-key ordering conventions (containers/env/volumes/ports) — lives in
35
+ * `@intentius/chant/managed-fields` (chant #1087), because a GCP Config
36
+ * Connector custom resource is a Kubernetes object too and needs the exact
37
+ * same rules without depending on this lexicon's package. What stays here is
38
+ * only what's genuinely k8s-*lexicon*-specific: {@link K8S_SERVICE_DEFAULTS},
39
+ * keyed by chant's own k8s entityType catalog.
40
+ */
41
+ import type { DeepNormalizationHooks } from "@intentius/chant/lexicon";
42
+ /**
43
+ * Kubernetes-defaulted fields, per entity type, as index-erased property
44
+ * paths. Subtracted only where source never declared the property
45
+ * (`side === "live" && counterpart === "absent"`) — cdk-real-drift's default
46
+ * subtraction, same convention as AWS/Azure/Temporal's tables.
47
+ *
48
+ * Sparse and evidence-based rather than derived from the generated schema:
49
+ * the k8s OpenAPI spec this lexicon's codegen consumes
50
+ * (`lexicons/k8s/src/spec/parse.ts`) does not carry a `default` value for
51
+ * these fields the way ARM's schema sometimes does, so "per discovery" is not
52
+ * actually expressible today. Widening this table is additive and needs no
53
+ * contract change.
54
+ *
55
+ * `spec.strategy` is listed whole, not as `spec.strategy.type`, for the same
56
+ * reason Temporal's `TEMPORAL_SCHEDULE_DEFAULTS` lists `state` whole: pruning
57
+ * only the leaf would still recurse into the object, and a nested default the
58
+ * table does not separately name (`rollingUpdate.maxSurge`/`maxUnavailable`,
59
+ * both `"25%"` when `spec.strategy` is omitted entirely) would leave behind an
60
+ * empty `strategy: {}` — a value distinct from no `strategy` key at all, and
61
+ * itself a spurious "undeclared" finding. Matching the whole node first, before
62
+ * its children are ever visited, drops the wrapper outright when every field
63
+ * under it is exactly at its default.
64
+ */
65
+ export declare const K8S_SERVICE_DEFAULTS: Record<string, Record<string, unknown>>;
66
+ /**
67
+ * The k8s lexicon's static noise rules: the generic Kubernetes object
68
+ * envelope (unconditional, by pattern, `@intentius/chant/managed-fields`) and
69
+ * Kubernetes-defaulted fields (gated on `counterpart === "absent"`), plus the
70
+ * array orderings the acceptance criteria name — `x-kubernetes-patch-merge-
71
+ * key`/`list-map-keys` conventions the generated surface does not currently
72
+ * carry (see the module doc), so these are the "else named-by-name
73
+ * conventions" the issue calls for: containers by `name`, `env` by `name`,
74
+ * `volumes` by `name`, container/service `ports` by `containerPort`/`port` +
75
+ * `protocol` — the same conventions `@intentius/chant/managed-fields`'s
76
+ * `k8sListMapOrderKey` implements, reused verbatim.
77
+ *
78
+ * This is the object `k8sPlugin.deepNormalizationHooks` is. It is also what
79
+ * `./deep-observe.ts` layers its per-resource managed-fields prune on top of,
80
+ * so the two normalization passes (the reader's own, and core's later
81
+ * re-normalization of both the declared and the already-normalized live tree
82
+ * — see `packages/core/src/lifecycle/deep-observe.ts`) apply the identical
83
+ * entityType-keyed rules either way.
84
+ */
85
+ export declare const k8sDeepNormalizationHooks: DeepNormalizationHooks;
86
+ //# sourceMappingURL=deep-observe-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-observe-hooks.d.ts","sourceRoot":"","sources":["../src/deep-observe-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAY,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGjF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAcxE,CAAC;AAaF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,yBAAyB,EAAE,sBAWvC,CAAC"}