@intentius/chant-lexicon-k8s 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/components/kubectl-apply.d.ts +5 -0
- package/dist/components/kubectl-apply.d.ts.map +1 -1
- package/dist/composites/flux-app.d.ts +12 -0
- package/dist/composites/flux-app.d.ts.map +1 -1
- package/dist/composites/index.d.ts +6 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/inference-service.d.ts +86 -0
- package/dist/composites/inference-service.d.ts.map +1 -0
- package/dist/composites/model.d.ts +80 -0
- package/dist/composites/model.d.ts.map +1 -0
- package/dist/composites/vllm-serving-runtime.d.ts +100 -0
- package/dist/composites/vllm-serving-runtime.d.ts.map +1 -0
- package/dist/crd/crd-sources.d.ts.map +1 -1
- package/dist/deep-observe-hooks.d.ts.map +1 -1
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/generated/index.d.ts +167 -40
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/group-namespace.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +13 -5
- package/dist/kube/apply.d.ts.map +1 -1
- 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/k8s-helpers.d.ts +28 -1
- package/dist/lint/post-synth/k8s-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/sops-helpers.d.ts +38 -0
- package/dist/lint/post-synth/sops-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8404.d.ts +12 -0
- package/dist/lint/post-synth/wk8404.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8405.d.ts +13 -0
- package/dist/lint/post-synth/wk8405.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8406.d.ts +12 -0
- package/dist/lint/post-synth/wk8406.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8407.d.ts +21 -0
- package/dist/lint/post-synth/wk8407.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8503.d.ts +39 -0
- package/dist/lint/post-synth/wk8503.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8504.d.ts +28 -0
- package/dist/lint/post-synth/wk8504.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8505.d.ts +28 -0
- package/dist/lint/post-synth/wk8505.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/meta.json +1039 -68
- package/dist/okf/index.md +26 -2
- package/dist/okf/rules/FLUX002.md +0 -1
- package/dist/okf/rules/WK8404.md +11 -0
- package/dist/okf/rules/WK8405.md +17 -0
- package/dist/okf/rules/WK8406.md +11 -0
- package/dist/okf/rules/WK8407.md +15 -0
- package/dist/okf/rules/WK8503.md +17 -0
- package/dist/okf/rules/WK8504.md +11 -0
- package/dist/okf/rules/WK8505.md +15 -0
- package/dist/okf/types/AWSClusterControllerIdentity.md +14 -0
- package/dist/okf/types/AWSManagedCluster.md +14 -0
- package/dist/okf/types/AWSManagedControlPlane.md +14 -0
- package/dist/okf/types/AWSManagedMachinePool.md +14 -0
- package/dist/okf/types/CAPICluster.md +14 -0
- package/dist/okf/types/Certificate.md +1 -0
- package/dist/okf/types/ClusterResourceSet.md +14 -0
- package/dist/okf/types/ClusterServingRuntime.md +14 -0
- package/dist/okf/types/{Cluster.md → CnpgCluster.md} +2 -2
- package/dist/okf/types/DBInstance.md +14 -0
- package/dist/okf/types/{Bucket.md → FluxBucket.md} +2 -6
- package/dist/okf/types/HelmChartProxy.md +14 -0
- package/dist/okf/types/IamRole.md +14 -0
- package/dist/okf/types/InferenceService.md +19 -0
- package/dist/okf/types/InfisicalDynamicSecret.md +4 -0
- package/dist/okf/types/InfisicalSecret.md +4 -0
- package/dist/okf/types/Kustomization.md +1 -0
- package/dist/okf/types/MachinePool.md +14 -0
- package/dist/okf/types/PDB.md +1 -0
- package/dist/okf/types/PodIdentityAssociation.md +14 -0
- package/dist/okf/types/Policy.md +14 -0
- package/dist/okf/types/S3Bucket.md +14 -0
- package/dist/okf/types/ServingRuntime.md +14 -0
- package/dist/okf/types/StatefulSet.md +1 -0
- package/dist/okf/types/User.md +14 -0
- package/dist/op/activities/ensure-secret.d.ts +41 -0
- package/dist/op/activities/ensure-secret.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +2 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/kubectl.d.ts +9 -0
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/op/activities/wait-for-ready.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/rules/k8s-helpers.ts +55 -1
- package/dist/rules/sops-helpers.ts +76 -0
- package/dist/rules/wk8404.ts +55 -0
- package/dist/rules/wk8405.ts +88 -0
- package/dist/rules/wk8406.ts +60 -0
- package/dist/rules/wk8407.ts +71 -0
- package/dist/rules/wk8503.ts +220 -0
- package/dist/rules/wk8504.ts +51 -0
- package/dist/rules/wk8505.ts +63 -0
- package/dist/secret-labels.d.ts +31 -0
- package/dist/secret-labels.d.ts.map +1 -0
- package/dist/secret-store.d.ts +73 -0
- package/dist/secret-store.d.ts.map +1 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/sops/encrypted-secret-file.d.ts +52 -0
- package/dist/sops/encrypted-secret-file.d.ts.map +1 -0
- package/dist/sops/entity.d.ts +31 -0
- package/dist/sops/entity.d.ts.map +1 -0
- package/dist/teardown.d.ts +46 -0
- package/dist/teardown.d.ts.map +1 -0
- package/dist/types/index.d.ts +261 -9
- package/package.json +4 -4
- package/src/components/kubectl-apply.ts +5 -0
- package/src/composites/composites.test.ts +273 -0
- package/src/composites/flux-app.ts +23 -0
- package/src/composites/index.ts +11 -0
- package/src/composites/inference-service.ts +140 -0
- package/src/composites/model.ts +150 -0
- package/src/composites/vllm-serving-runtime.test.ts +167 -0
- package/src/composites/vllm-serving-runtime.ts +196 -0
- package/src/crd/cnpg.test.ts +8 -3
- package/src/crd/crd-sources.ts +183 -0
- package/src/crd/parser.test.ts +14 -0
- package/src/deep-observe-hooks.ts +24 -0
- package/src/deep-observe.test.ts +89 -0
- package/src/describe-resources.ts +6 -1
- package/src/generated/index.d.ts +261 -9
- package/src/generated/index.ts +167 -40
- package/src/generated/lexicon-k8s.json +1039 -68
- package/src/generated/operations.json +272 -0
- package/src/group-namespace.test.ts +31 -0
- package/src/group-namespace.ts +13 -0
- package/src/index.ts +6 -0
- package/src/kube/apply.ts +5 -0
- package/src/lifecycle-integration.test.ts +42 -0
- package/src/lint/audit-catalog.ts +7 -0
- package/src/lint/post-synth/index.ts +14 -0
- package/src/lint/post-synth/k8s-helpers.ts +55 -1
- package/src/lint/post-synth/post-synth.test.ts +826 -0
- package/src/lint/post-synth/sops-helpers.ts +76 -0
- package/src/lint/post-synth/wk8404.ts +55 -0
- package/src/lint/post-synth/wk8405.ts +88 -0
- package/src/lint/post-synth/wk8406.ts +60 -0
- package/src/lint/post-synth/wk8407.ts +71 -0
- package/src/lint/post-synth/wk8503.ts +220 -0
- package/src/lint/post-synth/wk8504.ts +51 -0
- package/src/lint/post-synth/wk8505.ts +63 -0
- package/src/op/activities/ensure-secret.ts +71 -0
- package/src/op/activities/index.ts +7 -0
- package/src/op/activities/kubectl.test.ts +32 -0
- package/src/op/activities/kubectl.ts +28 -5
- package/src/op/activities/wait-for-ready.test.ts +34 -0
- package/src/op/activities/wait-for-ready.ts +26 -0
- package/src/plugin.ts +34 -2
- package/src/secret-labels.ts +36 -0
- package/src/secret-store.test.ts +184 -0
- package/src/secret-store.ts +165 -0
- package/src/serializer.ts +33 -2
- package/src/sops/encrypted-secret-file.test.ts +333 -0
- package/src/sops/encrypted-secret-file.ts +264 -0
- package/src/sops/entity.ts +53 -0
- package/src/teardown.test.ts +240 -0
- package/src/teardown.ts +239 -0
- package/src/testdata/sops/db-credentials.sops.yaml +23 -0
package/src/teardown.ts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Env teardown for the k8s lexicon (chant #1222) — both halves of the
|
|
3
|
+
* `teardownOwned` / `executeTeardown` capability pair.
|
|
4
|
+
*
|
|
5
|
+
* Selection is the prune's marker selector (op/activities/kubectl.ts) with the
|
|
6
|
+
* env dimension added: `app.kubernetes.io/managed-by=chant` +
|
|
7
|
+
* `chant.intentius.io/stack=<stack>` + `chant.intentius.io/env=<env>`, sent to
|
|
8
|
+
* the server as a label selector and re-checked object by object with
|
|
9
|
+
* `readOwnership` — the server-side filter narrows the read, the client-side
|
|
10
|
+
* re-check is the one that matters, because a delete is not undoable.
|
|
11
|
+
*
|
|
12
|
+
* Swept kinds are chant's default sweep set (`DEFAULT_IMPORT_TYPES`, the same
|
|
13
|
+
* list the ownership-scoped prune unions in), listed cluster-wide: env
|
|
14
|
+
* teardown has no apply set to scope namespaces by, and the marker selector is
|
|
15
|
+
* the scope. A kind the cluster's discovery does not serve cannot hold a
|
|
16
|
+
* marked object and is skipped; a kind that resolves but fails to list is a
|
|
17
|
+
* hole (#1089) — unknown, never absent.
|
|
18
|
+
*
|
|
19
|
+
* Execution deletes the handed-over candidates through the typed client's own
|
|
20
|
+
* `delete()` — the identical delete the prune and `chant kube delete` use —
|
|
21
|
+
* with namespaces last, so a namespace's own members get individual outcomes
|
|
22
|
+
* before the cascade would have swallowed them. Before each delete the live
|
|
23
|
+
* object is re-read and its marker re-verified; an object that vanished is
|
|
24
|
+
* `deleted` (teardown is idempotent), one whose identity no longer matches is
|
|
25
|
+
* `not-prunable`, never deleted.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type {
|
|
29
|
+
TeardownCandidate,
|
|
30
|
+
TeardownEnumeration,
|
|
31
|
+
TeardownExecution,
|
|
32
|
+
TeardownHole,
|
|
33
|
+
TeardownOutcome,
|
|
34
|
+
} from "@intentius/chant/lexicon";
|
|
35
|
+
import {
|
|
36
|
+
LABEL_OWNERSHIP_KEYS,
|
|
37
|
+
OWNERSHIP_MANAGED_BY_VALUE,
|
|
38
|
+
readOwnership,
|
|
39
|
+
type OwnershipMarker,
|
|
40
|
+
} from "@intentius/chant/ownership";
|
|
41
|
+
import type { K8sClient } from "@intentius/chant-k8s-client";
|
|
42
|
+
import { DEFAULT_IMPORT_TYPES } from "./api/sweep-types";
|
|
43
|
+
import { operationFor } from "./api/operation-surface";
|
|
44
|
+
import { defaultK8sConnector, type K8sConnector } from "./api/connect";
|
|
45
|
+
import { isGeneratedOnce } from "./secret-labels";
|
|
46
|
+
|
|
47
|
+
const NAMESPACE_TYPE = "K8s::Core::Namespace";
|
|
48
|
+
|
|
49
|
+
export interface K8sTeardownOptions {
|
|
50
|
+
environment: string;
|
|
51
|
+
marker: OwnershipMarker;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The label selector that scopes everything here: managed-by + stack + env. */
|
|
55
|
+
function markerSelector(marker: OwnershipMarker): string {
|
|
56
|
+
return [
|
|
57
|
+
`${LABEL_OWNERSHIP_KEYS.managedBy}=${OWNERSHIP_MANAGED_BY_VALUE}`,
|
|
58
|
+
`${LABEL_OWNERSHIP_KEYS.stack}=${marker.stack}`,
|
|
59
|
+
...(marker.env ? [`${LABEL_OWNERSHIP_KEYS.env}=${marker.env}`] : []),
|
|
60
|
+
].join(",");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** True when a live object's own labels carry exactly the requested identity. */
|
|
64
|
+
function matchesMarker(
|
|
65
|
+
labels: Record<string, string> | undefined,
|
|
66
|
+
marker: OwnershipMarker,
|
|
67
|
+
): boolean {
|
|
68
|
+
const read = readOwnership(labels, LABEL_OWNERSHIP_KEYS);
|
|
69
|
+
return read !== undefined && read.stack === marker.stack && read.env === marker.env;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Enumerate the cluster's marker-matching objects — the k8s half of
|
|
74
|
+
* `chant lifecycle teardown <env>` planning.
|
|
75
|
+
*/
|
|
76
|
+
export async function teardownOwned(
|
|
77
|
+
options: K8sTeardownOptions,
|
|
78
|
+
connect: K8sConnector = defaultK8sConnector,
|
|
79
|
+
): Promise<TeardownEnumeration> {
|
|
80
|
+
const { client } = await connect({ environment: options.environment });
|
|
81
|
+
const selector = markerSelector(options.marker);
|
|
82
|
+
|
|
83
|
+
const candidates: TeardownCandidate[] = [];
|
|
84
|
+
const holes: TeardownHole[] = [];
|
|
85
|
+
|
|
86
|
+
for (const entityType of DEFAULT_IMPORT_TYPES) {
|
|
87
|
+
const operation = operationFor(entityType);
|
|
88
|
+
if (!operation) continue;
|
|
89
|
+
const ref = { apiVersion: operation.apiVersion, kind: operation.kind };
|
|
90
|
+
|
|
91
|
+
let served: boolean;
|
|
92
|
+
try {
|
|
93
|
+
served = (await client.resolve(ref)) !== undefined;
|
|
94
|
+
} catch (err) {
|
|
95
|
+
holes.push({
|
|
96
|
+
name: entityType,
|
|
97
|
+
type: entityType,
|
|
98
|
+
reason: "read-failed",
|
|
99
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
100
|
+
});
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// A kind this cluster's discovery does not serve cannot hold a marked
|
|
104
|
+
// object — absence of the kind is knowledge, not a hole.
|
|
105
|
+
if (!served) continue;
|
|
106
|
+
|
|
107
|
+
let items;
|
|
108
|
+
try {
|
|
109
|
+
items = await client.list(ref, { labelSelector: selector });
|
|
110
|
+
} catch (err) {
|
|
111
|
+
holes.push({
|
|
112
|
+
name: entityType,
|
|
113
|
+
type: entityType,
|
|
114
|
+
reason: "read-failed",
|
|
115
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const item of items) {
|
|
121
|
+
const name = item.metadata?.name;
|
|
122
|
+
if (!name) continue;
|
|
123
|
+
// The re-check that matters: a server (or fake) that ignored the label
|
|
124
|
+
// selector must not widen the set past the requested identity.
|
|
125
|
+
if (!matchesMarker(item.metadata?.labels, options.marker)) continue;
|
|
126
|
+
// Already terminating — deleting again is noise, not progress.
|
|
127
|
+
if (item.metadata?.deletionTimestamp !== undefined) continue;
|
|
128
|
+
const namespace = item.metadata?.namespace;
|
|
129
|
+
candidates.push({
|
|
130
|
+
name: namespace ? `${namespace}/${name}` : name,
|
|
131
|
+
type: entityType,
|
|
132
|
+
...(item.metadata?.uid ? { physicalId: String(item.metadata.uid) } : {}),
|
|
133
|
+
marker: readOwnership(item.metadata?.labels, LABEL_OWNERSHIP_KEYS)!,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return { candidates, ...(holes.length > 0 ? { holes } : {}) };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Delete the handed-over candidates, namespaces last. One outcome per
|
|
143
|
+
* candidate, always.
|
|
144
|
+
*/
|
|
145
|
+
export async function executeTeardown(
|
|
146
|
+
options: K8sTeardownOptions & { candidates: TeardownCandidate[] },
|
|
147
|
+
connect: K8sConnector = defaultK8sConnector,
|
|
148
|
+
): Promise<TeardownExecution> {
|
|
149
|
+
const { client } = await connect({ environment: options.environment });
|
|
150
|
+
|
|
151
|
+
// Namespaces last: their members get individual deletes (and individual
|
|
152
|
+
// outcomes) before the namespace cascade sweeps whatever is left.
|
|
153
|
+
const ordered = [
|
|
154
|
+
...options.candidates.filter((c) => c.type !== NAMESPACE_TYPE),
|
|
155
|
+
...options.candidates.filter((c) => c.type === NAMESPACE_TYPE),
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const outcomes: TeardownOutcome[] = [];
|
|
159
|
+
for (const candidate of ordered) {
|
|
160
|
+
outcomes.push(await deleteCandidate(client, candidate, options.marker));
|
|
161
|
+
}
|
|
162
|
+
return { outcomes };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function deleteCandidate(
|
|
166
|
+
client: K8sClient,
|
|
167
|
+
candidate: TeardownCandidate,
|
|
168
|
+
marker: OwnershipMarker,
|
|
169
|
+
): Promise<TeardownOutcome> {
|
|
170
|
+
const base = {
|
|
171
|
+
name: candidate.name,
|
|
172
|
+
type: candidate.type,
|
|
173
|
+
...(candidate.physicalId ? { physicalId: candidate.physicalId } : {}),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const operation = operationFor(candidate.type);
|
|
177
|
+
if (!operation) {
|
|
178
|
+
return { ...base, outcome: "not-prunable", detail: `no operation mapping for type ${candidate.type}` };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let info;
|
|
182
|
+
try {
|
|
183
|
+
info = await client.resolve({ apiVersion: operation.apiVersion, kind: operation.kind });
|
|
184
|
+
} catch (err) {
|
|
185
|
+
return { ...base, outcome: "failed", detail: err instanceof Error ? err.message : String(err) };
|
|
186
|
+
}
|
|
187
|
+
if (!info) {
|
|
188
|
+
return { ...base, outcome: "not-prunable", detail: `the cluster does not serve ${operation.kind}` };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const slash = candidate.name.indexOf("/");
|
|
192
|
+
const namespace = info.namespaced && slash > 0 ? candidate.name.slice(0, slash) : undefined;
|
|
193
|
+
const name = info.namespaced && slash > 0 ? candidate.name.slice(slash + 1) : candidate.name;
|
|
194
|
+
const ref = {
|
|
195
|
+
apiVersion: operation.apiVersion,
|
|
196
|
+
kind: operation.kind,
|
|
197
|
+
name,
|
|
198
|
+
...(namespace !== undefined ? { namespace } : {}),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// Re-read and re-verify the identity right before deleting: the enumeration
|
|
202
|
+
// is a moment old at best, and a delete is not undoable.
|
|
203
|
+
let live;
|
|
204
|
+
try {
|
|
205
|
+
live = await client.readIfPresent(ref);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
return { ...base, outcome: "failed", detail: err instanceof Error ? err.message : String(err) };
|
|
208
|
+
}
|
|
209
|
+
if (live === undefined) {
|
|
210
|
+
return { ...base, outcome: "deleted", detail: "already absent" };
|
|
211
|
+
}
|
|
212
|
+
if (!matchesMarker(live.metadata?.labels, marker)) {
|
|
213
|
+
return {
|
|
214
|
+
...base,
|
|
215
|
+
outcome: "not-prunable",
|
|
216
|
+
detail: "the live object no longer carries the requested marker identity",
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// A generated-once Secret survives every sweep, env teardown included
|
|
220
|
+
// (#1830, epic #1365 decision 5): the stored bytes are the only copy of
|
|
221
|
+
// material chant never held. `retained` is the loud keep — the row says the
|
|
222
|
+
// env is not clean and why. Deletion is an explicit act (`kubectl delete
|
|
223
|
+
// secret <name>`, or a future gated op), never a teardown's.
|
|
224
|
+
if (operation.kind === "Secret" && isGeneratedOnce(live.metadata?.labels)) {
|
|
225
|
+
return {
|
|
226
|
+
...base,
|
|
227
|
+
outcome: "retained",
|
|
228
|
+
detail:
|
|
229
|
+
"generated-once secret — deliberately kept, never swept; delete it explicitly (kubectl delete) if you mean to",
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
await client.delete(ref);
|
|
235
|
+
} catch (err) {
|
|
236
|
+
return { ...base, outcome: "failed", detail: err instanceof Error ? err.message : String(err) };
|
|
237
|
+
}
|
|
238
|
+
return { ...base, outcome: "deleted" };
|
|
239
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Secret
|
|
3
|
+
metadata:
|
|
4
|
+
name: db-credentials
|
|
5
|
+
namespace: apps
|
|
6
|
+
type: Opaque
|
|
7
|
+
stringData:
|
|
8
|
+
POSTGRES_USER: ENC[AES256_GCM,data:U2FsdGVkX18=,iv:kX9mQ2p7rT4vB1nZ8cLdE6hJ0sYwG3aF5uV7iO9kPqM=,tag:Rj4tKq9wL2xN6bV8cH1zPg==,type:str]
|
|
9
|
+
POSTGRES_PASSWORD: ENC[AES256_GCM,data:bXlwYXNzd29yZA==,iv:tY2nB7vC4xZ1qW8eR5uI3oP6aS9dF0gH2jK4lM6nO8Q=,tag:Wq2eR5tY7uI9oP1aS3dF4g==,type:str]
|
|
10
|
+
sops:
|
|
11
|
+
age:
|
|
12
|
+
- recipient: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
|
|
13
|
+
enc: |
|
|
14
|
+
-----BEGIN AGE ENCRYPTED FILE-----
|
|
15
|
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGVUZmZ2hJak
|
|
16
|
+
tMbW5PcFFyU3RVdld4WXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZ
|
|
17
|
+
WmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OQotLS
|
|
18
|
+
0gRlVGZmdoSWpLTG1uT3BRclN0VXZXeFl6QUJDREVGR0hJSktMTU5P
|
|
19
|
+
-----END AGE ENCRYPTED FILE-----
|
|
20
|
+
lastmodified: "2026-08-25T14:02:11Z"
|
|
21
|
+
mac: ENC[AES256_GCM,data:cUw3ZlZ4TXAyUXJTdFV2V3hZeg==,iv:zX8cV5bN2mQ7wE4rT1yU6iO3pA9sD0fG5hJ8kL2nB4M=,tag:Nb6vC3xZ9qW1eR4tY7uI2o==,type:str]
|
|
22
|
+
encrypted_regex: ^(data|stringData)$
|
|
23
|
+
version: 3.9.4
|