@pleri/olam-cli 0.1.152 → 0.1.157

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 (146) hide show
  1. package/dist/commands/bootstrap.d.ts +2 -1
  2. package/dist/commands/bootstrap.d.ts.map +1 -1
  3. package/dist/commands/bootstrap.js +8 -10
  4. package/dist/commands/bootstrap.js.map +1 -1
  5. package/dist/commands/doctor.d.ts +46 -0
  6. package/dist/commands/doctor.d.ts.map +1 -1
  7. package/dist/commands/doctor.js +146 -8
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/flywheel/check-persona-skeleton.d.ts +7 -0
  10. package/dist/commands/flywheel/check-persona-skeleton.d.ts.map +1 -0
  11. package/dist/commands/flywheel/check-persona-skeleton.js +14 -0
  12. package/dist/commands/flywheel/check-persona-skeleton.js.map +1 -0
  13. package/dist/commands/flywheel/diversity-check.d.ts +7 -0
  14. package/dist/commands/flywheel/diversity-check.d.ts.map +1 -0
  15. package/dist/commands/flywheel/diversity-check.js +14 -0
  16. package/dist/commands/flywheel/diversity-check.js.map +1 -0
  17. package/dist/commands/flywheel/emit-breadcrumb.d.ts +20 -0
  18. package/dist/commands/flywheel/emit-breadcrumb.d.ts.map +1 -0
  19. package/dist/commands/flywheel/emit-breadcrumb.js +137 -0
  20. package/dist/commands/flywheel/emit-breadcrumb.js.map +1 -0
  21. package/dist/commands/flywheel/index.d.ts +27 -0
  22. package/dist/commands/flywheel/index.d.ts.map +1 -0
  23. package/dist/commands/flywheel/index.js +48 -0
  24. package/dist/commands/flywheel/index.js.map +1 -0
  25. package/dist/commands/flywheel/install-shims.d.ts +8 -0
  26. package/dist/commands/flywheel/install-shims.d.ts.map +1 -0
  27. package/dist/commands/flywheel/install-shims.js +15 -0
  28. package/dist/commands/flywheel/install-shims.js.map +1 -0
  29. package/dist/commands/flywheel/k10-measure.d.ts +7 -0
  30. package/dist/commands/flywheel/k10-measure.d.ts.map +1 -0
  31. package/dist/commands/flywheel/k10-measure.js +14 -0
  32. package/dist/commands/flywheel/k10-measure.js.map +1 -0
  33. package/dist/commands/flywheel/k5-score.d.ts +14 -0
  34. package/dist/commands/flywheel/k5-score.d.ts.map +1 -0
  35. package/dist/commands/flywheel/k5-score.js +59 -0
  36. package/dist/commands/flywheel/k5-score.js.map +1 -0
  37. package/dist/commands/flywheel/k5-validate.d.ts +15 -0
  38. package/dist/commands/flywheel/k5-validate.d.ts.map +1 -0
  39. package/dist/commands/flywheel/k5-validate.js +185 -0
  40. package/dist/commands/flywheel/k5-validate.js.map +1 -0
  41. package/dist/commands/flywheel/ping.d.ts +21 -0
  42. package/dist/commands/flywheel/ping.d.ts.map +1 -0
  43. package/dist/commands/flywheel/ping.js +79 -0
  44. package/dist/commands/flywheel/ping.js.map +1 -0
  45. package/dist/commands/flywheel/sanitize-persona-output.d.ts +7 -0
  46. package/dist/commands/flywheel/sanitize-persona-output.d.ts.map +1 -0
  47. package/dist/commands/flywheel/sanitize-persona-output.js +14 -0
  48. package/dist/commands/flywheel/sanitize-persona-output.js.map +1 -0
  49. package/dist/commands/hermes-kg-hook.d.ts +36 -0
  50. package/dist/commands/hermes-kg-hook.d.ts.map +1 -0
  51. package/dist/commands/hermes-kg-hook.js +80 -0
  52. package/dist/commands/hermes-kg-hook.js.map +1 -0
  53. package/dist/commands/hermes.d.ts +46 -0
  54. package/dist/commands/hermes.d.ts.map +1 -0
  55. package/dist/commands/hermes.js +320 -0
  56. package/dist/commands/hermes.js.map +1 -0
  57. package/dist/commands/host-cp.d.ts.map +1 -1
  58. package/dist/commands/host-cp.js +17 -0
  59. package/dist/commands/host-cp.js.map +1 -1
  60. package/dist/commands/kg-install-hook.d.ts +7 -1
  61. package/dist/commands/kg-install-hook.d.ts.map +1 -1
  62. package/dist/commands/kg-install-hook.js +122 -6
  63. package/dist/commands/kg-install-hook.js.map +1 -1
  64. package/dist/commands/memory/_paths.d.ts +13 -3
  65. package/dist/commands/memory/_paths.d.ts.map +1 -1
  66. package/dist/commands/memory/_paths.js +25 -22
  67. package/dist/commands/memory/_paths.js.map +1 -1
  68. package/dist/commands/memory/logs.d.ts +8 -4
  69. package/dist/commands/memory/logs.d.ts.map +1 -1
  70. package/dist/commands/memory/logs.js +18 -13
  71. package/dist/commands/memory/logs.js.map +1 -1
  72. package/dist/commands/memory/mode.d.ts.map +1 -1
  73. package/dist/commands/memory/mode.js +7 -3
  74. package/dist/commands/memory/mode.js.map +1 -1
  75. package/dist/commands/memory/start.d.ts +16 -14
  76. package/dist/commands/memory/start.d.ts.map +1 -1
  77. package/dist/commands/memory/start.js +55 -189
  78. package/dist/commands/memory/start.js.map +1 -1
  79. package/dist/commands/memory/status.d.ts +10 -8
  80. package/dist/commands/memory/status.d.ts.map +1 -1
  81. package/dist/commands/memory/status.js +35 -38
  82. package/dist/commands/memory/status.js.map +1 -1
  83. package/dist/commands/memory/stop.d.ts +5 -4
  84. package/dist/commands/memory/stop.d.ts.map +1 -1
  85. package/dist/commands/memory/stop.js +26 -55
  86. package/dist/commands/memory/stop.js.map +1 -1
  87. package/dist/commands/memory-service-container.d.ts +78 -0
  88. package/dist/commands/memory-service-container.d.ts.map +1 -0
  89. package/dist/commands/memory-service-container.js +187 -0
  90. package/dist/commands/memory-service-container.js.map +1 -0
  91. package/dist/commands/services.d.ts +16 -1
  92. package/dist/commands/services.d.ts.map +1 -1
  93. package/dist/commands/services.js +97 -38
  94. package/dist/commands/services.js.map +1 -1
  95. package/dist/commands/substrate.d.ts +19 -1
  96. package/dist/commands/substrate.d.ts.map +1 -1
  97. package/dist/commands/substrate.js +19 -11
  98. package/dist/commands/substrate.js.map +1 -1
  99. package/dist/commands/upgrade.d.ts.map +1 -1
  100. package/dist/commands/upgrade.js +11 -0
  101. package/dist/commands/upgrade.js.map +1 -1
  102. package/dist/image-digests.json +7 -7
  103. package/dist/index.js +3662 -2044
  104. package/dist/index.js.map +1 -1
  105. package/dist/lib/auth-refresh-kubernetes.d.ts +3 -0
  106. package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -1
  107. package/dist/lib/auth-refresh-kubernetes.js +6 -17
  108. package/dist/lib/auth-refresh-kubernetes.js.map +1 -1
  109. package/dist/lib/health-probes.d.ts +20 -0
  110. package/dist/lib/health-probes.d.ts.map +1 -1
  111. package/dist/lib/health-probes.js +55 -0
  112. package/dist/lib/health-probes.js.map +1 -1
  113. package/dist/lib/k8s-bootstrap.d.ts +120 -0
  114. package/dist/lib/k8s-bootstrap.d.ts.map +1 -0
  115. package/dist/lib/k8s-bootstrap.js +193 -0
  116. package/dist/lib/k8s-bootstrap.js.map +1 -0
  117. package/dist/lib/k8s-secret-render.d.ts +139 -0
  118. package/dist/lib/k8s-secret-render.d.ts.map +1 -0
  119. package/dist/lib/k8s-secret-render.js +281 -0
  120. package/dist/lib/k8s-secret-render.js.map +1 -0
  121. package/dist/lib/kubectl-context.d.ts +38 -0
  122. package/dist/lib/kubectl-context.d.ts.map +1 -0
  123. package/dist/lib/kubectl-context.js +43 -0
  124. package/dist/lib/kubectl-context.js.map +1 -0
  125. package/dist/lib/memory-host-process-migration.d.ts +56 -0
  126. package/dist/lib/memory-host-process-migration.d.ts.map +1 -0
  127. package/dist/lib/memory-host-process-migration.js +156 -0
  128. package/dist/lib/memory-host-process-migration.js.map +1 -0
  129. package/dist/lib/upgrade-kubernetes.d.ts +42 -0
  130. package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
  131. package/dist/lib/upgrade-kubernetes.js +258 -24
  132. package/dist/lib/upgrade-kubernetes.js.map +1 -1
  133. package/dist/mcp-server.js +56 -22
  134. package/hermes-bundle/kg-first.sh +100 -0
  135. package/hermes-bundle/version.json +4 -0
  136. package/host-cp/k8s/manifests/50-deployment.yaml +54 -27
  137. package/host-cp/k8s/manifests/auth-service/30-configmap.yaml +5 -0
  138. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +5 -1
  139. package/host-cp/k8s/manifests/kg-service/30-configmap.yaml +5 -0
  140. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +5 -1
  141. package/host-cp/k8s/manifests/mcp-auth-service/30-configmap.yaml +4 -0
  142. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +5 -1
  143. package/host-cp/k8s/manifests/memory-service/30-configmap.yaml +4 -0
  144. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +5 -1
  145. package/package.json +3 -4
  146. package/memory-service-bundle/scripts/ensure-iii-engine.mjs +0 -179
@@ -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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * memory-host-process-migration.ts — idempotent cleanup of the Phase A
3
+ * host-process model's residual state on disk.
4
+ *
5
+ * Phase A spawned `agentmemory` as a host child process and recorded its PID
6
+ * at `~/.olam/memory.pid` + stdout/stderr at `~/.olam/memory-service.log`.
7
+ * Phase B repoints `olam memory start` at the Docker substrate (this skill's
8
+ * `MemoryServiceContainerController`); the legacy pidfile + log become orphan
9
+ * artefacts the moment the new substrate runs.
10
+ *
11
+ * This helper is called from `runMemoryStart` / `runMemoryStop` (B1 / B2) BEFORE
12
+ * the substrate handoff so operators upgrading from the host-process model
13
+ * never have to manually clean up.
14
+ *
15
+ * PID-reuse defence (T2 mitigation). A stale pidfile can record a PID that
16
+ * the OS has since recycled to an unrelated process. SIGTERMing the wrong PID
17
+ * is a foot-gun. Defence:
18
+ * 1. If pidfile is absent → no-op.
19
+ * 2. If recorded PID is dead (kill(0) throws ESRCH) → unlink pidfile only.
20
+ * 3. If recorded PID is alive BUT `ps -p <pid> -o comm=` doesn't return
21
+ * `node` (the legacy host-process was always a node child) → unlink
22
+ * pidfile WITHOUT signalling. Logs a warning so support can diagnose.
23
+ * 4. Only when PID is alive AND comm=node → SIGTERM, wait up to 5s,
24
+ * SIGKILL on timeout, then unlink.
25
+ *
26
+ * Plan reference: docs/plans/memory-service-as-docker-peripheral/phase-b-tasks.md B5
27
+ */
28
+ export interface MigrationResult {
29
+ /** True if any legacy artefact (pidfile or log) was found + cleaned. */
30
+ readonly cleaned: boolean;
31
+ /** One-line description of what happened (for operator-visible logging). */
32
+ readonly summary: string;
33
+ }
34
+ export interface MigrationOptions {
35
+ /** Remove `memory-service.log` in addition to the pidfile (B2 stop path uses this). */
36
+ removeLog?: boolean;
37
+ /** Override the pidfile path. Defaults to MEMORY_PID_PATH. Used by tests. */
38
+ pidPath?: string;
39
+ /** Override the log path. Defaults to MEMORY_LOG_PATH. Used by tests. */
40
+ logPath?: string;
41
+ }
42
+ /**
43
+ * Detect + clean up legacy host-process state. Idempotent — safe to call on
44
+ * every `olam memory start` / `olam memory stop` invocation; no-op when no
45
+ * legacy artefacts present.
46
+ *
47
+ * Side effects (only when artefacts present):
48
+ * - Unlink `~/.olam/memory.pid` if it exists.
49
+ * - Send SIGTERM (then SIGKILL on timeout) to the recorded PID iff it's
50
+ * alive AND its comm name is `node` (the legacy spawn shape).
51
+ * - Leave `~/.olam/memory-service.log` in place by default — operators
52
+ * may want to inspect it post-migration. Pass `{ removeLog: true }` to
53
+ * remove it explicitly (B2's stop path uses this).
54
+ */
55
+ export declare function migrateFromHostProcess(opts?: MigrationOptions): MigrationResult;
56
+ //# sourceMappingURL=memory-host-process-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-host-process-migration.d.ts","sourceRoot":"","sources":["../../src/lib/memory-host-process-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,uFAAuF;IACvF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,gBAAqB,GAAG,eAAe,CAoDnF"}