@intentius/chant-lexicon-helm 0.45.0 → 0.49.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/dist/archive-render.d.ts +94 -0
- package/dist/archive-render.d.ts.map +1 -0
- package/dist/commands.d.ts +54 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/config.d.ts +135 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/deep-observe-hooks.d.ts +2 -0
- package/dist/deep-observe-hooks.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +54 -0
- package/dist/deep-observe.d.ts.map +1 -0
- package/dist/describe-resources.d.ts +17 -0
- package/dist/describe-resources.d.ts.map +1 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +5 -3
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/whm503.d.ts +34 -0
- package/dist/lint/post-synth/whm503.d.ts.map +1 -0
- package/dist/lint/post-synth/whm504.d.ts +20 -0
- package/dist/lint/post-synth/whm504.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +2 -0
- package/dist/okf/rules/WHM503.md +15 -0
- package/dist/okf/rules/WHM504.md +11 -0
- package/dist/okf/types/Values.md +1 -0
- package/dist/op/activities/cluster-probe.d.ts +44 -0
- package/dist/op/activities/cluster-probe.d.ts.map +1 -0
- package/dist/op/activities/helm.d.ts +179 -5
- package/dist/op/activities/helm.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +4 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/pinnability/actions.d.ts +76 -0
- package/dist/pinnability/actions.d.ts.map +1 -0
- package/dist/pinnability/classify.d.ts +129 -0
- package/dist/pinnability/classify.d.ts.map +1 -0
- package/dist/pinnability/conditions.d.ts +109 -0
- package/dist/pinnability/conditions.d.ts.map +1 -0
- package/dist/pinnability/index.d.ts +17 -0
- package/dist/pinnability/index.d.ts.map +1 -0
- package/dist/pinnability/localize.d.ts +124 -0
- package/dist/pinnability/localize.d.ts.map +1 -0
- package/dist/pinnability/render-stream.d.ts +27 -0
- package/dist/pinnability/render-stream.d.ts.map +1 -0
- package/dist/pinnability/values.d.ts +69 -0
- package/dist/pinnability/values.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/release-observe.d.ts +109 -0
- package/dist/release-observe.d.ts.map +1 -0
- package/dist/render-diff.d.ts +192 -0
- package/dist/render-diff.d.ts.map +1 -0
- package/dist/render-digest.d.ts +135 -0
- package/dist/render-digest.d.ts.map +1 -0
- package/dist/render-store.d.ts +310 -0
- package/dist/render-store.d.ts.map +1 -0
- package/dist/render-wrapper.d.ts +140 -0
- package/dist/render-wrapper.d.ts.map +1 -0
- package/dist/render.d.ts +81 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/rules/whm503.ts +101 -0
- package/dist/rules/whm504.ts +52 -0
- package/dist/skills/chant-helm.md +7 -0
- package/dist/values-probe.d.ts +177 -0
- package/dist/values-probe.d.ts.map +1 -0
- package/dist/wrapper-chart.d.ts +61 -0
- package/dist/wrapper-chart.d.ts.map +1 -0
- package/package.json +10 -4
- package/src/archive-render.test.ts +201 -0
- package/src/archive-render.ts +119 -0
- package/src/commands.test.ts +487 -0
- package/src/commands.ts +445 -0
- package/src/config.test.ts +130 -0
- package/src/config.ts +220 -0
- package/src/deep-observe-hooks.ts +20 -0
- package/src/deep-observe.test.ts +165 -0
- package/src/deep-observe.ts +121 -0
- package/src/describe-resources.test.ts +255 -0
- package/src/describe-resources.ts +198 -0
- package/src/index.ts +98 -2
- package/src/lifecycle-integration.test.ts +289 -0
- package/src/lint/audit-catalog.ts +2 -0
- package/src/lint/post-synth/index.ts +4 -0
- package/src/lint/post-synth/whm503.test.ts +134 -0
- package/src/lint/post-synth/whm503.ts +101 -0
- package/src/lint/post-synth/whm504.test.ts +105 -0
- package/src/lint/post-synth/whm504.ts +52 -0
- package/src/op/activities/cluster-probe.test.ts +66 -0
- package/src/op/activities/cluster-probe.ts +148 -0
- package/src/op/activities/helm.test.ts +824 -0
- package/src/op/activities/helm.ts +628 -5
- package/src/op/activities/index.ts +17 -2
- package/src/pinnability/actions.ts +263 -0
- package/src/pinnability/classify.ts +579 -0
- package/src/pinnability/conditions.ts +0 -0
- package/src/pinnability/index.ts +77 -0
- package/src/pinnability/localize.test.ts +234 -0
- package/src/pinnability/localize.ts +644 -0
- package/src/pinnability/pinnability.test.ts +560 -0
- package/src/pinnability/render-stream.ts +59 -0
- package/src/pinnability/values.ts +205 -0
- package/src/plugin.test.ts +3 -1
- package/src/plugin.ts +47 -0
- package/src/release-observe.ts +392 -0
- package/src/render-diff.test.ts +366 -0
- package/src/render-diff.ts +407 -0
- package/src/render-digest.test.ts +186 -0
- package/src/render-digest.ts +207 -0
- package/src/render-store.test.ts +412 -0
- package/src/render-store.ts +621 -0
- package/src/render-wrapper.test.ts +259 -0
- package/src/render-wrapper.ts +274 -0
- package/src/render.test.ts +383 -4
- package/src/render.ts +319 -8
- package/src/skills/chant-helm.md +7 -0
- package/src/values-probe.test.ts +400 -0
- package/src/values-probe.ts +627 -0
- package/src/wrapper-chart.test.ts +110 -0
- package/src/wrapper-chart.ts +124 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render canonicalization and the contentDigest/inputDigest split
|
|
3
|
+
* (#1237, epic #1228 Phase 2).
|
|
4
|
+
*
|
|
5
|
+
* A pinned render's output is normalized to a canonical byte form before
|
|
6
|
+
* digesting, and two digests are recorded with different jobs:
|
|
7
|
+
*
|
|
8
|
+
* - `inputDigest` answers "same inputs?" cheaply — a `sha256:` over the
|
|
9
|
+
* canonical JSON of { chart reference, chart version, resolved values,
|
|
10
|
+
* capability profile }. It is the same digest `helmInstall` records in the
|
|
11
|
+
* release ledger (#1243), computed by the same helper, so a render and a
|
|
12
|
+
* deploy of the same inputs share an identity.
|
|
13
|
+
* - `contentDigest` answers "same bytes on the cluster?" — a `sha256:` over
|
|
14
|
+
* the canonical rendered bytes. It is the artifact identity.
|
|
15
|
+
*
|
|
16
|
+
* The two diverge exactly when rendering is unpinned or the chart is
|
|
17
|
+
* unstable: two renders with the same inputDigest but different
|
|
18
|
+
* contentDigests mean the render function is not a function of its declared
|
|
19
|
+
* inputs. That divergence is itself a signal — `renderStability` names it.
|
|
20
|
+
*
|
|
21
|
+
* Canonicalization scope (what the epic measured, not more):
|
|
22
|
+
* - Mapping key order is normalized (sorted) — YAML mappings are unordered
|
|
23
|
+
* in Kubernetes semantics, so key order is render noise. Sequence order is
|
|
24
|
+
* never touched; list order is meaningful to Kubernetes.
|
|
25
|
+
* - Document order is preserved, not sorted. The epic verified document
|
|
26
|
+
* ordering is already stable across renders (three renders, again with
|
|
27
|
+
* subcharts), so reordering would only destroy information.
|
|
28
|
+
* - Duplicate documents are preserved. An aliased dependency emits the same
|
|
29
|
+
* CRD twice (epic finding 11); helm dedupes on install, the artifact keeps
|
|
30
|
+
* both, and the digest stays stable because canonicalization is
|
|
31
|
+
* per-document and order-preserving.
|
|
32
|
+
* - The helm-inserted `# Source:` header is kept (it is the origin-routing
|
|
33
|
+
* key the archive wrapper builds on) and normalized to a single leading
|
|
34
|
+
* line. All other comments, trailing whitespace, CRLF line endings, and
|
|
35
|
+
* document-separator styling are render noise and are dropped or
|
|
36
|
+
* normalized.
|
|
37
|
+
*/
|
|
38
|
+
import type { HelmRenderRecord } from "./render.js";
|
|
39
|
+
/**
|
|
40
|
+
* The declared inputs of a helm render or deploy, in the exact shape #1243
|
|
41
|
+
* digests for the release ledger. `helmInstallInputDigest`
|
|
42
|
+
* (op/activities/helm.ts) and `HelmRender`'s recorded `inputDigest` both
|
|
43
|
+
* delegate here, so the two cannot drift: the same chart reference, version,
|
|
44
|
+
* resolved values, and capability facts produce the same digest whether they
|
|
45
|
+
* reach helm through a render or a deploy.
|
|
46
|
+
*/
|
|
47
|
+
export interface HelmInputDigestSource {
|
|
48
|
+
/** Chart reference — a local path, or `<repo-url>/<chart>` for repo-fetched charts. */
|
|
49
|
+
chart: string;
|
|
50
|
+
/** Pinned chart version. Digested as `null` when absent. */
|
|
51
|
+
chartVersion?: string;
|
|
52
|
+
/** Resolved values (file merged with overrides). Digested as `{}` when absent. */
|
|
53
|
+
values?: Record<string, unknown>;
|
|
54
|
+
/**
|
|
55
|
+
* Capability facts the render is pinned against. Only the facts join the
|
|
56
|
+
* digest — the profile's *name* is a label, not an input, so two profiles
|
|
57
|
+
* declaring the same cluster digest identically. `apiVersions` is sorted:
|
|
58
|
+
* it declares a set, not an order.
|
|
59
|
+
*/
|
|
60
|
+
capabilityProfile?: {
|
|
61
|
+
kubeVersion?: string;
|
|
62
|
+
apiVersions?: string[];
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The input-side identity of a helm render or deploy: `sha256:` over the
|
|
67
|
+
* canonical JSON (core's `canonicalJson`, RFC 8785 shape) of the declared
|
|
68
|
+
* inputs. Shared with #1243's release-ledger digest — see
|
|
69
|
+
* `HelmInputDigestSource`. Deliberately excludes the release name and
|
|
70
|
+
* namespace: those are baked into the rendered bytes but the ledger uses
|
|
71
|
+
* this digest as a cross-environment join key, and two environments
|
|
72
|
+
* deploying the same chart, version, and values must share it.
|
|
73
|
+
*/
|
|
74
|
+
export declare function helmInputDigest(source: HelmInputDigestSource): string;
|
|
75
|
+
/**
|
|
76
|
+
* Normalize a `helm template` stream to its canonical byte form.
|
|
77
|
+
*
|
|
78
|
+
* Per document: the `# Source:` header (if any) becomes the single leading
|
|
79
|
+
* comment line, the YAML body is re-serialized with sorted mapping keys
|
|
80
|
+
* (sequences untouched), no line-width folding, and a trailing newline.
|
|
81
|
+
* Documents are emitted in render order, each introduced by a `---` line.
|
|
82
|
+
* CRLF endings, trailing whitespace, non-Source comments, and empty or
|
|
83
|
+
* comment-only documents are render noise and do not survive.
|
|
84
|
+
*
|
|
85
|
+
* A document that fails to parse as YAML is kept verbatim (trimmed) rather
|
|
86
|
+
* than dropped — the canonical form must never silently lose content, and a
|
|
87
|
+
* verbatim document still digests deterministically.
|
|
88
|
+
*/
|
|
89
|
+
export declare function canonicalizeRender(rendered: string): string;
|
|
90
|
+
/**
|
|
91
|
+
* The content-side identity of a render: `sha256:` over the canonical bytes
|
|
92
|
+
* of the rendered stream (see `canonicalizeRender`). Unlike `inputDigest`,
|
|
93
|
+
* this changes whenever the bytes that would reach the cluster change — a
|
|
94
|
+
* chart upgrade with identical values, a helm version that renders
|
|
95
|
+
* differently, an unstable template.
|
|
96
|
+
*/
|
|
97
|
+
export declare function helmContentDigest(rendered: string): string;
|
|
98
|
+
/** One inputDigest's renders and the distinct content identities they produced. */
|
|
99
|
+
export interface RenderStabilityGroup {
|
|
100
|
+
inputDigest: string;
|
|
101
|
+
/** Render names in this group, in record order. */
|
|
102
|
+
names: string[];
|
|
103
|
+
/** Distinct content digests observed, in first-seen order. */
|
|
104
|
+
contentDigests: string[];
|
|
105
|
+
}
|
|
106
|
+
export interface RenderStabilityReport {
|
|
107
|
+
/** Groups whose every render produced the same bytes. */
|
|
108
|
+
stable: RenderStabilityGroup[];
|
|
109
|
+
/**
|
|
110
|
+
* Groups where the same inputs produced different bytes: the render is
|
|
111
|
+
* not pinned down by its declared inputs — an unstable chart, or an input
|
|
112
|
+
* that escaped declaration. Every group here is a defect signal.
|
|
113
|
+
*/
|
|
114
|
+
unstable: RenderStabilityGroup[];
|
|
115
|
+
/** Names of records carrying no digests (unpinned renders) — unassessable. */
|
|
116
|
+
unassessed: string[];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Group recorded renders by input identity and report whether the same
|
|
120
|
+
* inputs always produced the same bytes.
|
|
121
|
+
*
|
|
122
|
+
* Two renders with equal `inputDigest` and different `contentDigest` mean
|
|
123
|
+
* the render is not a function of its declared inputs — the chart is
|
|
124
|
+
* unstable (generated values, timestamps) or an input escaped declaration.
|
|
125
|
+
* That divergence is the signal this helper exists to name; a single render
|
|
126
|
+
* per input proves nothing and lands in `stable` by default.
|
|
127
|
+
*
|
|
128
|
+
* Grouping keys on `(inputDigest, name)` because the release name is a real
|
|
129
|
+
* render input baked into the bytes but deliberately absent from
|
|
130
|
+
* `inputDigest` (see `helmInputDigest`) — two differently named renders of
|
|
131
|
+
* the same chart legitimately differ in content and must not be read as
|
|
132
|
+
* instability.
|
|
133
|
+
*/
|
|
134
|
+
export declare function renderStability(records: readonly HelmRenderRecord[]): RenderStabilityReport;
|
|
135
|
+
//# sourceMappingURL=render-digest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-digest.d.ts","sourceRoot":"","sources":["../src/render-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAQH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAarE;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoB3D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,8EAA8E;IAC9E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,qBAAqB,CAwB3F"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderManifest + content-addressed render storage (#1238, epic #1228
|
|
3
|
+
* Phase 2).
|
|
4
|
+
*
|
|
5
|
+
* #1237 gave a pinned render its identities — `inputDigest` over the
|
|
6
|
+
* declared inputs, `contentDigest` over the canonical rendered bytes. This
|
|
7
|
+
* module makes the render durable: the canonical bytes land in a
|
|
8
|
+
* content-addressed store keyed by `contentDigest`, and a `RenderManifest`
|
|
9
|
+
* — modeled on core's `BuildArchiveManifest`
|
|
10
|
+
* (packages/core/src/components/verbs/build-archive.ts) — records what the
|
|
11
|
+
* bytes are, what produced them, and how to find each document inside them.
|
|
12
|
+
*
|
|
13
|
+
* Storage layout, under `~/.chant/helm-renders/` (override with
|
|
14
|
+
* `CHANT_HELM_RENDER_ROOT`):
|
|
15
|
+
*
|
|
16
|
+
* ```
|
|
17
|
+
* sha256-<64 hex>/ one per distinct contentDigest
|
|
18
|
+
* content.yaml the canonical rendered bytes (canonicalizeRender)
|
|
19
|
+
* manifest.json the RenderManifest
|
|
20
|
+
* inputs/<64 hex>.json inputs index: full-render-inputs key -> digests
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* The `sha256-<hex>` entries are the new root the issue asks for: the
|
|
24
|
+
* pre-#1238 cache keyed entries by a *truncated, input-derived* hash
|
|
25
|
+
* (16 hex characters, no algorithm prefix), which is a cache key, not an
|
|
26
|
+
* artifact identity. Those legacy entries are left exactly where they are —
|
|
27
|
+
* unpinned renders keep using them — and pinned renders write here instead.
|
|
28
|
+
* No migration: a truncated key cannot be turned back into a digest.
|
|
29
|
+
*
|
|
30
|
+
* Two renders that produce the same bytes share one `sha256-<hex>` entry —
|
|
31
|
+
* the content file and manifest are written once and never rewritten
|
|
32
|
+
* (first writer wins; the store is immutable, like a build archive entry).
|
|
33
|
+
* Dedup falls out of content addressing rather than being a feature.
|
|
34
|
+
*
|
|
35
|
+
* The inputs index preserves cache-hit behavior: before shelling out to
|
|
36
|
+
* helm, `HelmRender` computes the full-inputs key and reads
|
|
37
|
+
* `inputs/<key>.json` to find the bytes a previous identical render stored.
|
|
38
|
+
* The index key deliberately differs from `inputDigest`: the release name
|
|
39
|
+
* and namespace are baked into the rendered bytes (`.Release.Name`,
|
|
40
|
+
* `--namespace`) but are excluded from `inputDigest` because the release
|
|
41
|
+
* ledger uses that digest as a cross-environment join key (see
|
|
42
|
+
* `helmInputDigest` in ./render-digest.ts). A cache must key on everything
|
|
43
|
+
* that changes the bytes, so the index key includes both.
|
|
44
|
+
*
|
|
45
|
+
* Retention: none, deliberately. The build archive this is modeled on has
|
|
46
|
+
* no garbage collection — an archive entry lives until someone deletes it —
|
|
47
|
+
* and the pre-#1238 render cache behaved the same way. This store follows
|
|
48
|
+
* suit: entries accumulate until removed by hand. If the archive ever grows
|
|
49
|
+
* a retention story, this store should adopt the same one.
|
|
50
|
+
*/
|
|
51
|
+
import type { HelmCapabilityProfile } from "./config.js";
|
|
52
|
+
import type { ValueOrigin } from "./values-probe.js";
|
|
53
|
+
/**
|
|
54
|
+
* One document's entry in a render's document index: enough identity to ask
|
|
55
|
+
* "give me the ServiceAccount named X in namespace Y" and enough addressing
|
|
56
|
+
* to answer it without parsing the whole stream.
|
|
57
|
+
*/
|
|
58
|
+
export interface RenderDocumentEntry {
|
|
59
|
+
/** Kubernetes kind, e.g. `Deployment`. */
|
|
60
|
+
kind: string;
|
|
61
|
+
/** apiVersion as rendered, e.g. `apps/v1`. */
|
|
62
|
+
apiVersion: string;
|
|
63
|
+
/** `metadata.name`. */
|
|
64
|
+
name: string;
|
|
65
|
+
/** `metadata.namespace`, or `null` for cluster-scoped / namespace-less documents. */
|
|
66
|
+
namespace: string | null;
|
|
67
|
+
/** The helm-inserted `# Source:` origin path, when the document carries one. */
|
|
68
|
+
source: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Byte offset of this document's first byte inside `content.yaml`
|
|
71
|
+
* (pointing just past the `---` separator line, at the `# Source:` header
|
|
72
|
+
* when there is one).
|
|
73
|
+
*/
|
|
74
|
+
start: number;
|
|
75
|
+
/** Byte length of the document, up to the next separator (or end of file). */
|
|
76
|
+
length: number;
|
|
77
|
+
/** `sha256:` over exactly those bytes — lets a reader verify a slice without trusting offsets. */
|
|
78
|
+
digest: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The durable record of one pinned render — what `manifest.json` holds.
|
|
82
|
+
* Modeled on `BuildArchiveManifest`: versioned, content-addressed, and
|
|
83
|
+
* carrying both identity sides the epic's Decisions require — the
|
|
84
|
+
* input-side join key (`inputDigest`, with `valuesDigest` as its
|
|
85
|
+
* values-only component) for cross-environment questions, and
|
|
86
|
+
* `contentDigest` proving what this cluster's profile actually received.
|
|
87
|
+
*/
|
|
88
|
+
export interface RenderManifest {
|
|
89
|
+
/** Manifest schema version, so an incompatible future shape is detected before being misread. */
|
|
90
|
+
version: 1;
|
|
91
|
+
/** Chart name or local chart path, as the render declared it. */
|
|
92
|
+
chart: string;
|
|
93
|
+
/** Pinned chart version, or `null` for a local chart rendered without one. */
|
|
94
|
+
chartVersion: string | null;
|
|
95
|
+
/** Chart repo URL, or `null` for a local chart. */
|
|
96
|
+
repo: string | null;
|
|
97
|
+
/** Helm release name baked into the bytes (`.Release.Name`). */
|
|
98
|
+
releaseName: string;
|
|
99
|
+
/** Namespace the render targeted (`--namespace`), or `null`. */
|
|
100
|
+
namespace: string | null;
|
|
101
|
+
/**
|
|
102
|
+
* `sha256:` over the canonical JSON of the resolved values alone — the
|
|
103
|
+
* input-side join key the epic's ledger queries use together with
|
|
104
|
+
* `(chart, chartVersion)`.
|
|
105
|
+
*/
|
|
106
|
+
valuesDigest: string;
|
|
107
|
+
/**
|
|
108
|
+
* `sha256:` over the full declared-input set (chart reference, version,
|
|
109
|
+
* values, capability facts) — `helmInputDigest`, the same digest the
|
|
110
|
+
* release ledger records on deploy (#1243).
|
|
111
|
+
*/
|
|
112
|
+
inputDigest: string;
|
|
113
|
+
/** The capability profile the render was pinned against. `cluster` is the profile's declared name — profiles are per cluster. */
|
|
114
|
+
capabilityProfile: {
|
|
115
|
+
cluster: string;
|
|
116
|
+
kubeVersion: string;
|
|
117
|
+
apiVersions: string[];
|
|
118
|
+
};
|
|
119
|
+
/** `sha256:` over the canonical rendered bytes — the artifact identity, and this entry's storage key. */
|
|
120
|
+
contentDigest: string;
|
|
121
|
+
/** Number of documents in the canonical stream (including any the index could not identify). */
|
|
122
|
+
docCount: number;
|
|
123
|
+
/** Index of identifiable documents: kind/namespace/name -> byte span + per-document digest. */
|
|
124
|
+
documents: RenderDocumentEntry[];
|
|
125
|
+
/** ISO-8601 timestamp this manifest was written. Not part of any digest. */
|
|
126
|
+
renderedAt: string;
|
|
127
|
+
/**
|
|
128
|
+
* Version of the helm binary that produced the bytes. Load-bearing: the
|
|
129
|
+
* default kube version is a property of the binary (epic finding 1), so
|
|
130
|
+
* this field is what explains a digest mismatch between two machines.
|
|
131
|
+
*/
|
|
132
|
+
helmVersion: string;
|
|
133
|
+
/** chant version that wrote this manifest. */
|
|
134
|
+
chantVersion: string;
|
|
135
|
+
/** Source ref/commit the render was produced from, when the caller supplied one. */
|
|
136
|
+
sourceRef: string | null;
|
|
137
|
+
/**
|
|
138
|
+
* `sha256:` over the canonical JSON of the coalesced values the
|
|
139
|
+
* build-time probe (#1251) observed for every chart instance, keyed by
|
|
140
|
+
* scope path — `coalescedValuesDigest` from `./values-probe.ts`. `null`
|
|
141
|
+
* when the probe did not run for this render (a repo-fetched chart, whose
|
|
142
|
+
* source the probe needs on disk, or a probe failure — never fabricated).
|
|
143
|
+
*/
|
|
144
|
+
coalescedValuesDigest: string | null;
|
|
145
|
+
/**
|
|
146
|
+
* Each coalesced value's winning layer (#1252), dot-joined root-coordinate
|
|
147
|
+
* path to `ValueOrigin` — `computeValueSources` from `./values-probe.ts`.
|
|
148
|
+
* `null` under the same conditions as `coalescedValuesDigest`.
|
|
149
|
+
*/
|
|
150
|
+
valueSources: Record<string, ValueOrigin> | null;
|
|
151
|
+
}
|
|
152
|
+
/** What `inputs/<key>.json` holds: the digests a full-inputs cache key resolves to. */
|
|
153
|
+
export interface RenderInputsIndexEntry {
|
|
154
|
+
version: 1;
|
|
155
|
+
inputDigest: string;
|
|
156
|
+
contentDigest: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Root of the render store. `CHANT_HELM_RENDER_ROOT` overrides the default
|
|
160
|
+
* `~/.chant/helm-renders` — the same directory the legacy input-keyed cache
|
|
161
|
+
* lives in; the two coexist because legacy entries are bare 16-hex names
|
|
162
|
+
* and store entries are `sha256-` prefixed.
|
|
163
|
+
*/
|
|
164
|
+
export declare function renderStoreRoot(): string;
|
|
165
|
+
/** The full set of inputs that determine a pinned render's bytes. */
|
|
166
|
+
export interface RenderCacheKeySource {
|
|
167
|
+
/** Chart reference — a local path, or `<repo-url>/<chart>` for repo-fetched charts (same convention `helmInputDigest` uses). */
|
|
168
|
+
chart: string;
|
|
169
|
+
chartVersion?: string;
|
|
170
|
+
/** Release name — baked into the bytes via `.Release.Name`, so a real cache input even though `inputDigest` excludes it. */
|
|
171
|
+
releaseName: string;
|
|
172
|
+
/** Namespace — baked in via `--namespace`, likewise excluded from `inputDigest`. */
|
|
173
|
+
namespace?: string;
|
|
174
|
+
values?: Record<string, unknown>;
|
|
175
|
+
capabilityProfile: HelmCapabilityProfile;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Cache key over *everything* that changes a pinned render's bytes — a
|
|
179
|
+
* strict superset of `helmInputDigest`'s inputs (adds release name,
|
|
180
|
+
* namespace, and the profile's declared name, mirroring the legacy cache
|
|
181
|
+
* key's fields). 64 hex characters, no prefix: this is a lookup key, not an
|
|
182
|
+
* artifact identity.
|
|
183
|
+
*/
|
|
184
|
+
export declare function renderCacheKey(source: RenderCacheKeySource): string;
|
|
185
|
+
/**
|
|
186
|
+
* `sha256:` over the canonical JSON of the resolved values alone — the
|
|
187
|
+
* `valuesDigest` half of the ledger's input-side join key
|
|
188
|
+
* `(chart, chartVersion, valuesDigest)`. Absent values digest as `{}`,
|
|
189
|
+
* matching `helmInputDigest`'s treatment.
|
|
190
|
+
*/
|
|
191
|
+
export declare function helmValuesDigest(values?: Record<string, unknown>): string;
|
|
192
|
+
/**
|
|
193
|
+
* Build the document index over a canonical stream: for every identifiable
|
|
194
|
+
* document (it parses and carries `kind` + `metadata.name`), its
|
|
195
|
+
* kind/namespace/name identity, byte span, and per-document digest.
|
|
196
|
+
* Returns the index and the total document count — the count includes
|
|
197
|
+
* documents the index could not identify, so `docCount` is always the
|
|
198
|
+
* number of documents the artifact carries.
|
|
199
|
+
*/
|
|
200
|
+
export declare function indexRenderDocuments(canonical: string): {
|
|
201
|
+
documents: RenderDocumentEntry[];
|
|
202
|
+
docCount: number;
|
|
203
|
+
};
|
|
204
|
+
export interface PersistHelmRenderInput {
|
|
205
|
+
/** The `helm template` output — raw or already canonical; it is canonicalized before storage either way. */
|
|
206
|
+
rendered: string;
|
|
207
|
+
/** Release name the render was produced under (`HelmRenderProps.name`). */
|
|
208
|
+
releaseName: string;
|
|
209
|
+
/** Chart name or local chart path, as declared. */
|
|
210
|
+
chart: string;
|
|
211
|
+
/** Chart repo URL for repo-fetched charts. */
|
|
212
|
+
repo?: string;
|
|
213
|
+
chartVersion?: string;
|
|
214
|
+
namespace?: string;
|
|
215
|
+
values?: Record<string, unknown>;
|
|
216
|
+
/**
|
|
217
|
+
* The capability profile the render was pinned against. Absent means the
|
|
218
|
+
* render was unpinned — persistence is refused, because an unpinned
|
|
219
|
+
* render's bytes are a function of the local helm binary's defaults and
|
|
220
|
+
* have no identity worth storing.
|
|
221
|
+
*/
|
|
222
|
+
capabilityProfile?: HelmCapabilityProfile;
|
|
223
|
+
/** Version of the helm binary that produced the bytes. Recorded as `"unknown"` when not supplied. */
|
|
224
|
+
helmVersion?: string;
|
|
225
|
+
/** Source ref/commit, when the caller has one. Never fabricated. */
|
|
226
|
+
sourceRef?: string;
|
|
227
|
+
/**
|
|
228
|
+
* The build-time coalesced-values probe's digest (#1251), when the caller
|
|
229
|
+
* ran one for this render. Absent (not merely `undefined`-passed) records
|
|
230
|
+
* `null` in the manifest — the probe needs the chart source on disk, so a
|
|
231
|
+
* repo-fetched render legitimately has none.
|
|
232
|
+
*/
|
|
233
|
+
coalescedValuesDigest?: string;
|
|
234
|
+
/** The probe's value-source attribution (#1252), alongside `coalescedValuesDigest`. */
|
|
235
|
+
valueSources?: Record<string, ValueOrigin>;
|
|
236
|
+
/** Clock override for tests. */
|
|
237
|
+
now?: () => Date;
|
|
238
|
+
/** Store root override; defaults to `renderStoreRoot()`. */
|
|
239
|
+
root?: string;
|
|
240
|
+
}
|
|
241
|
+
export interface PersistedHelmRender {
|
|
242
|
+
/** The manifest now on disk — the existing one when the content was already stored. */
|
|
243
|
+
manifest: RenderManifest;
|
|
244
|
+
/** Directory the render lives in: `<root>/sha256-<hex>`. */
|
|
245
|
+
dir: string;
|
|
246
|
+
/**
|
|
247
|
+
* True when this contentDigest was already in the store — the bytes and
|
|
248
|
+
* manifest were left untouched (only the inputs index was updated).
|
|
249
|
+
*/
|
|
250
|
+
deduplicated: boolean;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Persist one pinned render: canonical bytes under their `contentDigest`,
|
|
254
|
+
* the `RenderManifest` beside them, and an inputs-index entry so an
|
|
255
|
+
* identical future render is a cache hit.
|
|
256
|
+
*
|
|
257
|
+
* Content-addressed entries are immutable: when the digest directory
|
|
258
|
+
* already holds a manifest, both files are left as they are and the
|
|
259
|
+
* existing manifest is returned (`deduplicated: true`). The inputs index is
|
|
260
|
+
* still written — a new input combination can legitimately map to bytes the
|
|
261
|
+
* store already holds.
|
|
262
|
+
*
|
|
263
|
+
* Refuses an unpinned render (no capability profile) with the specific
|
|
264
|
+
* reason: no profile means the bytes depend on the local helm binary's
|
|
265
|
+
* defaulted capabilities, so they have no stable content identity to store
|
|
266
|
+
* under.
|
|
267
|
+
*/
|
|
268
|
+
export declare function persistHelmRender(input: PersistHelmRenderInput): PersistedHelmRender;
|
|
269
|
+
/** Load the `RenderManifest` stored under a content digest, or `undefined` when the store has no such entry. */
|
|
270
|
+
export declare function loadRenderManifest(contentDigest: string, opts?: {
|
|
271
|
+
root?: string;
|
|
272
|
+
}): RenderManifest | undefined;
|
|
273
|
+
/** Load the canonical rendered bytes stored under a content digest, or `undefined` when absent. */
|
|
274
|
+
export declare function loadRenderContent(contentDigest: string, opts?: {
|
|
275
|
+
root?: string;
|
|
276
|
+
}): string | undefined;
|
|
277
|
+
/** Resolve a full-inputs cache key through the inputs index, or `undefined` on a miss. */
|
|
278
|
+
export declare function findRenderByCacheKey(cacheKey: string, opts?: {
|
|
279
|
+
root?: string;
|
|
280
|
+
}): RenderInputsIndexEntry | undefined;
|
|
281
|
+
/**
|
|
282
|
+
* Every manifest in the store, sorted by `renderedAt` then `contentDigest`
|
|
283
|
+
* for a stable listing. Entries whose manifest is missing or unreadable are
|
|
284
|
+
* skipped — a listing never fails on one corrupt entry. This is the query
|
|
285
|
+
* surface the diff issues (#1249/#1250) resolve digests against.
|
|
286
|
+
*/
|
|
287
|
+
export declare function listRenderManifests(opts?: {
|
|
288
|
+
root?: string;
|
|
289
|
+
}): RenderManifest[];
|
|
290
|
+
/** How a caller names one document inside a stored render. */
|
|
291
|
+
export interface RenderDocumentRef {
|
|
292
|
+
kind: string;
|
|
293
|
+
name: string;
|
|
294
|
+
/** Omit (or pass `null`) to match a cluster-scoped / namespace-less document. */
|
|
295
|
+
namespace?: string | null;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Resolve one document by kind/namespace/name to its exact bytes inside a
|
|
299
|
+
* stored render, via the manifest's document index. The slice is verified
|
|
300
|
+
* against the entry's per-document digest before being returned — corrupt
|
|
301
|
+
* content is an error, never silently wrong bytes. `undefined` means the
|
|
302
|
+
* store has no such render or the index has no such document.
|
|
303
|
+
*/
|
|
304
|
+
export declare function readRenderDocument(contentDigest: string, ref: RenderDocumentRef, opts?: {
|
|
305
|
+
root?: string;
|
|
306
|
+
}): {
|
|
307
|
+
entry: RenderDocumentEntry;
|
|
308
|
+
text: string;
|
|
309
|
+
} | undefined;
|
|
310
|
+
//# sourceMappingURL=render-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-store.d.ts","sourceRoot":"","sources":["../src/render-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structure-preserving render wrapper (#1239, epic #1228 Phase 3).
|
|
3
|
+
*
|
|
4
|
+
* Turns a pinned render's document stream into chant-shaped routing groups
|
|
5
|
+
* WITHOUT restructuring the documents. Structure-preserving means the bytes
|
|
6
|
+
* that deploy are the bytes the render store recorded — this module only
|
|
7
|
+
* routes and labels; it never re-serializes, reorders lines, or edits a
|
|
8
|
+
* document. Each `RoutedDocument.text` is the exact document text from the
|
|
9
|
+
* input stream.
|
|
10
|
+
*
|
|
11
|
+
* Routing is by origin, not by kind. `helm template` stamps every document
|
|
12
|
+
* with `# Source: <chart>/<path>`, and the discriminator is whether that
|
|
13
|
+
* path contains a `crds/` **segment** (`(^|/)crds/` — `isCrdSource` from
|
|
14
|
+
* the #1234 classifier seeds):
|
|
15
|
+
*
|
|
16
|
+
* - A `crds/`-segment origin routes to the CRD group — the wrapper's
|
|
17
|
+
* `crds/`. Segment matching is load-bearing: a subchart's CRDs arrive as
|
|
18
|
+
* `charts/<child>/crds/<file>`, so a prefix rule catches none of them and
|
|
19
|
+
* would route every subchart CRD into `templates/`, making it deletable
|
|
20
|
+
* on uninstall (epic findings 4, 10 — the A/B test showed a flat wrap
|
|
21
|
+
* converts `helm uninstall` from safe to data-destroying).
|
|
22
|
+
* - A hook-annotated template document (`helm.sh/hook` in
|
|
23
|
+
* `metadata.annotations`) routes to its own group, annotations intact.
|
|
24
|
+
* Hooks survive pinning (epic finding 5); they are surfaced separately so
|
|
25
|
+
* the install path can account for them, never silently dropped.
|
|
26
|
+
* - Everything else routes to the main group — the wrapper's `templates/`.
|
|
27
|
+
* A template-rendered `CustomResourceDefinition` stays here, because the
|
|
28
|
+
* `crds/`-segment is the discriminator, not the kind: a chart that
|
|
29
|
+
* templates its CRDs opted into template lifecycle semantics (upgrades
|
|
30
|
+
* and deletes apply to them), and moving them to `crds/` would change
|
|
31
|
+
* that. The routing notes it with a warning so the choice is visible.
|
|
32
|
+
*
|
|
33
|
+
* Aliased dependencies emit duplicate CRDs (epic finding 11): the same
|
|
34
|
+
* dependency included twice under an alias renders its `crds/` once per
|
|
35
|
+
* instance — two documents, one distinct CRD. The stored artifact keeps
|
|
36
|
+
* both (canonicalization is order- and duplicate-preserving), but a wrapper
|
|
37
|
+
* chart's `crds/` holds each CRD once, so the routed CRD group deduplicates
|
|
38
|
+
* by `(group, kind)`: the first occurrence wins and a warning names both
|
|
39
|
+
* sources. A CRD document that cannot be identified (unparseable, or
|
|
40
|
+
* missing `spec.group` / `spec.names.kind`) is never deduplicated — the
|
|
41
|
+
* routing must not silently drop what it cannot identify.
|
|
42
|
+
*
|
|
43
|
+
* The wrapper inherits the source chart's name and version (epic
|
|
44
|
+
* Decisions), keeping `helm history` continuous across the pinned
|
|
45
|
+
* migration; `RoutedRender.chart` / `chartVersion` carry them.
|
|
46
|
+
*
|
|
47
|
+
* This is the seam the pinned-install path (#1242) consumes:
|
|
48
|
+
* `routeStoredRender(contentDigest)` loads a stored render's canonical
|
|
49
|
+
* bytes and manifest and routes them.
|
|
50
|
+
*/
|
|
51
|
+
/** One routed document: exact bytes plus the labels routing derived from them. */
|
|
52
|
+
export interface RoutedDocument {
|
|
53
|
+
/**
|
|
54
|
+
* The document's exact text from the input stream (from just past the
|
|
55
|
+
* `---` separator, trimmed of surrounding blank lines — the same split
|
|
56
|
+
* `splitDocuments` performs). Never re-serialized: what deploys is what
|
|
57
|
+
* was recorded.
|
|
58
|
+
*/
|
|
59
|
+
text: string;
|
|
60
|
+
/**
|
|
61
|
+
* Chart-relative `# Source:` origin path (e.g. `crds/a.yaml`,
|
|
62
|
+
* `charts/kid/crds/kidcrd.yaml`), or `null` when the document carries no
|
|
63
|
+
* source header.
|
|
64
|
+
*/
|
|
65
|
+
source: string | null;
|
|
66
|
+
/** Kubernetes kind, or `null` when the document does not parse to a kinded object. */
|
|
67
|
+
kind: string | null;
|
|
68
|
+
/** apiVersion as rendered, or `null`. */
|
|
69
|
+
apiVersion: string | null;
|
|
70
|
+
/** `metadata.name`, or `null`. */
|
|
71
|
+
name: string | null;
|
|
72
|
+
}
|
|
73
|
+
/** Machine-readable warning categories the routing emits. */
|
|
74
|
+
export type RoutedRenderWarningCode = "duplicate-crd" | "template-crd";
|
|
75
|
+
export interface RoutedRenderWarning {
|
|
76
|
+
/**
|
|
77
|
+
* - `duplicate-crd` — an aliased dependency emitted the same CRD twice;
|
|
78
|
+
* the first occurrence was kept, the duplicate dropped. The message
|
|
79
|
+
* names both sources.
|
|
80
|
+
* - `template-crd` — a `CustomResourceDefinition` was rendered from
|
|
81
|
+
* `templates/` (no `crds/` segment in its origin). It stays in the main
|
|
82
|
+
* group per the segment rule; this note makes the lifecycle choice
|
|
83
|
+
* visible.
|
|
84
|
+
*/
|
|
85
|
+
code: RoutedRenderWarningCode;
|
|
86
|
+
message: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A pinned render routed into the structure the wrapper chart preserves.
|
|
90
|
+
* The document groups partition the input stream (minus deduplicated CRD
|
|
91
|
+
* duplicates, each named in `warnings`); no document is ever silently
|
|
92
|
+
* dropped and no document text is ever altered.
|
|
93
|
+
*/
|
|
94
|
+
export interface RoutedRender {
|
|
95
|
+
/**
|
|
96
|
+
* Wrapper chart name — inherited from the source chart, so `helm history`
|
|
97
|
+
* stays continuous across the pinned migration (epic Decisions).
|
|
98
|
+
*/
|
|
99
|
+
chart: string;
|
|
100
|
+
/** Wrapper chart version — inherited from the source chart; `null` for a local chart rendered without one. */
|
|
101
|
+
chartVersion: string | null;
|
|
102
|
+
/**
|
|
103
|
+
* Documents whose origin has a `crds/` segment — the wrapper's `crds/`,
|
|
104
|
+
* which is what keeps `helm uninstall` from deleting them (epic finding
|
|
105
|
+
* 4). Deduplicated by `(group, kind)`, first occurrence winning.
|
|
106
|
+
*/
|
|
107
|
+
crds: RoutedDocument[];
|
|
108
|
+
/**
|
|
109
|
+
* Hook-annotated template documents (`helm.sh/hook`), annotations intact.
|
|
110
|
+
* Routed as their own group so the install path can account for them —
|
|
111
|
+
* never silently dropped (epic finding 5).
|
|
112
|
+
*/
|
|
113
|
+
hooks: RoutedDocument[];
|
|
114
|
+
/** Everything else — the wrapper's `templates/`. */
|
|
115
|
+
main: RoutedDocument[];
|
|
116
|
+
/** What routing had to decide beyond the mechanical rule: dropped duplicates, template-rendered CRDs. */
|
|
117
|
+
warnings: RoutedRenderWarning[];
|
|
118
|
+
}
|
|
119
|
+
export interface RouteRenderOptions {
|
|
120
|
+
/** Source chart name — becomes the wrapper's name. */
|
|
121
|
+
chart: string;
|
|
122
|
+
/** Source chart version — becomes the wrapper's version. */
|
|
123
|
+
chartVersion?: string | null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Route a rendered stream (canonical or raw `helm template` output) into
|
|
127
|
+
* `RoutedRender` groups. Pure over the stream: no store access, no helm.
|
|
128
|
+
*/
|
|
129
|
+
export declare function routeRender(rendered: string, opts: RouteRenderOptions): RoutedRender;
|
|
130
|
+
/**
|
|
131
|
+
* Route a stored pinned render by its `contentDigest`: loads the canonical
|
|
132
|
+
* bytes and the `RenderManifest` from the render store (#1238) and routes
|
|
133
|
+
* them, inheriting the manifest's chart name and version. This is the seam
|
|
134
|
+
* the pinned-install path (#1242) consumes. `undefined` when the store has
|
|
135
|
+
* no such entry.
|
|
136
|
+
*/
|
|
137
|
+
export declare function routeStoredRender(contentDigest: string, opts?: {
|
|
138
|
+
root?: string;
|
|
139
|
+
}): RoutedRender | undefined;
|
|
140
|
+
//# sourceMappingURL=render-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-wrapper.d.ts","sourceRoot":"","sources":["../src/render-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AASH,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sFAAsF;IACtF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,yCAAyC;IACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kCAAkC;IAClC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,6DAA6D;AAC7D,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEvE,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,IAAI,EAAE,uBAAuB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,8GAA8G;IAC9G,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB;;;;OAIG;IACH,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,oDAAoD;IACpD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,yGAAyG;IACzG,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AA0DD,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,YAAY,CA0DpF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACvB,YAAY,GAAG,SAAS,CAM1B"}
|