@tomflow/proflow-platform-cli 0.1.13 → 0.1.15

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 (142) hide show
  1. package/README.md +48 -43
  2. package/dist/deployment/adapter.d.ts +5 -5
  3. package/dist/deployment/adapter.js +2 -1
  4. package/dist/deployment/descriptor.d.ts +2 -3
  5. package/dist/deployment/descriptor.js +2 -3
  6. package/dist/src/binding/production-bindings.d.ts +17 -15
  7. package/dist/src/binding/production-bindings.js +18 -59
  8. package/dist/src/cli.d.ts +7 -9
  9. package/dist/src/cli.js +329 -1237
  10. package/dist/src/contracts.d.ts +4 -97
  11. package/dist/src/discovery/discover.js +0 -1
  12. package/dist/src/docs/aggregate.d.ts +18 -0
  13. package/dist/src/docs/aggregate.js +44 -0
  14. package/dist/src/docs/docs.d.ts +0 -31
  15. package/dist/src/docs/docs.js +0 -61
  16. package/dist/src/docs/index.d.ts +2 -1
  17. package/dist/src/docs/index.js +1 -1
  18. package/dist/src/errors.d.ts +1 -1
  19. package/dist/src/errors.js +0 -18
  20. package/dist/src/graph/graph.d.ts +1 -4
  21. package/dist/src/graph/graph.js +1 -13
  22. package/dist/src/graph/index.d.ts +2 -2
  23. package/dist/src/graph/index.js +1 -1
  24. package/dist/src/index.d.ts +4 -24
  25. package/dist/src/index.js +2 -16
  26. package/dist/src/install/package-manager.d.ts +21 -0
  27. package/dist/src/install/package-manager.js +153 -0
  28. package/dist/src/lifecycle/dispatch.d.ts +0 -30
  29. package/dist/src/lifecycle/dispatch.js +0 -120
  30. package/dist/src/lifecycle/index.d.ts +4 -3
  31. package/dist/src/lifecycle/index.js +2 -2
  32. package/dist/src/lifecycle/thin.d.ts +11 -0
  33. package/dist/src/lifecycle/thin.js +68 -0
  34. package/dist/src/paths.d.ts +0 -14
  35. package/dist/src/paths.js +0 -39
  36. package/dist/src/persistence/config.d.ts +0 -6
  37. package/dist/src/persistence/config.js +0 -14
  38. package/dist/src/persistence/guards.d.ts +0 -6
  39. package/dist/src/persistence/guards.js +0 -114
  40. package/dist/src/persistence/index.d.ts +4 -6
  41. package/dist/src/persistence/index.js +2 -5
  42. package/dist/src/persistence/workspace-metadata.d.ts +7 -0
  43. package/dist/src/persistence/workspace-metadata.js +39 -0
  44. package/dist/src/registry/index.d.ts +1 -1
  45. package/dist/src/registry/index.js +1 -1
  46. package/dist/src/registry/npm-registry.d.ts +0 -14
  47. package/dist/src/registry/npm-registry.js +1 -132
  48. package/package.json +2 -6
  49. package/proflow.module.json +2 -3
  50. package/CHANGELOG.md +0 -79
  51. package/dist/src/apply/apply.d.ts +0 -26
  52. package/dist/src/apply/apply.js +0 -314
  53. package/dist/src/apply/cleanup.d.ts +0 -12
  54. package/dist/src/apply/cleanup.js +0 -37
  55. package/dist/src/apply/current.d.ts +0 -5
  56. package/dist/src/apply/current.js +0 -95
  57. package/dist/src/apply/driver.d.ts +0 -28
  58. package/dist/src/apply/driver.js +0 -239
  59. package/dist/src/apply/execute.d.ts +0 -36
  60. package/dist/src/apply/execute.js +0 -152
  61. package/dist/src/apply/index.d.ts +0 -8
  62. package/dist/src/apply/index.js +0 -4
  63. package/dist/src/apply/reality.d.ts +0 -20
  64. package/dist/src/apply/reality.js +0 -105
  65. package/dist/src/binding/global-binding.d.ts +0 -69
  66. package/dist/src/binding/global-binding.js +0 -349
  67. package/dist/src/doctor/doctor.d.ts +0 -41
  68. package/dist/src/doctor/doctor.js +0 -80
  69. package/dist/src/doctor/index.d.ts +0 -2
  70. package/dist/src/doctor/index.js +0 -1
  71. package/dist/src/install/bootstrap.d.ts +0 -10
  72. package/dist/src/install/bootstrap.js +0 -79
  73. package/dist/src/install/environment.d.ts +0 -30
  74. package/dist/src/install/environment.js +0 -230
  75. package/dist/src/install/index.d.ts +0 -6
  76. package/dist/src/install/index.js +0 -3
  77. package/dist/src/install/install.d.ts +0 -19
  78. package/dist/src/install/install.js +0 -172
  79. package/dist/src/lifecycle/service-process.d.ts +0 -11
  80. package/dist/src/lifecycle/service-process.js +0 -356
  81. package/dist/src/manifest/index.d.ts +0 -2
  82. package/dist/src/manifest/index.js +0 -1
  83. package/dist/src/manifest/manifest.d.ts +0 -61
  84. package/dist/src/manifest/manifest.js +0 -167
  85. package/dist/src/observer/deployment-summary.d.ts +0 -31
  86. package/dist/src/observer/deployment-summary.js +0 -34
  87. package/dist/src/persistence/atomic.d.ts +0 -2
  88. package/dist/src/persistence/atomic.js +0 -16
  89. package/dist/src/persistence/effective-config.d.ts +0 -3
  90. package/dist/src/persistence/effective-config.js +0 -20
  91. package/dist/src/persistence/generated.d.ts +0 -2
  92. package/dist/src/persistence/generated.js +0 -4
  93. package/dist/src/persistence/plans.d.ts +0 -5
  94. package/dist/src/persistence/plans.js +0 -34
  95. package/dist/src/persistence/state.d.ts +0 -7
  96. package/dist/src/persistence/state.js +0 -34
  97. package/dist/src/persistence/verification.d.ts +0 -5
  98. package/dist/src/persistence/verification.js +0 -47
  99. package/dist/src/planner/assemble.d.ts +0 -16
  100. package/dist/src/planner/assemble.js +0 -107
  101. package/dist/src/planner/check.d.ts +0 -20
  102. package/dist/src/planner/check.js +0 -107
  103. package/dist/src/planner/fingerprint.d.ts +0 -12
  104. package/dist/src/planner/fingerprint.js +0 -164
  105. package/dist/src/planner/index.d.ts +0 -13
  106. package/dist/src/planner/index.js +0 -7
  107. package/dist/src/planner/plan.d.ts +0 -15
  108. package/dist/src/planner/plan.js +0 -144
  109. package/dist/src/planner/repair.d.ts +0 -28
  110. package/dist/src/planner/repair.js +0 -131
  111. package/dist/src/planner/stale.d.ts +0 -7
  112. package/dist/src/planner/stale.js +0 -23
  113. package/dist/src/planner/steps.d.ts +0 -37
  114. package/dist/src/planner/steps.js +0 -165
  115. package/dist/src/planner/target-catalog.d.ts +0 -13
  116. package/dist/src/planner/target-catalog.js +0 -48
  117. package/dist/src/planner/upgrade.d.ts +0 -18
  118. package/dist/src/planner/upgrade.js +0 -114
  119. package/dist/src/preflight/config.d.ts +0 -11
  120. package/dist/src/preflight/config.js +0 -88
  121. package/dist/src/preflight/findings.d.ts +0 -26
  122. package/dist/src/preflight/findings.js +0 -1
  123. package/dist/src/preflight/index.d.ts +0 -7
  124. package/dist/src/preflight/index.js +0 -3
  125. package/dist/src/preflight/preflight.d.ts +0 -10
  126. package/dist/src/preflight/preflight.js +0 -190
  127. package/dist/src/preflight/requirements.d.ts +0 -11
  128. package/dist/src/preflight/requirements.js +0 -231
  129. package/dist/src/ready/index.d.ts +0 -2
  130. package/dist/src/ready/index.js +0 -1
  131. package/dist/src/ready/ready.d.ts +0 -40
  132. package/dist/src/ready/ready.js +0 -201
  133. package/dist/src/security/index.d.ts +0 -3
  134. package/dist/src/security/index.js +0 -2
  135. package/dist/src/security/lock.d.ts +0 -9
  136. package/dist/src/security/lock.js +0 -127
  137. package/dist/src/security/redact.d.ts +0 -6
  138. package/dist/src/security/redact.js +0 -48
  139. package/dist/src/verification/index.d.ts +0 -2
  140. package/dist/src/verification/index.js +0 -1
  141. package/dist/src/verification/verify.d.ts +0 -33
  142. package/dist/src/verification/verify.js +0 -114
@@ -1,79 +0,0 @@
1
- import { PlatformError } from "../errors.js";
2
- import { PRO_FLOW_PACKAGE_PREFIX, } from "../registry/index.js";
3
- /**
4
- * Registry bootstrap targets intentionally carry only facts available before
5
- * installation. They are package-plan placeholders, never substitutes for the
6
- * package-owned Module Descriptor that is loaded after installation.
7
- */
8
- export function registryCandidateToBootstrapModule(candidate) {
9
- if (!candidate.packageName.startsWith(PRO_FLOW_PACKAGE_PREFIX)) {
10
- throw new PlatformError("PACKAGE_NOT_PROFLOW", `package ${candidate.packageName} is outside ${PRO_FLOW_PACKAGE_PREFIX}*`);
11
- }
12
- const moduleRef = candidate.packageName.slice(PRO_FLOW_PACKAGE_PREFIX.length);
13
- if (moduleRef === "") {
14
- throw new PlatformError("REGISTRY_RESPONSE_INVALID", `cannot derive moduleRef from ${candidate.packageName}`);
15
- }
16
- return {
17
- moduleRef,
18
- packageName: candidate.packageName,
19
- moduleVersion: candidate.moduleVersion,
20
- kind: "registry-package",
21
- installClass: candidate.installClass,
22
- provides: [],
23
- requires: [],
24
- requirements: [],
25
- configSlots: [],
26
- lifecycle: [],
27
- verification: { checks: [] },
28
- effects: [],
29
- documentation: [],
30
- source: { type: "registry" },
31
- };
32
- }
33
- export function selectBootstrapModules(candidates, explicitPackageName) {
34
- const byPackage = new Map(candidates.map((candidate) => [candidate.packageName, candidate]));
35
- const roots = explicitPackageName === undefined
36
- ? candidates.filter((candidate) => candidate.installClass === "core")
37
- : candidates.filter((candidate) => candidate.packageName === explicitPackageName);
38
- if (roots.length === 0) {
39
- throw new PlatformError(explicitPackageName === undefined
40
- ? "REGISTRY_RESPONSE_INVALID"
41
- : "PACKAGE_NOT_FOUND", explicitPackageName === undefined
42
- ? "Registry discovery returned no installable core ProFlow packages"
43
- : `no installable ProFlow package found for ${explicitPackageName}`);
44
- }
45
- const selected = new Map();
46
- const queue = [...roots];
47
- while (queue.length > 0) {
48
- const candidate = queue.shift();
49
- if (!candidate)
50
- continue;
51
- if (selected.has(candidate.packageName))
52
- continue;
53
- selected.set(candidate.packageName, candidate);
54
- for (const dependencyName of candidate.installRequires) {
55
- const dependency = byPackage.get(dependencyName);
56
- if (dependency === undefined) {
57
- throw new PlatformError("DEPENDENCY_UNRESOLVED", `Registry bootstrap dependency ${dependencyName} required by ${candidate.packageName} was not discovered`);
58
- }
59
- queue.push(dependency);
60
- }
61
- }
62
- return [...selected.values()]
63
- .sort((a, b) => a.packageName.localeCompare(b.packageName))
64
- .map(registryCandidateToBootstrapModule);
65
- }
66
- export function selectUpgradeBootstrapModules(currentModules, candidates) {
67
- const byPackage = new Map(candidates.map((candidate) => [candidate.packageName, candidate]));
68
- const targets = [];
69
- for (const current of currentModules) {
70
- const candidate = byPackage.get(current.packageName);
71
- if (candidate === undefined) {
72
- throw new PlatformError("PACKAGE_NOT_FOUND", `no installable Registry target found for managed package ${current.packageName}`);
73
- }
74
- if (candidate.moduleVersion === current.moduleVersion)
75
- continue;
76
- targets.push(registryCandidateToBootstrapModule(candidate));
77
- }
78
- return targets;
79
- }
@@ -1,30 +0,0 @@
1
- import { type NpmCommandRunner } from "../registry/index.ts";
2
- import { type PackageManagerSelectionSource, type SupportedWorkspacePackageManager } from "./package-manager.ts";
3
- export declare const PLATFORM_INSTALL_NODE_RANGE = ">=24.19.0";
4
- export type InstallerPreflightStatus = "READY" | "ACTION_REQUIRED" | "BLOCKED";
5
- export type InstallerFindingSeverity = "info" | "action" | "error";
6
- export interface InstallerFinding {
7
- code: string;
8
- severity: InstallerFindingSeverity;
9
- message: string;
10
- }
11
- export interface InstallerEnvironmentPreflightResult {
12
- contract: "deployment.installer-preflight.v1";
13
- ok: boolean;
14
- status: InstallerPreflightStatus;
15
- workspaceRoot: string;
16
- nodeVersion: string;
17
- npmVersion?: string;
18
- packageManager?: {
19
- name: SupportedWorkspacePackageManager;
20
- source: PackageManagerSelectionSource;
21
- declared?: string;
22
- version?: string;
23
- };
24
- registry?: string;
25
- findings: InstallerFinding[];
26
- }
27
- export declare function preflightInstallerEnvironment(options: {
28
- workspaceRoot: string;
29
- runner?: NpmCommandRunner;
30
- }): Promise<InstallerEnvironmentPreflightResult>;
@@ -1,230 +0,0 @@
1
- import { constants } from "node:fs";
2
- import { access, readFile, stat } from "node:fs/promises";
3
- import { join } from "node:path";
4
- import { PlatformError } from "../errors.js";
5
- import { versionSatisfies } from "../modules.js";
6
- import { resolveScopeRegistry, systemNpmRunner, } from "../registry/index.js";
7
- import { findExecutable, readWorkspacePackageManagerSelection, systemPackageCommandRunner, } from "./package-manager.js";
8
- export const PLATFORM_INSTALL_NODE_RANGE = ">=24.19.0";
9
- export async function preflightInstallerEnvironment(options) {
10
- const runner = options.runner ?? systemNpmRunner();
11
- const findings = [];
12
- const nodeVersion = process.versions.node;
13
- if (!versionSatisfies(nodeVersion, PLATFORM_INSTALL_NODE_RANGE)) {
14
- findings.push({
15
- code: "NODE_VERSION_UNSUPPORTED",
16
- severity: "error",
17
- message: `node ${nodeVersion} does not satisfy ${PLATFORM_INSTALL_NODE_RANGE}`,
18
- });
19
- }
20
- else {
21
- findings.push({
22
- code: "NODE_VERSION_READY",
23
- severity: "info",
24
- message: `node ${nodeVersion} satisfies ${PLATFORM_INSTALL_NODE_RANGE}`,
25
- });
26
- }
27
- const workspace = await inspectWorkspace(options.workspaceRoot);
28
- findings.push(...workspace.findings);
29
- let npmVersion;
30
- if (!findExecutable("npm")) {
31
- findings.push({
32
- code: "NPM_UNAVAILABLE",
33
- severity: "error",
34
- message: "npm executable is not available on PATH",
35
- });
36
- }
37
- else {
38
- try {
39
- const npm = await runner.run(["--version"], options.workspaceRoot);
40
- npmVersion = npm.stdout.trim();
41
- findings.push({
42
- code: "NPM_READY",
43
- severity: "info",
44
- message: `npm ${npmVersion || "<unknown>"} is available`,
45
- });
46
- }
47
- catch (error) {
48
- findings.push(platformErrorFinding(error, "NPM_UNAVAILABLE"));
49
- }
50
- }
51
- let packageManager;
52
- let packageManagerVersion;
53
- try {
54
- packageManager = await readWorkspacePackageManagerSelection(options.workspaceRoot);
55
- if (!findExecutable(packageManager.name)) {
56
- findings.push({
57
- code: "PACKAGE_MANAGER_UNAVAILABLE",
58
- severity: "action",
59
- message: `workspace selects ${packageManager.name}, but that executable is not available on PATH`,
60
- });
61
- }
62
- else if (packageManager.name === "npm" && npmVersion !== undefined) {
63
- packageManagerVersion = npmVersion;
64
- }
65
- else {
66
- try {
67
- packageManagerVersion = (await systemPackageCommandRunner().run(packageManager.name, ["--version"], options.workspaceRoot)).trim();
68
- }
69
- catch (error) {
70
- findings.push({
71
- code: "PACKAGE_MANAGER_UNAVAILABLE",
72
- severity: "action",
73
- message: error instanceof Error ? error.message : String(error),
74
- });
75
- }
76
- }
77
- if (packageManagerVersion !== undefined) {
78
- findings.push({
79
- code: "PACKAGE_MANAGER_READY",
80
- severity: "info",
81
- message: `${packageManager.name} ${packageManagerVersion} is selected via ${packageManager.source}`,
82
- });
83
- }
84
- }
85
- catch (error) {
86
- if (error instanceof PlatformError) {
87
- findings.push({
88
- code: error.code,
89
- severity: error.code === "PACKAGE_MANAGER_CONFLICT" ? "error" : "action",
90
- message: error.message,
91
- });
92
- }
93
- else {
94
- findings.push({
95
- code: "PACKAGE_MANAGER_UNAVAILABLE",
96
- severity: "action",
97
- message: error instanceof Error ? error.message : String(error),
98
- });
99
- }
100
- }
101
- let registry;
102
- if (npmVersion !== undefined) {
103
- try {
104
- registry = await resolveScopeRegistry(options.workspaceRoot, runner);
105
- await runner.run(["ping", "--json", "--prefer-online", `--registry=${registry}`], options.workspaceRoot, 10_000);
106
- findings.push({
107
- code: "REGISTRY_READY",
108
- severity: "info",
109
- message: `npm registry is reachable: ${registry}`,
110
- });
111
- }
112
- catch (error) {
113
- findings.push(platformErrorFinding(error, "REGISTRY_UNAVAILABLE"));
114
- }
115
- }
116
- const status = aggregateInstallerStatus(findings);
117
- return {
118
- contract: "deployment.installer-preflight.v1",
119
- ok: status === "READY",
120
- status,
121
- workspaceRoot: options.workspaceRoot,
122
- nodeVersion,
123
- ...(npmVersion === undefined ? {} : { npmVersion }),
124
- ...(packageManager === undefined
125
- ? {}
126
- : {
127
- packageManager: {
128
- ...packageManager,
129
- ...(packageManagerVersion === undefined
130
- ? {}
131
- : { version: packageManagerVersion }),
132
- },
133
- }),
134
- ...(registry === undefined ? {} : { registry }),
135
- findings,
136
- };
137
- }
138
- async function inspectWorkspace(workspaceRoot) {
139
- const findings = [];
140
- try {
141
- const info = await stat(workspaceRoot);
142
- if (!info.isDirectory()) {
143
- return {
144
- findings: [
145
- {
146
- code: "WORKSPACE_INVALID",
147
- severity: "error",
148
- message: `${workspaceRoot} is not a directory`,
149
- },
150
- ],
151
- };
152
- }
153
- await access(workspaceRoot, constants.R_OK | constants.W_OK);
154
- findings.push({
155
- code: "WORKSPACE_WRITABLE",
156
- severity: "info",
157
- message: `workspace is readable and writable: ${workspaceRoot}`,
158
- });
159
- }
160
- catch {
161
- return {
162
- findings: [
163
- {
164
- code: "WORKSPACE_NOT_WRITABLE",
165
- severity: "error",
166
- message: `workspace is missing or not writable: ${workspaceRoot}`,
167
- },
168
- ],
169
- };
170
- }
171
- const manifestPath = join(workspaceRoot, "package.json");
172
- try {
173
- const raw = await readFile(manifestPath, "utf8");
174
- const parsed = JSON.parse(raw);
175
- if (!isRecord(parsed))
176
- throw new Error("package.json root is not an object");
177
- const manifest = parsed;
178
- findings.push({
179
- code: "PACKAGE_JSON_READY",
180
- severity: "info",
181
- message: "workspace package.json is readable",
182
- });
183
- return {
184
- ...(typeof manifest.packageManager === "string"
185
- ? { packageManager: manifest.packageManager }
186
- : {}),
187
- findings,
188
- };
189
- }
190
- catch (error) {
191
- if (isMissingFile(error)) {
192
- findings.push({
193
- code: "PACKAGE_JSON_CREATABLE",
194
- severity: "info",
195
- message: "workspace has no package.json; installer may create one before the first package mutation",
196
- });
197
- return { findings };
198
- }
199
- findings.push({
200
- code: "PACKAGE_JSON_INVALID",
201
- severity: "error",
202
- message: error instanceof Error ? error.message : String(error),
203
- });
204
- return { findings };
205
- }
206
- }
207
- function aggregateInstallerStatus(findings) {
208
- if (findings.some((finding) => finding.severity === "error"))
209
- return "BLOCKED";
210
- if (findings.some((finding) => finding.severity === "action")) {
211
- return "ACTION_REQUIRED";
212
- }
213
- return "READY";
214
- }
215
- function platformErrorFinding(error, fallbackCode) {
216
- if (error instanceof PlatformError) {
217
- return { code: error.code, severity: "error", message: error.message };
218
- }
219
- return {
220
- code: fallbackCode,
221
- severity: "error",
222
- message: error instanceof Error ? error.message : String(error),
223
- };
224
- }
225
- function isRecord(value) {
226
- return typeof value === "object" && value !== null && !Array.isArray(value);
227
- }
228
- function isMissingFile(error) {
229
- return isRecord(error) && error.code === "ENOENT";
230
- }
@@ -1,6 +0,0 @@
1
- export { registryCandidateToBootstrapModule, selectBootstrapModules, } from "./bootstrap.ts";
2
- export type { InstallerEnvironmentPreflightResult, InstallerFinding, InstallerFindingSeverity, InstallerPreflightStatus, } from "./environment.ts";
3
- export { PLATFORM_INSTALL_NODE_RANGE, preflightInstallerEnvironment, } from "./environment.ts";
4
- export type { GenerateInstallDocInput, InstallDocInput, } from "./install.ts";
5
- export { generateInstallDoc, renderInstallDoc } from "./install.ts";
6
- export type { SupportedWorkspacePackageManager, WorkspacePackageManagerSelection, } from "./package-manager.ts";
@@ -1,3 +0,0 @@
1
- export { registryCandidateToBootstrapModule, selectBootstrapModules, } from "./bootstrap.js";
2
- export { PLATFORM_INSTALL_NODE_RANGE, preflightInstallerEnvironment, } from "./environment.js";
3
- export { generateInstallDoc, renderInstallDoc } from "./install.js";
@@ -1,19 +0,0 @@
1
- import type { ResolvedModule } from "../contracts.ts";
2
- import type { WorkspacePaths } from "../paths.ts";
3
- export interface InstallDocInput {
4
- modules: readonly ResolvedModule[];
5
- config?: Record<string, Record<string, string>>;
6
- now?: Date;
7
- }
8
- export interface GenerateInstallDocInput extends InstallDocInput {
9
- paths: WorkspacePaths;
10
- }
11
- /**
12
- * Renders the generated INSTALL document from the real selected module set:
13
- * module refs/versions, machine/runtime requirements, secret-redacted config
14
- * slots, external resources, effects, human actions, and the verification plan.
15
- * No raw secret value may survive — config values are redacted by key, and the
16
- * whole document is deep-redacted against every known raw secret value.
17
- */
18
- export declare function renderInstallDoc(input: InstallDocInput): string;
19
- export declare function generateInstallDoc(input: GenerateInstallDocInput): Promise<string>;
@@ -1,172 +0,0 @@
1
- import { writeInstallDoc } from "../persistence/index.js";
2
- import { resolveModuleConfig } from "../preflight/index.js";
3
- import { redactDeep, redactSecretValues } from "../security/index.js";
4
- function compareRef(a, b) {
5
- return a < b ? -1 : a > b ? 1 : 0;
6
- }
7
- function requirementLine(moduleRef, requirement) {
8
- switch (requirement.kind) {
9
- case "runtime":
10
- return `- \`${moduleRef}\`: runtime \`${requirement.runtime}\` ${requirement.versionRange}`;
11
- case "executable":
12
- return `- \`${moduleRef}\`: executable \`${requirement.command}\`${requirement.versionRange !== undefined
13
- ? ` ${requirement.versionRange}`
14
- : ""}`;
15
- case "filesystem":
16
- return `- \`${moduleRef}\`: filesystem \`${requirement.path}\` (${requirement.access})`;
17
- case "port":
18
- return `- \`${moduleRef}\`: port ${requirement.port}/${requirement.protocol}`;
19
- case "network":
20
- return `- \`${moduleRef}\`: network \`${requirement.url}\``;
21
- case "module-contract":
22
- return `- \`${moduleRef}\`: module-contract \`${requirement.contractRef}\` ${requirement.versionRange}`;
23
- case "human":
24
- return `- \`${moduleRef}\`: human — ${requirement.action}`;
25
- }
26
- }
27
- function collectRawSecrets(modules, config) {
28
- const secrets = [];
29
- for (const module of modules) {
30
- const resolved = resolveModuleConfig(module, config?.[module.moduleRef]);
31
- const sensitiveKeys = new Set(module.configSlots
32
- .filter((slot) => slot.sensitive === true && slot.type !== "secretRef")
33
- .map((slot) => slot.key));
34
- for (const [key, value] of Object.entries(resolved.values)) {
35
- if (sensitiveKeys.has(key) && value.length > 0)
36
- secrets.push(value);
37
- }
38
- }
39
- return secrets;
40
- }
41
- /**
42
- * Renders the generated INSTALL document from the real selected module set:
43
- * module refs/versions, machine/runtime requirements, secret-redacted config
44
- * slots, external resources, effects, human actions, and the verification plan.
45
- * No raw secret value may survive — config values are redacted by key, and the
46
- * whole document is deep-redacted against every known raw secret value.
47
- */
48
- export function renderInstallDoc(input) {
49
- const generatedAt = (input.now ?? new Date()).toISOString();
50
- const modules = [...input.modules].sort((a, b) => compareRef(a.moduleRef, b.moduleRef));
51
- const lines = [];
52
- lines.push("# ProFlow Deployment — Generated INSTALL");
53
- lines.push("");
54
- lines.push(`> Generated at ${generatedAt}. Regenerated by \`platform manifest\`.`);
55
- lines.push("");
56
- lines.push("## Selected Module Set");
57
- lines.push("");
58
- for (const module of modules) {
59
- lines.push(`- \`${module.moduleRef}\` (\`${module.packageName}@${module.moduleVersion}\`, kind: \`${module.kind}\`)`);
60
- }
61
- lines.push("");
62
- lines.push("## Requirements");
63
- lines.push("");
64
- for (const module of modules) {
65
- for (const requirement of module.requirements) {
66
- lines.push(requirementLine(module.moduleRef, requirement));
67
- }
68
- }
69
- lines.push("");
70
- lines.push("## Config Slots");
71
- lines.push("");
72
- for (const module of modules) {
73
- const resolved = resolveModuleConfig(module, input.config?.[module.moduleRef]);
74
- const values = redactSecretValues(resolved.values, resolved.secretRefs);
75
- for (const slot of module.configSlots) {
76
- const value = values[slot.key];
77
- const suffix = value !== undefined ? ` = \`${value}\`` : "";
78
- const required = slot.required ? " (required)" : "";
79
- lines.push(`- \`${module.moduleRef}\`.\`${slot.key}\` [${slot.type}]${required}${suffix}`);
80
- }
81
- }
82
- lines.push("");
83
- const external = modules.filter((module) => module.kind === "external-resource");
84
- if (external.length > 0) {
85
- lines.push("## External Resources");
86
- lines.push("");
87
- for (const module of external) {
88
- lines.push(`- \`${module.moduleRef}\` (\`${module.packageName}@${module.moduleVersion}\`)`);
89
- }
90
- lines.push("");
91
- }
92
- lines.push("## Effects");
93
- lines.push("");
94
- for (const module of modules) {
95
- for (const effect of module.effects) {
96
- lines.push(`- \`${module.moduleRef}\`: [${effect.kind}] ${effect.description}`);
97
- }
98
- }
99
- lines.push("");
100
- const humanActions = modules.flatMap((module) => module.requirements
101
- .filter((requirement) => requirement.kind === "human")
102
- .map((requirement) => ({
103
- moduleRef: module.moduleRef,
104
- action: requirement.action,
105
- })));
106
- if (humanActions.length > 0) {
107
- lines.push("## Human Actions");
108
- lines.push("");
109
- for (const action of humanActions) {
110
- lines.push(`- \`${action.moduleRef}\`: ${action.action}`);
111
- }
112
- lines.push("");
113
- }
114
- const missingRequiredConfig = {};
115
- for (const module of modules) {
116
- const resolved = resolveModuleConfig(module, input.config?.[module.moduleRef]);
117
- for (const slot of module.configSlots) {
118
- if (!slot.required || resolved.values[slot.key] !== undefined)
119
- continue;
120
- const placeholder = slot.type === "secretRef"
121
- ? "secret://provider/name"
122
- : slot.type === "url"
123
- ? "https://example.invalid"
124
- : slot.type === "path"
125
- ? "/absolute/path"
126
- : slot.type === "moduleRef"
127
- ? "module-ref"
128
- : "<value>";
129
- const moduleConfig = missingRequiredConfig[module.moduleRef] ?? {};
130
- moduleConfig[slot.key] = placeholder;
131
- missingRequiredConfig[module.moduleRef] = moduleConfig;
132
- }
133
- }
134
- lines.push("## Configure Before Start");
135
- lines.push("");
136
- if (Object.keys(missingRequiredConfig).length === 0) {
137
- lines.push("No required configuration is currently missing. Re-run `platform preflight --intent start` before starting to confirm current runtime readiness.");
138
- }
139
- else {
140
- lines.push("Create a JSON config file (for example `./proflow-config.json`) using the required missing slots below. Replace placeholders with real environment-specific values. `secretRef` values must remain opaque references such as `secret://provider/name`; do not place raw secrets in this file.");
141
- lines.push("");
142
- lines.push("```json");
143
- lines.push(JSON.stringify({ modules: missingRequiredConfig }, null, 2));
144
- lines.push("```");
145
- lines.push("");
146
- lines.push("Apply and re-check the configuration:");
147
- lines.push("");
148
- lines.push("1. `platform plan --intent configure --config ./proflow-config.json`");
149
- lines.push("2. Copy the returned `planRef`.");
150
- lines.push("3. `platform apply <planRef>`");
151
- lines.push("4. `platform preflight --intent start`");
152
- lines.push("5. Resolve any remaining human or external-resource actions reported by preflight, then run the same preflight command again until the Platform reports the expected readiness state.");
153
- }
154
- lines.push("");
155
- lines.push("## Verification Plan");
156
- lines.push("");
157
- for (const module of modules) {
158
- for (const verificationCheck of module.verification.checks) {
159
- lines.push(`- \`${module.moduleRef}\`: \`${verificationCheck.id}\` (${verificationCheck.lifecycle}) — ${verificationCheck.description}`);
160
- }
161
- }
162
- const content = `${lines.join("\n")}\n`;
163
- // defense-in-depth: deep-redact every raw secret value wherever it appears
164
- const rawSecrets = collectRawSecrets(modules, input.config);
165
- const redacted = redactDeep(content, rawSecrets);
166
- return typeof redacted === "string" ? redacted : content;
167
- }
168
- export async function generateInstallDoc(input) {
169
- const content = renderInstallDoc(input);
170
- await writeInstallDoc(input.paths, content);
171
- return content;
172
- }
@@ -1,11 +0,0 @@
1
- import { type ModuleOperationResult } from "@tomflow/proflow-module-contract";
2
- import type { ResolvedModule } from "../contracts.ts";
3
- import type { WorkspacePaths } from "../paths.ts";
4
- export interface ManagedServiceInvocation {
5
- result: ModuleOperationResult;
6
- observedEffects: string[];
7
- }
8
- export declare function managedServiceStatus(paths: WorkspacePaths, module: ResolvedModule): Promise<ManagedServiceInvocation>;
9
- export declare function startManagedService(paths: WorkspacePaths, module: ResolvedModule, rawBinding: unknown): Promise<ManagedServiceInvocation>;
10
- export declare function stopManagedService(paths: WorkspacePaths, module: ResolvedModule): Promise<ManagedServiceInvocation>;
11
- export declare function restartManagedService(paths: WorkspacePaths, module: ResolvedModule, binding: unknown): Promise<ManagedServiceInvocation>;