@tomflow/proflow-platform-cli 0.1.14 → 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.
- package/README.md +48 -43
- package/dist/deployment/adapter.d.ts +5 -5
- package/dist/deployment/adapter.js +2 -1
- package/dist/deployment/descriptor.d.ts +2 -3
- package/dist/deployment/descriptor.js +2 -3
- package/dist/src/binding/production-bindings.d.ts +17 -15
- package/dist/src/binding/production-bindings.js +18 -59
- package/dist/src/cli.d.ts +7 -9
- package/dist/src/cli.js +327 -1316
- package/dist/src/contracts.d.ts +4 -97
- package/dist/src/discovery/discover.js +0 -1
- package/dist/src/docs/aggregate.d.ts +18 -0
- package/dist/src/docs/aggregate.js +44 -0
- package/dist/src/docs/docs.d.ts +0 -31
- package/dist/src/docs/docs.js +0 -61
- package/dist/src/docs/index.d.ts +2 -1
- package/dist/src/docs/index.js +1 -1
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js +0 -18
- package/dist/src/graph/graph.d.ts +1 -4
- package/dist/src/graph/graph.js +1 -13
- package/dist/src/graph/index.d.ts +2 -2
- package/dist/src/graph/index.js +1 -1
- package/dist/src/index.d.ts +4 -24
- package/dist/src/index.js +2 -16
- package/dist/src/install/package-manager.d.ts +21 -0
- package/dist/src/install/package-manager.js +153 -0
- package/dist/src/lifecycle/dispatch.d.ts +0 -31
- package/dist/src/lifecycle/dispatch.js +0 -125
- package/dist/src/lifecycle/index.d.ts +4 -3
- package/dist/src/lifecycle/index.js +2 -2
- package/dist/src/lifecycle/thin.d.ts +11 -0
- package/dist/src/lifecycle/thin.js +68 -0
- package/dist/src/paths.d.ts +0 -14
- package/dist/src/paths.js +0 -39
- package/dist/src/persistence/config.d.ts +0 -6
- package/dist/src/persistence/config.js +0 -14
- package/dist/src/persistence/guards.d.ts +0 -6
- package/dist/src/persistence/guards.js +0 -114
- package/dist/src/persistence/index.d.ts +4 -6
- package/dist/src/persistence/index.js +2 -5
- package/dist/src/persistence/workspace-metadata.d.ts +7 -0
- package/dist/src/persistence/workspace-metadata.js +39 -0
- package/dist/src/registry/index.d.ts +1 -1
- package/dist/src/registry/index.js +1 -1
- package/dist/src/registry/npm-registry.d.ts +0 -14
- package/dist/src/registry/npm-registry.js +1 -132
- package/package.json +2 -6
- package/proflow.module.json +2 -3
- package/CHANGELOG.md +0 -85
- package/dist/src/apply/apply.d.ts +0 -26
- package/dist/src/apply/apply.js +0 -314
- package/dist/src/apply/cleanup.d.ts +0 -12
- package/dist/src/apply/cleanup.js +0 -37
- package/dist/src/apply/current.d.ts +0 -5
- package/dist/src/apply/current.js +0 -95
- package/dist/src/apply/driver.d.ts +0 -28
- package/dist/src/apply/driver.js +0 -239
- package/dist/src/apply/execute.d.ts +0 -36
- package/dist/src/apply/execute.js +0 -152
- package/dist/src/apply/index.d.ts +0 -8
- package/dist/src/apply/index.js +0 -4
- package/dist/src/apply/reality.d.ts +0 -20
- package/dist/src/apply/reality.js +0 -105
- package/dist/src/binding/global-binding.d.ts +0 -69
- package/dist/src/binding/global-binding.js +0 -349
- package/dist/src/doctor/doctor.d.ts +0 -41
- package/dist/src/doctor/doctor.js +0 -80
- package/dist/src/doctor/index.d.ts +0 -2
- package/dist/src/doctor/index.js +0 -1
- package/dist/src/install/bootstrap.d.ts +0 -10
- package/dist/src/install/bootstrap.js +0 -79
- package/dist/src/install/environment.d.ts +0 -30
- package/dist/src/install/environment.js +0 -230
- package/dist/src/install/index.d.ts +0 -6
- package/dist/src/install/index.js +0 -3
- package/dist/src/install/install.d.ts +0 -19
- package/dist/src/install/install.js +0 -172
- package/dist/src/lifecycle/service-process.d.ts +0 -11
- package/dist/src/lifecycle/service-process.js +0 -356
- package/dist/src/manifest/index.d.ts +0 -2
- package/dist/src/manifest/index.js +0 -1
- package/dist/src/manifest/manifest.d.ts +0 -61
- package/dist/src/manifest/manifest.js +0 -167
- package/dist/src/observer/deployment-summary.d.ts +0 -31
- package/dist/src/observer/deployment-summary.js +0 -34
- package/dist/src/persistence/atomic.d.ts +0 -2
- package/dist/src/persistence/atomic.js +0 -16
- package/dist/src/persistence/effective-config.d.ts +0 -3
- package/dist/src/persistence/effective-config.js +0 -20
- package/dist/src/persistence/generated.d.ts +0 -2
- package/dist/src/persistence/generated.js +0 -4
- package/dist/src/persistence/plans.d.ts +0 -5
- package/dist/src/persistence/plans.js +0 -34
- package/dist/src/persistence/state.d.ts +0 -7
- package/dist/src/persistence/state.js +0 -34
- package/dist/src/persistence/verification.d.ts +0 -5
- package/dist/src/persistence/verification.js +0 -47
- package/dist/src/planner/assemble.d.ts +0 -16
- package/dist/src/planner/assemble.js +0 -107
- package/dist/src/planner/check.d.ts +0 -20
- package/dist/src/planner/check.js +0 -107
- package/dist/src/planner/fingerprint.d.ts +0 -12
- package/dist/src/planner/fingerprint.js +0 -164
- package/dist/src/planner/index.d.ts +0 -13
- package/dist/src/planner/index.js +0 -7
- package/dist/src/planner/plan.d.ts +0 -15
- package/dist/src/planner/plan.js +0 -144
- package/dist/src/planner/repair.d.ts +0 -28
- package/dist/src/planner/repair.js +0 -131
- package/dist/src/planner/stale.d.ts +0 -7
- package/dist/src/planner/stale.js +0 -23
- package/dist/src/planner/steps.d.ts +0 -37
- package/dist/src/planner/steps.js +0 -165
- package/dist/src/planner/target-catalog.d.ts +0 -13
- package/dist/src/planner/target-catalog.js +0 -48
- package/dist/src/planner/upgrade.d.ts +0 -18
- package/dist/src/planner/upgrade.js +0 -114
- package/dist/src/preflight/config.d.ts +0 -11
- package/dist/src/preflight/config.js +0 -88
- package/dist/src/preflight/findings.d.ts +0 -26
- package/dist/src/preflight/findings.js +0 -1
- package/dist/src/preflight/index.d.ts +0 -7
- package/dist/src/preflight/index.js +0 -3
- package/dist/src/preflight/preflight.d.ts +0 -10
- package/dist/src/preflight/preflight.js +0 -190
- package/dist/src/preflight/requirements.d.ts +0 -11
- package/dist/src/preflight/requirements.js +0 -231
- package/dist/src/ready/index.d.ts +0 -2
- package/dist/src/ready/index.js +0 -1
- package/dist/src/ready/ready.d.ts +0 -40
- package/dist/src/ready/ready.js +0 -201
- package/dist/src/security/index.d.ts +0 -3
- package/dist/src/security/index.js +0 -2
- package/dist/src/security/lock.d.ts +0 -9
- package/dist/src/security/lock.js +0 -127
- package/dist/src/security/redact.d.ts +0 -6
- package/dist/src/security/redact.js +0 -48
- package/dist/src/verification/index.d.ts +0 -2
- package/dist/src/verification/index.js +0 -1
- package/dist/src/verification/verify.d.ts +0 -33
- 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,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>;
|