@pleri/olam-cli 0.1.152 → 0.1.153

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 (49) hide show
  1. package/dist/commands/doctor.d.ts +24 -0
  2. package/dist/commands/doctor.d.ts.map +1 -1
  3. package/dist/commands/doctor.js +36 -1
  4. package/dist/commands/doctor.js.map +1 -1
  5. package/dist/commands/host-cp.d.ts.map +1 -1
  6. package/dist/commands/host-cp.js +17 -0
  7. package/dist/commands/host-cp.js.map +1 -1
  8. package/dist/commands/services.d.ts.map +1 -1
  9. package/dist/commands/services.js +9 -26
  10. package/dist/commands/services.js.map +1 -1
  11. package/dist/commands/substrate.d.ts +19 -1
  12. package/dist/commands/substrate.d.ts.map +1 -1
  13. package/dist/commands/substrate.js +19 -11
  14. package/dist/commands/substrate.js.map +1 -1
  15. package/dist/commands/upgrade.d.ts.map +1 -1
  16. package/dist/commands/upgrade.js +11 -0
  17. package/dist/commands/upgrade.js.map +1 -1
  18. package/dist/image-digests.json +7 -7
  19. package/dist/index.js +13326 -12904
  20. package/dist/lib/auth-refresh-kubernetes.d.ts +3 -0
  21. package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -1
  22. package/dist/lib/auth-refresh-kubernetes.js +6 -17
  23. package/dist/lib/auth-refresh-kubernetes.js.map +1 -1
  24. package/dist/lib/health-probes.d.ts +20 -0
  25. package/dist/lib/health-probes.d.ts.map +1 -1
  26. package/dist/lib/health-probes.js +55 -0
  27. package/dist/lib/health-probes.js.map +1 -1
  28. package/dist/lib/k8s-bootstrap.d.ts +120 -0
  29. package/dist/lib/k8s-bootstrap.d.ts.map +1 -0
  30. package/dist/lib/k8s-bootstrap.js +193 -0
  31. package/dist/lib/k8s-bootstrap.js.map +1 -0
  32. package/dist/lib/k8s-secret-render.d.ts +139 -0
  33. package/dist/lib/k8s-secret-render.d.ts.map +1 -0
  34. package/dist/lib/k8s-secret-render.js +281 -0
  35. package/dist/lib/k8s-secret-render.js.map +1 -0
  36. package/dist/lib/kubectl-context.d.ts +38 -0
  37. package/dist/lib/kubectl-context.d.ts.map +1 -0
  38. package/dist/lib/kubectl-context.js +43 -0
  39. package/dist/lib/kubectl-context.js.map +1 -0
  40. package/dist/lib/upgrade-kubernetes.d.ts +23 -0
  41. package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
  42. package/dist/lib/upgrade-kubernetes.js +67 -22
  43. package/dist/lib/upgrade-kubernetes.js.map +1 -1
  44. package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
  45. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
  46. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  47. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
  48. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ /**
2
+ * k8s-secret-render.ts — render `REPLACE_ME_FROM_*` placeholders in the
3
+ * shipped k8s Secret templates with real values, and persist the rendered
4
+ * set so reapply is idempotent.
5
+ *
6
+ * B5 of olam-issue-npm-only-k3s (npm-only operator bootstrap completion).
7
+ *
8
+ * The templates at `packages/host-cp/k8s/templates/*-secret-template.yaml`
9
+ * carry placeholders like `REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET`. The
10
+ * source-of-truth value for each placeholder is documented in the template
11
+ * comment block; it's either a host-side file in `~/.olam/` (the compose
12
+ * bootstrap path) or a subprocess output (e.g. `gh auth token`).
13
+ *
14
+ * Source resolution per placeholder:
15
+ *
16
+ * placeholder → source
17
+ * REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET → file ~/.olam/auth-secret (generate if missing)
18
+ * REPLACE_ME_FROM_GH_AUTH_TOKEN → subprocess `gh auth token` (warn + skip if absent)
19
+ * REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET → file ~/.olam/auth-db-secret (generate if missing)
20
+ * REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET → file ~/.olam/mcp-auth-jwt-secret (generate if missing)
21
+ * REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN → file ~/.olam/kg-bearer-token (generate if missing)
22
+ * REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET → file ~/.olam/memory-bearer-secret (generate if missing)
23
+ *
24
+ * State persistence: `~/.olam/k8s-secrets-state.json` records the rendered
25
+ * Secret set so re-runs (idempotent reapply) reuse the same values. Without
26
+ * the state file every `olam upgrade` would rotate tokens silently, breaking
27
+ * worlds that have cached the previous value. Operator opts in to rotation
28
+ * via `--rotate-secrets`.
29
+ *
30
+ * D20 stdin-safe design: rendered YAML is built in-process and applied via
31
+ * stdin to `kubectl apply -f -`. Placeholder values are NEVER inlined into
32
+ * subprocess argv (audit:auth-callers + general security hygiene).
33
+ */
34
+ export declare const K8S_SECRETS_STATE_PATH: string;
35
+ /**
36
+ * One template's placeholder set + the per-host-file source it reads from.
37
+ * Hardcoded mapping — every secret template's `# Source:` comment names the
38
+ * file; the audit:cli-bundle-k8s gate ensures the templates stay in sync.
39
+ */
40
+ export interface SecretTemplateBinding {
41
+ readonly secretName: string;
42
+ readonly templateRelPath: string;
43
+ readonly placeholders: ReadonlyArray<{
44
+ readonly placeholder: string;
45
+ readonly key: string;
46
+ readonly source: {
47
+ readonly kind: 'file';
48
+ readonly hostFile: string;
49
+ } | {
50
+ readonly kind: 'gh-token';
51
+ };
52
+ }>;
53
+ }
54
+ /** Canonical mapping for the 5 secret templates that ship with the CLI. */
55
+ export declare const SECRET_TEMPLATE_BINDINGS: ReadonlyArray<SecretTemplateBinding>;
56
+ /** Per-secret state record — keys map to RENDERED values reused on re-apply. */
57
+ export interface RenderedSecret {
58
+ readonly keys: Record<string, string>;
59
+ readonly skipped?: ReadonlyArray<string>;
60
+ }
61
+ /** State file shape. version=1 lets us migrate the schema without breaking older state. */
62
+ export interface K8sSecretsState {
63
+ readonly version: 1;
64
+ readonly context: string;
65
+ readonly namespace: string;
66
+ readonly generatedAt: string;
67
+ readonly secrets: Record<string, RenderedSecret>;
68
+ }
69
+ /** Injectable deps so tests don't touch the real filesystem / shell. */
70
+ export interface RenderDeps {
71
+ readonly olamHome?: string;
72
+ readonly statePath?: string;
73
+ readonly readFile?: (path: string, enc: 'utf8') => string;
74
+ readonly writeFile?: (path: string, data: string, mode: number) => void;
75
+ readonly fileExists?: (path: string) => boolean;
76
+ readonly genRandomHex?: () => string;
77
+ readonly runGhTokenCmd?: () => {
78
+ ok: boolean;
79
+ token: string;
80
+ };
81
+ readonly readState?: () => K8sSecretsState | null;
82
+ readonly writeState?: (state: K8sSecretsState) => void;
83
+ readonly stderr?: NodeJS.WritableStream;
84
+ }
85
+ /**
86
+ * Read the state file. Returns null when missing OR when the version doesn't match (forward-compat).
87
+ */
88
+ export declare function readSecretsState(statePath?: string): K8sSecretsState | null;
89
+ /** Atomically write the state file (0600). */
90
+ export declare function writeSecretsState(state: K8sSecretsState, statePath?: string): void;
91
+ /**
92
+ * Result of rendering one Secret. Either:
93
+ * - resolved: every placeholder got a value (rendered YAML is ready to apply).
94
+ * - skipped: at least one source was unavailable AND not generatable (e.g.
95
+ * gh auth token absent); the operator must apply this secret
96
+ * manually OR install gh + retry.
97
+ */
98
+ export interface RenderResult {
99
+ readonly secretName: string;
100
+ readonly status: 'resolved' | 'skipped';
101
+ readonly renderedYaml?: string;
102
+ readonly keys: Record<string, string>;
103
+ readonly missingSources: ReadonlyArray<string>;
104
+ }
105
+ /**
106
+ * Substitute the placeholder strings in the template YAML with real values.
107
+ * Builds a fresh Secret YAML string (does NOT touch the template on disk).
108
+ *
109
+ * The templates hold ONE placeholder per stringData key; literal string
110
+ * substitution suffices. We avoid YAML parsing to keep the template comment
111
+ * block (which carries operator-facing documentation) intact in the rendered
112
+ * output.
113
+ */
114
+ export declare function substitutePlaceholders(templateYaml: string, values: Record<string, string>): string;
115
+ /**
116
+ * Render ONE secret template. Reads the template YAML from `templatesRoot`
117
+ * (resolved by the caller to either source or install-mode location),
118
+ * resolves each placeholder, persists generated values to host files,
119
+ * substitutes, and returns the rendered YAML.
120
+ *
121
+ * `reuse` carries the prior state's per-key values when an unrotated
122
+ * re-apply is requested; null means "this is the first apply or operator
123
+ * asked for rotation."
124
+ */
125
+ export declare function renderOneSecret(binding: SecretTemplateBinding, templatesRoot: string, reuse: RenderedSecret | null, deps?: RenderDeps, rotate?: boolean): RenderResult;
126
+ /**
127
+ * Render the full set of shipped Secret templates. `rotate=true` discards
128
+ * the on-disk state and regenerates every value; `rotate=false` reuses
129
+ * state for unchanged secrets so worlds caching old tokens don't break.
130
+ */
131
+ export declare function renderAllSecrets(templatesRoot: string, opts: {
132
+ rotate: boolean;
133
+ context: string;
134
+ namespace: string;
135
+ }, deps?: RenderDeps): {
136
+ results: ReadonlyArray<RenderResult>;
137
+ nextState: K8sSecretsState;
138
+ };
139
+ //# sourceMappingURL=k8s-secret-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k8s-secret-render.d.ts","sourceRoot":"","sources":["../../src/lib/k8s-secret-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,281 @@
1
+ /**
2
+ * k8s-secret-render.ts — render `REPLACE_ME_FROM_*` placeholders in the
3
+ * shipped k8s Secret templates with real values, and persist the rendered
4
+ * set so reapply is idempotent.
5
+ *
6
+ * B5 of olam-issue-npm-only-k3s (npm-only operator bootstrap completion).
7
+ *
8
+ * The templates at `packages/host-cp/k8s/templates/*-secret-template.yaml`
9
+ * carry placeholders like `REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET`. The
10
+ * source-of-truth value for each placeholder is documented in the template
11
+ * comment block; it's either a host-side file in `~/.olam/` (the compose
12
+ * bootstrap path) or a subprocess output (e.g. `gh auth token`).
13
+ *
14
+ * Source resolution per placeholder:
15
+ *
16
+ * placeholder → source
17
+ * REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET → file ~/.olam/auth-secret (generate if missing)
18
+ * REPLACE_ME_FROM_GH_AUTH_TOKEN → subprocess `gh auth token` (warn + skip if absent)
19
+ * REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET → file ~/.olam/auth-db-secret (generate if missing)
20
+ * REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET → file ~/.olam/mcp-auth-jwt-secret (generate if missing)
21
+ * REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN → file ~/.olam/kg-bearer-token (generate if missing)
22
+ * REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET → file ~/.olam/memory-bearer-secret (generate if missing)
23
+ *
24
+ * State persistence: `~/.olam/k8s-secrets-state.json` records the rendered
25
+ * Secret set so re-runs (idempotent reapply) reuse the same values. Without
26
+ * the state file every `olam upgrade` would rotate tokens silently, breaking
27
+ * worlds that have cached the previous value. Operator opts in to rotation
28
+ * via `--rotate-secrets`.
29
+ *
30
+ * D20 stdin-safe design: rendered YAML is built in-process and applied via
31
+ * stdin to `kubectl apply -f -`. Placeholder values are NEVER inlined into
32
+ * subprocess argv (audit:auth-callers + general security hygiene).
33
+ */
34
+ import { spawnSync } from 'node:child_process';
35
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, statSync } from 'node:fs';
36
+ import { join, dirname } from 'node:path';
37
+ import { randomBytes } from 'node:crypto';
38
+ import { OLAM_HOME } from './config.js';
39
+ export const K8S_SECRETS_STATE_PATH = join(OLAM_HOME, 'k8s-secrets-state.json');
40
+ const SECRET_HEX_BYTES = 32; // 64-char hex tokens — mirrors memory-secret.ts SECRET_LEN_BYTES.
41
+ /** Canonical mapping for the 5 secret templates that ship with the CLI. */
42
+ export const SECRET_TEMPLATE_BINDINGS = [
43
+ {
44
+ secretName: 'olam-host-cp-secret',
45
+ templateRelPath: 'templates/40-secret-template.yaml',
46
+ placeholders: [
47
+ {
48
+ placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET',
49
+ key: 'OLAM_AUTH_SECRET',
50
+ source: { kind: 'file', hostFile: 'auth-secret' },
51
+ },
52
+ {
53
+ placeholder: 'REPLACE_ME_FROM_GH_AUTH_TOKEN',
54
+ key: 'GH_TOKEN',
55
+ source: { kind: 'gh-token' },
56
+ },
57
+ ],
58
+ },
59
+ {
60
+ secretName: 'olam-auth-service-secret',
61
+ templateRelPath: 'templates/auth-service-secret-template.yaml',
62
+ placeholders: [
63
+ {
64
+ placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET',
65
+ key: 'OLAM_AUTH_DB_SECRET',
66
+ source: { kind: 'file', hostFile: 'auth-db-secret' },
67
+ },
68
+ ],
69
+ },
70
+ {
71
+ secretName: 'olam-mcp-auth-service-secret',
72
+ templateRelPath: 'templates/mcp-auth-service-secret-template.yaml',
73
+ placeholders: [
74
+ {
75
+ placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET',
76
+ key: 'OLAM_MCP_AUTH_JWT_SECRET',
77
+ source: { kind: 'file', hostFile: 'mcp-auth-jwt-secret' },
78
+ },
79
+ ],
80
+ },
81
+ {
82
+ secretName: 'olam-kg-service-secret',
83
+ templateRelPath: 'templates/kg-service-secret-template.yaml',
84
+ placeholders: [
85
+ {
86
+ placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN',
87
+ key: 'OLAM_KG_BEARER_TOKEN',
88
+ source: { kind: 'file', hostFile: 'kg-bearer-token' },
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ secretName: 'olam-memory-service-secret',
94
+ templateRelPath: 'templates/memory-service-secret-template.yaml',
95
+ placeholders: [
96
+ {
97
+ placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET',
98
+ key: 'OLAM_MEMORY_BEARER_SECRET',
99
+ source: { kind: 'file', hostFile: 'memory-bearer-secret' },
100
+ },
101
+ ],
102
+ },
103
+ ];
104
+ const defaultGenRandomHex = () => randomBytes(SECRET_HEX_BYTES).toString('hex');
105
+ const defaultRunGhTokenCmd = () => {
106
+ const r = spawnSync('gh', ['auth', 'token'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
107
+ if (r.status === 0 && r.stdout.trim().length > 0) {
108
+ return { ok: true, token: r.stdout.trim() };
109
+ }
110
+ return { ok: false, token: '' };
111
+ };
112
+ const defaultReadFile = (p, enc) => readFileSync(p, enc);
113
+ const defaultWriteFile = (p, data, mode) => {
114
+ mkdirSync(dirname(p), { recursive: true });
115
+ writeFileSync(p, data, { encoding: 'utf8', mode });
116
+ // writeFileSync's mode is umask-respecting; chmod explicitly to be safe.
117
+ chmodSync(p, mode);
118
+ };
119
+ const defaultFileExists = (p) => existsSync(p);
120
+ /**
121
+ * Read the state file. Returns null when missing OR when the version doesn't match (forward-compat).
122
+ */
123
+ export function readSecretsState(statePath = K8S_SECRETS_STATE_PATH) {
124
+ if (!existsSync(statePath))
125
+ return null;
126
+ try {
127
+ const raw = readFileSync(statePath, 'utf8');
128
+ const parsed = JSON.parse(raw);
129
+ if (parsed.version !== 1)
130
+ return null;
131
+ return parsed;
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ }
137
+ /** Atomically write the state file (0600). */
138
+ export function writeSecretsState(state, statePath = K8S_SECRETS_STATE_PATH) {
139
+ mkdirSync(dirname(statePath), { recursive: true });
140
+ const tmp = `${statePath}.tmp.${process.pid}`;
141
+ writeFileSync(tmp, JSON.stringify(state, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
142
+ chmodSync(tmp, 0o600);
143
+ // renameSync is atomic on POSIX
144
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
145
+ require('node:fs').renameSync(tmp, statePath);
146
+ }
147
+ /**
148
+ * Resolve a single placeholder's value. Returns null when the source is
149
+ * absent AND not generatable (gh-token only). For file-sourced placeholders
150
+ * we always generate if missing — that's the npm-only operator path.
151
+ */
152
+ function resolveSourceValue(source, olamHome, reuseFromState, rotate, deps) {
153
+ if (!rotate && reuseFromState !== undefined && reuseFromState !== '') {
154
+ return { ok: true, value: reuseFromState };
155
+ }
156
+ if (source.kind === 'file') {
157
+ const filePath = join(olamHome, source.hostFile);
158
+ // Rotation: always generate fresh value, overwrite the host file.
159
+ if (rotate) {
160
+ const fresh = deps.genRandomHex();
161
+ deps.writeFile(filePath, fresh, 0o600);
162
+ return { ok: true, value: fresh };
163
+ }
164
+ if (deps.fileExists(filePath)) {
165
+ const value = deps.readFile(filePath, 'utf8').trim();
166
+ if (value.length > 0)
167
+ return { ok: true, value };
168
+ }
169
+ // Missing or empty — generate, persist, return.
170
+ const fresh = deps.genRandomHex();
171
+ deps.writeFile(filePath, fresh, 0o600);
172
+ return { ok: true, value: fresh };
173
+ }
174
+ // kind === 'gh-token' — not generatable; warn + skip if absent.
175
+ // Rotation reads gh CLI again (gh manages its own session rotation).
176
+ const r = deps.runGhTokenCmd();
177
+ if (r.ok)
178
+ return { ok: true, value: r.token };
179
+ return { ok: false, reason: 'gh CLI not authenticated; run `gh auth login` then re-run' };
180
+ }
181
+ /**
182
+ * Substitute the placeholder strings in the template YAML with real values.
183
+ * Builds a fresh Secret YAML string (does NOT touch the template on disk).
184
+ *
185
+ * The templates hold ONE placeholder per stringData key; literal string
186
+ * substitution suffices. We avoid YAML parsing to keep the template comment
187
+ * block (which carries operator-facing documentation) intact in the rendered
188
+ * output.
189
+ */
190
+ export function substitutePlaceholders(templateYaml, values) {
191
+ let out = templateYaml;
192
+ for (const [placeholder, value] of Object.entries(values)) {
193
+ // Use split/join rather than .replace to avoid regex escaping pitfalls.
194
+ out = out.split(`"${placeholder}"`).join(`"${value}"`);
195
+ }
196
+ return out;
197
+ }
198
+ /**
199
+ * Render ONE secret template. Reads the template YAML from `templatesRoot`
200
+ * (resolved by the caller to either source or install-mode location),
201
+ * resolves each placeholder, persists generated values to host files,
202
+ * substitutes, and returns the rendered YAML.
203
+ *
204
+ * `reuse` carries the prior state's per-key values when an unrotated
205
+ * re-apply is requested; null means "this is the first apply or operator
206
+ * asked for rotation."
207
+ */
208
+ export function renderOneSecret(binding, templatesRoot, reuse, deps = {}, rotate = false) {
209
+ const olamHome = deps.olamHome ?? OLAM_HOME;
210
+ const readFile = deps.readFile ?? defaultReadFile;
211
+ const writeFile = deps.writeFile ?? defaultWriteFile;
212
+ const fileExists = deps.fileExists ?? defaultFileExists;
213
+ const genRandomHex = deps.genRandomHex ?? defaultGenRandomHex;
214
+ const runGhTokenCmd = deps.runGhTokenCmd ?? defaultRunGhTokenCmd;
215
+ const templatePath = join(templatesRoot, binding.templateRelPath);
216
+ const templateYaml = readFile(templatePath, 'utf8');
217
+ const keys = {};
218
+ const placeholderToValue = {};
219
+ const missingSources = [];
220
+ for (const p of binding.placeholders) {
221
+ const resolved = resolveSourceValue(p.source, olamHome, reuse?.keys[p.key], rotate, { readFile, writeFile, fileExists, genRandomHex, runGhTokenCmd });
222
+ if (!resolved.ok) {
223
+ missingSources.push(`${p.key}: ${resolved.reason}`);
224
+ continue;
225
+ }
226
+ keys[p.key] = resolved.value;
227
+ placeholderToValue[p.placeholder] = resolved.value;
228
+ }
229
+ if (missingSources.length > 0) {
230
+ return {
231
+ secretName: binding.secretName,
232
+ status: 'skipped',
233
+ keys,
234
+ missingSources,
235
+ };
236
+ }
237
+ const renderedYaml = substitutePlaceholders(templateYaml, placeholderToValue);
238
+ return {
239
+ secretName: binding.secretName,
240
+ status: 'resolved',
241
+ renderedYaml,
242
+ keys,
243
+ missingSources: [],
244
+ };
245
+ }
246
+ /**
247
+ * Render the full set of shipped Secret templates. `rotate=true` discards
248
+ * the on-disk state and regenerates every value; `rotate=false` reuses
249
+ * state for unchanged secrets so worlds caching old tokens don't break.
250
+ */
251
+ export function renderAllSecrets(templatesRoot, opts, deps = {}) {
252
+ const readState = deps.readState ?? (() => readSecretsState(deps.statePath ?? K8S_SECRETS_STATE_PATH));
253
+ const writeState = deps.writeState ?? ((s) => writeSecretsState(s, deps.statePath ?? K8S_SECRETS_STATE_PATH));
254
+ const prior = opts.rotate ? null : readState();
255
+ const results = [];
256
+ const nextSecrets = {};
257
+ for (const binding of SECRET_TEMPLATE_BINDINGS) {
258
+ const reuse = prior?.secrets[binding.secretName] ?? null;
259
+ const r = renderOneSecret(binding, templatesRoot, reuse, deps, opts.rotate);
260
+ results.push(r);
261
+ nextSecrets[binding.secretName] = {
262
+ keys: r.keys,
263
+ ...(r.missingSources.length > 0 ? { skipped: r.missingSources } : {}),
264
+ };
265
+ }
266
+ const nextState = {
267
+ version: 1,
268
+ context: opts.context,
269
+ namespace: opts.namespace,
270
+ generatedAt: new Date().toISOString(),
271
+ secrets: nextSecrets,
272
+ };
273
+ // Only persist when at least one secret resolved — avoids an empty state file
274
+ // on a wholly-failed first run (where every gh-token source was absent and
275
+ // the operator hadn't yet generated `~/.olam/*` files).
276
+ if (results.some((r) => r.status === 'resolved')) {
277
+ writeState(nextState);
278
+ }
279
+ return { results, nextState };
280
+ }
281
+ //# sourceMappingURL=k8s-secret-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k8s-secret-render.js","sourceRoot":"","sources":["../../src/lib/k8s-secret-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * kubectl-context.ts — shared kubectl-context resolver.
3
+ *
4
+ * Single source of truth for the D1 / SEC-NEW-003 context-resolution
5
+ * policy. Extracted so `upgrade-kubernetes.ts`, `auth-refresh-kubernetes.ts`,
6
+ * `services.ts`, and any future kubernetes-substrate consumer can call the
7
+ * same helper instead of duplicating it.
8
+ *
9
+ * Policy (matches the pre-existing auth-refresh-kubernetes.ts and services.ts
10
+ * behaviour — see also docs/architecture/peripheral-services-on-k3s.md):
11
+ *
12
+ * 1. `host.kubectl_context_pinned` in `~/.olam/config.json` (preferred,
13
+ * persistent — the doc-recommended way).
14
+ * 2. `OLAM_K8S_CONTEXT_ACK` env var (deprecated fallback; emits a
15
+ * deprecation warning to nudge operators toward (1)).
16
+ * 3. Both absent → error result with actionable remediation.
17
+ *
18
+ * No `fs` reads in this module beyond what `readConfig` does; no kubectl
19
+ * invocations. Pure resolution. Safe to call from any layer.
20
+ */
21
+ /**
22
+ * Result shape mirrors `auth-refresh-kubernetes.ts`'s pre-existing public
23
+ * `resolveKubectlContext` so callers there can be migrated without source
24
+ * changes. Exactly one of `context` or `error` is set.
25
+ */
26
+ export interface KubectlContextResolution {
27
+ readonly context?: string;
28
+ readonly deprecationWarning?: string;
29
+ readonly error?: string;
30
+ }
31
+ /**
32
+ * Resolve the operator's kubectl context name. See module docstring for policy.
33
+ *
34
+ * `configPath` lets callers (and tests) point at a non-default config file.
35
+ * Returns a `KubectlContextResolution` — callers branch on `error` vs `context`.
36
+ */
37
+ export declare function resolveKubectlContext(configPath?: string): KubectlContextResolution;
38
+ //# sourceMappingURL=kubectl-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kubectl-context.d.ts","sourceRoot":"","sources":["../../src/lib/kubectl-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AASD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,wBAAwB,CAcnF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * kubectl-context.ts — shared kubectl-context resolver.
3
+ *
4
+ * Single source of truth for the D1 / SEC-NEW-003 context-resolution
5
+ * policy. Extracted so `upgrade-kubernetes.ts`, `auth-refresh-kubernetes.ts`,
6
+ * `services.ts`, and any future kubernetes-substrate consumer can call the
7
+ * same helper instead of duplicating it.
8
+ *
9
+ * Policy (matches the pre-existing auth-refresh-kubernetes.ts and services.ts
10
+ * behaviour — see also docs/architecture/peripheral-services-on-k3s.md):
11
+ *
12
+ * 1. `host.kubectl_context_pinned` in `~/.olam/config.json` (preferred,
13
+ * persistent — the doc-recommended way).
14
+ * 2. `OLAM_K8S_CONTEXT_ACK` env var (deprecated fallback; emits a
15
+ * deprecation warning to nudge operators toward (1)).
16
+ * 3. Both absent → error result with actionable remediation.
17
+ *
18
+ * No `fs` reads in this module beyond what `readConfig` does; no kubectl
19
+ * invocations. Pure resolution. Safe to call from any layer.
20
+ */
21
+ import { readConfig } from './config.js';
22
+ const DEPRECATION_WARNING = 'OLAM_K8S_CONTEXT_ACK is deprecated; set host.kubectl_context_pinned in ~/.olam/config.json';
23
+ const NO_CONTEXT_ERROR = 'kubectl_context_pinned is not set in ~/.olam/config.json and OLAM_K8S_CONTEXT_ACK is not set.\n' +
24
+ ' Set host.kubectl_context_pinned in ~/.olam/config.json to your kubectl context name.';
25
+ /**
26
+ * Resolve the operator's kubectl context name. See module docstring for policy.
27
+ *
28
+ * `configPath` lets callers (and tests) point at a non-default config file.
29
+ * Returns a `KubectlContextResolution` — callers branch on `error` vs `context`.
30
+ */
31
+ export function resolveKubectlContext(configPath) {
32
+ const cfg = readConfig({ configPath });
33
+ const raw = cfg.host['kubectl_context_pinned'];
34
+ if (typeof raw === 'string' && raw.length > 0) {
35
+ return { context: raw };
36
+ }
37
+ const ack = process.env['OLAM_K8S_CONTEXT_ACK'];
38
+ if (typeof ack === 'string' && ack.length > 0) {
39
+ return { context: ack, deprecationWarning: DEPRECATION_WARNING };
40
+ }
41
+ return { error: NO_CONTEXT_ERROR };
42
+ }
43
+ //# sourceMappingURL=kubectl-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kubectl-context.js","sourceRoot":"","sources":["../../src/lib/kubectl-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAazC,MAAM,mBAAmB,GACvB,4FAA4F,CAAC;AAE/F,MAAM,gBAAgB,GACpB,iGAAiG;IACjG,wFAAwF,CAAC;AAE3F;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAmB;IACvD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACvC,MAAM,GAAG,GAAI,GAAG,CAAC,IAAgC,CAAC,wBAAwB,CAAC,CAAC;IAE5E,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;AACrC,CAAC"}
@@ -44,6 +44,7 @@ import { kubectlWrap } from './kubectl-wrap.js';
44
44
  import { spawnPortForward, spawnAllPeripheralPortForwards, probePortForwardLiveness, type PortForwardDeps, type PeripheralPortForwardDeps } from './port-forward.js';
45
45
  import { emitUpgradeComplete, type EmitOpts } from './instrumentation.js';
46
46
  import { runManifestRefresh, seedManifestsFromBundle, type SeedManifestsDeps } from './manifest-refresh.js';
47
+ import { ensureK8sBootstrap, type BootstrapDeps as K8sBootstrapDeps } from './k8s-bootstrap.js';
47
48
  export declare const OLAM_K8S_MANIFESTS_DIR: string;
48
49
  export declare const K8S_NAMESPACE = "olam";
49
50
  export declare const HOST_CP_SECRET_NAME = "olam-host-cp-secret";
@@ -99,10 +100,32 @@ export interface UpgradeKubernetesDeps {
99
100
  * Tests inject a mock to avoid real kubectl invocations.
100
101
  */
101
102
  readonly checkDockerSocketImpl?: (context: string) => Promise<boolean>;
103
+ /**
104
+ * B3: override config path passed to resolveKubectlContext (tests use a
105
+ * tmpdir fixture). Defaults to the real ~/.olam/config.json.
106
+ */
107
+ readonly configPath?: string;
108
+ /**
109
+ * B4: override the k8s-bootstrap step (tests inject a mock so kubectl
110
+ * isn't called). When omitted defaults to the real `ensureK8sBootstrap`.
111
+ */
112
+ readonly k8sBootstrapImpl?: typeof ensureK8sBootstrap;
113
+ /** B4: pass-through deps for `ensureK8sBootstrap`. */
114
+ readonly k8sBootstrapDeps?: K8sBootstrapDeps;
102
115
  }
103
116
  export interface UpgradeKubernetesOpts {
104
117
  readonly forceRefreshManifests?: boolean;
105
118
  readonly acceptSecurityRegression?: boolean;
119
+ /** B4/B5: regenerate all rendered Secret values (overwrites k8s-secrets-state.json). */
120
+ readonly rotateSecrets?: boolean;
121
+ /**
122
+ * B4: run the namespace + RBAC + secret bootstrap step BEFORE step 1.
123
+ * Default is `false` for direct lib callers (preserves existing test
124
+ * ordering invariants); the CLI command in `upgrade.ts` passes `true` so
125
+ * npm-only operators get the bootstrap automatically. Operators who
126
+ * manage secrets out-of-band (GitOps) can disable via `--skip-k8s-bootstrap`.
127
+ */
128
+ readonly runK8sBootstrap?: boolean;
106
129
  }
107
130
  export interface UpgradeKubernetesResult {
108
131
  readonly exitCode: number;
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade-kubernetes.d.ts","sourceRoot":"","sources":["../../src/lib/upgrade-kubernetes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"upgrade-kubernetes.d.ts","sourceRoot":"","sources":["../../src/lib/upgrade-kubernetes.ts"],"names":[],"mappings":"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"}