@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
@@ -7,14 +7,6 @@ export interface LifecycleDispatchResult {
7
7
  result: ModuleOperationResult;
8
8
  observedEffects: string[];
9
9
  }
10
- export type LifecycleRunStatus = "EXECUTED" | "SKIP_UNSUPPORTED";
11
- export interface LifecycleRunResult {
12
- moduleRef: string;
13
- primitive: LifecyclePrimitive;
14
- status: LifecycleRunStatus;
15
- result: ModuleOperationResult | undefined;
16
- observedEffects: string[];
17
- }
18
10
  /**
19
11
  * Dispatches a single lifecycle primitive against one module through its
20
12
  * public deployment adapter. The descriptor is the source of truth for what is
@@ -23,25 +15,3 @@ export interface LifecycleRunResult {
23
15
  * runtime-validated against the Module Operation Result schema.
24
16
  */
25
17
  export declare function dispatchLifecycle(catalog: ModuleCatalog, module: ResolvedModule, primitive: LifecyclePrimitive): Promise<LifecycleDispatchResult>;
26
- /**
27
- * Starts a module set in forward dependency topological order, dispatching the
28
- * `start` primitive only to modules that declare it.
29
- */
30
- export declare function startModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
31
- /**
32
- * Stops a module set in reverse dependency topological order, dispatching the
33
- * `stop` primitive only to modules that declare it.
34
- */
35
- export declare function stopModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
36
- /**
37
- * Restarts a module set in forward dependency topological order, dispatching
38
- * `restart` only to modules that explicitly declare it. Dependencies are
39
- * settled before the modules that consume them.
40
- */
41
- export declare function restartModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
42
- /**
43
- * Queries current reality by dispatching the `status` primitive to every
44
- * module that declares it. Status is always read live from the adapter; no
45
- * persisted or cached value is substituted for current reality.
46
- */
47
- export declare function statusModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleRunResult[]>;
@@ -1,6 +1,5 @@
1
1
  import { moduleOperationResultSchema, } from "@tomflow/proflow-module-contract";
2
2
  import { PlatformError } from "../errors.js";
3
- import { buildDependencyGraph } from "../graph/graph.js";
4
3
  function isRecord(value) {
5
4
  return typeof value === "object" && value !== null;
6
5
  }
@@ -11,9 +10,6 @@ function isWrappedResult(value) {
11
10
  return isRecord(value) && "result" in value;
12
11
  }
13
12
  function moduleSource(module) {
14
- if (module.source.type === "registry") {
15
- throw new PlatformError("DESCRIPTOR_INVALID", `registry bootstrap target ${module.packageName} has no local lifecycle adapter`);
16
- }
17
13
  const source = {
18
14
  type: module.source.type,
19
15
  packageName: module.packageName,
@@ -75,119 +71,3 @@ export async function dispatchLifecycle(catalog, module, primitive) {
75
71
  observedEffects,
76
72
  };
77
73
  }
78
- async function runOne(catalog, module, primitive) {
79
- if (!module.lifecycle.includes(primitive)) {
80
- return {
81
- moduleRef: module.moduleRef,
82
- primitive,
83
- status: "SKIP_UNSUPPORTED",
84
- result: undefined,
85
- observedEffects: [],
86
- };
87
- }
88
- const dispatched = await dispatchLifecycle(catalog, module, primitive);
89
- return {
90
- moduleRef: dispatched.moduleRef,
91
- primitive,
92
- status: "EXECUTED",
93
- result: dispatched.result,
94
- observedEffects: dispatched.observedEffects,
95
- };
96
- }
97
- async function runInOrder(catalog, modules, order, primitive) {
98
- const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
99
- const results = [];
100
- for (const moduleRef of order) {
101
- const module = byRef.get(moduleRef);
102
- if (module === undefined)
103
- continue;
104
- results.push(await runOne(catalog, module, primitive));
105
- }
106
- return results;
107
- }
108
- /**
109
- * Starts a module set in forward dependency topological order, dispatching the
110
- * `start` primitive only to modules that declare it.
111
- */
112
- export async function startModules(catalog, modules) {
113
- const graph = buildDependencyGraph(modules);
114
- const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
115
- const resultByRef = new Map();
116
- const results = [];
117
- for (const moduleRef of graph.order) {
118
- const module = byRef.get(moduleRef);
119
- if (module === undefined)
120
- continue;
121
- if (!module.lifecycle.includes("start")) {
122
- const skipped = await runOne(catalog, module, "start");
123
- results.push(skipped);
124
- resultByRef.set(moduleRef, skipped);
125
- continue;
126
- }
127
- const blockingDependency = graph.edges
128
- .filter((edge) => edge.from === moduleRef)
129
- .map((edge) => edge.to)
130
- .find((dependencyRef) => {
131
- const dependencyModule = byRef.get(dependencyRef);
132
- if (!dependencyModule?.lifecycle.includes("start"))
133
- return false;
134
- const dependencyResult = resultByRef.get(dependencyRef);
135
- return dependencyResult?.result?.status !== "SUCCEEDED";
136
- });
137
- if (blockingDependency !== undefined) {
138
- const blocked = {
139
- moduleRef,
140
- primitive: "start",
141
- status: "EXECUTED",
142
- result: {
143
- contract: "deployment.result.v1",
144
- ok: false,
145
- status: "BLOCKED",
146
- moduleRef: module.moduleRef,
147
- moduleVersion: module.moduleVersion,
148
- error: {
149
- code: "COMMAND_FAILED",
150
- message: `dependency ${blockingDependency} did not start successfully; ${moduleRef} was not started`,
151
- retryable: true,
152
- },
153
- },
154
- observedEffects: [],
155
- };
156
- results.push(blocked);
157
- resultByRef.set(moduleRef, blocked);
158
- continue;
159
- }
160
- const result = await runOne(catalog, module, "start");
161
- results.push(result);
162
- resultByRef.set(moduleRef, result);
163
- }
164
- return results;
165
- }
166
- /**
167
- * Stops a module set in reverse dependency topological order, dispatching the
168
- * `stop` primitive only to modules that declare it.
169
- */
170
- export async function stopModules(catalog, modules) {
171
- const order = [...buildDependencyGraph(modules).order].reverse();
172
- return runInOrder(catalog, modules, order, "stop");
173
- }
174
- /**
175
- * Restarts a module set in forward dependency topological order, dispatching
176
- * `restart` only to modules that explicitly declare it. Dependencies are
177
- * settled before the modules that consume them.
178
- */
179
- export async function restartModules(catalog, modules) {
180
- return runInOrder(catalog, modules, buildDependencyGraph(modules).order, "restart");
181
- }
182
- /**
183
- * Queries current reality by dispatching the `status` primitive to every
184
- * module that declares it. Status is always read live from the adapter; no
185
- * persisted or cached value is substituted for current reality.
186
- */
187
- export async function statusModules(catalog, modules) {
188
- const results = [];
189
- for (const module of modules) {
190
- results.push(await runOne(catalog, module, "status"));
191
- }
192
- return results;
193
- }
@@ -1,3 +1,4 @@
1
- export type { LifecycleDispatchResult, LifecycleRunResult, LifecycleRunStatus, } from "./dispatch.ts";
2
- export { dispatchLifecycle, restartModules, startModules, statusModules, stopModules, } from "./dispatch.ts";
3
- export { managedServiceStatus, restartManagedService, startManagedService, stopManagedService, } from "./service-process.ts";
1
+ export type { LifecycleDispatchResult } from "./dispatch.ts";
2
+ export { dispatchLifecycle } from "./dispatch.ts";
3
+ export type { ThinLifecycleResult } from "./thin.ts";
4
+ export { observeStatuses, preflightAndStartModules, stopModulesThin, } from "./thin.ts";
@@ -1,2 +1,2 @@
1
- export { dispatchLifecycle, restartModules, startModules, statusModules, stopModules, } from "./dispatch.js";
2
- export { managedServiceStatus, restartManagedService, startManagedService, stopManagedService, } from "./service-process.js";
1
+ export { dispatchLifecycle } from "./dispatch.js";
2
+ export { observeStatuses, preflightAndStartModules, stopModulesThin, } from "./thin.js";
@@ -0,0 +1,11 @@
1
+ import type { ResolvedModule } from "../contracts.ts";
2
+ import type { ModuleCatalog } from "../modules.ts";
3
+ import { type LifecycleDispatchResult } from "./dispatch.ts";
4
+ export interface ThinLifecycleResult {
5
+ phase: "preflight" | "start" | "stop";
6
+ results: LifecycleDispatchResult[];
7
+ completed: boolean;
8
+ }
9
+ export declare function observeStatuses(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<LifecycleDispatchResult[]>;
10
+ export declare function preflightAndStartModules(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<ThinLifecycleResult>;
11
+ export declare function stopModulesThin(catalog: ModuleCatalog, modules: readonly ResolvedModule[]): Promise<ThinLifecycleResult>;
@@ -0,0 +1,68 @@
1
+ import { buildDependencyGraph } from "../graph/graph.js";
2
+ import { dispatchLifecycle } from "./dispatch.js";
3
+ function succeeded(result) {
4
+ return result.status === "SUCCEEDED";
5
+ }
6
+ async function dispatchIfSupported(catalog, module, primitive) {
7
+ if (!module.lifecycle.includes(primitive))
8
+ return undefined;
9
+ return dispatchLifecycle(catalog, module, primitive);
10
+ }
11
+ export async function observeStatuses(catalog, modules) {
12
+ const results = [];
13
+ for (const module of [...modules].sort((a, b) => a.moduleRef.localeCompare(b.moduleRef))) {
14
+ if (!module.lifecycle.includes("status"))
15
+ continue;
16
+ results.push(await dispatchLifecycle(catalog, module, "status"));
17
+ }
18
+ return results;
19
+ }
20
+ export async function preflightAndStartModules(catalog, modules) {
21
+ const graph = buildDependencyGraph(modules);
22
+ const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
23
+ const preflight = [];
24
+ for (const moduleRef of graph.order) {
25
+ const module = byRef.get(moduleRef);
26
+ if (module === undefined)
27
+ continue;
28
+ const result = await dispatchIfSupported(catalog, module, "preflight");
29
+ if (result === undefined)
30
+ continue;
31
+ preflight.push(result);
32
+ if (!succeeded(result.result)) {
33
+ return { phase: "preflight", results: preflight, completed: false };
34
+ }
35
+ }
36
+ const started = [];
37
+ for (const moduleRef of graph.order) {
38
+ const module = byRef.get(moduleRef);
39
+ if (module === undefined)
40
+ continue;
41
+ const result = await dispatchIfSupported(catalog, module, "start");
42
+ if (result === undefined)
43
+ continue;
44
+ started.push(result);
45
+ if (!succeeded(result.result)) {
46
+ return { phase: "start", results: started, completed: false };
47
+ }
48
+ }
49
+ return { phase: "start", results: started, completed: true };
50
+ }
51
+ export async function stopModulesThin(catalog, modules) {
52
+ const order = [...buildDependencyGraph(modules).order].reverse();
53
+ const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
54
+ const stopped = [];
55
+ for (const moduleRef of order) {
56
+ const module = byRef.get(moduleRef);
57
+ if (module === undefined)
58
+ continue;
59
+ const result = await dispatchIfSupported(catalog, module, "stop");
60
+ if (result === undefined)
61
+ continue;
62
+ stopped.push(result);
63
+ if (!succeeded(result.result)) {
64
+ return { phase: "stop", results: stopped, completed: false };
65
+ }
66
+ }
67
+ return { phase: "stop", results: stopped, completed: true };
68
+ }
@@ -2,20 +2,6 @@ export interface WorkspacePaths {
2
2
  root: string;
3
3
  proflow: string;
4
4
  config: string;
5
- data: string;
6
- logs: string;
7
- logsDeployment: string;
8
- runtime: string;
9
- cache: string;
10
- tmp: string;
11
- deployment: string;
12
- stateJson: string;
13
- plans: string;
14
- verification: string;
15
- generated: string;
16
- installMd: string;
17
5
  }
18
6
  export declare function workspacePaths(root: string): WorkspacePaths;
19
- export declare function ensureLayout(paths: WorkspacePaths): Promise<void>;
20
7
  export declare function atomicWrite(file: string, content: string): Promise<void>;
21
- export declare function readJson<T>(file: string): Promise<T | undefined>;
package/dist/src/paths.js CHANGED
@@ -3,54 +3,15 @@ import { mkdir, rename, writeFile } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  export function workspacePaths(root) {
5
5
  const proflow = join(root, ".proflow");
6
- const deployment = join(proflow, "deployment");
7
6
  return {
8
7
  root,
9
8
  proflow,
10
9
  config: join(proflow, "config"),
11
- data: join(proflow, "data"),
12
- logs: join(proflow, "logs"),
13
- logsDeployment: join(proflow, "logs", "deployment"),
14
- runtime: join(proflow, "runtime"),
15
- cache: join(proflow, "cache"),
16
- tmp: join(proflow, "tmp"),
17
- deployment,
18
- stateJson: join(deployment, "state.json"),
19
- plans: join(deployment, "plans"),
20
- verification: join(deployment, "verification"),
21
- generated: join(deployment, "generated"),
22
- installMd: join(deployment, "generated", "INSTALL.md"),
23
10
  };
24
11
  }
25
- export async function ensureLayout(paths) {
26
- for (const dir of [
27
- paths.config,
28
- paths.data,
29
- paths.logsDeployment,
30
- paths.runtime,
31
- paths.cache,
32
- paths.tmp,
33
- paths.plans,
34
- paths.verification,
35
- paths.generated,
36
- ]) {
37
- await mkdir(dir, { recursive: true });
38
- }
39
- }
40
- // Atomic write: bounded write to a temp sibling then rename into place.
41
12
  export async function atomicWrite(file, content) {
42
13
  await mkdir(dirname(file), { recursive: true });
43
14
  const tmp = `${file}.tmp-${randomBytes(6).toString("hex")}`;
44
15
  await writeFile(tmp, content, "utf8");
45
16
  await rename(tmp, file);
46
17
  }
47
- export async function readJson(file) {
48
- try {
49
- const { readFile } = await import("node:fs/promises");
50
- const raw = await readFile(file, "utf8");
51
- return JSON.parse(raw);
52
- }
53
- catch {
54
- return undefined;
55
- }
56
- }
@@ -3,10 +3,4 @@ export interface MaterializedConfig {
3
3
  publicValues: Record<string, string>;
4
4
  secretValues: Record<string, string>;
5
5
  }
6
- export interface ModuleConfig {
7
- moduleRef: string;
8
- values: Record<string, string>;
9
- secretRefs: readonly string[];
10
- }
11
- export declare function materializeConfig(paths: WorkspacePaths, config: ModuleConfig): Promise<void>;
12
6
  export declare function loadConfig(paths: WorkspacePaths, moduleRef: string): Promise<MaterializedConfig | undefined>;
@@ -1,7 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { PlatformError } from "../errors.js";
4
- import { writeJsonAtomic } from "./atomic.js";
5
4
  import { assertSafeFileName } from "./guards.js";
6
5
  function configFilePath(paths, moduleRef) {
7
6
  assertSafeFileName(moduleRef, "moduleRef");
@@ -43,19 +42,6 @@ async function readConfigValues(file, moduleRef, kind) {
43
42
  throw new PlatformError("CONFIG_INVALID", `${kind} config for ${moduleRef} is invalid JSON/config: ${error instanceof Error ? error.message : String(error)}`);
44
43
  }
45
44
  }
46
- // secretRef config values are opaque reference identities (e.g.
47
- // `secret://model-provider/default`), not raw secrets, so they materialize to
48
- // the public config file verbatim. A raw secret would go to the separate 0o600
49
- // secrets file — but v1 planning produces no raw secrets, so it stays empty and
50
- // must never hold a secretRef reference.
51
- export async function materializeConfig(paths, config) {
52
- const publicValues = {};
53
- for (const [key, value] of Object.entries(config.values)) {
54
- publicValues[key] = value;
55
- }
56
- await writeJsonAtomic(configFilePath(paths, config.moduleRef), publicValues, 0o644);
57
- await writeJsonAtomic(secretsFilePath(paths, config.moduleRef), {}, 0o600);
58
- }
59
45
  export async function loadConfig(paths, moduleRef) {
60
46
  const publicValues = await readConfigValues(configFilePath(paths, moduleRef), moduleRef, "public");
61
47
  const secretValues = await readConfigValues(secretsFilePath(paths, moduleRef), moduleRef, "secret");
@@ -1,7 +1 @@
1
- import type { DeploymentPlan, DeploymentState, LockRecord, VerificationRecord } from "../contracts.ts";
2
- export declare const DEPLOYMENT_STATE_CONTRACT = "proflow.deployment-state.v1";
3
1
  export declare function assertSafeFileName(name: string, kind: string): void;
4
- export declare function isDeploymentState(value: unknown): value is DeploymentState;
5
- export declare function isVerificationRecord(value: unknown): value is VerificationRecord;
6
- export declare function isDeploymentPlan(value: unknown): value is DeploymentPlan;
7
- export declare function isLockRecord(value: unknown): value is LockRecord;
@@ -1,121 +1,7 @@
1
1
  import { PlatformError } from "../errors.js";
2
- export const DEPLOYMENT_STATE_CONTRACT = "proflow.deployment-state.v1";
3
2
  const SAFE_FILE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
4
3
  export function assertSafeFileName(name, kind) {
5
4
  if (!SAFE_FILE_NAME.test(name)) {
6
5
  throw new PlatformError("INVALID_REQUEST", `invalid ${kind} name: ${name}`);
7
6
  }
8
7
  }
9
- function isRecord(value) {
10
- return typeof value === "object" && value !== null && !Array.isArray(value);
11
- }
12
- function isString(value) {
13
- return typeof value === "string";
14
- }
15
- function isStringArray(value) {
16
- return Array.isArray(value) && value.every(isString);
17
- }
18
- function isDeploymentIntent(value) {
19
- return (value === "install" ||
20
- value === "configure" ||
21
- value === "upgrade" ||
22
- value === "uninstall" ||
23
- value === "repair");
24
- }
25
- function isSelectedModuleFact(value) {
26
- return (isRecord(value) &&
27
- isString(value.moduleRef) &&
28
- isString(value.moduleVersion));
29
- }
30
- function isLastAppliedPlan(value) {
31
- return (isRecord(value) &&
32
- isString(value.planRef) &&
33
- isDeploymentIntent(value.intent) &&
34
- isString(value.appliedAt));
35
- }
36
- function isVerificationIndexEntry(value) {
37
- return (isRecord(value) && isString(value.moduleRef) && isString(value.latestRef));
38
- }
39
- function isPendingAction(value) {
40
- return (isRecord(value) &&
41
- isString(value.planRef) &&
42
- isString(value.stepRef) &&
43
- isString(value.moduleRef) &&
44
- isString(value.action) &&
45
- (value.description === undefined || isString(value.description)) &&
46
- isString(value.createdAt));
47
- }
48
- export function isDeploymentState(value) {
49
- if (!isRecord(value))
50
- return false;
51
- if (value.contract !== DEPLOYMENT_STATE_CONTRACT)
52
- return false;
53
- if (!Array.isArray(value.selectedModules))
54
- return false;
55
- if (!value.selectedModules.every(isSelectedModuleFact))
56
- return false;
57
- if (!Array.isArray(value.lastAppliedPlans))
58
- return false;
59
- if (!value.lastAppliedPlans.every(isLastAppliedPlan))
60
- return false;
61
- if (!Array.isArray(value.verificationIndex))
62
- return false;
63
- if (!value.verificationIndex.every(isVerificationIndexEntry))
64
- return false;
65
- if (!Array.isArray(value.pendingActions))
66
- return false;
67
- if (!value.pendingActions.every(isPendingAction))
68
- return false;
69
- return isString(value.updatedAt);
70
- }
71
- export function isVerificationRecord(value) {
72
- if (!isRecord(value))
73
- return false;
74
- if (!isString(value.verificationRef))
75
- return false;
76
- if (!isString(value.moduleRef))
77
- return false;
78
- if (!isString(value.moduleVersion))
79
- return false;
80
- if (value.resourceIdentity !== undefined && !isString(value.resourceIdentity))
81
- return false;
82
- if (value.resourceVersion !== undefined && !isString(value.resourceVersion))
83
- return false;
84
- if (value.result !== "PASS" && value.result !== "FAIL")
85
- return false;
86
- if (!isString(value.summary))
87
- return false;
88
- if (!isStringArray(value.evidenceRefs))
89
- return false;
90
- return isString(value.verifiedAt);
91
- }
92
- export function isDeploymentPlan(value) {
93
- if (!isRecord(value))
94
- return false;
95
- if (!isString(value.planRef))
96
- return false;
97
- if (!isDeploymentIntent(value.intent))
98
- return false;
99
- if (!Array.isArray(value.moduleTargets))
100
- return false;
101
- if (!Array.isArray(value.resolvedModules))
102
- return false;
103
- if (!Array.isArray(value.steps))
104
- return false;
105
- if (!Array.isArray(value.effects))
106
- return false;
107
- if (!Array.isArray(value.humanActions))
108
- return false;
109
- if (!Array.isArray(value.verification))
110
- return false;
111
- if (!isString(value.fingerprint))
112
- return false;
113
- return isString(value.createdAt);
114
- }
115
- export function isLockRecord(value) {
116
- return (isRecord(value) &&
117
- typeof value.pid === "number" &&
118
- isString(value.createdAt) &&
119
- isString(value.planRef) &&
120
- isString(value.workspaceFingerprint));
121
- }
@@ -1,6 +1,4 @@
1
- export type { MaterializedConfig, ModuleConfig } from "./config.ts";
2
- export { loadConfig, materializeConfig } from "./config.ts";
3
- export { writeInstallDoc } from "./generated.ts";
4
- export { listPlans, loadPlan, savePlan } from "./plans.ts";
5
- export { emptyDeploymentState, loadDeploymentState, saveDeploymentState, } from "./state.ts";
6
- export { appendVerification, loadLatestVerification, loadVerificationHistory, } from "./verification.ts";
1
+ export type { MaterializedConfig } from "./config.ts";
2
+ export { loadConfig } from "./config.ts";
3
+ export type { WorkspaceMetadata } from "./workspace-metadata.ts";
4
+ export { ensureWorkspaceMetadata } from "./workspace-metadata.ts";
@@ -1,5 +1,2 @@
1
- export { loadConfig, materializeConfig } from "./config.js";
2
- export { writeInstallDoc } from "./generated.js";
3
- export { listPlans, loadPlan, savePlan } from "./plans.js";
4
- export { emptyDeploymentState, loadDeploymentState, saveDeploymentState, } from "./state.js";
5
- export { appendVerification, loadLatestVerification, loadVerificationHistory, } from "./verification.js";
1
+ export { loadConfig } from "./config.js";
2
+ export { ensureWorkspaceMetadata } from "./workspace-metadata.js";
@@ -0,0 +1,7 @@
1
+ export interface WorkspaceMetadata {
2
+ contract: "proflow.workspace.v1";
3
+ workspaceInstanceId: string;
4
+ workspaceRoot: string;
5
+ createdAt: string;
6
+ }
7
+ export declare function ensureWorkspaceMetadata(workspaceRoot: string): Promise<WorkspaceMetadata>;
@@ -0,0 +1,39 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readFile, realpath } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { PlatformError } from "../errors.js";
5
+ import { atomicWrite } from "../paths.js";
6
+ export async function ensureWorkspaceMetadata(workspaceRoot) {
7
+ const canonicalRoot = await realpath(workspaceRoot);
8
+ const path = join(canonicalRoot, ".proflow", "workspace.json");
9
+ try {
10
+ const parsed = JSON.parse(await readFile(path, "utf8"));
11
+ if (typeof parsed !== "object" ||
12
+ parsed === null ||
13
+ Array.isArray(parsed) ||
14
+ Reflect.get(parsed, "contract") !== "proflow.workspace.v1" ||
15
+ typeof Reflect.get(parsed, "workspaceInstanceId") !== "string" ||
16
+ Reflect.get(parsed, "workspaceRoot") !== canonicalRoot ||
17
+ typeof Reflect.get(parsed, "createdAt") !== "string") {
18
+ throw new PlatformError("WORKSPACE_INSTANCE_INVALID", "existing .proflow/workspace.json does not match this Workspace");
19
+ }
20
+ return parsed;
21
+ }
22
+ catch (error) {
23
+ if (error instanceof PlatformError)
24
+ throw error;
25
+ if (typeof error !== "object" ||
26
+ error === null ||
27
+ Reflect.get(error, "code") !== "ENOENT") {
28
+ throw new PlatformError("WORKSPACE_INSTANCE_INVALID", `cannot read Workspace metadata: ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ }
31
+ const metadata = {
32
+ contract: "proflow.workspace.v1",
33
+ workspaceInstanceId: randomUUID(),
34
+ workspaceRoot: canonicalRoot,
35
+ createdAt: new Date().toISOString(),
36
+ };
37
+ await atomicWrite(path, `${JSON.stringify(metadata, null, 2)}\n`);
38
+ return metadata;
39
+ }
@@ -1,2 +1,2 @@
1
1
  export type { NpmCommandResult, NpmCommandRunner, RegistryDiscoveryResult, RegistryModuleCandidate, RegistryRejectedPackage, } from "./npm-registry.ts";
2
- export { discoverRegistryInstallClosure, discoverRegistryModules, loadRegistryModuleDescriptor, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.ts";
2
+ export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.ts";
@@ -1 +1 @@
1
- export { discoverRegistryInstallClosure, discoverRegistryModules, loadRegistryModuleDescriptor, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.js";
1
+ export { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, PRO_FLOW_SCOPE, resolveScopeRegistry, systemNpmRunner, } from "./npm-registry.js";
@@ -1,4 +1,3 @@
1
- import { type ModuleDescriptor, type ModuleInstallClass } from "@tomflow/proflow-module-contract";
2
1
  export declare const PRO_FLOW_SCOPE = "@tomflow";
3
2
  export declare const PRO_FLOW_PACKAGE_PREFIX = "@tomflow/proflow-";
4
3
  export interface NpmCommandResult {
@@ -12,10 +11,8 @@ export interface RegistryModuleCandidate {
12
11
  packageName: string;
13
12
  moduleVersion: string;
14
13
  description?: string;
15
- installClass: ModuleInstallClass;
16
14
  descriptor: string;
17
15
  manifest: "./proflow.module.json";
18
- installRequires: string[];
19
16
  nodeVersionRange?: string;
20
17
  registry: string;
21
18
  }
@@ -38,14 +35,3 @@ export declare function discoverRegistryModules(options: {
38
35
  runner?: NpmCommandRunner;
39
36
  nodeVersion?: string;
40
37
  }): Promise<RegistryDiscoveryResult>;
41
- export declare function loadRegistryModuleDescriptor(options: {
42
- workspaceRoot: string;
43
- candidate: RegistryModuleCandidate;
44
- runner?: NpmCommandRunner;
45
- }): Promise<ModuleDescriptor>;
46
- export declare function discoverRegistryInstallClosure(options: {
47
- workspaceRoot: string;
48
- packageName: string;
49
- runner?: NpmCommandRunner;
50
- nodeVersion?: string;
51
- }): Promise<RegistryDiscoveryResult>;