@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,196 @@
|
|
|
1
|
+
import { Worker } from 'node:worker_threads';
|
|
2
|
+
import { CogentaError } from '@cogenta/core';
|
|
3
|
+
import { resolveGrantedCapabilities } from '../permissions/resolve.js';
|
|
4
|
+
/**
|
|
5
|
+
* The isolated worker boundary itself — "Tout plugin tiers s'exécute dans un
|
|
6
|
+
* worker séparé" (docs/lots/L7-extensibilite.md § Isolation). This is task
|
|
7
|
+
* 3's real deliverable: spawn a worker that cannot reach `fs`/`net`/`process`
|
|
8
|
+
* /env/secrets no matter what code runs inside it, talk to it over a real
|
|
9
|
+
* serialized message protocol, and kill it if it doesn't answer in time.
|
|
10
|
+
*
|
|
11
|
+
* What this does NOT build (deliberately, per the lot's own task split):
|
|
12
|
+
* the real capability-gated SDK object a plugin actually calls (task 4/5),
|
|
13
|
+
* or the full time/memory-limit-and-disable-with-alert policy (task 6) — the
|
|
14
|
+
* timeout below is the minimal, real mechanism this task's own tests need so
|
|
15
|
+
* a hostile or runaway plugin can't hang the process; task 6 owns the
|
|
16
|
+
* complete policy layer on top of it.
|
|
17
|
+
*/
|
|
18
|
+
const SANDBOX_ENTRY_URL = new URL('../guest/sandbox-entry.mjs', import.meta.url);
|
|
19
|
+
const DEFAULT_TIMEOUT_MS = 2000;
|
|
20
|
+
const DEFAULT_MAX_OLD_GENERATION_MB = 64;
|
|
21
|
+
/**
|
|
22
|
+
* Node signals a `resourceLimits` heap-limit violation to the parent via the
|
|
23
|
+
* `Worker`'s `'error'` event, carrying a message from V8's own OOM reporting
|
|
24
|
+
* (observed shape: "Worker terminated due to reaching memory limit: JS heap
|
|
25
|
+
* out of memory") — never a distinct error class or a dedicated event type,
|
|
26
|
+
* so this is a real, deliberately narrow message-pattern match, not a guess
|
|
27
|
+
* at a documented API. Anything else that reaches `'error'`/a non-zero exit
|
|
28
|
+
* is classified `'crash'`: still real grounds to disable the plugin, just
|
|
29
|
+
* not a heap-limit violation specifically.
|
|
30
|
+
*/
|
|
31
|
+
function classifyFailure(message) {
|
|
32
|
+
return /heap|memory limit|out of memory/i.test(message) ? 'memory' : 'crash';
|
|
33
|
+
}
|
|
34
|
+
let nextRequestId = 1;
|
|
35
|
+
/**
|
|
36
|
+
* Dispatches one real SDK call from the sandbox to its host-side handler
|
|
37
|
+
* (`./capabilities.js`) and reports the outcome back — the handler itself
|
|
38
|
+
* re-verifies the specific request (a domain, a storage key) against the
|
|
39
|
+
* specific granted capability parameters; this function only routes.
|
|
40
|
+
*/
|
|
41
|
+
async function handleSdkCall(message, handlers, grantedCapabilities, worker) {
|
|
42
|
+
const handler = handlers[message.method];
|
|
43
|
+
if (handler === undefined) {
|
|
44
|
+
const reply = {
|
|
45
|
+
type: 'sdk-error',
|
|
46
|
+
callId: message.callId,
|
|
47
|
+
message: `no host handler registered for "${message.method}"`,
|
|
48
|
+
};
|
|
49
|
+
worker.postMessage(reply);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const value = await handler(message.args, { grantedCapabilities });
|
|
54
|
+
const reply = { type: 'sdk-result', callId: message.callId, value };
|
|
55
|
+
worker.postMessage(reply);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const reply = {
|
|
59
|
+
type: 'sdk-error',
|
|
60
|
+
callId: message.callId,
|
|
61
|
+
message: error instanceof Error ? error.message : String(error),
|
|
62
|
+
};
|
|
63
|
+
worker.postMessage(reply);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Runs `code` inside a fresh, isolated worker and reports the outcome.
|
|
68
|
+
* `code` is a classic (non-module) script body — the sandbox's real,
|
|
69
|
+
* documented restriction, not an accident: `vm.Script` without an
|
|
70
|
+
* `importModuleDynamically` callback refuses `import()`, and no `require`
|
|
71
|
+
* is ever injected into the sandbox, which is exactly what stops a plugin
|
|
72
|
+
* from reaching `node:fs`/`node:net` no matter which syntax it tries.
|
|
73
|
+
*
|
|
74
|
+
* A fresh `Worker` per call, not a pool — task 6 decides whether a
|
|
75
|
+
* long-lived, reusable worker (with the resource/time policy it owns) is
|
|
76
|
+
* worth the complexity; this task only needs a real, working isolation
|
|
77
|
+
* primitive to build on.
|
|
78
|
+
*/
|
|
79
|
+
export async function runIsolated(code, options = {}) {
|
|
80
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
81
|
+
const grantedCapabilities = options.grantedCapabilities ?? [];
|
|
82
|
+
const handlers = options.handlers ?? {};
|
|
83
|
+
const id = nextRequestId;
|
|
84
|
+
nextRequestId += 1;
|
|
85
|
+
const worker = new Worker(SANDBOX_ENTRY_URL, {
|
|
86
|
+
// Never inherit the host's environment — "n'a accès... ni aux variables
|
|
87
|
+
// d'environnement, ni aux secrets" is structural here, not a convention
|
|
88
|
+
// the plugin is merely asked to respect: an empty `env` means the
|
|
89
|
+
// worker's `process.env` (if it were even reachable, which it is not
|
|
90
|
+
// inside the vm sandbox either) genuinely has nothing in it.
|
|
91
|
+
env: {},
|
|
92
|
+
argv: [],
|
|
93
|
+
resourceLimits: {
|
|
94
|
+
maxOldGenerationSizeMb: options.maxOldGenerationSizeMb ?? DEFAULT_MAX_OLD_GENERATION_MB,
|
|
95
|
+
maxYoungGenerationSizeMb: 16,
|
|
96
|
+
},
|
|
97
|
+
stdout: false,
|
|
98
|
+
stderr: false,
|
|
99
|
+
});
|
|
100
|
+
return await new Promise((resolve) => {
|
|
101
|
+
let settled = false;
|
|
102
|
+
const finish = (result) => {
|
|
103
|
+
if (settled)
|
|
104
|
+
return;
|
|
105
|
+
settled = true;
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
void worker.terminate();
|
|
108
|
+
resolve(result);
|
|
109
|
+
};
|
|
110
|
+
const timer = setTimeout(() => {
|
|
111
|
+
finish({ ok: false, error: 'plugin worker timed out', reason: 'timeout' });
|
|
112
|
+
}, timeoutMs);
|
|
113
|
+
// `sdk-call` messages arrive zero or more times WHILE `code` runs, each
|
|
114
|
+
// one a real capability request that must be re-verified and executed
|
|
115
|
+
// host-side before the sandbox's own `await sdk.<ns>.<method>(...)` can
|
|
116
|
+
// resolve — this is the RPC loop the guest-side SDK methods (task 4)
|
|
117
|
+
// are built on. It stays a real `.on` listener, not `.once`, since a
|
|
118
|
+
// single run may call several SDK methods before finishing.
|
|
119
|
+
worker.on('message', (message) => {
|
|
120
|
+
if (message.type === 'result') {
|
|
121
|
+
finish({ ok: true, value: message.value });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (message.type === 'error') {
|
|
125
|
+
finish({ ok: false, error: message.message });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
void handleSdkCall(message, handlers, grantedCapabilities, worker);
|
|
129
|
+
});
|
|
130
|
+
worker.once('error', (error) => {
|
|
131
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
132
|
+
finish({ ok: false, error: message, reason: classifyFailure(message) });
|
|
133
|
+
});
|
|
134
|
+
worker.once('exit', (exitCode) => {
|
|
135
|
+
if (exitCode !== 0) {
|
|
136
|
+
const message = `plugin worker exited with code ${exitCode}`;
|
|
137
|
+
finish({ ok: false, error: message, reason: 'crash' });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const request = { id, type: 'run', code, grantedCapabilities };
|
|
141
|
+
worker.postMessage(request);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The real entry point for actually running a resolved plugin — unlike
|
|
146
|
+
* `runIsolated`, which task 4 left accepting an externally-decided
|
|
147
|
+
* `grantedCapabilities` list as a placeholder, this computes that list
|
|
148
|
+
* itself via `resolveGrantedCapabilities` (task 5) from the plugin's real
|
|
149
|
+
* manifest and its real, persisted grants. A caller cannot bypass grant
|
|
150
|
+
* resolution by simply passing whatever capability list it wants — the only
|
|
151
|
+
* way a capability reaches the sandbox is a real row in the grant store.
|
|
152
|
+
*
|
|
153
|
+
* Task 6 adds the other two real gates the lot demands: a disabled plugin is
|
|
154
|
+
* refused BEFORE a worker is ever spawned (`PLUGIN_DISABLED`, not a silent
|
|
155
|
+
* no-op), and a timeout or memory-limit violation disables the plugin for
|
|
156
|
+
* every future run, not just the one that failed — "il ne peut pas faire
|
|
157
|
+
* tomber le CMS" is the isolation boundary's job (task 3); making sure it
|
|
158
|
+
* cannot even try again unsupervised is this task's.
|
|
159
|
+
*/
|
|
160
|
+
export async function runPlugin(manifest, code, grants, options) {
|
|
161
|
+
const alreadyDisabled = await options.disableStore.isDisabled(manifest.name);
|
|
162
|
+
if (alreadyDisabled !== null) {
|
|
163
|
+
throw new CogentaError({
|
|
164
|
+
code: 'PLUGIN_DISABLED',
|
|
165
|
+
message: `Plugin "${manifest.name}" is disabled (${alreadyDisabled.reason}, since ${alreadyDisabled.disabledAt}) and cannot be run.`,
|
|
166
|
+
hint: 'A human must explicitly re-enable this plugin before it can run again.',
|
|
167
|
+
details: { pluginName: manifest.name, reason: alreadyDisabled.reason },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const grantedCapabilities = resolveGrantedCapabilities(manifest, grants);
|
|
171
|
+
const result = await runIsolated(code, { ...options, grantedCapabilities });
|
|
172
|
+
if (!result.ok && (result.reason === 'timeout' || result.reason === 'memory')) {
|
|
173
|
+
await options.disableStore.disable(manifest.name, result.reason, result.error);
|
|
174
|
+
options.onPluginDisabled?.({
|
|
175
|
+
pluginName: manifest.name,
|
|
176
|
+
reason: result.reason,
|
|
177
|
+
at: new Date().toISOString(),
|
|
178
|
+
...(result.error === undefined ? {} : { details: result.error }),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
/** Throws instead of returning a discriminated failure — for call sites that want a plain success value or a real error. */
|
|
184
|
+
export async function runIsolatedOrThrow(code, options) {
|
|
185
|
+
const result = await runIsolated(code, options);
|
|
186
|
+
if (result.ok)
|
|
187
|
+
return result.value;
|
|
188
|
+
throw new CogentaError({
|
|
189
|
+
code: result.error === 'plugin worker timed out'
|
|
190
|
+
? 'PLUGIN_WORKER_TIMEOUT'
|
|
191
|
+
: 'PLUGIN_WORKER_RUNTIME_ERROR',
|
|
192
|
+
message: result.error ?? 'Plugin worker failed for an unknown reason.',
|
|
193
|
+
hint: 'Check the plugin code for an unhandled error, an infinite loop, or excessive memory use.',
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=worker-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-runner.js","sourceRoot":"","sources":["../../src/host/worker-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAI5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AAStE;;;;;;;;;;;;;GAaG;AAEH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,4BAA4B,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;AA6BhF,MAAM,kBAAkB,GAAG,IAAI,CAAA;AAC/B,MAAM,6BAA6B,GAAG,EAAE,CAAA;AAkBxC;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,kCAAkC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;AAC9E,CAAC;AAED,IAAI,aAAa,GAAG,CAAC,CAAA;AAErB;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAC1B,OAA6B,EAC7B,QAAqD,EACrD,mBAAsC,EACtC,MAAc;IAEd,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,KAAK,GAA2B;YACpC,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,mCAAmC,OAAO,CAAC,MAAM,GAAG;SAC9D,CAAA;QACD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QACzB,OAAM;IACR,CAAC;IACD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,mBAAmB,EAAE,CAAC,CAAA;QAClE,MAAM,KAAK,GAA2B,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAA;QAC3F,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAA2B;YACpC,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAA;QACD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,OAAO,GAAuB,EAAE;IAEhC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;IACzD,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAA;IAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAA;IACvC,MAAM,EAAE,GAAG,aAAa,CAAA;IACxB,aAAa,IAAI,CAAC,CAAA;IAElB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,iBAAiB,EAAE;QAC3C,wEAAwE;QACxE,wEAAwE;QACxE,kEAAkE;QAClE,qEAAqE;QACrE,6DAA6D;QAC7D,GAAG,EAAE,EAAE;QACP,IAAI,EAAE,EAAE;QACR,cAAc,EAAE;YACd,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,6BAA6B;YACvF,wBAAwB,EAAE,EAAE;SAC7B;QACD,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,KAAK;KACd,CAAC,CAAA;IAEF,OAAO,MAAM,IAAI,OAAO,CAAoB,CAAC,OAAO,EAAE,EAAE;QACtD,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,MAAM,MAAM,GAAG,CAAC,MAAyB,EAAQ,EAAE;YACjD,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,KAAK,MAAM,CAAC,SAAS,EAAE,CAAA;YACvB,OAAO,CAAC,MAAM,CAAC,CAAA;QACjB,CAAC,CAAA;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;QAC5E,CAAC,EAAE,SAAS,CAAC,CAAA;QAEb,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,qEAAqE;QACrE,4DAA4D;QAC5D,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAA2B,EAAE,EAAE;YACnD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;gBAC1C,OAAM;YACR,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;gBAC7C,OAAM;YACR,CAAC;YACD,KAAK,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACzE,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC/B,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACnB,MAAM,OAAO,GAAG,kCAAkC,QAAQ,EAAE,CAAA;gBAC5D,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;YACxD,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,MAAM,OAAO,GAAqB,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAA;QAChF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,CAAC,CAAC,CAAA;AACJ,CAAC;AAiBD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAwB,EACxB,IAAY,EACZ,MAA8B,EAC9B,OAAyB;IAEzB,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5E,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,WAAW,QAAQ,CAAC,IAAI,kBAAkB,eAAe,CAAC,MAAM,WAAW,eAAe,CAAC,UAAU,sBAAsB;YACpI,IAAI,EAAE,wEAAwE;YAC9E,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE;SACvE,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,mBAAmB,GAAG,0BAA0B,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACxE,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAA;IAE3E,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC9E,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9E,OAAO,CAAC,gBAAgB,EAAE,CAAC;YACzB,UAAU,EAAE,QAAQ,CAAC,IAAI;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;SACjE,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,4HAA4H;AAC5H,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,OAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC/C,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC,KAAK,CAAA;IAClC,MAAM,IAAI,YAAY,CAAC;QACrB,IAAI,EACF,MAAM,CAAC,KAAK,KAAK,yBAAyB;YACxC,CAAC,CAAC,uBAAuB;YACzB,CAAC,CAAC,6BAA6B;QACnC,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,6CAA6C;QACtE,IAAI,EAAE,0FAA0F;KACjG,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type { CapabilityCallContext, CapabilityHandler } from './host/capabilities.js';
|
|
2
|
+
export { createContentReadHandler, createHttpFetchHandler, createStorageReadHandler, createStorageWriteHandler, } from './host/capabilities.js';
|
|
3
|
+
export type { IsolatedRunResult, PluginDisabledEvent, RunIsolatedOptions, RunPluginOptions, } from './host/worker-runner.js';
|
|
4
|
+
export { runIsolated, runIsolatedOrThrow, runPlugin } from './host/worker-runner.js';
|
|
5
|
+
export type { LoadPluginOptions, PluginSource, ResolvedPlugin } from './loader.js';
|
|
6
|
+
export { loadPlugin, PLUGIN_MANIFEST_FILE_NAMES, resolveSignatureStatus } from './loader.js';
|
|
7
|
+
export type { PluginBlockProvision, PluginCapabilityName, PluginManifest, PluginManifestIssue, PluginProvides, PluginRuntime, } from './manifest.js';
|
|
8
|
+
export { definePlugin, PLUGIN_CAPABILITY_NAMES, PLUGIN_RUNTIMES, } from './manifest.js';
|
|
9
|
+
export type { PluginCapabilityDescription, PluginCapabilityRisk, } from './permissions/describe.js';
|
|
10
|
+
export { DESCRIBABLE_CAPABILITY_NAMES, describeCapability } from './permissions/describe.js';
|
|
11
|
+
export type { PluginDisabledRecord, PluginDisableStore, PluginViolationReason, } from './permissions/disabled.js';
|
|
12
|
+
export { createPluginDisableStore } from './permissions/disabled.js';
|
|
13
|
+
export type { PluginGrant, PluginGrantStore } from './permissions/grants.js';
|
|
14
|
+
export { createPluginGrantStore } from './permissions/grants.js';
|
|
15
|
+
export { detectCapabilitiesNeedingApproval, resolveGrantedCapabilities, } from './permissions/resolve.js';
|
|
16
|
+
export type { GrantedCapabilityReview, PendingCapabilityReview, } from './permissions/review.js';
|
|
17
|
+
export { describePendingApproval, listGrantedCapabilities, revokeCapability, } from './permissions/review.js';
|
|
18
|
+
export { ensurePluginTables, PERMISSION_TABLES } from './permissions/tables.js';
|
|
19
|
+
export type { PluginRegistry, PluginRegistryOptions, PluginReviewDecision, PluginReviewResult, PluginSubmissionEntry, PluginSubmissionInput, PluginSubmissionStatus, } from './registries/plugins.js';
|
|
20
|
+
export { createPluginRegistry } from './registries/plugins.js';
|
|
21
|
+
export type { SkillRegistry, SkillReviewDecision, SkillReviewResult, SkillSubmissionEntry, SkillSubmissionInput, SkillSubmissionStatus, } from './registries/skills.js';
|
|
22
|
+
export { createSkillRegistry } from './registries/skills.js';
|
|
23
|
+
export type { SkinGallery, SkinGalleryEntry, SkinSubmissionInput, SkinSubmissionStatus, } from './registries/skins.js';
|
|
24
|
+
export { createSkinGallery } from './registries/skins.js';
|
|
25
|
+
export { ensureRegistryTables, REGISTRY_TABLES } from './registries/tables.js';
|
|
26
|
+
export type { ThemeRegistry, ThemeRegistryEntry, ThemeRegistryOptions, ThemeSubmissionInput, ThemeSubmissionStatus, } from './registries/themes.js';
|
|
27
|
+
export { createThemeRegistry } from './registries/themes.js';
|
|
28
|
+
export type { SemverVersion } from './semver.js';
|
|
29
|
+
export { compareVersions, parseVersion, satisfiesRange } from './semver.js';
|
|
30
|
+
export type { SigningKeyPair } from './signing/keys.js';
|
|
31
|
+
export { exportPrivateKey, exportPublicKey, generateSigningKeyPair } from './signing/keys.js';
|
|
32
|
+
export { canonicalizeContent, canonicalizeManifest, signContent, signManifest, } from './signing/sign.js';
|
|
33
|
+
export { readSignatureFile, TRUSTED_REGISTRY_PUBLIC_KEYS, verifyContentAgainstTrustedKeys, verifyContentSignature, verifyManifestSignature, verifyPluginSignature, } from './signing/verify.js';
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { createContentReadHandler, createHttpFetchHandler, createStorageReadHandler, createStorageWriteHandler, } from './host/capabilities.js';
|
|
2
|
+
export { runIsolated, runIsolatedOrThrow, runPlugin } from './host/worker-runner.js';
|
|
3
|
+
export { loadPlugin, PLUGIN_MANIFEST_FILE_NAMES, resolveSignatureStatus } from './loader.js';
|
|
4
|
+
export { definePlugin, PLUGIN_CAPABILITY_NAMES, PLUGIN_RUNTIMES, } from './manifest.js';
|
|
5
|
+
export { DESCRIBABLE_CAPABILITY_NAMES, describeCapability } from './permissions/describe.js';
|
|
6
|
+
export { createPluginDisableStore } from './permissions/disabled.js';
|
|
7
|
+
export { createPluginGrantStore } from './permissions/grants.js';
|
|
8
|
+
export { detectCapabilitiesNeedingApproval, resolveGrantedCapabilities, } from './permissions/resolve.js';
|
|
9
|
+
export { describePendingApproval, listGrantedCapabilities, revokeCapability, } from './permissions/review.js';
|
|
10
|
+
export { ensurePluginTables, PERMISSION_TABLES } from './permissions/tables.js';
|
|
11
|
+
export { createPluginRegistry } from './registries/plugins.js';
|
|
12
|
+
export { createSkillRegistry } from './registries/skills.js';
|
|
13
|
+
export { createSkinGallery } from './registries/skins.js';
|
|
14
|
+
export { ensureRegistryTables, REGISTRY_TABLES } from './registries/tables.js';
|
|
15
|
+
export { createThemeRegistry } from './registries/themes.js';
|
|
16
|
+
export { compareVersions, parseVersion, satisfiesRange } from './semver.js';
|
|
17
|
+
export { exportPrivateKey, exportPublicKey, generateSigningKeyPair } from './signing/keys.js';
|
|
18
|
+
export { canonicalizeContent, canonicalizeManifest, signContent, signManifest, } from './signing/sign.js';
|
|
19
|
+
export { readSignatureFile, TRUSTED_REGISTRY_PUBLIC_KEYS, verifyContentAgainstTrustedKeys, verifyContentSignature, verifyManifestSignature, verifyPluginSignature, } from './signing/verify.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAA;AAO/B,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEpF,OAAO,EAAE,UAAU,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAS5F,OAAO,EACL,YAAY,EACZ,uBAAuB,EACvB,eAAe,GAChB,MAAM,eAAe,CAAA;AAKtB,OAAO,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAM5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EACL,iCAAiC,EACjC,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA;AAKjC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAU/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAS9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAO5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAQ9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE3E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC7F,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,YAAY,GACb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,+BAA+B,EAC/B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,qBAAqB,CAAA"}
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type PluginManifest } from './manifest.js';
|
|
2
|
+
/**
|
|
3
|
+
* Where a resolved plugin came from — structural, not cosmetic: task 9
|
|
4
|
+
* (signing) and the permissions screen's "avertissement permanent" both key
|
|
5
|
+
* off this. A `local`/`git` plugin is allowed in development mode without a
|
|
6
|
+
* signature; a `registry` plugin is not.
|
|
7
|
+
*/
|
|
8
|
+
export type PluginSource = 'registry' | 'local' | 'git';
|
|
9
|
+
/**
|
|
10
|
+
* Checked in order, mirroring `@cogenta/core`'s `CONFIG_FILE_NAMES`
|
|
11
|
+
* (`load-config.ts`) exactly — a plugin's manifest is a user-authored file
|
|
12
|
+
* loaded the same way `cogenta.config.mjs`/`cogenta.schema.mjs` already are,
|
|
13
|
+
* not a bespoke new mechanism.
|
|
14
|
+
*/
|
|
15
|
+
export declare const PLUGIN_MANIFEST_FILE_NAMES: readonly ['plugin.manifest.ts', 'plugin.manifest.mts', 'plugin.manifest.js', 'plugin.manifest.mjs'];
|
|
16
|
+
export interface ResolvedPlugin {
|
|
17
|
+
readonly manifest: PluginManifest;
|
|
18
|
+
readonly source: PluginSource;
|
|
19
|
+
/** Absolute path to the package root that was resolved. */
|
|
20
|
+
readonly packageRoot: string;
|
|
21
|
+
/** Absolute path to the manifest file that was loaded. */
|
|
22
|
+
readonly manifestPath: string;
|
|
23
|
+
/** Whether `manifest.engine` is satisfied by `engineVersion` (`loadPlugin`'s option). */
|
|
24
|
+
readonly engineCompatible: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* `true` only for a `local` (or, once resolvable, `git`) source: allowed
|
|
27
|
+
* to run unsigned, "en mode développement" — the real datum a later admin
|
|
28
|
+
* banner's "avertissement permanent" would render. A `registry` plugin is
|
|
29
|
+
* never dev mode: it either verified or `loadPlugin` already refused it.
|
|
30
|
+
*/
|
|
31
|
+
readonly devMode: boolean;
|
|
32
|
+
/** `true` only when a `registry` plugin's signature was checked and matched a trusted key. Always `false` in dev mode — there was nothing to check. */
|
|
33
|
+
readonly signatureVerified: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface LoadPluginOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Cogenta's own version, checked against `manifest.engine`. No real,
|
|
38
|
+
* meaningful Cogenta version exists anywhere yet (pre-alpha; the root
|
|
39
|
+
* `package.json` carries no `version` field, and every workspace package
|
|
40
|
+
* still uses the `0.0.0` placeholder) — `engineCompatible` is real and
|
|
41
|
+
* correctly computed against whatever is passed here, but until a real
|
|
42
|
+
* versioning scheme exists, pass a real Cogenta version explicitly when
|
|
43
|
+
* one exists; the default below is a placeholder that makes every plugin
|
|
44
|
+
* appear compatible, which is the honest behaviour of "no check exists
|
|
45
|
+
* yet" rather than a fabricated pass/fail.
|
|
46
|
+
*/
|
|
47
|
+
readonly engineVersion?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Base64 SPKI Ed25519 public keys this call trusts for `registry`-source
|
|
50
|
+
* signature verification. Defaults to `TRUSTED_REGISTRY_PUBLIC_KEYS`
|
|
51
|
+
* (`./signing/verify.js`) — empty until a real registry exists, so every
|
|
52
|
+
* `registry` plugin fails verification by default rather than trusting a
|
|
53
|
+
* placeholder key.
|
|
54
|
+
*/
|
|
55
|
+
readonly trustedPublicKeys?: readonly string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* `source: 'registry'` is where "## Signature" (docs/lots/L7-extensibilite.md)
|
|
59
|
+
* actually bites: "Une signature invalide bloque, sans possibilité de passer
|
|
60
|
+
* outre depuis l'interface." There is deliberately no parameter here that
|
|
61
|
+
* lets a caller force past a missing/invalid signature — the only way past
|
|
62
|
+
* this function is a real, matching signature, because the override this
|
|
63
|
+
* shape could otherwise offer is exactly what the lot's own line means by
|
|
64
|
+
* "sans possibilité de passer outre." `local`/`git` sources skip
|
|
65
|
+
* verification entirely, by design ("autorisé en mode développement"), and
|
|
66
|
+
* are reported back as `devMode: true` for a future admin banner to render
|
|
67
|
+
* as the "avertissement permanent" the lot also asks for.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveSignatureStatus(source: PluginSource, manifest: PluginManifest, manifestPath: string, trustedPublicKeys: readonly string[]): Promise<{
|
|
70
|
+
readonly devMode: boolean;
|
|
71
|
+
readonly signatureVerified: boolean;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Resolves a plugin reference to its package root and source kind, loads
|
|
75
|
+
* and validates its manifest (via `definePlugin`), verifies its signature
|
|
76
|
+
* when required, and reports engine compatibility. Executes no plugin code
|
|
77
|
+
* beyond importing the manifest-declaring module — spawning a worker to run
|
|
78
|
+
* the plugin's actual runtime is task 3, not this one.
|
|
79
|
+
*/
|
|
80
|
+
export declare function loadPlugin(reference: string, options?: LoadPluginOptions): Promise<ResolvedPlugin>;
|
|
81
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAQjE;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAA;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,YACrC,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,CACb,CAAA;AAEV,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAA;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,uJAAuJ;IACvJ,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;CACpC;AA4ED,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/C;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,cAAc,EACxB,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAAC,CA0B7E;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAiCzB"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { access, stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname, isAbsolute, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
|
+
import { CogentaError } from '@cogenta/core';
|
|
5
|
+
import { definePlugin } from './manifest.js';
|
|
6
|
+
import { satisfiesRange } from './semver.js';
|
|
7
|
+
import { readSignatureFile, TRUSTED_REGISTRY_PUBLIC_KEYS, verifyPluginSignature, } from './signing/verify.js';
|
|
8
|
+
/**
|
|
9
|
+
* Checked in order, mirroring `@cogenta/core`'s `CONFIG_FILE_NAMES`
|
|
10
|
+
* (`load-config.ts`) exactly — a plugin's manifest is a user-authored file
|
|
11
|
+
* loaded the same way `cogenta.config.mjs`/`cogenta.schema.mjs` already are,
|
|
12
|
+
* not a bespoke new mechanism.
|
|
13
|
+
*/
|
|
14
|
+
export const PLUGIN_MANIFEST_FILE_NAMES = [
|
|
15
|
+
'plugin.manifest.ts',
|
|
16
|
+
'plugin.manifest.mts',
|
|
17
|
+
'plugin.manifest.js',
|
|
18
|
+
'plugin.manifest.mjs',
|
|
19
|
+
];
|
|
20
|
+
async function exists(path) {
|
|
21
|
+
try {
|
|
22
|
+
await access(path);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A git reference: `git+https://...`, a bare `https://...\.git`, or the
|
|
31
|
+
* `github:owner/repo` shorthand. Cloning it is a real network/filesystem
|
|
32
|
+
* operation this task deliberately does not build — "résolution" here means
|
|
33
|
+
* "recognise a git source and refuse honestly," not "implement a git
|
|
34
|
+
* client." A local checkout of a git-sourced plugin is loaded exactly like
|
|
35
|
+
* any other local path once it exists on disk.
|
|
36
|
+
*/
|
|
37
|
+
function isGitReference(reference) {
|
|
38
|
+
return (reference.startsWith('git+') ||
|
|
39
|
+
reference.startsWith('github:') ||
|
|
40
|
+
/^https?:\/\/.+\.git$/.test(reference));
|
|
41
|
+
}
|
|
42
|
+
function looksLikeLocalPath(reference) {
|
|
43
|
+
return reference.startsWith('.') || reference.startsWith('/') || isAbsolute(reference);
|
|
44
|
+
}
|
|
45
|
+
async function findManifestFile(packageRoot) {
|
|
46
|
+
for (const name of PLUGIN_MANIFEST_FILE_NAMES) {
|
|
47
|
+
const candidate = join(packageRoot, name);
|
|
48
|
+
if (await exists(candidate))
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
throw new CogentaError({
|
|
52
|
+
code: 'PLUGIN_MANIFEST_FILE_NOT_FOUND',
|
|
53
|
+
message: `No plugin manifest found in ${packageRoot}.`,
|
|
54
|
+
hint: `Add one of: ${PLUGIN_MANIFEST_FILE_NAMES.join(', ')}.`,
|
|
55
|
+
details: { packageRoot },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function importManifest(manifestPath) {
|
|
59
|
+
let module;
|
|
60
|
+
try {
|
|
61
|
+
module = (await import(pathToFileURL(manifestPath).href));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new CogentaError({
|
|
65
|
+
code: 'PLUGIN_MANIFEST_LOAD_FAILED',
|
|
66
|
+
message: `Could not load ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
67
|
+
hint: manifestPath.endsWith('.ts')
|
|
68
|
+
? 'A TypeScript manifest needs a Node runtime that strips types (Node 22.18+). Use plugin.manifest.mjs on an older one.'
|
|
69
|
+
: 'Check the file for a syntax error, and that every import it uses is installed.',
|
|
70
|
+
cause: error,
|
|
71
|
+
details: { manifestPath },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (module.default === undefined) {
|
|
75
|
+
throw new CogentaError({
|
|
76
|
+
code: 'PLUGIN_MANIFEST_EXPORT_INVALID',
|
|
77
|
+
message: `${manifestPath} has no default export.`,
|
|
78
|
+
hint: 'Export the manifest as the default: `export default definePlugin({ … })`.',
|
|
79
|
+
details: { manifestPath },
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// `definePlugin` re-validates even though a well-formed manifest module
|
|
83
|
+
// already called it once at module-load time — a manifest file could
|
|
84
|
+
// export a plain object instead of calling `definePlugin` itself, and
|
|
85
|
+
// this is the only place that can catch that.
|
|
86
|
+
return definePlugin(module.default);
|
|
87
|
+
}
|
|
88
|
+
const NO_REAL_ENGINE_VERSION_YET = '0.0.0';
|
|
89
|
+
/**
|
|
90
|
+
* `source: 'registry'` is where "## Signature" (docs/lots/L7-extensibilite.md)
|
|
91
|
+
* actually bites: "Une signature invalide bloque, sans possibilité de passer
|
|
92
|
+
* outre depuis l'interface." There is deliberately no parameter here that
|
|
93
|
+
* lets a caller force past a missing/invalid signature — the only way past
|
|
94
|
+
* this function is a real, matching signature, because the override this
|
|
95
|
+
* shape could otherwise offer is exactly what the lot's own line means by
|
|
96
|
+
* "sans possibilité de passer outre." `local`/`git` sources skip
|
|
97
|
+
* verification entirely, by design ("autorisé en mode développement"), and
|
|
98
|
+
* are reported back as `devMode: true` for a future admin banner to render
|
|
99
|
+
* as the "avertissement permanent" the lot also asks for.
|
|
100
|
+
*/
|
|
101
|
+
export async function resolveSignatureStatus(source, manifest, manifestPath, trustedPublicKeys) {
|
|
102
|
+
if (source !== 'registry') {
|
|
103
|
+
return { devMode: true, signatureVerified: false };
|
|
104
|
+
}
|
|
105
|
+
const signature = await readSignatureFile(manifestPath);
|
|
106
|
+
if (signature === null) {
|
|
107
|
+
throw new CogentaError({
|
|
108
|
+
code: 'PLUGIN_SIGNATURE_MISSING',
|
|
109
|
+
message: `Plugin "${manifest.name}" has no signature file at ${manifestPath}.sig.`,
|
|
110
|
+
hint: 'Registry plugins must be signed. Install from a local path for unsigned development use.',
|
|
111
|
+
details: { pluginName: manifest.name, manifestPath },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const verified = verifyPluginSignature(manifest, signature, trustedPublicKeys);
|
|
115
|
+
if (!verified) {
|
|
116
|
+
throw new CogentaError({
|
|
117
|
+
code: 'PLUGIN_SIGNATURE_INVALID',
|
|
118
|
+
message: `Plugin "${manifest.name}"'s signature does not match any trusted key.`,
|
|
119
|
+
hint: 'The package may be tampered with, or its signing key is not (yet) trusted by this installation.',
|
|
120
|
+
details: { pluginName: manifest.name, manifestPath },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return { devMode: false, signatureVerified: true };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolves a plugin reference to its package root and source kind, loads
|
|
127
|
+
* and validates its manifest (via `definePlugin`), verifies its signature
|
|
128
|
+
* when required, and reports engine compatibility. Executes no plugin code
|
|
129
|
+
* beyond importing the manifest-declaring module — spawning a worker to run
|
|
130
|
+
* the plugin's actual runtime is task 3, not this one.
|
|
131
|
+
*/
|
|
132
|
+
export async function loadPlugin(reference, options = {}) {
|
|
133
|
+
const engineVersion = options.engineVersion ?? NO_REAL_ENGINE_VERSION_YET;
|
|
134
|
+
const trustedPublicKeys = options.trustedPublicKeys ?? TRUSTED_REGISTRY_PUBLIC_KEYS;
|
|
135
|
+
if (isGitReference(reference)) {
|
|
136
|
+
throw new CogentaError({
|
|
137
|
+
code: 'PLUGIN_SOURCE_NOT_FOUND',
|
|
138
|
+
message: `Git-sourced plugins are not resolvable yet: "${reference}".`,
|
|
139
|
+
hint: 'Clone the repository locally and pass its local path instead.',
|
|
140
|
+
details: { reference },
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const source = looksLikeLocalPath(reference) ? 'local' : 'registry';
|
|
144
|
+
const packageRoot = await resolvePackageRoot(reference, source);
|
|
145
|
+
const manifestPath = await findManifestFile(packageRoot);
|
|
146
|
+
const manifest = await importManifest(manifestPath);
|
|
147
|
+
const { devMode, signatureVerified } = await resolveSignatureStatus(source, manifest, manifestPath, trustedPublicKeys);
|
|
148
|
+
return {
|
|
149
|
+
manifest,
|
|
150
|
+
source,
|
|
151
|
+
packageRoot,
|
|
152
|
+
manifestPath,
|
|
153
|
+
engineCompatible: satisfiesRange(engineVersion, manifest.engine),
|
|
154
|
+
devMode,
|
|
155
|
+
signatureVerified,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
async function resolvePackageRoot(reference, source) {
|
|
159
|
+
if (source === 'local') {
|
|
160
|
+
const stats = await stat(reference).catch(() => null);
|
|
161
|
+
if (stats === null || !stats.isDirectory()) {
|
|
162
|
+
throw new CogentaError({
|
|
163
|
+
code: 'PLUGIN_SOURCE_NOT_FOUND',
|
|
164
|
+
message: `No plugin directory at "${reference}".`,
|
|
165
|
+
hint: 'Check the path — it must be an existing directory.',
|
|
166
|
+
details: { reference },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return reference;
|
|
170
|
+
}
|
|
171
|
+
// A registry package name: resolved via Node's own ESM resolution, the
|
|
172
|
+
// same mechanism any other workspace/npm dependency uses — no bespoke
|
|
173
|
+
// registry client. `import.meta.resolve` throws `ERR_MODULE_NOT_FOUND` on
|
|
174
|
+
// a package that is not installed, which is exactly the failure this task
|
|
175
|
+
// needs to report.
|
|
176
|
+
try {
|
|
177
|
+
const resolvedUrl = import.meta.resolve(`${reference}/package.json`);
|
|
178
|
+
return dirname(fileURLToPath(resolvedUrl));
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
throw new CogentaError({
|
|
182
|
+
code: 'PLUGIN_SOURCE_NOT_FOUND',
|
|
183
|
+
message: `Could not resolve plugin package "${reference}": ${error instanceof Error ? error.message : String(error)}`,
|
|
184
|
+
hint: 'Install the plugin package, or pass a local path instead.',
|
|
185
|
+
cause: error,
|
|
186
|
+
details: { reference },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
|