@tomflow/proflow-execution-browser-extension 0.1.4 → 0.1.5
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/DOCS.md +29 -0
- package/SETUP.md +7 -0
- package/dist/deployment/adapter.d.ts +102 -49
- package/dist/deployment/adapter.js +244 -161
- package/dist/deployment/descriptor.d.ts +7 -72
- package/dist/deployment/descriptor.js +7 -87
- package/manifest.json +1 -1
- package/package.json +7 -6
- package/proflow.module.json +7 -87
- package/CONFIGURATION.md +0 -33
package/DOCS.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @tomflow/proflow-execution-browser-extension — Module Docs
|
|
2
|
+
|
|
3
|
+
Module ref: `execution-browser-extension`
|
|
4
|
+
Domain: `execution`
|
|
5
|
+
Kind: `browser-extension`
|
|
6
|
+
|
|
7
|
+
Execution-owned MV3 Browser executor, evidence provider and browser application surface.
|
|
8
|
+
|
|
9
|
+
## Standard management surface
|
|
10
|
+
|
|
11
|
+
`install / uninstall / status / setup / docs / start / stop`
|
|
12
|
+
|
|
13
|
+
## Provides
|
|
14
|
+
|
|
15
|
+
- `execution-browser-executor` `1.0.0`
|
|
16
|
+
|
|
17
|
+
## Requires
|
|
18
|
+
|
|
19
|
+
- `execution` `>=1.0.0 <2.0.0`
|
|
20
|
+
- `task-orchestration` `>=1.0.0 <2.0.0`
|
|
21
|
+
- `agent-runtime` `>=1.0.0 <2.0.0`
|
|
22
|
+
|
|
23
|
+
## Public setup inputs
|
|
24
|
+
|
|
25
|
+
- None. Deterministic/private values and cross-Module shared facts are not public configuration.
|
|
26
|
+
|
|
27
|
+
## Ownership boundary
|
|
28
|
+
|
|
29
|
+
Module business APIs and any module-specific extra commands remain package-owned. Platform does not proxy or interpret them. Current human/external preparation is documented in `SETUP.md`.
|
package/SETUP.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @tomflow/proflow-execution-browser-extension — Module Setup
|
|
2
|
+
|
|
3
|
+
After Module.install materializes the deployment directory and deterministic local configuration, load the unpacked extension in Chrome when requested. Confirm the real extension Service Worker is running, then rerun Module.setup so it can re-observe Chrome reality and record evidence. Endpoints, tokens and evidence paths are not user configuration.
|
|
4
|
+
|
|
5
|
+
## Completion
|
|
6
|
+
|
|
7
|
+
Setup is complete only when the Module's own `status` reports `setupStatus=READY`. Re-running setup must re-observe reality; it must not resume from a blind historical step index.
|
|
@@ -1,77 +1,130 @@
|
|
|
1
|
+
import { type ModuleCommandContext } from "@tomflow/proflow-module-contract";
|
|
2
|
+
export declare function browserExtensionLoadDir(workspaceRoot: string): string;
|
|
3
|
+
export declare function materializeProductionConfig(input: {
|
|
4
|
+
moduleRef: string;
|
|
5
|
+
config: Record<string, string>;
|
|
6
|
+
workspaceRoot: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
loadDir: string;
|
|
9
|
+
}>;
|
|
1
10
|
export declare const behaviorAdapter: {
|
|
2
|
-
readonly
|
|
11
|
+
readonly install: (context: ModuleCommandContext) => Promise<{
|
|
3
12
|
result: {
|
|
4
13
|
contract: "deployment.result.v1";
|
|
14
|
+
ok: true;
|
|
15
|
+
status: "SUCCEEDED";
|
|
5
16
|
moduleRef: "execution-browser-extension";
|
|
6
|
-
moduleVersion: "0.1.
|
|
7
|
-
|
|
8
|
-
|
|
17
|
+
moduleVersion: "0.1.5";
|
|
18
|
+
data: {
|
|
19
|
+
loadDir: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
observedEffects: string[];
|
|
23
|
+
}>;
|
|
24
|
+
readonly uninstall: (_context: ModuleCommandContext) => Promise<{
|
|
25
|
+
result: {
|
|
26
|
+
readonly contract: "deployment.result.v1";
|
|
27
|
+
readonly ok: true;
|
|
28
|
+
readonly status: "SUCCEEDED";
|
|
29
|
+
readonly moduleRef: "execution-browser-extension";
|
|
30
|
+
readonly moduleVersion: "0.1.5";
|
|
9
31
|
};
|
|
10
32
|
observedEffects: never[];
|
|
11
|
-
}
|
|
12
|
-
readonly
|
|
33
|
+
}>;
|
|
34
|
+
readonly status: (context: ModuleCommandContext) => Promise<{
|
|
13
35
|
result: {
|
|
14
36
|
contract: "deployment.result.v1";
|
|
37
|
+
ok: true;
|
|
38
|
+
status: "SUCCEEDED";
|
|
15
39
|
moduleRef: "execution-browser-extension";
|
|
16
|
-
moduleVersion: "0.1.
|
|
17
|
-
|
|
18
|
-
|
|
40
|
+
moduleVersion: "0.1.5";
|
|
41
|
+
data: {
|
|
42
|
+
setupStatus: "ACTION_REQUIRED" | "READY";
|
|
43
|
+
runtimeStatus: "RUNNING" | "STOPPED";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
observedEffects: string[];
|
|
47
|
+
}>;
|
|
48
|
+
readonly setup: (context: ModuleCommandContext) => Promise<{
|
|
49
|
+
result: {
|
|
50
|
+
contract: "deployment.result.v1";
|
|
51
|
+
moduleRef: "execution-browser-extension";
|
|
52
|
+
moduleVersion: "0.1.5";
|
|
53
|
+
ok: false;
|
|
54
|
+
status: "FAILED";
|
|
55
|
+
error: {
|
|
56
|
+
code: "SETUP_FAILED" | "START_FAILED";
|
|
57
|
+
message: string;
|
|
58
|
+
retryable: boolean;
|
|
59
|
+
};
|
|
19
60
|
};
|
|
20
61
|
observedEffects: never[];
|
|
21
|
-
}
|
|
22
|
-
readonly status: () => {
|
|
62
|
+
} | {
|
|
23
63
|
result: {
|
|
24
64
|
contract: "deployment.result.v1";
|
|
25
65
|
moduleRef: "execution-browser-extension";
|
|
26
|
-
moduleVersion: "0.1.
|
|
27
|
-
ok:
|
|
28
|
-
status:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
runtimeStatus: "FAILED" | "RUNNING" | "STOPPED" | "UNKNOWN";
|
|
66
|
+
moduleVersion: "0.1.5";
|
|
67
|
+
ok: false;
|
|
68
|
+
status: "ACTION_REQUIRED";
|
|
69
|
+
actionRequired: {
|
|
70
|
+
action: string;
|
|
71
|
+
description: string;
|
|
33
72
|
};
|
|
34
73
|
};
|
|
35
74
|
observedEffects: never[];
|
|
36
|
-
}
|
|
37
|
-
|
|
75
|
+
} | {
|
|
76
|
+
result: {
|
|
77
|
+
readonly contract: "deployment.result.v1";
|
|
78
|
+
readonly ok: true;
|
|
79
|
+
readonly status: "SUCCEEDED";
|
|
80
|
+
readonly moduleRef: "execution-browser-extension";
|
|
81
|
+
readonly moduleVersion: "0.1.5";
|
|
82
|
+
};
|
|
83
|
+
observedEffects: string[];
|
|
84
|
+
}>;
|
|
85
|
+
readonly docs: (_context: ModuleCommandContext) => Promise<{
|
|
38
86
|
result: {
|
|
39
87
|
contract: "deployment.result.v1";
|
|
88
|
+
ok: true;
|
|
89
|
+
status: "SUCCEEDED";
|
|
40
90
|
moduleRef: "execution-browser-extension";
|
|
41
|
-
moduleVersion: "0.1.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
status: string;
|
|
47
|
-
message: string;
|
|
48
|
-
}[];
|
|
91
|
+
moduleVersion: "0.1.5";
|
|
92
|
+
data: {
|
|
93
|
+
docs: string;
|
|
94
|
+
setup: string;
|
|
95
|
+
};
|
|
49
96
|
};
|
|
50
97
|
observedEffects: never[];
|
|
51
|
-
}
|
|
52
|
-
readonly
|
|
98
|
+
}>;
|
|
99
|
+
readonly start: (context: ModuleCommandContext) => Promise<{
|
|
53
100
|
result: {
|
|
101
|
+
readonly contract: "deployment.result.v1";
|
|
102
|
+
readonly ok: true;
|
|
103
|
+
readonly status: "SUCCEEDED";
|
|
104
|
+
readonly moduleRef: "execution-browser-extension";
|
|
105
|
+
readonly moduleVersion: "0.1.5";
|
|
106
|
+
} | {
|
|
54
107
|
contract: "deployment.result.v1";
|
|
55
108
|
moduleRef: "execution-browser-extension";
|
|
56
|
-
moduleVersion: "0.1.
|
|
57
|
-
ok:
|
|
58
|
-
status:
|
|
109
|
+
moduleVersion: "0.1.5";
|
|
110
|
+
ok: false;
|
|
111
|
+
status: "FAILED";
|
|
112
|
+
error: {
|
|
113
|
+
code: "SETUP_FAILED" | "START_FAILED";
|
|
114
|
+
message: string;
|
|
115
|
+
retryable: boolean;
|
|
116
|
+
};
|
|
59
117
|
};
|
|
60
118
|
observedEffects: never[];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
moduleRef: string;
|
|
73
|
-
config: Record<string, string>;
|
|
74
|
-
workspaceRoot: string;
|
|
75
|
-
}): {
|
|
76
|
-
behaviorAdapter: Record<string, unknown>;
|
|
119
|
+
}>;
|
|
120
|
+
readonly stop: (_context: ModuleCommandContext) => Promise<{
|
|
121
|
+
result: {
|
|
122
|
+
readonly contract: "deployment.result.v1";
|
|
123
|
+
readonly ok: true;
|
|
124
|
+
readonly status: "SUCCEEDED";
|
|
125
|
+
readonly moduleRef: "execution-browser-extension";
|
|
126
|
+
readonly moduleVersion: "0.1.5";
|
|
127
|
+
};
|
|
128
|
+
observedEffects: never[];
|
|
129
|
+
}>;
|
|
77
130
|
};
|
|
@@ -1,76 +1,46 @@
|
|
|
1
1
|
import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { basename, dirname, join } from "node:path";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import {
|
|
4
|
+
import { deterministicLoopbackPort, ensureModuleSecretFile, moduleWorkspaceStateDirectory, readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
|
|
5
5
|
import { descriptor } from "./descriptor.js";
|
|
6
6
|
const base = {
|
|
7
7
|
contract: "deployment.result.v1",
|
|
8
|
+
ok: true,
|
|
9
|
+
status: "SUCCEEDED",
|
|
8
10
|
moduleRef: descriptor.moduleRef,
|
|
9
11
|
moduleVersion: descriptor.moduleVersion,
|
|
10
12
|
};
|
|
11
|
-
|
|
12
|
-
describe: () => ({
|
|
13
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
14
|
-
observedEffects: [],
|
|
15
|
-
}),
|
|
16
|
-
preflight: () => ({
|
|
17
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
18
|
-
observedEffects: [],
|
|
19
|
-
}),
|
|
20
|
-
status: () => ({
|
|
21
|
-
result: {
|
|
22
|
-
...base,
|
|
23
|
-
ok: true,
|
|
24
|
-
status: "SUCCEEDED",
|
|
25
|
-
data: observeDeclaredModuleStatus(descriptor, undefined, "UNKNOWN"),
|
|
26
|
-
},
|
|
27
|
-
observedEffects: [],
|
|
28
|
-
}),
|
|
29
|
-
verify: () => ({
|
|
30
|
-
result: {
|
|
31
|
-
...base,
|
|
32
|
-
ok: true,
|
|
33
|
-
status: "SUCCEEDED",
|
|
34
|
-
checks: [
|
|
35
|
-
{
|
|
36
|
-
id: "extension-package",
|
|
37
|
-
status: "PASS",
|
|
38
|
-
message: "The MV3 package is structurally verified; real Carrier readiness remains ACTION_REQUIRED in status",
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
observedEffects: [],
|
|
43
|
-
}),
|
|
44
|
-
doctor: () => ({
|
|
45
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
46
|
-
observedEffects: [],
|
|
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
|
-
}
|
|
13
|
+
const factString = (facts, name) => (typeof facts?.[name] === "string" ? String(facts[name]) : undefined);
|
|
66
14
|
function packageRoot() {
|
|
67
15
|
const candidate = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
68
16
|
return basename(candidate) === "dist" ? dirname(candidate) : candidate;
|
|
69
17
|
}
|
|
70
18
|
export function browserExtensionLoadDir(workspaceRoot) {
|
|
71
|
-
return join(workspaceRoot, ".proflow", "deployment", "browser-extension", "execution-browser-extension");
|
|
19
|
+
return join(resolve(workspaceRoot), ".proflow", "deployment", "browser-extension", "execution-browser-extension");
|
|
20
|
+
}
|
|
21
|
+
const stateDir = (context) => moduleWorkspaceStateDirectory(context, descriptor.moduleRef);
|
|
22
|
+
const setupFile = (context) => join(stateDir(context), "setup.json");
|
|
23
|
+
const verificationFile = (context) => join(stateDir(context), "verification.json");
|
|
24
|
+
const executorConfigFile = (context) => join(stateDir(context), "browser-executor.json");
|
|
25
|
+
async function credential(file) {
|
|
26
|
+
const value = (await readFile(file, "utf8")).trim();
|
|
27
|
+
if (value.length < 32)
|
|
28
|
+
throw new Error(`credential ${file} is invalid`);
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function loopbackEndpoint(value, name) {
|
|
32
|
+
const url = new URL(value);
|
|
33
|
+
if (url.protocol !== "http:" ||
|
|
34
|
+
url.hostname !== "127.0.0.1" ||
|
|
35
|
+
url.pathname !== "/" ||
|
|
36
|
+
url.search ||
|
|
37
|
+
url.hash)
|
|
38
|
+
throw new Error(`${name} must be a loopback HTTP origin`);
|
|
39
|
+
return value.replace(/\/$/, "");
|
|
72
40
|
}
|
|
73
41
|
export async function materializeProductionConfig(input) {
|
|
42
|
+
const context = { workspaceRoot: input.workspaceRoot };
|
|
43
|
+
const loadDir = await installPackage(context);
|
|
74
44
|
const required = [
|
|
75
45
|
"bridge.endpoint",
|
|
76
46
|
"bridge.token",
|
|
@@ -79,31 +49,31 @@ export async function materializeProductionConfig(input) {
|
|
|
79
49
|
"approvalApplication.endpoint",
|
|
80
50
|
"approvalApplication.token",
|
|
81
51
|
];
|
|
82
|
-
for (const
|
|
83
|
-
if (!input.config[
|
|
84
|
-
throw new Error(`missing required browser config ${
|
|
85
|
-
}
|
|
52
|
+
for (const name of required)
|
|
53
|
+
if (!input.config[name])
|
|
54
|
+
throw new Error(`missing required browser config ${name}`);
|
|
86
55
|
const runtimeConfig = {
|
|
87
56
|
proflowRuntimeBridge: {
|
|
88
57
|
endpoint: loopbackEndpoint(input.config["bridge.endpoint"] ?? "", "bridge.endpoint"),
|
|
89
|
-
token: await credential(input.config["bridge.token"] ?? ""
|
|
58
|
+
token: await credential(input.config["bridge.token"] ?? ""),
|
|
90
59
|
},
|
|
91
60
|
proflowTaskApplication: {
|
|
92
61
|
endpoint: loopbackEndpoint(input.config["taskApplication.endpoint"] ?? "", "taskApplication.endpoint"),
|
|
93
|
-
token: await credential(input.config["taskApplication.token"] ?? ""
|
|
62
|
+
token: await credential(input.config["taskApplication.token"] ?? ""),
|
|
94
63
|
},
|
|
95
64
|
proflowApprovalApplication: {
|
|
96
65
|
endpoint: loopbackEndpoint(input.config["approvalApplication.endpoint"] ?? "", "approvalApplication.endpoint"),
|
|
97
|
-
token: await credential(input.config["approvalApplication.token"] ?? ""
|
|
66
|
+
token: await credential(input.config["approvalApplication.token"] ?? ""),
|
|
98
67
|
},
|
|
99
68
|
};
|
|
69
|
+
await writeFile(join(loadDir, "runtime-config.json"), `${JSON.stringify(runtimeConfig, null, 2)}\n`, { mode: 0o600 });
|
|
70
|
+
return { loadDir };
|
|
71
|
+
}
|
|
72
|
+
async function installPackage(context) {
|
|
100
73
|
const sourceRoot = packageRoot();
|
|
101
|
-
const loadDir = browserExtensionLoadDir(
|
|
74
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
102
75
|
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
|
-
});
|
|
76
|
+
await cp(join(sourceRoot, "dist", "extension"), join(loadDir, "dist", "extension"), { recursive: true, force: true });
|
|
107
77
|
await cp(join(sourceRoot, "extension"), join(loadDir, "extension"), {
|
|
108
78
|
recursive: true,
|
|
109
79
|
force: true,
|
|
@@ -111,108 +81,221 @@ export async function materializeProductionConfig(input) {
|
|
|
111
81
|
await cp(join(sourceRoot, "manifest.json"), join(loadDir, "manifest.json"), {
|
|
112
82
|
force: true,
|
|
113
83
|
});
|
|
114
|
-
|
|
115
|
-
return { loadDir };
|
|
84
|
+
return loadDir;
|
|
116
85
|
}
|
|
117
|
-
async function
|
|
118
|
-
|
|
86
|
+
async function readSetup(context) {
|
|
87
|
+
try {
|
|
88
|
+
const raw = JSON.parse(await readFile(setupFile(context), "utf8"));
|
|
89
|
+
return typeof raw.extensionId === "string" &&
|
|
90
|
+
/^[a-z]{32}$/.test(raw.extensionId)
|
|
91
|
+
? raw
|
|
92
|
+
: undefined;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
119
95
|
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function readEvidence(context, loadDir) {
|
|
120
99
|
try {
|
|
121
|
-
const raw = JSON.parse(await readFile(
|
|
122
|
-
|
|
123
|
-
raw.moduleVersion
|
|
124
|
-
raw.loadDir
|
|
125
|
-
typeof raw.extensionId
|
|
126
|
-
raw.extensionId
|
|
127
|
-
raw.serviceWorker
|
|
128
|
-
typeof raw.observedAt
|
|
129
|
-
Number.isNaN(Date.parse(raw.observedAt))
|
|
130
|
-
|
|
131
|
-
|
|
100
|
+
const raw = JSON.parse(await readFile(verificationFile(context), "utf8"));
|
|
101
|
+
return raw.contract === "proflow.browser-extension-verification.v1" &&
|
|
102
|
+
raw.moduleVersion === descriptor.moduleVersion &&
|
|
103
|
+
raw.loadDir === loadDir &&
|
|
104
|
+
typeof raw.extensionId === "string" &&
|
|
105
|
+
/^[a-z]{32}$/.test(raw.extensionId) &&
|
|
106
|
+
raw.serviceWorker === "RUNNING" &&
|
|
107
|
+
typeof raw.observedAt === "string" &&
|
|
108
|
+
!Number.isNaN(Date.parse(raw.observedAt))
|
|
109
|
+
? raw
|
|
110
|
+
: undefined;
|
|
132
111
|
}
|
|
133
112
|
catch {
|
|
134
113
|
return undefined;
|
|
135
114
|
}
|
|
136
115
|
}
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
116
|
+
function input(context) {
|
|
117
|
+
const value = context.input;
|
|
118
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
119
|
+
return {};
|
|
120
|
+
const extensionId = Reflect.get(value, "extensionId"), serviceWorker = Reflect.get(value, "serviceWorker"), observedAt = Reflect.get(value, "observedAt");
|
|
121
|
+
return {
|
|
122
|
+
...(typeof extensionId === "string" ? { extensionId } : {}),
|
|
123
|
+
...(serviceWorker === "RUNNING"
|
|
124
|
+
? { serviceWorker: "RUNNING" }
|
|
125
|
+
: {}),
|
|
126
|
+
...(typeof observedAt === "string" ? { observedAt } : {}),
|
|
144
127
|
};
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
128
|
+
}
|
|
129
|
+
async function ownFacts(context) {
|
|
130
|
+
await mkdir(stateDir(context), { recursive: true, mode: 0o700 });
|
|
131
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
132
|
+
const bridgeTokenFile = await ensureModuleSecretFile(context, descriptor.moduleRef, "bridge");
|
|
133
|
+
const bridgePort = deterministicLoopbackPort(context, descriptor.moduleRef, "bridge");
|
|
134
|
+
const facts = {
|
|
135
|
+
loadDir,
|
|
136
|
+
bridgeTokenFile,
|
|
137
|
+
bridgeEndpoint: `http://127.0.0.1:${bridgePort}`,
|
|
138
|
+
verificationEvidenceFile: verificationFile(context),
|
|
153
139
|
};
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
140
|
+
const setup = await readSetup(context);
|
|
141
|
+
if (setup)
|
|
142
|
+
facts.extensionId = setup.extensionId;
|
|
143
|
+
try {
|
|
144
|
+
await readFile(executorConfigFile(context), "utf8");
|
|
145
|
+
facts.browserExecutorConfigPath = executorConfigFile(context);
|
|
146
|
+
}
|
|
147
|
+
catch { }
|
|
148
|
+
await writeModuleSharedFacts(context, descriptor.moduleRef, facts);
|
|
149
|
+
return facts;
|
|
150
|
+
}
|
|
151
|
+
async function materialize(context, setup) {
|
|
152
|
+
const host = await readModuleSharedFacts(context, "platform-host");
|
|
153
|
+
const endpoint = factString(host, "endpoint"), taskTokenFile = factString(host, "taskApplicationTokenFile"), approvalTokenFile = factString(host, "approvalApplicationTokenFile");
|
|
154
|
+
if (!endpoint || !taskTokenFile || !approvalTokenFile)
|
|
155
|
+
throw new Error("platform-host application shared facts are unavailable");
|
|
156
|
+
const facts = await ownFacts(context);
|
|
157
|
+
const loadDir = String(facts.loadDir);
|
|
158
|
+
const bridgeTokenFile = String(facts.bridgeTokenFile);
|
|
159
|
+
const bridgeEndpoint = String(facts.bridgeEndpoint);
|
|
160
|
+
const runtimeConfig = {
|
|
161
|
+
proflowRuntimeBridge: {
|
|
162
|
+
endpoint: bridgeEndpoint,
|
|
163
|
+
token: await credential(bridgeTokenFile),
|
|
164
|
+
},
|
|
165
|
+
proflowTaskApplication: {
|
|
166
|
+
endpoint,
|
|
167
|
+
token: await credential(taskTokenFile),
|
|
168
|
+
},
|
|
169
|
+
proflowApprovalApplication: {
|
|
170
|
+
endpoint,
|
|
171
|
+
token: await credential(approvalTokenFile),
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
await writeFile(join(loadDir, "runtime-config.json"), `${JSON.stringify(runtimeConfig, null, 2)}\n`, { mode: 0o600 });
|
|
175
|
+
await writeFile(executorConfigFile(context), `${JSON.stringify({ platformHost: { endpoint, tokenFile: taskTokenFile }, bridge: { extensionId: setup.extensionId, tokenFile: bridgeTokenFile, host: "127.0.0.1", port: Number(new URL(bridgeEndpoint).port) } }, null, 2)}\n`, { mode: 0o600 });
|
|
176
|
+
await writeModuleSharedFacts(context, descriptor.moduleRef, {
|
|
177
|
+
...facts,
|
|
178
|
+
extensionId: setup.extensionId,
|
|
179
|
+
browserExecutorConfigPath: executorConfigFile(context),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const failed = (code, message, retryable = true) => ({
|
|
183
|
+
...base,
|
|
184
|
+
ok: false,
|
|
185
|
+
status: "FAILED",
|
|
186
|
+
error: { code, message, retryable },
|
|
187
|
+
});
|
|
188
|
+
export const behaviorAdapter = {
|
|
189
|
+
install: async (context) => {
|
|
190
|
+
const loadDir = await installPackage(context);
|
|
191
|
+
return {
|
|
192
|
+
result: { ...base, data: { ...(await ownFacts(context)), loadDir } },
|
|
193
|
+
observedEffects: ["Materialize the unpacked MV3 extension package"],
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
uninstall: async (_context) => ({
|
|
197
|
+
result: base,
|
|
198
|
+
observedEffects: [],
|
|
199
|
+
}),
|
|
200
|
+
status: async (context) => {
|
|
201
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
202
|
+
const setup = await readSetup(context);
|
|
203
|
+
const evidence = await readEvidence(context, loadDir);
|
|
204
|
+
return {
|
|
205
|
+
result: {
|
|
206
|
+
...base,
|
|
207
|
+
data: {
|
|
208
|
+
setupStatus: setup && evidence
|
|
209
|
+
? "READY"
|
|
210
|
+
: "ACTION_REQUIRED",
|
|
211
|
+
runtimeStatus: evidence ? "RUNNING" : "STOPPED",
|
|
212
|
+
},
|
|
185
213
|
},
|
|
186
|
-
|
|
187
|
-
|
|
214
|
+
observedEffects: evidence
|
|
215
|
+
? ["Observes real Chrome MV3 load evidence"]
|
|
216
|
+
: [],
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
setup: async (context) => {
|
|
220
|
+
await mkdir(stateDir(context), { recursive: true, mode: 0o700 });
|
|
221
|
+
const supplied = input(context);
|
|
222
|
+
let setup = await readSetup(context);
|
|
223
|
+
if (supplied.extensionId) {
|
|
224
|
+
if (!/^[a-z]{32}$/.test(supplied.extensionId))
|
|
188
225
|
return {
|
|
189
|
-
result: (
|
|
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
|
-
: [],
|
|
226
|
+
result: failed("SETUP_FAILED", "extensionId must be a canonical 32-character Chromium extension id", false),
|
|
227
|
+
observedEffects: [],
|
|
214
228
|
};
|
|
229
|
+
setup = { extensionId: supplied.extensionId };
|
|
230
|
+
await writeFile(setupFile(context), `${JSON.stringify(setup, null, 2)}\n`, { mode: 0o600 });
|
|
231
|
+
}
|
|
232
|
+
if (!setup)
|
|
233
|
+
return {
|
|
234
|
+
result: {
|
|
235
|
+
...base,
|
|
236
|
+
ok: false,
|
|
237
|
+
status: "ACTION_REQUIRED",
|
|
238
|
+
actionRequired: {
|
|
239
|
+
action: "load-unpacked-extension",
|
|
240
|
+
description: `Load ${browserExtensionLoadDir(context.workspaceRoot)} in Chrome, copy its extensionId, then rerun Module.setup with extensionId.`,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
observedEffects: [],
|
|
244
|
+
};
|
|
245
|
+
try {
|
|
246
|
+
await materialize(context, setup);
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
return {
|
|
250
|
+
result: failed("SETUP_FAILED", error instanceof Error
|
|
251
|
+
? error.message
|
|
252
|
+
: "browser extension config materialization failed"),
|
|
253
|
+
observedEffects: [],
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
if (supplied.serviceWorker === "RUNNING") {
|
|
257
|
+
const evidence = {
|
|
258
|
+
contract: "proflow.browser-extension-verification.v1",
|
|
259
|
+
moduleVersion: descriptor.moduleVersion,
|
|
260
|
+
loadDir: browserExtensionLoadDir(context.workspaceRoot),
|
|
261
|
+
extensionId: setup.extensionId,
|
|
262
|
+
serviceWorker: "RUNNING",
|
|
263
|
+
observedAt: supplied.observedAt ?? new Date().toISOString(),
|
|
264
|
+
};
|
|
265
|
+
await writeFile(verificationFile(context), `${JSON.stringify(evidence, null, 2)}\n`, { mode: 0o600 });
|
|
266
|
+
return {
|
|
267
|
+
result: base,
|
|
268
|
+
observedEffects: ["Records real Chrome MV3 load evidence"],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
result: {
|
|
273
|
+
...base,
|
|
274
|
+
ok: false,
|
|
275
|
+
status: "ACTION_REQUIRED",
|
|
276
|
+
actionRequired: {
|
|
277
|
+
action: "reload-and-verify-extension",
|
|
278
|
+
description: "Reload the unpacked extension after runtime config materialization, confirm its MV3 service worker is RUNNING, then rerun Module.setup with serviceWorker=RUNNING.",
|
|
279
|
+
},
|
|
215
280
|
},
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
281
|
+
observedEffects: [],
|
|
282
|
+
};
|
|
283
|
+
},
|
|
284
|
+
docs: async (_context) => ({
|
|
285
|
+
result: { ...base, data: { docs: "DOCS.md", setup: "SETUP.md" } },
|
|
286
|
+
observedEffects: [],
|
|
287
|
+
}),
|
|
288
|
+
start: async (context) => {
|
|
289
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
290
|
+
return {
|
|
291
|
+
result: (await readEvidence(context, loadDir))
|
|
292
|
+
? base
|
|
293
|
+
: failed("START_FAILED", "browser extension setup is not READY"),
|
|
294
|
+
observedEffects: [],
|
|
295
|
+
};
|
|
296
|
+
},
|
|
297
|
+
stop: async (_context) => ({
|
|
298
|
+
result: base,
|
|
299
|
+
observedEffects: [],
|
|
300
|
+
}),
|
|
301
|
+
};
|
|
@@ -3,7 +3,7 @@ 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.
|
|
6
|
+
readonly moduleVersion: "0.1.5";
|
|
7
7
|
readonly kind: "browser-extension";
|
|
8
8
|
readonly templateVersion: "1.0.0";
|
|
9
9
|
readonly platformCompatibility: ">=1.0.0 <2.0.0";
|
|
@@ -33,79 +33,14 @@ export declare const descriptor: {
|
|
|
33
33
|
readonly kind: "human";
|
|
34
34
|
readonly action: "Load and verify the unpacked MV3 extension in the real Chrome profile";
|
|
35
35
|
}];
|
|
36
|
-
readonly configSlots: readonly [
|
|
37
|
-
readonly key: "bridge.endpoint";
|
|
38
|
-
readonly type: "url";
|
|
39
|
-
readonly required: true;
|
|
40
|
-
readonly description: "Loopback Browser Reality Bridge endpoint";
|
|
41
|
-
}, {
|
|
42
|
-
readonly key: "bridge.token";
|
|
43
|
-
readonly type: "path";
|
|
44
|
-
readonly required: true;
|
|
45
|
-
readonly sensitive: true;
|
|
46
|
-
readonly description: "File containing the Browser Reality Bridge extension token";
|
|
47
|
-
}, {
|
|
48
|
-
readonly key: "taskApplication.endpoint";
|
|
49
|
-
readonly type: "url";
|
|
50
|
-
readonly required: true;
|
|
51
|
-
readonly description: "Loopback Platform Host Task application endpoint";
|
|
52
|
-
}, {
|
|
53
|
-
readonly key: "taskApplication.token";
|
|
54
|
-
readonly type: "path";
|
|
55
|
-
readonly required: true;
|
|
56
|
-
readonly sensitive: true;
|
|
57
|
-
readonly description: "File containing the Platform Host Task application token";
|
|
58
|
-
}, {
|
|
59
|
-
readonly key: "approvalApplication.endpoint";
|
|
60
|
-
readonly type: "url";
|
|
61
|
-
readonly required: true;
|
|
62
|
-
readonly description: "Loopback Platform Host Approval application endpoint";
|
|
63
|
-
}, {
|
|
64
|
-
readonly key: "approvalApplication.token";
|
|
65
|
-
readonly type: "path";
|
|
66
|
-
readonly required: true;
|
|
67
|
-
readonly sensitive: true;
|
|
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";
|
|
74
|
-
}, {
|
|
75
|
-
readonly key: "chromeRuntimeModuleRef";
|
|
76
|
-
readonly type: "moduleRef";
|
|
77
|
-
readonly required: false;
|
|
78
|
-
readonly description: "External resource module governing the Chrome runtime";
|
|
79
|
-
readonly default: "chrome-runtime";
|
|
80
|
-
}, {
|
|
81
|
-
readonly key: "carrierModuleRef";
|
|
82
|
-
readonly type: "moduleRef";
|
|
83
|
-
readonly required: false;
|
|
84
|
-
readonly description: "External resource module governing the Custom GPT carrier";
|
|
85
|
-
readonly default: "chatgpt-carrier";
|
|
86
|
-
}];
|
|
87
|
-
readonly lifecycle: {
|
|
88
|
-
readonly supported: readonly ["describe", "preflight", "status", "verify", "doctor"];
|
|
89
|
-
};
|
|
90
|
-
readonly verification: {
|
|
91
|
-
readonly checks: readonly [{
|
|
92
|
-
readonly id: "real-carrier-e3-e4";
|
|
93
|
-
readonly description: "Real Chrome and ChatGPT E3/E4 evidence is present";
|
|
94
|
-
readonly lifecycle: "verify";
|
|
95
|
-
}];
|
|
96
|
-
};
|
|
36
|
+
readonly configSlots: readonly [];
|
|
97
37
|
readonly effects: readonly [{
|
|
98
38
|
readonly kind: "external-resource";
|
|
99
|
-
readonly description: "
|
|
39
|
+
readonly description: "Materialize the unpacked MV3 extension package";
|
|
100
40
|
readonly retention: "preserve";
|
|
101
41
|
}];
|
|
102
|
-
readonly documentation:
|
|
103
|
-
readonly
|
|
104
|
-
readonly
|
|
105
|
-
|
|
106
|
-
}, {
|
|
107
|
-
readonly id: "configuration";
|
|
108
|
-
readonly path: "./CONFIGURATION.md";
|
|
109
|
-
readonly description: "Module configuration fields, sources and materialization instructions";
|
|
110
|
-
}];
|
|
42
|
+
readonly documentation: {
|
|
43
|
+
readonly docs: "DOCS.md";
|
|
44
|
+
readonly setup: "SETUP.md";
|
|
45
|
+
};
|
|
111
46
|
};
|
|
@@ -3,7 +3,7 @@ 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.
|
|
6
|
+
moduleVersion: "0.1.5",
|
|
7
7
|
kind: "browser-extension",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
|
@@ -42,96 +42,16 @@ export const descriptor = {
|
|
|
42
42
|
action: "Load and verify the unpacked MV3 extension in the real Chrome profile",
|
|
43
43
|
},
|
|
44
44
|
],
|
|
45
|
-
configSlots: [
|
|
46
|
-
{
|
|
47
|
-
key: "bridge.endpoint",
|
|
48
|
-
type: "url",
|
|
49
|
-
required: true,
|
|
50
|
-
description: "Loopback Browser Reality Bridge endpoint",
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
key: "bridge.token",
|
|
54
|
-
type: "path",
|
|
55
|
-
required: true,
|
|
56
|
-
sensitive: true,
|
|
57
|
-
description: "File containing the Browser Reality Bridge extension token",
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
key: "taskApplication.endpoint",
|
|
61
|
-
type: "url",
|
|
62
|
-
required: true,
|
|
63
|
-
description: "Loopback Platform Host Task application endpoint",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
key: "taskApplication.token",
|
|
67
|
-
type: "path",
|
|
68
|
-
required: true,
|
|
69
|
-
sensitive: true,
|
|
70
|
-
description: "File containing the Platform Host Task application token",
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
key: "approvalApplication.endpoint",
|
|
74
|
-
type: "url",
|
|
75
|
-
required: true,
|
|
76
|
-
description: "Loopback Platform Host Approval application endpoint",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
key: "approvalApplication.token",
|
|
80
|
-
type: "path",
|
|
81
|
-
required: true,
|
|
82
|
-
sensitive: true,
|
|
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",
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
key: "chromeRuntimeModuleRef",
|
|
93
|
-
type: "moduleRef",
|
|
94
|
-
required: false,
|
|
95
|
-
description: "External resource module governing the Chrome runtime",
|
|
96
|
-
default: "chrome-runtime",
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
key: "carrierModuleRef",
|
|
100
|
-
type: "moduleRef",
|
|
101
|
-
required: false,
|
|
102
|
-
description: "External resource module governing the Custom GPT carrier",
|
|
103
|
-
default: "chatgpt-carrier",
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
lifecycle: {
|
|
107
|
-
supported: ["describe", "preflight", "status", "verify", "doctor"],
|
|
108
|
-
},
|
|
109
|
-
verification: {
|
|
110
|
-
checks: [
|
|
111
|
-
{
|
|
112
|
-
id: "real-carrier-e3-e4",
|
|
113
|
-
description: "Real Chrome and ChatGPT E3/E4 evidence is present",
|
|
114
|
-
lifecycle: "verify",
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
},
|
|
45
|
+
configSlots: [],
|
|
118
46
|
effects: [
|
|
119
47
|
{
|
|
120
48
|
kind: "external-resource",
|
|
121
|
-
description: "
|
|
49
|
+
description: "Materialize the unpacked MV3 extension package",
|
|
122
50
|
retention: "preserve",
|
|
123
51
|
},
|
|
124
52
|
],
|
|
125
|
-
documentation:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
description: "Package-owned module overview",
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
id: "configuration",
|
|
133
|
-
path: "./CONFIGURATION.md",
|
|
134
|
-
description: "Module configuration fields, sources and materialization instructions",
|
|
135
|
-
},
|
|
136
|
-
],
|
|
53
|
+
documentation: {
|
|
54
|
+
docs: "DOCS.md",
|
|
55
|
+
setup: "SETUP.md",
|
|
56
|
+
},
|
|
137
57
|
};
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomflow/proflow-execution-browser-extension",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -22,15 +22,16 @@
|
|
|
22
22
|
"proflow.module.json",
|
|
23
23
|
"conformance.json",
|
|
24
24
|
"README.md",
|
|
25
|
-
"
|
|
25
|
+
"DOCS.md",
|
|
26
|
+
"SETUP.md"
|
|
26
27
|
],
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@tomflow/proflow-
|
|
29
|
-
"@tomflow/proflow-
|
|
29
|
+
"@tomflow/proflow-execution-contracts": "^0.1.4",
|
|
30
|
+
"@tomflow/proflow-module-contract": "^0.1.4"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@tomflow/proflow-
|
|
33
|
-
"@tomflow/proflow-
|
|
33
|
+
"@tomflow/proflow-execution-runtime": "^0.1.7",
|
|
34
|
+
"@tomflow/proflow-deployment-conformance": "^0.1.4"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"proflow",
|
package/proflow.module.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"contractVersion": "1.0.0",
|
|
4
4
|
"moduleRef": "execution-browser-extension",
|
|
5
5
|
"packageName": "@tomflow/proflow-execution-browser-extension",
|
|
6
|
-
"moduleVersion": "0.1.
|
|
6
|
+
"moduleVersion": "0.1.5",
|
|
7
7
|
"kind": "browser-extension",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|
|
@@ -42,96 +42,16 @@
|
|
|
42
42
|
"action": "Load and verify the unpacked MV3 extension in the real Chrome profile"
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
|
-
"configSlots": [
|
|
46
|
-
{
|
|
47
|
-
"key": "bridge.endpoint",
|
|
48
|
-
"type": "url",
|
|
49
|
-
"required": true,
|
|
50
|
-
"description": "Loopback Browser Reality Bridge endpoint"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"key": "bridge.token",
|
|
54
|
-
"type": "path",
|
|
55
|
-
"required": true,
|
|
56
|
-
"sensitive": true,
|
|
57
|
-
"description": "File containing the Browser Reality Bridge extension token"
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
"key": "taskApplication.endpoint",
|
|
61
|
-
"type": "url",
|
|
62
|
-
"required": true,
|
|
63
|
-
"description": "Loopback Platform Host Task application endpoint"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"key": "taskApplication.token",
|
|
67
|
-
"type": "path",
|
|
68
|
-
"required": true,
|
|
69
|
-
"sensitive": true,
|
|
70
|
-
"description": "File containing the Platform Host Task application token"
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"key": "approvalApplication.endpoint",
|
|
74
|
-
"type": "url",
|
|
75
|
-
"required": true,
|
|
76
|
-
"description": "Loopback Platform Host Approval application endpoint"
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"key": "approvalApplication.token",
|
|
80
|
-
"type": "path",
|
|
81
|
-
"required": true,
|
|
82
|
-
"sensitive": true,
|
|
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"
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"key": "chromeRuntimeModuleRef",
|
|
93
|
-
"type": "moduleRef",
|
|
94
|
-
"required": false,
|
|
95
|
-
"description": "External resource module governing the Chrome runtime",
|
|
96
|
-
"default": "chrome-runtime"
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"key": "carrierModuleRef",
|
|
100
|
-
"type": "moduleRef",
|
|
101
|
-
"required": false,
|
|
102
|
-
"description": "External resource module governing the Custom GPT carrier",
|
|
103
|
-
"default": "chatgpt-carrier"
|
|
104
|
-
}
|
|
105
|
-
],
|
|
106
|
-
"lifecycle": {
|
|
107
|
-
"supported": ["describe", "preflight", "status", "verify", "doctor"]
|
|
108
|
-
},
|
|
109
|
-
"verification": {
|
|
110
|
-
"checks": [
|
|
111
|
-
{
|
|
112
|
-
"id": "real-carrier-e3-e4",
|
|
113
|
-
"description": "Real Chrome and ChatGPT E3/E4 evidence is present",
|
|
114
|
-
"lifecycle": "verify"
|
|
115
|
-
}
|
|
116
|
-
]
|
|
117
|
-
},
|
|
45
|
+
"configSlots": [],
|
|
118
46
|
"effects": [
|
|
119
47
|
{
|
|
120
48
|
"kind": "external-resource",
|
|
121
|
-
"description": "
|
|
49
|
+
"description": "Materialize the unpacked MV3 extension package",
|
|
122
50
|
"retention": "preserve"
|
|
123
51
|
}
|
|
124
52
|
],
|
|
125
|
-
"documentation":
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
"description": "Package-owned module overview"
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
"id": "configuration",
|
|
133
|
-
"path": "./CONFIGURATION.md",
|
|
134
|
-
"description": "Module configuration fields, sources and materialization instructions"
|
|
135
|
-
}
|
|
136
|
-
]
|
|
53
|
+
"documentation": {
|
|
54
|
+
"docs": "DOCS.md",
|
|
55
|
+
"setup": "SETUP.md"
|
|
56
|
+
}
|
|
137
57
|
}
|
package/CONFIGURATION.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
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.
|