@tomflow/proflow-execution-browser-extension 0.1.2 → 0.1.4

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.
@@ -0,0 +1,33 @@
1
+ # execution-browser-extension configuration
2
+
3
+ Canonical public config: `.proflow/config/execution-browser-extension.json`
4
+
5
+ This file is Workspace-owned data. `platform uninstall` does not delete it. Values are JSON strings. Raw secrets must not be stored here; `secretRef` fields contain opaque references only.
6
+
7
+ ## Fields
8
+
9
+ | Key | Type | Required | Sensitive | Source | Meaning |
10
+ |---|---|---:|---:|---|---|
11
+ | `bridge.endpoint` | `url` | yes | no | User or owning external/runtime Module supplies the reachable endpoint URL. | Loopback Browser Reality Bridge endpoint |
12
+ | `bridge.token` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Browser Reality Bridge extension token |
13
+ | `taskApplication.endpoint` | `url` | yes | no | User or owning external/runtime Module supplies the reachable endpoint URL. | Loopback Platform Host Task application endpoint |
14
+ | `taskApplication.token` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Platform Host Task application token |
15
+ | `approvalApplication.endpoint` | `url` | yes | no | User or owning external/runtime Module supplies the reachable endpoint URL. | Loopback Platform Host Approval application endpoint |
16
+ | `approvalApplication.token` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Platform Host Approval application token |
17
+ | `verificationEvidenceFile` | `path` | yes | no | User or owning Module supplies an absolute/local path that exists on this Workspace. | JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs |
18
+ | `chromeRuntimeModuleRef` | `moduleRef` | no | no | Another installed ProFlow Module reference selected from `platform docs` / Module topology. | External resource module governing the Chrome runtime |
19
+ | `carrierModuleRef` | `moduleRef` | no | no | Another installed ProFlow Module reference selected from `platform docs` / Module topology. | External resource module governing the Custom GPT carrier |
20
+
21
+ ## Materialize
22
+
23
+ Create or update the canonical JSON object at:
24
+
25
+ `.proflow/config/execution-browser-extension.json`
26
+
27
+ Use only declared keys and string values. Do not create a second Platform configuration database.
28
+
29
+ The Browser Extension also requires a package-owned physical runtime config artifact. After the canonical Module config is present, run `proflow-execution-browser-extension materialize-config --workspace <path>`. This package-owned command writes the private runtime artifact under `.proflow/deployment/browser-extension/execution-browser-extension/`; `platform start` must not perform this materialization implicitly.
30
+
31
+ ## Base completion check
32
+
33
+ Run `platform modules`. This Module should no longer report required keys in `missingConfig`. `platform start` performs the authoritative Module-owned validation before starting anything.
@@ -3,7 +3,7 @@ export declare const behaviorAdapter: {
3
3
  result: {
4
4
  contract: "deployment.result.v1";
5
5
  moduleRef: "execution-browser-extension";
6
- moduleVersion: "0.1.2";
6
+ moduleVersion: "0.1.4";
7
7
  ok: boolean;
8
8
  status: string;
9
9
  };
@@ -13,7 +13,7 @@ export declare const behaviorAdapter: {
13
13
  result: {
14
14
  contract: "deployment.result.v1";
15
15
  moduleRef: "execution-browser-extension";
16
- moduleVersion: "0.1.2";
16
+ moduleVersion: "0.1.4";
17
17
  ok: boolean;
18
18
  status: string;
19
19
  };
@@ -23,12 +23,13 @@ export declare const behaviorAdapter: {
23
23
  result: {
24
24
  contract: "deployment.result.v1";
25
25
  moduleRef: "execution-browser-extension";
26
- moduleVersion: "0.1.2";
26
+ moduleVersion: "0.1.4";
27
27
  ok: boolean;
28
28
  status: string;
29
- actionRequired: {
30
- action: string;
31
- description: string;
29
+ data: {
30
+ configStatus: "INCOMPLETE" | "INVALID" | "READY";
31
+ missingConfig?: string[] | undefined;
32
+ runtimeStatus: "FAILED" | "RUNNING" | "STOPPED" | "UNKNOWN";
32
33
  };
33
34
  };
34
35
  observedEffects: never[];
@@ -37,7 +38,7 @@ export declare const behaviorAdapter: {
37
38
  result: {
38
39
  contract: "deployment.result.v1";
39
40
  moduleRef: "execution-browser-extension";
40
- moduleVersion: "0.1.2";
41
+ moduleVersion: "0.1.4";
41
42
  ok: boolean;
42
43
  status: string;
43
44
  checks: {
@@ -52,10 +53,25 @@ export declare const behaviorAdapter: {
52
53
  result: {
53
54
  contract: "deployment.result.v1";
54
55
  moduleRef: "execution-browser-extension";
55
- moduleVersion: "0.1.2";
56
+ moduleVersion: "0.1.4";
56
57
  ok: boolean;
57
58
  status: string;
58
59
  };
59
60
  observedEffects: never[];
60
61
  };
61
62
  };
63
+ export declare function browserExtensionLoadDir(workspaceRoot: string): string;
64
+ export declare function materializeProductionConfig(input: {
65
+ moduleRef: string;
66
+ config: Record<string, string>;
67
+ workspaceRoot: string;
68
+ }): Promise<{
69
+ loadDir: string;
70
+ }>;
71
+ export declare function createProductionBinding(input: {
72
+ moduleRef: string;
73
+ config: Record<string, string>;
74
+ workspaceRoot: string;
75
+ }): {
76
+ behaviorAdapter: Record<string, unknown>;
77
+ };
@@ -1,3 +1,7 @@
1
+ import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { observeDeclaredModuleStatus } from "@tomflow/proflow-module-contract";
1
5
  import { descriptor } from "./descriptor.js";
2
6
  const base = {
3
7
  contract: "deployment.result.v1",
@@ -16,12 +20,9 @@ export const behaviorAdapter = {
16
20
  status: () => ({
17
21
  result: {
18
22
  ...base,
19
- ok: false,
20
- status: "ACTION_REQUIRED",
21
- actionRequired: {
22
- action: "verify-real-carrier",
23
- description: "Load in real Chrome and collect ChatGPT E3/E4 evidence",
24
- },
23
+ ok: true,
24
+ status: "SUCCEEDED",
25
+ data: observeDeclaredModuleStatus(descriptor, undefined, "UNKNOWN"),
25
26
  },
26
27
  observedEffects: [],
27
28
  }),
@@ -45,3 +46,173 @@ export const behaviorAdapter = {
45
46
  observedEffects: [],
46
47
  }),
47
48
  };
49
+ function loopbackEndpoint(value, key) {
50
+ const url = new URL(value);
51
+ if (url.protocol !== "http:" ||
52
+ url.hostname !== "127.0.0.1" ||
53
+ url.pathname !== "/" ||
54
+ url.search !== "" ||
55
+ url.hash !== "") {
56
+ throw new Error(`${key} must be a loopback HTTP origin`);
57
+ }
58
+ return value.replace(/\/$/, "");
59
+ }
60
+ async function credential(file, key) {
61
+ const token = (await readFile(file, "utf8")).trim();
62
+ if (token.length < 32)
63
+ throw new Error(`${key} must contain at least 32 characters`);
64
+ return token;
65
+ }
66
+ function packageRoot() {
67
+ const candidate = dirname(dirname(fileURLToPath(import.meta.url)));
68
+ return basename(candidate) === "dist" ? dirname(candidate) : candidate;
69
+ }
70
+ export function browserExtensionLoadDir(workspaceRoot) {
71
+ return join(workspaceRoot, ".proflow", "deployment", "browser-extension", "execution-browser-extension");
72
+ }
73
+ export async function materializeProductionConfig(input) {
74
+ const required = [
75
+ "bridge.endpoint",
76
+ "bridge.token",
77
+ "taskApplication.endpoint",
78
+ "taskApplication.token",
79
+ "approvalApplication.endpoint",
80
+ "approvalApplication.token",
81
+ ];
82
+ for (const key of required) {
83
+ if (!input.config[key])
84
+ throw new Error(`missing required browser config ${key}`);
85
+ }
86
+ const runtimeConfig = {
87
+ proflowRuntimeBridge: {
88
+ endpoint: loopbackEndpoint(input.config["bridge.endpoint"] ?? "", "bridge.endpoint"),
89
+ token: await credential(input.config["bridge.token"] ?? "", "bridge.token"),
90
+ },
91
+ proflowTaskApplication: {
92
+ endpoint: loopbackEndpoint(input.config["taskApplication.endpoint"] ?? "", "taskApplication.endpoint"),
93
+ token: await credential(input.config["taskApplication.token"] ?? "", "taskApplication.token"),
94
+ },
95
+ proflowApprovalApplication: {
96
+ endpoint: loopbackEndpoint(input.config["approvalApplication.endpoint"] ?? "", "approvalApplication.endpoint"),
97
+ token: await credential(input.config["approvalApplication.token"] ?? "", "approvalApplication.token"),
98
+ },
99
+ };
100
+ const sourceRoot = packageRoot();
101
+ const loadDir = browserExtensionLoadDir(input.workspaceRoot);
102
+ await mkdir(join(loadDir, "dist"), { recursive: true });
103
+ await cp(join(sourceRoot, "dist", "extension"), join(loadDir, "dist", "extension"), {
104
+ recursive: true,
105
+ force: true,
106
+ });
107
+ await cp(join(sourceRoot, "extension"), join(loadDir, "extension"), {
108
+ recursive: true,
109
+ force: true,
110
+ });
111
+ await cp(join(sourceRoot, "manifest.json"), join(loadDir, "manifest.json"), {
112
+ force: true,
113
+ });
114
+ await writeFile(join(loadDir, "runtime-config.json"), `${JSON.stringify(runtimeConfig, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
115
+ return { loadDir };
116
+ }
117
+ async function readBrowserVerificationEvidence(file, expectedLoadDir) {
118
+ if (!file)
119
+ return undefined;
120
+ try {
121
+ const raw = JSON.parse(await readFile(file, "utf8"));
122
+ if (raw.contract !== "proflow.browser-extension-verification.v1" ||
123
+ raw.moduleVersion !== descriptor.moduleVersion ||
124
+ raw.loadDir !== expectedLoadDir ||
125
+ typeof raw.extensionId !== "string" ||
126
+ raw.extensionId.length < 16 ||
127
+ raw.serviceWorker !== "RUNNING" ||
128
+ typeof raw.observedAt !== "string" ||
129
+ Number.isNaN(Date.parse(raw.observedAt)))
130
+ return undefined;
131
+ return raw;
132
+ }
133
+ catch {
134
+ return undefined;
135
+ }
136
+ }
137
+ export function createProductionBinding(input) {
138
+ const loadDir = browserExtensionLoadDir(input.workspaceRoot);
139
+ const verificationEvidenceFile = input.config.verificationEvidenceFile;
140
+ const boundBase = {
141
+ contract: "deployment.result.v1",
142
+ moduleRef: descriptor.moduleRef,
143
+ moduleVersion: descriptor.moduleVersion,
144
+ };
145
+ const configured = async () => {
146
+ try {
147
+ const raw = JSON.parse(await readFile(join(loadDir, "runtime-config.json"), "utf8"));
148
+ return typeof raw === "object" && raw !== null;
149
+ }
150
+ catch {
151
+ return false;
152
+ }
153
+ };
154
+ return {
155
+ behaviorAdapter: {
156
+ ...behaviorAdapter,
157
+ preflight: async () => ({
158
+ result: (await configured())
159
+ ? { ...boundBase, ok: true, status: "SUCCEEDED" }
160
+ : {
161
+ ...boundBase,
162
+ ok: false,
163
+ status: "ACTION_REQUIRED",
164
+ actionRequired: {
165
+ action: "configure-browser-extension",
166
+ description: `Materialize Browser Extension runtime config before loading ${loadDir}`,
167
+ },
168
+ },
169
+ observedEffects: [],
170
+ }),
171
+ status: async () => {
172
+ const isConfigured = await configured();
173
+ const evidence = await readBrowserVerificationEvidence(verificationEvidenceFile, loadDir);
174
+ return {
175
+ result: {
176
+ ...boundBase,
177
+ ok: true,
178
+ status: "SUCCEEDED",
179
+ data: observeDeclaredModuleStatus(descriptor, input.config, evidence ? "RUNNING" : "STOPPED", isConfigured),
180
+ },
181
+ observedEffects: evidence
182
+ ? ["Observes real Chrome MV3 load evidence"]
183
+ : [],
184
+ };
185
+ },
186
+ verify: async () => {
187
+ const evidence = await readBrowserVerificationEvidence(verificationEvidenceFile, loadDir);
188
+ return {
189
+ result: (await configured()) && evidence
190
+ ? {
191
+ ...boundBase,
192
+ ok: true,
193
+ status: "SUCCEEDED",
194
+ checks: [
195
+ {
196
+ id: "real-carrier-e3-e4",
197
+ status: "PASS",
198
+ message: `Real Chrome loaded extension ${evidence.extensionId} from ${loadDir} and its MV3 Service Worker was observed running`,
199
+ },
200
+ ],
201
+ }
202
+ : {
203
+ ...boundBase,
204
+ ok: false,
205
+ status: "ACTION_REQUIRED",
206
+ actionRequired: {
207
+ action: "verify-real-chrome-extension",
208
+ description: `Load ${loadDir} in real Chrome and write verified evidence to ${verificationEvidenceFile ?? "the configured verificationEvidenceFile"}`,
209
+ },
210
+ },
211
+ observedEffects: evidence
212
+ ? ["Observes real Chrome MV3 load evidence"]
213
+ : [],
214
+ };
215
+ },
216
+ },
217
+ };
218
+ }
@@ -3,11 +3,10 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "execution-browser-extension";
5
5
  readonly packageName: "@tomflow/proflow-execution-browser-extension";
6
- readonly moduleVersion: "0.1.2";
6
+ readonly moduleVersion: "0.1.4";
7
7
  readonly kind: "browser-extension";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
10
- readonly installClass: "core";
11
10
  readonly identity: {
12
11
  readonly domain: "execution";
13
12
  readonly summary: "Execution-owned MV3 Browser executor, evidence provider and browser application surface.";
@@ -41,10 +40,10 @@ export declare const descriptor: {
41
40
  readonly description: "Loopback Browser Reality Bridge endpoint";
42
41
  }, {
43
42
  readonly key: "bridge.token";
44
- readonly type: "secretRef";
43
+ readonly type: "path";
45
44
  readonly required: true;
46
45
  readonly sensitive: true;
47
- readonly description: "Browser Reality Bridge extension token reference";
46
+ readonly description: "File containing the Browser Reality Bridge extension token";
48
47
  }, {
49
48
  readonly key: "taskApplication.endpoint";
50
49
  readonly type: "url";
@@ -52,10 +51,10 @@ export declare const descriptor: {
52
51
  readonly description: "Loopback Platform Host Task application endpoint";
53
52
  }, {
54
53
  readonly key: "taskApplication.token";
55
- readonly type: "secretRef";
54
+ readonly type: "path";
56
55
  readonly required: true;
57
56
  readonly sensitive: true;
58
- readonly description: "Platform Host Task application token reference";
57
+ readonly description: "File containing the Platform Host Task application token";
59
58
  }, {
60
59
  readonly key: "approvalApplication.endpoint";
61
60
  readonly type: "url";
@@ -63,10 +62,15 @@ export declare const descriptor: {
63
62
  readonly description: "Loopback Platform Host Approval application endpoint";
64
63
  }, {
65
64
  readonly key: "approvalApplication.token";
66
- readonly type: "secretRef";
65
+ readonly type: "path";
67
66
  readonly required: true;
68
67
  readonly sensitive: true;
69
- readonly description: "Platform Host Approval application token reference";
68
+ readonly description: "File containing the Platform Host Approval application token";
69
+ }, {
70
+ readonly key: "verificationEvidenceFile";
71
+ readonly type: "path";
72
+ readonly required: true;
73
+ readonly description: "JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs";
70
74
  }, {
71
75
  readonly key: "chromeRuntimeModuleRef";
72
76
  readonly type: "moduleRef";
@@ -99,5 +103,9 @@ export declare const descriptor: {
99
103
  readonly id: "overview";
100
104
  readonly path: "./README.md";
101
105
  readonly description: "Package-owned module overview";
106
+ }, {
107
+ readonly id: "configuration";
108
+ readonly path: "./CONFIGURATION.md";
109
+ readonly description: "Module configuration fields, sources and materialization instructions";
102
110
  }];
103
111
  };
@@ -3,23 +3,40 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "execution-browser-extension",
5
5
  packageName: "@tomflow/proflow-execution-browser-extension",
6
- moduleVersion: "0.1.2",
6
+ moduleVersion: "0.1.4",
7
7
  kind: "browser-extension",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
10
- installClass: "core",
11
10
  identity: {
12
11
  domain: "execution",
13
12
  summary: "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
14
13
  },
15
- provides: [{ contractRef: "execution-browser-executor", version: "1.0.0" }],
14
+ provides: [
15
+ {
16
+ contractRef: "execution-browser-executor",
17
+ version: "1.0.0",
18
+ },
19
+ ],
16
20
  requires: [
17
- { contractRef: "execution", versionRange: ">=1.0.0 <2.0.0" },
18
- { contractRef: "task-orchestration", versionRange: ">=1.0.0 <2.0.0" },
19
- { contractRef: "agent-runtime", versionRange: ">=1.0.0 <2.0.0" },
21
+ {
22
+ contractRef: "execution",
23
+ versionRange: ">=1.0.0 <2.0.0",
24
+ },
25
+ {
26
+ contractRef: "task-orchestration",
27
+ versionRange: ">=1.0.0 <2.0.0",
28
+ },
29
+ {
30
+ contractRef: "agent-runtime",
31
+ versionRange: ">=1.0.0 <2.0.0",
32
+ },
20
33
  ],
21
34
  requirements: [
22
- { kind: "runtime", runtime: "browser", versionRange: ">=1" },
35
+ {
36
+ kind: "runtime",
37
+ runtime: "browser",
38
+ versionRange: ">=1",
39
+ },
23
40
  {
24
41
  kind: "human",
25
42
  action: "Load and verify the unpacked MV3 extension in the real Chrome profile",
@@ -34,10 +51,10 @@ export const descriptor = {
34
51
  },
35
52
  {
36
53
  key: "bridge.token",
37
- type: "secretRef",
54
+ type: "path",
38
55
  required: true,
39
56
  sensitive: true,
40
- description: "Browser Reality Bridge extension token reference",
57
+ description: "File containing the Browser Reality Bridge extension token",
41
58
  },
42
59
  {
43
60
  key: "taskApplication.endpoint",
@@ -47,10 +64,10 @@ export const descriptor = {
47
64
  },
48
65
  {
49
66
  key: "taskApplication.token",
50
- type: "secretRef",
67
+ type: "path",
51
68
  required: true,
52
69
  sensitive: true,
53
- description: "Platform Host Task application token reference",
70
+ description: "File containing the Platform Host Task application token",
54
71
  },
55
72
  {
56
73
  key: "approvalApplication.endpoint",
@@ -60,10 +77,16 @@ export const descriptor = {
60
77
  },
61
78
  {
62
79
  key: "approvalApplication.token",
63
- type: "secretRef",
80
+ type: "path",
64
81
  required: true,
65
82
  sensitive: true,
66
- description: "Platform Host Approval application token reference",
83
+ description: "File containing the Platform Host Approval application token",
84
+ },
85
+ {
86
+ key: "verificationEvidenceFile",
87
+ type: "path",
88
+ required: true,
89
+ description: "JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs",
67
90
  },
68
91
  {
69
92
  key: "chromeRuntimeModuleRef",
@@ -105,5 +128,10 @@ export const descriptor = {
105
128
  path: "./README.md",
106
129
  description: "Package-owned module overview",
107
130
  },
131
+ {
132
+ id: "configuration",
133
+ path: "./CONFIGURATION.md",
134
+ description: "Module configuration fields, sources and materialization instructions",
135
+ },
108
136
  ],
109
137
  };