@cogenta/plugins 0.1.0
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/dist/guest/sandbox-entry.mjs +155 -0
- package/dist/host/capabilities.d.ts +46 -0
- package/dist/host/capabilities.d.ts.map +1 -0
- package/dist/host/capabilities.js +105 -0
- package/dist/host/capabilities.js.map +1 -0
- package/dist/host/protocol.d.ts +58 -0
- package/dist/host/protocol.d.ts.map +1 -0
- package/dist/host/protocol.js +10 -0
- package/dist/host/protocol.js.map +1 -0
- package/dist/host/worker-runner.d.ts +92 -0
- package/dist/host/worker-runner.d.ts.map +1 -0
- package/dist/host/worker-runner.js +196 -0
- package/dist/host/worker-runner.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +81 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +190 -0
- package/dist/loader.js.map +1 -0
- package/dist/manifest.d.ts +93 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +197 -0
- package/dist/manifest.js.map +1 -0
- package/dist/permissions/describe.d.ts +22 -0
- package/dist/permissions/describe.d.ts.map +1 -0
- package/dist/permissions/describe.js +158 -0
- package/dist/permissions/describe.js.map +1 -0
- package/dist/permissions/disabled.d.ts +25 -0
- package/dist/permissions/disabled.d.ts.map +1 -0
- package/dist/permissions/disabled.js +29 -0
- package/dist/permissions/disabled.js.map +1 -0
- package/dist/permissions/grants.d.ts +22 -0
- package/dist/permissions/grants.d.ts.map +1 -0
- package/dist/permissions/grants.js +31 -0
- package/dist/permissions/grants.js.map +1 -0
- package/dist/permissions/resolve.d.ts +47 -0
- package/dist/permissions/resolve.d.ts.map +1 -0
- package/dist/permissions/resolve.js +51 -0
- package/dist/permissions/resolve.js.map +1 -0
- package/dist/permissions/review.d.ts +50 -0
- package/dist/permissions/review.d.ts.map +1 -0
- package/dist/permissions/review.js +46 -0
- package/dist/permissions/review.js.map +1 -0
- package/dist/permissions/tables.d.ts +18 -0
- package/dist/permissions/tables.d.ts.map +1 -0
- package/dist/permissions/tables.js +48 -0
- package/dist/permissions/tables.js.map +1 -0
- package/dist/registries/plugins.d.ts +74 -0
- package/dist/registries/plugins.d.ts.map +1 -0
- package/dist/registries/plugins.js +127 -0
- package/dist/registries/plugins.js.map +1 -0
- package/dist/registries/skills.d.ts +54 -0
- package/dist/registries/skills.d.ts.map +1 -0
- package/dist/registries/skills.js +113 -0
- package/dist/registries/skills.js.map +1 -0
- package/dist/registries/skins.d.ts +33 -0
- package/dist/registries/skins.d.ts.map +1 -0
- package/dist/registries/skins.js +65 -0
- package/dist/registries/skins.js.map +1 -0
- package/dist/registries/tables.d.ts +44 -0
- package/dist/registries/tables.d.ts.map +1 -0
- package/dist/registries/tables.js +118 -0
- package/dist/registries/tables.js.map +1 -0
- package/dist/registries/themes.d.ts +59 -0
- package/dist/registries/themes.d.ts.map +1 -0
- package/dist/registries/themes.js +82 -0
- package/dist/registries/themes.js.map +1 -0
- package/dist/semver.d.ts +24 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/semver.js +93 -0
- package/dist/semver.js.map +1 -0
- package/dist/signing/keys.d.ts +18 -0
- package/dist/signing/keys.d.ts.map +1 -0
- package/dist/signing/keys.js +15 -0
- package/dist/signing/keys.js.map +1 -0
- package/dist/signing/sign.d.ts +35 -0
- package/dist/signing/sign.d.ts.map +1 -0
- package/dist/signing/sign.js +63 -0
- package/dist/signing/sign.js.map +1 -0
- package/dist/signing/verify.d.ts +40 -0
- package/dist/signing/verify.d.ts.map +1 -0
- package/dist/signing/verify.js +73 -0
- package/dist/signing/verify.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Hand-written plain JS, not compiled from TypeScript — this file is loaded
|
|
2
|
+
// directly by `node:worker_threads`' `Worker` constructor, which reads it as
|
|
3
|
+
// real Node-executable JS with no build step involved (the same reasoning
|
|
4
|
+
// `create-cogenta`'s scaffolded `cogenta.config.mjs` is hand-written rather
|
|
5
|
+
// than routed through a TS-to-JS build: this file must run as-is, before any
|
|
6
|
+
// bundler or `tsc` output exists during `vitest` runs against `src/`).
|
|
7
|
+
//
|
|
8
|
+
// This is the ENTIRE trusted surface a plugin's code runs against. It does
|
|
9
|
+
// three things, and nothing else:
|
|
10
|
+
// 1. Creates a fresh `vm` context whose global object has no `process`, no
|
|
11
|
+
// `require`, no `fs`/`net`, and no dynamic `import()` — a plugin cannot
|
|
12
|
+
// reach any of these because they were never put there, not because
|
|
13
|
+
// they were removed after being present.
|
|
14
|
+
// 2. Runs the plugin's code as a classic (non-module) `vm.Script` inside
|
|
15
|
+
// that context, with `codeGeneration: { strings: false }` — this is a
|
|
16
|
+
// real, documented V8/Node guarantee that blocks `eval()`/`new
|
|
17
|
+
// Function(...)`, closing the most common "climb the prototype chain to
|
|
18
|
+
// reach the real Function constructor" vm-escape technique.
|
|
19
|
+
// 3. Reports the outcome back over `parentPort`, JSON-round-tripped so no
|
|
20
|
+
// live object (a function, a class instance, a Proxy) can leak out.
|
|
21
|
+
//
|
|
22
|
+
// Honest limitation, stated plainly rather than oversold: Node's own docs
|
|
23
|
+
// are explicit that `vm` is not a hardened security boundary against a
|
|
24
|
+
// sufficiently determined co-located attacker on its own — it is one layer.
|
|
25
|
+
// The real isolation here is the COMBINATION of this vm sandbox (blocks the
|
|
26
|
+
// Node API surface) running inside a separate `worker_threads` thread
|
|
27
|
+
// spawned with `env: {}` (blocks secrets/environment access structurally,
|
|
28
|
+
// not by convention) and bounded `resourceLimits` + a host-side timeout
|
|
29
|
+
// (blocks resource exhaustion). No single layer is claimed to be sufficient
|
|
30
|
+
// alone.
|
|
31
|
+
|
|
32
|
+
import vm from 'node:vm'
|
|
33
|
+
import { parentPort } from 'node:worker_threads'
|
|
34
|
+
|
|
35
|
+
if (!parentPort) {
|
|
36
|
+
throw new Error('sandbox-entry.mjs must run inside a worker_threads Worker')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** JSON round-trip strips functions/symbols/live references — nothing but plain data survives. */
|
|
40
|
+
function toSerializable(value) {
|
|
41
|
+
if (value === undefined) return null
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(JSON.stringify(value))
|
|
44
|
+
} catch {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let nextCallId = 1
|
|
50
|
+
/** Pending SDK calls this sandbox is waiting on a host reply for, keyed by `callId`. */
|
|
51
|
+
const pendingSdkCalls = new Map()
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* One real RPC method, bound to a specific capability name. Calling it posts
|
|
55
|
+
* a `sdk-call` message to the host and returns a Promise that resolves or
|
|
56
|
+
* rejects when the matching `sdk-result`/`sdk-error` arrives — the host
|
|
57
|
+
* re-verifies the request against what was actually granted before ever
|
|
58
|
+
* executing it (`./host/capabilities.js`).
|
|
59
|
+
*/
|
|
60
|
+
function makeSdkMethod(method) {
|
|
61
|
+
return (args) =>
|
|
62
|
+
new Promise((resolve, reject) => {
|
|
63
|
+
const callId = nextCallId
|
|
64
|
+
nextCallId += 1
|
|
65
|
+
pendingSdkCalls.set(callId, { resolve, reject })
|
|
66
|
+
parentPort.postMessage({ type: 'sdk-call', callId, method, args })
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Builds the plugin-visible `sdk` object from exactly the capability strings
|
|
72
|
+
* the host says were granted — task 4/5's central, testable property:
|
|
73
|
+
* "toute méthode non accordée est absente de l'objet, pas présente et
|
|
74
|
+
* refusée : absente." A namespace or method whose capability was never
|
|
75
|
+
* granted is never assigned onto `sdk` at all, so `'read' in sdk.content`
|
|
76
|
+
* is `false`, not a present method that throws when called.
|
|
77
|
+
*/
|
|
78
|
+
function buildSdk(grantedCapabilities) {
|
|
79
|
+
const sdk = {}
|
|
80
|
+
for (const capability of grantedCapabilities) {
|
|
81
|
+
const separatorIndex = capability.indexOf(':')
|
|
82
|
+
const name = separatorIndex === -1 ? capability : capability.slice(0, separatorIndex)
|
|
83
|
+
const dotIndex = name.indexOf('.')
|
|
84
|
+
if (dotIndex === -1) continue
|
|
85
|
+
const namespace = name.slice(0, dotIndex)
|
|
86
|
+
const method = name.slice(dotIndex + 1)
|
|
87
|
+
if (sdk[namespace] === undefined) sdk[namespace] = {}
|
|
88
|
+
if (sdk[namespace][method] === undefined) sdk[namespace][method] = makeSdkMethod(name)
|
|
89
|
+
}
|
|
90
|
+
return sdk
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function buildSandbox(grantedCapabilities) {
|
|
94
|
+
// Deliberately minimal. No `process`, no `require`, no `fetch`, no
|
|
95
|
+
// `Buffer`, no `fs`/`net` — only `sdk`, and only the namespaces/methods
|
|
96
|
+
// `grantedCapabilities` actually names.
|
|
97
|
+
return {
|
|
98
|
+
console,
|
|
99
|
+
Math,
|
|
100
|
+
JSON,
|
|
101
|
+
Promise,
|
|
102
|
+
setTimeout,
|
|
103
|
+
clearTimeout,
|
|
104
|
+
sdk: buildSdk(grantedCapabilities),
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
parentPort.on('message', (message) => {
|
|
109
|
+
if (message == null) return
|
|
110
|
+
|
|
111
|
+
// A reply to a pending SDK call — resolve/reject its Promise and let the
|
|
112
|
+
// sandbox's own `await` resume; this is not a new `run` request.
|
|
113
|
+
if (message.type === 'sdk-result' || message.type === 'sdk-error') {
|
|
114
|
+
const pending = pendingSdkCalls.get(message.callId)
|
|
115
|
+
if (pending === undefined) return
|
|
116
|
+
pendingSdkCalls.delete(message.callId)
|
|
117
|
+
if (message.type === 'sdk-result') pending.resolve(message.value)
|
|
118
|
+
else pending.reject(new Error(message.message))
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (message.type !== 'run') return
|
|
123
|
+
const { id, code, grantedCapabilities } = message
|
|
124
|
+
|
|
125
|
+
// Fire-and-report, not awaited by the message handler itself: plugin code
|
|
126
|
+
// may be a top-level `async () => {...}()` (e.g. to `await import(...)`
|
|
127
|
+
// and observe the rejection a blocked dynamic import produces) — its
|
|
128
|
+
// returned Promise is awaited here before the result is serialized.
|
|
129
|
+
void (async () => {
|
|
130
|
+
let result
|
|
131
|
+
try {
|
|
132
|
+
const context = vm.createContext(buildSandbox(grantedCapabilities ?? []), {
|
|
133
|
+
codeGeneration: { strings: false, wasm: false },
|
|
134
|
+
})
|
|
135
|
+
const script = new vm.Script(code, { filename: 'plugin.js' })
|
|
136
|
+
// A second, independent time bound on top of the host's own
|
|
137
|
+
// worker.terminate() timeout — this one stops a synchronous infinite
|
|
138
|
+
// loop from inside the same thread, which a host-side terminate() can
|
|
139
|
+
// be slow to land on under heavy CPU contention.
|
|
140
|
+
const rawValue = script.runInContext(context, { timeout: 5000 })
|
|
141
|
+
const value =
|
|
142
|
+
rawValue !== null && typeof rawValue === 'object' && typeof rawValue.then === 'function'
|
|
143
|
+
? await rawValue
|
|
144
|
+
: rawValue
|
|
145
|
+
result = { id, type: 'result', value: toSerializable(value) }
|
|
146
|
+
} catch (error) {
|
|
147
|
+
result = {
|
|
148
|
+
id,
|
|
149
|
+
type: 'error',
|
|
150
|
+
message: error instanceof Error ? error.message : String(error),
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
parentPort.postMessage(result)
|
|
154
|
+
})()
|
|
155
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StorageDriver } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* Host-side implementations of the SDK methods a sandboxed plugin can call.
|
|
4
|
+
* "Commencer minimal" (docs/lots/L7-extensibilite.md § Pièges connus) — this
|
|
5
|
+
* is a deliberately small starter set: `content.read`, `http.fetch`,
|
|
6
|
+
* `storage.read`/`storage.write`. Task 5 owns turning a real permission grant
|
|
7
|
+
* into the `grantedCapabilities` list these handlers re-verify against; this
|
|
8
|
+
* file owns what each capability actually DOES once granted.
|
|
9
|
+
*
|
|
10
|
+
* Every handler re-checks the SPECIFIC request against the SPECIFIC granted
|
|
11
|
+
* capability parameter (the exact domain, the exact storage prefix) — never
|
|
12
|
+
* just "was this capability name granted at all." The manifest schema
|
|
13
|
+
* (task 1) already validates that a declared capability's parameter is
|
|
14
|
+
* well-formed (a real hostname, a prefix confined to the plugin's own
|
|
15
|
+
* namespace), but a well-formed *declaration* says nothing about what the
|
|
16
|
+
* *specific call a plugin makes at runtime* asks for — a plugin granted
|
|
17
|
+
* `http.fetch:api.example.com` could still ask its own SDK method to fetch
|
|
18
|
+
* `evil.example.com`, and only a host-side re-check of the actual request
|
|
19
|
+
* against the actual granted parameter closes that gap.
|
|
20
|
+
*/
|
|
21
|
+
export interface CapabilityCallContext {
|
|
22
|
+
/** The full manifest-shaped capability strings actually granted, e.g. `["http.fetch:api.example.com"]`. */
|
|
23
|
+
readonly grantedCapabilities: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
export type CapabilityHandler = (args: unknown, context: CapabilityCallContext) => Promise<unknown>;
|
|
26
|
+
/**
|
|
27
|
+
* `content.read` — read-only, via whatever real content-read function the
|
|
28
|
+
* host provides (typically `ContentStore.read`, `@cogenta/schema`) for a
|
|
29
|
+
* single, specific collection this plugin instance is scoped to. No
|
|
30
|
+
* per-call re-verification beyond capability presence: `content.read` is
|
|
31
|
+
* bare (task 1 never parameterizes it per-collection), so the host, not
|
|
32
|
+
* this handler, is what decides which collection's store gets wired in.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createContentReadHandler(readEntry: (id: string) => Promise<unknown>): CapabilityHandler;
|
|
35
|
+
/**
|
|
36
|
+
* `http.fetch:<domain>` — the requested URL's hostname must exactly match
|
|
37
|
+
* one of the domains actually granted, re-checked here against the real
|
|
38
|
+
* request, not merely against the fact that *some* `http.fetch` capability
|
|
39
|
+
* exists.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createHttpFetchHandler(fetchImpl?: typeof fetch): CapabilityHandler;
|
|
42
|
+
/** `storage.read:<prefix>` — the requested key must fall within a granted prefix, re-verified per call. */
|
|
43
|
+
export declare function createStorageReadHandler(driver: StorageDriver): CapabilityHandler;
|
|
44
|
+
/** `storage.write:<prefix>` — same per-call prefix re-verification as `storage.read`. */
|
|
45
|
+
export declare function createStorageWriteHandler(driver: StorageDriver): CapabilityHandler;
|
|
46
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/host/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,2GAA2G;IAC3G,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAA;CAChD;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AA6BnG;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,iBAAiB,CAQnB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,GAAE,OAAO,KAAa,GAAG,iBAAiB,CAYzF;AAgBD,2GAA2G;AAC3G,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,GAAG,iBAAiB,CAejF;AAED,yFAAyF;AACzF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,iBAAiB,CAYlF"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/** Parameters (the part after `:`) granted for a given bare capability name. */
|
|
3
|
+
function grantedParameters(name, context) {
|
|
4
|
+
const prefix = `${name}:`;
|
|
5
|
+
return context.grantedCapabilities
|
|
6
|
+
.filter((capability) => capability.startsWith(prefix))
|
|
7
|
+
.map((capability) => capability.slice(prefix.length));
|
|
8
|
+
}
|
|
9
|
+
function refused(message) {
|
|
10
|
+
throw new CogentaError({
|
|
11
|
+
code: 'PLUGIN_CAPABILITY_REFUSED',
|
|
12
|
+
message,
|
|
13
|
+
hint: 'The plugin requested something its granted capabilities do not cover.',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function asRecord(value) {
|
|
17
|
+
if (value === null || typeof value !== 'object')
|
|
18
|
+
refused('expected an object argument');
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function asString(value, field) {
|
|
22
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
23
|
+
refused(`"${field}" must be a non-empty string`);
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `content.read` — read-only, via whatever real content-read function the
|
|
28
|
+
* host provides (typically `ContentStore.read`, `@cogenta/schema`) for a
|
|
29
|
+
* single, specific collection this plugin instance is scoped to. No
|
|
30
|
+
* per-call re-verification beyond capability presence: `content.read` is
|
|
31
|
+
* bare (task 1 never parameterizes it per-collection), so the host, not
|
|
32
|
+
* this handler, is what decides which collection's store gets wired in.
|
|
33
|
+
*/
|
|
34
|
+
export function createContentReadHandler(readEntry) {
|
|
35
|
+
return async (args, context) => {
|
|
36
|
+
if (!context.grantedCapabilities.includes('content.read')) {
|
|
37
|
+
refused('"content.read" was not granted');
|
|
38
|
+
}
|
|
39
|
+
const id = asString(asRecord(args).id, 'id');
|
|
40
|
+
return await readEntry(id);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* `http.fetch:<domain>` — the requested URL's hostname must exactly match
|
|
45
|
+
* one of the domains actually granted, re-checked here against the real
|
|
46
|
+
* request, not merely against the fact that *some* `http.fetch` capability
|
|
47
|
+
* exists.
|
|
48
|
+
*/
|
|
49
|
+
export function createHttpFetchHandler(fetchImpl = fetch) {
|
|
50
|
+
return async (args, context) => {
|
|
51
|
+
const url = asString(asRecord(args).url, 'url');
|
|
52
|
+
const allowedDomains = grantedParameters('http.fetch', context);
|
|
53
|
+
const hostname = new URL(url).hostname;
|
|
54
|
+
if (!allowedDomains.includes(hostname)) {
|
|
55
|
+
refused(`"http.fetch" was not granted for domain "${hostname}"`);
|
|
56
|
+
}
|
|
57
|
+
const response = await fetchImpl(url);
|
|
58
|
+
const body = await response.text();
|
|
59
|
+
return { status: response.status, body };
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function isWithinGrantedPrefix(path, prefixes) {
|
|
63
|
+
return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
64
|
+
}
|
|
65
|
+
/** Refuses any request whose normalised path escapes what the granted prefix set allows — closes `../` traversal. */
|
|
66
|
+
function normalisedStorageKey(rawKey) {
|
|
67
|
+
const key = asString(rawKey, 'key');
|
|
68
|
+
const segments = key.split('/');
|
|
69
|
+
if (segments.some((segment) => segment === '..' || segment === '.')) {
|
|
70
|
+
refused(`storage key "${key}" must not contain "." or ".." segments`);
|
|
71
|
+
}
|
|
72
|
+
return key;
|
|
73
|
+
}
|
|
74
|
+
/** `storage.read:<prefix>` — the requested key must fall within a granted prefix, re-verified per call. */
|
|
75
|
+
export function createStorageReadHandler(driver) {
|
|
76
|
+
return async (args, context) => {
|
|
77
|
+
const record = asRecord(args);
|
|
78
|
+
const key = normalisedStorageKey(asString(record.key, 'key'));
|
|
79
|
+
const allowedPrefixes = grantedParameters('storage.read', context);
|
|
80
|
+
if (!isWithinGrantedPrefix(key, allowedPrefixes)) {
|
|
81
|
+
refused(`"storage.read" was not granted for key "${key}"`);
|
|
82
|
+
}
|
|
83
|
+
const readable = await driver.get(key);
|
|
84
|
+
const chunks = [];
|
|
85
|
+
for await (const chunk of readable) {
|
|
86
|
+
chunks.push(chunk);
|
|
87
|
+
}
|
|
88
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** `storage.write:<prefix>` — same per-call prefix re-verification as `storage.read`. */
|
|
92
|
+
export function createStorageWriteHandler(driver) {
|
|
93
|
+
return async (args, context) => {
|
|
94
|
+
const record = asRecord(args);
|
|
95
|
+
const key = normalisedStorageKey(asString(record.key, 'key'));
|
|
96
|
+
const content = asString(record.content, 'content');
|
|
97
|
+
const allowedPrefixes = grantedParameters('storage.write', context);
|
|
98
|
+
if (!isWithinGrantedPrefix(key, allowedPrefixes)) {
|
|
99
|
+
refused(`"storage.write" was not granted for key "${key}"`);
|
|
100
|
+
}
|
|
101
|
+
await driver.put(key, Buffer.from(content, 'utf8'));
|
|
102
|
+
return { ok: true };
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/host/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real, serialized message protocol between the host and an isolated
|
|
3
|
+
* plugin worker. Every field here must survive `worker_threads`' structured
|
|
4
|
+
* clone — no live objects, no functions, no class instances ever cross this
|
|
5
|
+
* boundary ("communication par messages sérialisés. Aucun objet vivant du
|
|
6
|
+
* noyau ne traverse la frontière" — docs/lots/L7-extensibilite.md §
|
|
7
|
+
* Isolation).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Host → worker: evaluate `code` inside the sandbox and report the result.
|
|
11
|
+
* `grantedCapabilities` (task 1's manifest capability strings, e.g.
|
|
12
|
+
* `"http.fetch:api.example.com"`) is what the guest-side sandbox uses to
|
|
13
|
+
* decide which SDK methods to construct — task 4's "absent, not refused"
|
|
14
|
+
* property is enforced entirely by which keys this list causes to exist on
|
|
15
|
+
* the sandbox's `sdk` object, never by a present-but-guarded method.
|
|
16
|
+
*/
|
|
17
|
+
export interface WorkerRunMessage {
|
|
18
|
+
readonly id: number;
|
|
19
|
+
readonly type: 'run';
|
|
20
|
+
readonly code: string;
|
|
21
|
+
readonly grantedCapabilities: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/** Worker → host: the plugin's sandboxed code is calling an SDK method — a real capability request, not yet executed. */
|
|
24
|
+
export interface WorkerSdkCallMessage {
|
|
25
|
+
readonly type: 'sdk-call';
|
|
26
|
+
readonly callId: number;
|
|
27
|
+
/** The capability name the requested method belongs to, e.g. `"content.read"`, `"http.fetch"`. */
|
|
28
|
+
readonly method: string;
|
|
29
|
+
readonly args: unknown;
|
|
30
|
+
}
|
|
31
|
+
export type WorkerHostMessage = WorkerRunMessage;
|
|
32
|
+
/** Host → worker: the SDK call succeeded — a JSON-safe value only, same "no live object crosses the boundary" rule as every other message here. */
|
|
33
|
+
export interface WorkerSdkResultMessage {
|
|
34
|
+
readonly type: 'sdk-result';
|
|
35
|
+
readonly callId: number;
|
|
36
|
+
readonly value: unknown;
|
|
37
|
+
}
|
|
38
|
+
/** Host → worker: the SDK call was refused or failed — re-verified host-side, never trusted from the manifest alone. */
|
|
39
|
+
export interface WorkerSdkErrorMessage {
|
|
40
|
+
readonly type: 'sdk-error';
|
|
41
|
+
readonly callId: number;
|
|
42
|
+
readonly message: string;
|
|
43
|
+
}
|
|
44
|
+
export type WorkerHostReplyMessage = WorkerSdkResultMessage | WorkerSdkErrorMessage;
|
|
45
|
+
/** Worker → host: `code` completed and returned a JSON-safe value. */
|
|
46
|
+
export interface WorkerResultMessage {
|
|
47
|
+
readonly id: number;
|
|
48
|
+
readonly type: 'result';
|
|
49
|
+
readonly value: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** Worker → host: `code` threw, or the sandbox itself refused to run it. */
|
|
52
|
+
export interface WorkerErrorMessage {
|
|
53
|
+
readonly id: number;
|
|
54
|
+
readonly type: 'error';
|
|
55
|
+
readonly message: string;
|
|
56
|
+
}
|
|
57
|
+
export type WorkerGuestMessage = WorkerResultMessage | WorkerErrorMessage | WorkerSdkCallMessage;
|
|
58
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/host/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAA;CAChD;AAED,yHAAyH;AACzH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAA;AAEhD,mJAAmJ;AACnJ,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,wHAAwH;AACxH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,GAAG,qBAAqB,CAAA;AAEnF,sEAAsE;AACtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real, serialized message protocol between the host and an isolated
|
|
3
|
+
* plugin worker. Every field here must survive `worker_threads`' structured
|
|
4
|
+
* clone — no live objects, no functions, no class instances ever cross this
|
|
5
|
+
* boundary ("communication par messages sérialisés. Aucun objet vivant du
|
|
6
|
+
* noyau ne traverse la frontière" — docs/lots/L7-extensibilite.md §
|
|
7
|
+
* Isolation).
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/host/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { PluginManifest } from '../manifest.js';
|
|
2
|
+
import type { PluginDisableStore, PluginViolationReason } from '../permissions/disabled.js';
|
|
3
|
+
import type { PluginGrant } from '../permissions/grants.js';
|
|
4
|
+
import type { CapabilityHandler } from './capabilities.js';
|
|
5
|
+
export interface RunIsolatedOptions {
|
|
6
|
+
/** Killed and reported as a timeout past this — the basic kill switch this task's tests need. */
|
|
7
|
+
readonly timeoutMs?: number;
|
|
8
|
+
/** Real V8 heap ceiling for the worker's old-generation heap. */
|
|
9
|
+
readonly maxOldGenerationSizeMb?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Task 1's manifest capability strings actually granted to this run, e.g.
|
|
12
|
+
* `["content.read", "http.fetch:api.example.com"]`. The guest-side sandbox
|
|
13
|
+
* uses this to decide which SDK methods to construct at all — an absent
|
|
14
|
+
* capability means an absent key on `sdk`, never a present-but-refusing
|
|
15
|
+
* method (docs/lots/L7-extensibilite.md § Isolation, and the explicit
|
|
16
|
+
* acceptance criterion "une méthode non accordée est absente de l'objet
|
|
17
|
+
* SDK, pas seulement refusée").
|
|
18
|
+
*/
|
|
19
|
+
readonly grantedCapabilities?: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* Real host-side implementations for each granted capability's SDK
|
|
22
|
+
* method, keyed by capability name (`"content.read"`, `"http.fetch"`,
|
|
23
|
+
* `"storage.read"`, `"storage.write"`, ...). Task 4's real deliverable —
|
|
24
|
+
* see `./capabilities.js`. A capability granted but with no matching
|
|
25
|
+
* handler here is a host misconfiguration, not a security gap: the guest
|
|
26
|
+
* sandbox still won't expose a method for it unless BOTH `grantedCapabilities`
|
|
27
|
+
* names it AND a handler exists.
|
|
28
|
+
*/
|
|
29
|
+
readonly handlers?: Readonly<Record<string, CapabilityHandler>>;
|
|
30
|
+
}
|
|
31
|
+
export interface IsolatedRunResult {
|
|
32
|
+
readonly ok: boolean;
|
|
33
|
+
readonly value?: unknown;
|
|
34
|
+
readonly error?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Set only when `ok` is `false` — classifies WHY the worker failed, so a
|
|
37
|
+
* caller (task 6's disable policy) can tell "the plugin's own code threw a
|
|
38
|
+
* normal error" apart from "it exceeded its time or memory budget", which
|
|
39
|
+
* is the distinction "tué et désactivé" hinges on. `'crash'` covers any
|
|
40
|
+
* other non-zero exit that isn't recognizably a timeout or a heap-limit
|
|
41
|
+
* violation (e.g. a native worker fault) — still real grounds to disable,
|
|
42
|
+
* just not one of the two named-and-required policies.
|
|
43
|
+
*/
|
|
44
|
+
readonly reason?: PluginViolationReason;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Runs `code` inside a fresh, isolated worker and reports the outcome.
|
|
48
|
+
* `code` is a classic (non-module) script body — the sandbox's real,
|
|
49
|
+
* documented restriction, not an accident: `vm.Script` without an
|
|
50
|
+
* `importModuleDynamically` callback refuses `import()`, and no `require`
|
|
51
|
+
* is ever injected into the sandbox, which is exactly what stops a plugin
|
|
52
|
+
* from reaching `node:fs`/`node:net` no matter which syntax it tries.
|
|
53
|
+
*
|
|
54
|
+
* A fresh `Worker` per call, not a pool — task 6 decides whether a
|
|
55
|
+
* long-lived, reusable worker (with the resource/time policy it owns) is
|
|
56
|
+
* worth the complexity; this task only needs a real, working isolation
|
|
57
|
+
* primitive to build on.
|
|
58
|
+
*/
|
|
59
|
+
export declare function runIsolated(code: string, options?: RunIsolatedOptions): Promise<IsolatedRunResult>;
|
|
60
|
+
/** Emitted once, synchronously, the moment a plugin is disabled — never a hard dependency on any specific notification transport (channels, email, ...); wiring this to a real alert is an integration decision for whatever assembles a site, not this package's job. */
|
|
61
|
+
export interface PluginDisabledEvent {
|
|
62
|
+
readonly pluginName: string;
|
|
63
|
+
readonly reason: PluginViolationReason;
|
|
64
|
+
readonly at: string;
|
|
65
|
+
readonly details?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface RunPluginOptions extends Omit<RunIsolatedOptions, 'grantedCapabilities'> {
|
|
68
|
+
/** Task 6's real, persisted "is this plugin currently disabled" gate — required, not optional, since a caller with no store to check against cannot honestly claim to enforce "tué et désactivé". */
|
|
69
|
+
readonly disableStore: PluginDisableStore;
|
|
70
|
+
/** Fired synchronously right after a violation is recorded — the real "avec alerte" half of "tué et désactivé, avec alerte". */
|
|
71
|
+
readonly onPluginDisabled?: (event: PluginDisabledEvent) => void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The real entry point for actually running a resolved plugin — unlike
|
|
75
|
+
* `runIsolated`, which task 4 left accepting an externally-decided
|
|
76
|
+
* `grantedCapabilities` list as a placeholder, this computes that list
|
|
77
|
+
* itself via `resolveGrantedCapabilities` (task 5) from the plugin's real
|
|
78
|
+
* manifest and its real, persisted grants. A caller cannot bypass grant
|
|
79
|
+
* resolution by simply passing whatever capability list it wants — the only
|
|
80
|
+
* way a capability reaches the sandbox is a real row in the grant store.
|
|
81
|
+
*
|
|
82
|
+
* Task 6 adds the other two real gates the lot demands: a disabled plugin is
|
|
83
|
+
* refused BEFORE a worker is ever spawned (`PLUGIN_DISABLED`, not a silent
|
|
84
|
+
* no-op), and a timeout or memory-limit violation disables the plugin for
|
|
85
|
+
* every future run, not just the one that failed — "il ne peut pas faire
|
|
86
|
+
* tomber le CMS" is the isolation boundary's job (task 3); making sure it
|
|
87
|
+
* cannot even try again unsupervised is this task's.
|
|
88
|
+
*/
|
|
89
|
+
export declare function runPlugin(manifest: PluginManifest, code: string, grants: readonly PluginGrant[], options: RunPluginOptions): Promise<IsolatedRunResult>;
|
|
90
|
+
/** Throws instead of returning a discriminated failure — for call sites that want a plain success value or a real error. */
|
|
91
|
+
export declare function runIsolatedOrThrow(code: string, options?: RunIsolatedOptions): Promise<unknown>;
|
|
92
|
+
//# sourceMappingURL=worker-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-runner.d.ts","sourceRoot":"","sources":["../../src/host/worker-runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAC3F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAyB1D,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAChD;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAA;CAChE;AAKD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CACxC;AAsDD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAsE5B;AAED,0QAA0Q;AAC1Q,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACvF,qMAAqM;IACrM,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAA;IACzC,gIAAgI;IAChI,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAA;CACjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAyB5B;AAED,4HAA4H;AAC5H,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAWlB"}
|