@dsh-enhanced/assistant-verifier 0.1.47 → 0.1.49
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/README.md +89 -0
- package/lib/config.d.ts +8 -0
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +4 -0
- package/lib/config.js.map +1 -1
- package/lib/creation-review-native.d.ts +30 -0
- package/lib/creation-review-native.d.ts.map +1 -0
- package/lib/creation-review-native.js +130 -0
- package/lib/creation-review-native.js.map +1 -0
- package/lib/creation-review-store.d.ts +29 -0
- package/lib/creation-review-store.d.ts.map +1 -0
- package/lib/creation-review-store.js +206 -0
- package/lib/creation-review-store.js.map +1 -0
- package/lib/creation-review.d.ts +159 -0
- package/lib/creation-review.d.ts.map +1 -0
- package/lib/creation-review.js +511 -0
- package/lib/creation-review.js.map +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/memory-review-native.d.ts +38 -0
- package/lib/memory-review-native.d.ts.map +1 -0
- package/lib/memory-review-native.js +149 -0
- package/lib/memory-review-native.js.map +1 -0
- package/lib/memory-review.d.ts +48 -0
- package/lib/memory-review.d.ts.map +1 -0
- package/lib/memory-review.js +260 -0
- package/lib/memory-review.js.map +1 -0
- package/lib/plugin-behavior-runner.d.ts +46 -0
- package/lib/plugin-behavior-runner.d.ts.map +1 -0
- package/lib/plugin-behavior-runner.js +437 -0
- package/lib/plugin-behavior-runner.js.map +1 -0
- package/lib/revision-regression-review.d.ts +38 -0
- package/lib/revision-regression-review.d.ts.map +1 -0
- package/lib/revision-regression-review.js +315 -0
- package/lib/revision-regression-review.js.map +1 -0
- package/lib/revision-review.d.ts +99 -0
- package/lib/revision-review.d.ts.map +1 -0
- package/lib/revision-review.js +275 -0
- package/lib/revision-review.js.map +1 -0
- package/lib/service.d.ts +30 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +139 -1
- package/lib/service.js.map +1 -1
- package/lib/source-review-native.d.ts +9 -0
- package/lib/source-review-native.d.ts.map +1 -1
- package/lib/source-review-native.js +6 -5
- package/lib/source-review-native.js.map +1 -1
- package/lib/source-review-store.d.ts +4 -0
- package/lib/source-review-store.d.ts.map +1 -1
- package/lib/source-review-store.js +65 -12
- package/lib/source-review-store.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +34 -25
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { IsolatedVerifierRunner } from '@dsh-enhanced/assistant-isolation';
|
|
3
|
+
const MAX_PACK_BYTES = 512 * 1024;
|
|
4
|
+
const MAX_OPERATION_BYTES = 64 * 1024;
|
|
5
|
+
const MAX_WORKER_OUTPUT_BYTES = 64 * 1024;
|
|
6
|
+
const SHA256 = /^[a-f0-9]{64}$/u;
|
|
7
|
+
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/u;
|
|
8
|
+
const SAFE_TOOL = /^[a-z][a-z0-9_-]{0,95}$/u;
|
|
9
|
+
const COMMAND = 'exec /usr/bin/env LD_PRELOAD=/opt/dsh-plugin-verifier/parent-protect.so /usr/local/bin/node --disable-sigusr1 /opt/dsh-plugin-verifier/worker.mjs';
|
|
10
|
+
const BOUNDARY = 'process-seccomp-v1';
|
|
11
|
+
function canonicalJson(value) {
|
|
12
|
+
try {
|
|
13
|
+
if (!deepJson(value))
|
|
14
|
+
return undefined;
|
|
15
|
+
const serialized = JSON.stringify(value);
|
|
16
|
+
return serialized === undefined ? undefined : serialized;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function deepJson(value, seen = new Set()) {
|
|
23
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
24
|
+
return true;
|
|
25
|
+
if (typeof value === 'number')
|
|
26
|
+
return Number.isFinite(value);
|
|
27
|
+
if (typeof value !== 'object' || seen.has(value))
|
|
28
|
+
return false;
|
|
29
|
+
seen.add(value);
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
const valid = value.every(item => deepJson(item, seen));
|
|
32
|
+
seen.delete(value);
|
|
33
|
+
return valid;
|
|
34
|
+
}
|
|
35
|
+
if (Object.getPrototypeOf(value) !== Object.prototype)
|
|
36
|
+
return false;
|
|
37
|
+
const valid = Object.keys(value).every(key => {
|
|
38
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
39
|
+
return descriptor !== undefined && Object.hasOwn(descriptor, 'value') && deepJson(descriptor.value, seen);
|
|
40
|
+
});
|
|
41
|
+
seen.delete(value);
|
|
42
|
+
return valid;
|
|
43
|
+
}
|
|
44
|
+
function validOperation(value) {
|
|
45
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
46
|
+
return false;
|
|
47
|
+
const operation = value;
|
|
48
|
+
if (operation.kind === 'discover')
|
|
49
|
+
return Object.keys(operation).length === 1;
|
|
50
|
+
if (operation.kind !== 'invoke' || typeof operation.schemaDigest !== 'string' || !SHA256.test(operation.schemaDigest)
|
|
51
|
+
|| !Array.isArray(operation.calls) || operation.calls.length < 1 || operation.calls.length > 8
|
|
52
|
+
|| Object.keys(operation).length !== 3)
|
|
53
|
+
return false;
|
|
54
|
+
const ids = new Set();
|
|
55
|
+
for (const call of operation.calls) {
|
|
56
|
+
if (!call || typeof call !== 'object' || Object.keys(call).length !== 3
|
|
57
|
+
|| !SAFE_ID.test(call.id) || !SAFE_TOOL.test(call.toolName) || ids.has(call.id) || !deepJson(call.arguments))
|
|
58
|
+
return false;
|
|
59
|
+
ids.add(call.id);
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
function validObservation(value, operation, sha256) {
|
|
64
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
65
|
+
return false;
|
|
66
|
+
const record = value;
|
|
67
|
+
if (record.schemaVersion !== 2 || record.boundary !== BOUNDARY || record.status !== 'observed' || record.artifactSha256 !== sha256
|
|
68
|
+
|| record.quiescent !== true || !SHA256.test(record.schemaDigest)
|
|
69
|
+
|| !record.environment || typeof record.environment !== 'object')
|
|
70
|
+
return false;
|
|
71
|
+
const environment = record.environment;
|
|
72
|
+
if (['node', 'cordis', 'tools', 'systemPrompt'].some(key => typeof environment[key] !== 'string'
|
|
73
|
+
|| environment[key].length > 80))
|
|
74
|
+
return false;
|
|
75
|
+
if (operation.kind === 'discover') {
|
|
76
|
+
if (!Array.isArray(record.schemas) || record.schemas.length < 1 || record.schemas.length > 64 || record.calls !== undefined)
|
|
77
|
+
return false;
|
|
78
|
+
if (createHash('sha256').update(JSON.stringify(record.schemas)).digest('hex') !== record.schemaDigest)
|
|
79
|
+
return false;
|
|
80
|
+
const names = new Set();
|
|
81
|
+
for (const schema of record.schemas) {
|
|
82
|
+
if (!schema || typeof schema !== 'object' || !SAFE_TOOL.test(schema.name ?? '')
|
|
83
|
+
|| names.has(schema.name))
|
|
84
|
+
return false;
|
|
85
|
+
names.add(schema.name);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (!Array.isArray(record.calls) || record.calls.length !== operation.calls.length
|
|
89
|
+
|| record.schemaDigest !== operation.schemaDigest || record.schemas !== undefined
|
|
90
|
+
|| record.calls.some((call, index) => !call || typeof call !== 'object'
|
|
91
|
+
|| call.id !== operation.calls[index].id
|
|
92
|
+
|| call.toolName !== operation.calls[index].toolName
|
|
93
|
+
|| !Object.hasOwn(call, 'result')))
|
|
94
|
+
return false;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
/** Host-only behavior observation. The candidate and worker receive no oracle or promotion authority. */
|
|
98
|
+
export class PluginBehaviorRunner {
|
|
99
|
+
#runner;
|
|
100
|
+
constructor(input) {
|
|
101
|
+
if (input.maxOutputBytes < MAX_WORKER_OUTPUT_BYTES)
|
|
102
|
+
throw new Error('plugin behavior output budget must be at least 64 KiB');
|
|
103
|
+
this.#runner = new IsolatedVerifierRunner({ ...input, command: COMMAND });
|
|
104
|
+
}
|
|
105
|
+
async run(input) {
|
|
106
|
+
const artifactSha256 = Buffer.isBuffer(input.artifact)
|
|
107
|
+
? createHash('sha256').update(input.artifact).digest('hex') : '';
|
|
108
|
+
const unknown = (reason, quiescent = false, jobId) => ({ status: 'unknown', quiescent, artifactSha256, reason, ...(jobId ? { jobId } : {}) });
|
|
109
|
+
if (!Buffer.isBuffer(input.artifact) || input.artifact.length < 1 || input.artifact.length > MAX_PACK_BYTES)
|
|
110
|
+
return unknown('plugin-artifact-out-of-bound', true);
|
|
111
|
+
try {
|
|
112
|
+
if (!validOperation(input.operation))
|
|
113
|
+
return unknown('plugin-operation-invalid', true);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return unknown('plugin-operation-invalid', true);
|
|
117
|
+
}
|
|
118
|
+
const request = { schemaVersion: 1, sha256: artifactSha256, sizeBytes: input.artifact.length, operation: input.operation };
|
|
119
|
+
const stdin = canonicalJson(request);
|
|
120
|
+
if (stdin === undefined || Buffer.byteLength(stdin) > MAX_OPERATION_BYTES)
|
|
121
|
+
return unknown('plugin-operation-out-of-bound', true);
|
|
122
|
+
let isolated;
|
|
123
|
+
try {
|
|
124
|
+
isolated = await this.#runner.run(input.key, input.artifact.toString('base64'), stdin, input.signal);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return unknown('plugin-runner-unavailable');
|
|
128
|
+
}
|
|
129
|
+
if (isolated.status !== 'succeeded' || isolated.quiescent !== true || isolated.exitCode !== 0)
|
|
130
|
+
return unknown(isolated.reason ?? 'plugin-runner-unsettled', isolated.quiescent, isolated.jobId);
|
|
131
|
+
if (Buffer.byteLength(isolated.stdout) > MAX_WORKER_OUTPUT_BYTES || !isolated.stdout.endsWith('\n')
|
|
132
|
+
|| isolated.stdout.indexOf('\n') !== isolated.stdout.length - 1)
|
|
133
|
+
return unknown('plugin-worker-output-invalid', true, isolated.jobId);
|
|
134
|
+
try {
|
|
135
|
+
const value = JSON.parse(isolated.stdout.slice(0, -1));
|
|
136
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
137
|
+
const record = value;
|
|
138
|
+
if (record.schemaVersion === 2 && record.boundary === BOUNDARY && record.status === 'unknown'
|
|
139
|
+
&& typeof record.reason === 'string' && record.reason.length > 0 && record.reason.length <= 128
|
|
140
|
+
&& Object.keys(record).length === 4)
|
|
141
|
+
return unknown(record.reason, true, isolated.jobId);
|
|
142
|
+
}
|
|
143
|
+
if (!validObservation(value, input.operation, artifactSha256))
|
|
144
|
+
return unknown('plugin-worker-observation-invalid', true, isolated.jobId);
|
|
145
|
+
const observation = value;
|
|
146
|
+
return { status: 'observed', quiescent: true, artifactSha256, jobId: isolated.jobId,
|
|
147
|
+
environment: observation.environment, schemaDigest: observation.schemaDigest,
|
|
148
|
+
...(input.operation.kind === 'discover' ? { schemas: observation.schemas } : { calls: observation.calls }) };
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return unknown('plugin-worker-output-invalid', true, isolated.jobId);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
close() { return this.#runner.close(); }
|
|
155
|
+
}
|
|
156
|
+
/* DSH_PLUGIN_VERIFIER_WORKER_START
|
|
157
|
+
// Copied verbatim into the manifest-only image by build-plugin-verifier-image.mjs.
|
|
158
|
+
// This code executes inside the isolation worker, never in the Host process.
|
|
159
|
+
import { createHash } from 'node:crypto'
|
|
160
|
+
import { spawn } from 'node:child_process'
|
|
161
|
+
import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
162
|
+
import { dirname, join, resolve } from 'node:path'
|
|
163
|
+
import { gunzipSync } from 'node:zlib'
|
|
164
|
+
|
|
165
|
+
const limit = 512 * 1024
|
|
166
|
+
const safeId = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/
|
|
167
|
+
const safeTool = /^[a-z][a-z0-9_-]{0,95}$/
|
|
168
|
+
const shaPattern = /^[a-f0-9]{64}$/
|
|
169
|
+
const fail = reason => { throw new Error(reason) }
|
|
170
|
+
const digest = bytes => createHash('sha256').update(bytes).digest('hex')
|
|
171
|
+
const text = bytes => {
|
|
172
|
+
const end = bytes.indexOf(0)
|
|
173
|
+
const sliced = end < 0 ? bytes : bytes.subarray(0, end)
|
|
174
|
+
const value = sliced.toString('utf8')
|
|
175
|
+
if (!Buffer.from(value, 'utf8').equals(sliced)) fail('invalid-utf8-tar')
|
|
176
|
+
return value
|
|
177
|
+
}
|
|
178
|
+
const octal = bytes => {
|
|
179
|
+
const raw = text(bytes).trim()
|
|
180
|
+
if (!/^[0-7]+$/.test(raw)) fail('invalid-tar-number')
|
|
181
|
+
const value = Number.parseInt(raw, 8)
|
|
182
|
+
if (!Number.isSafeInteger(value)) fail('invalid-tar-number')
|
|
183
|
+
return value
|
|
184
|
+
}
|
|
185
|
+
const parsePax = bytes => {
|
|
186
|
+
const values = {}
|
|
187
|
+
for (let at = 0; at < bytes.length;) {
|
|
188
|
+
const space = bytes.indexOf(32, at)
|
|
189
|
+
if (space < 0) fail('invalid-pax')
|
|
190
|
+
const size = Number(bytes.subarray(at, space).toString('ascii'))
|
|
191
|
+
if (!Number.isSafeInteger(size) || size <= space - at + 2 || at + size > bytes.length || bytes[at + size - 1] !== 10) fail('invalid-pax')
|
|
192
|
+
const line = bytes.subarray(space + 1, at + size - 1).toString('utf8')
|
|
193
|
+
const equal = line.indexOf('=')
|
|
194
|
+
if (equal < 1 || Object.hasOwn(values, line.slice(0, equal))) fail('invalid-pax')
|
|
195
|
+
values[line.slice(0, equal)] = line.slice(equal + 1)
|
|
196
|
+
at += size
|
|
197
|
+
}
|
|
198
|
+
return values
|
|
199
|
+
}
|
|
200
|
+
function extract(bytes) {
|
|
201
|
+
let tar
|
|
202
|
+
try { tar = gunzipSync(bytes, { maxOutputLength: 16 * 1024 * 1024 }) }
|
|
203
|
+
catch { fail('invalid-or-oversized-tgz') }
|
|
204
|
+
const destination = '/workspace/plugin'
|
|
205
|
+
mkdirSync(destination, { mode: 0o700 })
|
|
206
|
+
let at = 0, extension = {}, global = {}, count = 0
|
|
207
|
+
const seen = new Set()
|
|
208
|
+
while (at + 512 <= tar.length) {
|
|
209
|
+
const header = tar.subarray(at, at + 512)
|
|
210
|
+
if (header.every(byte => byte === 0)) break
|
|
211
|
+
const expectedChecksum = octal(header.subarray(148, 156))
|
|
212
|
+
let checksum = 0
|
|
213
|
+
for (let index = 0; index < 512; index += 1) checksum += index >= 148 && index < 156 ? 32 : header[index]
|
|
214
|
+
if (expectedChecksum !== checksum) fail('invalid-tar-checksum')
|
|
215
|
+
const size = octal(header.subarray(124, 136))
|
|
216
|
+
const end = at + 512 + size
|
|
217
|
+
if (!Number.isSafeInteger(end) || end > tar.length || ++count > 256) fail('invalid-tar-member')
|
|
218
|
+
const kind = String.fromCharCode(header[156] || 48)
|
|
219
|
+
if (kind === 'g' || kind === 'x') {
|
|
220
|
+
if (size > 1_048_576) fail('oversized-tar-extension')
|
|
221
|
+
const parsed = parsePax(tar.subarray(at + 512, end))
|
|
222
|
+
if (kind === 'g') global = { ...global, ...parsed }
|
|
223
|
+
else extension = parsed
|
|
224
|
+
} else {
|
|
225
|
+
const attributes = { ...global, ...extension }
|
|
226
|
+
if (Object.keys(attributes).some(key => !['path', 'mtime', 'atime', 'ctime', 'comment', 'uid', 'gid', 'uname', 'gname', 'mode'].includes(key))) fail('unsupported-tar-extension')
|
|
227
|
+
const prefix = text(header.subarray(345, 500))
|
|
228
|
+
const rawName = prefix ? prefix + '/' + text(header.subarray(0, 100)) : text(header.subarray(0, 100))
|
|
229
|
+
const raw = attributes.path ?? rawName
|
|
230
|
+
const name = typeof raw === 'string' && raw.endsWith('/') ? raw.slice(0, -1) : raw
|
|
231
|
+
if (typeof name !== 'string' || name.length > 256
|
|
232
|
+
|| name !== 'package' && (!name.startsWith('package/')
|
|
233
|
+
|| name.slice(8).split('/').some(part => !part || part === '.' || part === '..' || !/^[A-Za-z0-9._-]+$/.test(part)))) fail('unsafe-tar-path')
|
|
234
|
+
if (seen.has(name) || (kind !== '0' && kind !== '5' && kind !== '7')
|
|
235
|
+
|| name === 'package' && kind !== '5') fail('duplicate-or-unsafe-tar-entry')
|
|
236
|
+
seen.add(name)
|
|
237
|
+
const target = join(destination, name)
|
|
238
|
+
if (resolve(target) !== target || target !== join(destination, 'package') && !target.startsWith(destination + '/')) fail('unsafe-tar-path')
|
|
239
|
+
if (kind === '5') mkdirSync(target, { recursive: true, mode: 0o700 })
|
|
240
|
+
else {
|
|
241
|
+
mkdirSync(dirname(target), { recursive: true, mode: 0o700 })
|
|
242
|
+
writeFileSync(target, tar.subarray(at + 512, end), { flag: 'wx', mode: 0o600 })
|
|
243
|
+
}
|
|
244
|
+
extension = {}
|
|
245
|
+
}
|
|
246
|
+
at = end + (512 - size % 512) % 512
|
|
247
|
+
}
|
|
248
|
+
if (at + 1024 > tar.length || !tar.subarray(at).every(byte => byte === 0)) fail('invalid-tar-trailer')
|
|
249
|
+
if (!seen.has('package/package.json')) fail('missing-package-manifest')
|
|
250
|
+
const manifest = JSON.parse(readFileSync(join(destination, 'package/package.json'), 'utf8'))
|
|
251
|
+
if (!manifest || typeof manifest !== 'object' || typeof manifest.main !== 'string'
|
|
252
|
+
|| !/^\.\/lib\/[A-Za-z0-9._/-]+\.js$/.test(manifest.main)
|
|
253
|
+
|| manifest.main.split('/').includes('..')) fail('invalid-package-entry')
|
|
254
|
+
const entry = join(destination, 'package', manifest.main)
|
|
255
|
+
if (!existsSync(entry)) fail('missing-package-entry')
|
|
256
|
+
symlinkSync('/opt/dsh-plugin-verifier/node_modules', join(destination, 'package/node_modules'))
|
|
257
|
+
return entry
|
|
258
|
+
}
|
|
259
|
+
function validOperation(value) {
|
|
260
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false
|
|
261
|
+
if (value.kind === 'discover') return Object.keys(value).length === 1
|
|
262
|
+
if (value.kind !== 'invoke' || Object.keys(value).length !== 3 || !shaPattern.test(value.schemaDigest)
|
|
263
|
+
|| !Array.isArray(value.calls) || value.calls.length < 1 || value.calls.length > 8) return false
|
|
264
|
+
const ids = new Set()
|
|
265
|
+
for (const call of value.calls) {
|
|
266
|
+
if (!call || typeof call !== 'object' || Object.keys(call).length !== 3
|
|
267
|
+
|| !safeId.test(call.id) || !safeTool.test(call.toolName) || ids.has(call.id)) return false
|
|
268
|
+
ids.add(call.id)
|
|
269
|
+
}
|
|
270
|
+
return true
|
|
271
|
+
}
|
|
272
|
+
function version(name) {
|
|
273
|
+
return JSON.parse(readFileSync('/opt/dsh-plugin-verifier/node_modules/' + name + '/package.json', 'utf8')).version
|
|
274
|
+
}
|
|
275
|
+
const unknown = reason => ({ schemaVersion: 2, boundary: 'process-seccomp-v1', status: 'unknown', reason })
|
|
276
|
+
const decoded = bytes => new TextDecoder('utf-8', { fatal: true }).decode(bytes)
|
|
277
|
+
function validChild(value, operation) {
|
|
278
|
+
if (!value || typeof value !== 'object' || Array.isArray(value) || value.wireVersion !== 1) return false
|
|
279
|
+
if (value.status === 'unknown') return Object.keys(value).length === 3
|
|
280
|
+
&& typeof value.reason === 'string' && value.reason.length > 0 && value.reason.length <= 128
|
|
281
|
+
if (value.status !== 'result' || !Array.isArray(value.schemas) || value.schemas.length < 1
|
|
282
|
+
|| value.schemas.length > 64 || Object.keys(value).length !== (operation.kind === 'discover' ? 3 : 4)) return false
|
|
283
|
+
const names = new Set()
|
|
284
|
+
for (const schema of value.schemas) {
|
|
285
|
+
if (!schema || typeof schema !== 'object' || Array.isArray(schema)
|
|
286
|
+
|| !safeTool.test(schema.name) || names.has(schema.name)) return false
|
|
287
|
+
names.add(schema.name)
|
|
288
|
+
}
|
|
289
|
+
if (operation.kind === 'discover') return value.calls === undefined
|
|
290
|
+
if (!Array.isArray(value.calls) || value.calls.length !== operation.calls.length) return false
|
|
291
|
+
for (let index = 0; index < value.calls.length; index += 1) {
|
|
292
|
+
const call = value.calls[index], requested = operation.calls[index]
|
|
293
|
+
if (!call || typeof call !== 'object' || Array.isArray(call) || Object.keys(call).length !== 3
|
|
294
|
+
|| call.id !== requested.id || call.toolName !== requested.toolName || !names.has(call.toolName)
|
|
295
|
+
|| !Object.hasOwn(call, 'result')) return false
|
|
296
|
+
}
|
|
297
|
+
return true
|
|
298
|
+
}
|
|
299
|
+
function observeChild(entry, operation) {
|
|
300
|
+
return new Promise(resolvePromise => {
|
|
301
|
+
let child
|
|
302
|
+
try {
|
|
303
|
+
child = spawn('/opt/dsh-plugin-verifier/candidate-launcher', [], {
|
|
304
|
+
cwd: '/workspace/plugin/package',
|
|
305
|
+
env: { PATH: '/usr/bin:/bin', LANG: 'C', LC_ALL: 'C', NODE_ENV: 'production' },
|
|
306
|
+
stdio: ['pipe', 'ignore', 'ignore', 'pipe'],
|
|
307
|
+
})
|
|
308
|
+
} catch { resolvePromise({ reason: 'candidate-launch-failed' }); return }
|
|
309
|
+
let bytes = Buffer.alloc(0), overflow = false, error = false, timedOut = false
|
|
310
|
+
const timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL') }, 8000)
|
|
311
|
+
child.stdio[3].on('data', chunk => {
|
|
312
|
+
if (overflow) return
|
|
313
|
+
if (bytes.length + chunk.length > 60 * 1024) {
|
|
314
|
+
overflow = true
|
|
315
|
+
child.kill('SIGKILL')
|
|
316
|
+
} else bytes = Buffer.concat([bytes, chunk])
|
|
317
|
+
})
|
|
318
|
+
child.once('error', () => { error = true })
|
|
319
|
+
child.stdin.on('error', () => { error = true })
|
|
320
|
+
child.once('close', (code, signal) => {
|
|
321
|
+
clearTimeout(timer)
|
|
322
|
+
if (timedOut || overflow || error || code !== 0 || signal !== null) {
|
|
323
|
+
resolvePromise({ reason: timedOut ? 'candidate-timeout' : 'candidate-process-unsettled' }); return
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const text = decoded(bytes)
|
|
327
|
+
if (!text.endsWith('\n') || text.indexOf('\n') !== text.length - 1) fail('candidate-result-invalid')
|
|
328
|
+
const value = JSON.parse(text.slice(0, -1))
|
|
329
|
+
resolvePromise(validChild(value, operation) ? { value } : { reason: 'candidate-result-invalid' })
|
|
330
|
+
} catch { resolvePromise({ reason: 'candidate-result-invalid' }) }
|
|
331
|
+
})
|
|
332
|
+
child.stdin.end(JSON.stringify({ operation, entry }) + '\n')
|
|
333
|
+
})
|
|
334
|
+
}
|
|
335
|
+
let result
|
|
336
|
+
try {
|
|
337
|
+
const encoded = readFileSync('/workspace/artifact', 'utf8')
|
|
338
|
+
const request = JSON.parse(readFileSync('/workspace/input', 'utf8'))
|
|
339
|
+
// Remove both staged files before any candidate process exists. The candidate
|
|
340
|
+
// gets only its operation and the extracted package through its stdin/path.
|
|
341
|
+
unlinkSync('/workspace/artifact')
|
|
342
|
+
unlinkSync('/workspace/input')
|
|
343
|
+
if (!request || request.schemaVersion !== 1 || !shaPattern.test(request.sha256)
|
|
344
|
+
|| !Number.isSafeInteger(request.sizeBytes) || request.sizeBytes < 1 || request.sizeBytes > limit
|
|
345
|
+
|| !validOperation(request.operation) || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded)) fail('invalid-worker-input')
|
|
346
|
+
const packed = Buffer.from(encoded, 'base64')
|
|
347
|
+
if (packed.length !== request.sizeBytes || packed.toString('base64') !== encoded || digest(packed) !== request.sha256) fail('artifact-mismatch')
|
|
348
|
+
const entry = extract(packed)
|
|
349
|
+
const child = await observeChild(entry, request.operation)
|
|
350
|
+
if (!child.value) fail(child.reason)
|
|
351
|
+
if (child.value.status === 'unknown') fail(child.value.reason)
|
|
352
|
+
const schemas = child.value.schemas
|
|
353
|
+
const schemaDigest = digest(Buffer.from(JSON.stringify(schemas)))
|
|
354
|
+
if (request.operation.kind === 'invoke' && schemaDigest !== request.operation.schemaDigest) fail('schema-digest-changed')
|
|
355
|
+
const base = { schemaVersion: 2, boundary: 'process-seccomp-v1', status: 'observed',
|
|
356
|
+
artifactSha256: request.sha256, quiescent: true,
|
|
357
|
+
environment: { node: process.version, cordis: version('@deepseek-ai/cordis'),
|
|
358
|
+
tools: version('@deepseek-ai/dsh-tools'), systemPrompt: version('@deepseek-ai/dsh-system-prompt') }, schemaDigest }
|
|
359
|
+
result = request.operation.kind === 'discover' ? { ...base, schemas } : { ...base, calls: child.value.calls }
|
|
360
|
+
} catch (error) {
|
|
361
|
+
result = unknown(error instanceof Error ? error.message.slice(0, 128) : 'worker-error')
|
|
362
|
+
}
|
|
363
|
+
const output = JSON.stringify(result)
|
|
364
|
+
if (Buffer.byteLength(output) > 60 * 1024) process.stdout.write(JSON.stringify(unknown('worker-output-too-large')) + '\n')
|
|
365
|
+
else process.stdout.write(output + '\n')
|
|
366
|
+
DSH_PLUGIN_VERIFIER_WORKER_END */
|
|
367
|
+
/* DSH_PLUGIN_VERIFIER_CANDIDATE_START
|
|
368
|
+
// Executes only after the fixed launcher installs seccomp and Node permissions.
|
|
369
|
+
import { createHash } from 'node:crypto'
|
|
370
|
+
import { writeSync } from 'node:fs'
|
|
371
|
+
import { pathToFileURL } from 'node:url'
|
|
372
|
+
import { Context } from '@deepseek-ai/cordis'
|
|
373
|
+
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
|
374
|
+
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
|
375
|
+
|
|
376
|
+
const safeTool = /^[a-z][a-z0-9_-]{0,95}$/
|
|
377
|
+
let fiber, ctx, result, disposed = true
|
|
378
|
+
try {
|
|
379
|
+
const chunks = []
|
|
380
|
+
let total = 0
|
|
381
|
+
for await (const chunk of process.stdin) {
|
|
382
|
+
total += chunk.length
|
|
383
|
+
if (total > 64 * 1024) throw new Error('candidate-input-too-large')
|
|
384
|
+
chunks.push(chunk)
|
|
385
|
+
}
|
|
386
|
+
const request = JSON.parse(Buffer.concat(chunks).toString('utf8'))
|
|
387
|
+
if (!request || typeof request.entry !== 'string'
|
|
388
|
+
|| !/^\/workspace\/plugin\/package\/lib\/[A-Za-z0-9._/-]+\.js$/.test(request.entry)
|
|
389
|
+
|| request.entry.split('/').includes('..')
|
|
390
|
+
|| !request.operation || !['discover', 'invoke'].includes(request.operation.kind)) throw new Error('candidate-input-invalid')
|
|
391
|
+
ctx = new Context()
|
|
392
|
+
await ctx.plugin(SystemPrompt, { includeHarnessIdentity: false, includeRuntimeContext: false, personaPrefix: '' })
|
|
393
|
+
await ctx.plugin(ToolRuntime, { mode: 'native' })
|
|
394
|
+
const mod = await import(pathToFileURL(request.entry).href)
|
|
395
|
+
fiber = ctx.plugin(mod.default ?? mod)
|
|
396
|
+
let activationTimer
|
|
397
|
+
try {
|
|
398
|
+
await Promise.race([fiber, new Promise((_, reject) => {
|
|
399
|
+
activationTimer = setTimeout(() => reject(new Error('plugin-activation-timeout')), 5000)
|
|
400
|
+
})])
|
|
401
|
+
} finally { clearTimeout(activationTimer) }
|
|
402
|
+
if (fiber.state !== 2) throw new Error('plugin-fiber-not-active')
|
|
403
|
+
const schemas = (await ctx.systemPrompt.assemble({})).tools
|
|
404
|
+
if (!Array.isArray(schemas) || schemas.length < 1 || schemas.length > 64) throw new Error('invalid-tool-schemas')
|
|
405
|
+
const names = new Set()
|
|
406
|
+
for (const schema of schemas) {
|
|
407
|
+
if (!schema || !safeTool.test(schema.name) || names.has(schema.name)) throw new Error('invalid-tool-schemas')
|
|
408
|
+
names.add(schema.name)
|
|
409
|
+
}
|
|
410
|
+
const schemaDigest = createHash('sha256').update(JSON.stringify(schemas)).digest('hex')
|
|
411
|
+
if (request.operation.kind === 'invoke' && request.operation.schemaDigest !== schemaDigest)
|
|
412
|
+
throw new Error('schema-digest-changed')
|
|
413
|
+
if (request.operation.kind === 'discover') result = { wireVersion: 1, status: 'result', schemas }
|
|
414
|
+
else {
|
|
415
|
+
const calls = []
|
|
416
|
+
for (const call of request.operation.calls) {
|
|
417
|
+
if (!names.has(call.toolName)) throw new Error('unknown-invoked-tool')
|
|
418
|
+
const observed = await ctx.tools.execute({ callId: call.id, name: call.toolName,
|
|
419
|
+
arguments: call.arguments, signal: new AbortController().signal })
|
|
420
|
+
calls.push({ id: call.id, toolName: call.toolName, result: observed })
|
|
421
|
+
}
|
|
422
|
+
result = { wireVersion: 1, status: 'result', schemas, calls }
|
|
423
|
+
}
|
|
424
|
+
} catch (error) {
|
|
425
|
+
result = { wireVersion: 1, status: 'unknown', reason: error instanceof Error ? error.message.slice(0, 128) : 'candidate-error' }
|
|
426
|
+
} finally {
|
|
427
|
+
try { if (fiber) await fiber.dispose() } catch { disposed = false }
|
|
428
|
+
try { if (ctx) await ctx.fiber.dispose() } catch { disposed = false }
|
|
429
|
+
}
|
|
430
|
+
if (!disposed) result = { wireVersion: 1, status: 'unknown', reason: 'plugin-disposal-unconfirmed' }
|
|
431
|
+
try {
|
|
432
|
+
const output = JSON.stringify(result)
|
|
433
|
+
if (Buffer.byteLength(output) > 60 * 1024) throw new Error('candidate-output-too-large')
|
|
434
|
+
writeSync(3, output + '\n')
|
|
435
|
+
} catch { process.exitCode = 1 }
|
|
436
|
+
DSH_PLUGIN_VERIFIER_CANDIDATE_END */
|
|
437
|
+
//# sourceMappingURL=plugin-behavior-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-behavior-runner.js","sourceRoot":"","sources":["../src/plugin-behavior-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { type PluginCreationVerificationCertificate, type PluginRevisionRegressionRequest, type PluginRevisionRegressionResult, type RevisionRegressionAcceptanceAuthorityRef } from '@dsh-enhanced/assistant-growth-contract';
|
|
3
|
+
import { type CreationReviewConfig } from './creation-review.js';
|
|
4
|
+
export type RevisionRegressionReviewConfig = Omit<CreationReviewConfig, 'policy' | 'maxInputBytes' | 'maxOutputTokens'>;
|
|
5
|
+
export interface RevisionRegressionReviewAuthorityInspection {
|
|
6
|
+
authority: RevisionRegressionAcceptanceAuthorityRef;
|
|
7
|
+
publicKey: string;
|
|
8
|
+
remainingVerifications: number;
|
|
9
|
+
available: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function validateRevisionRegressionReviewConfig(input: RevisionRegressionReviewConfig): RevisionRegressionReviewConfig;
|
|
12
|
+
export declare function compileRevisionRegressionReviewConfig(input: RevisionRegressionReviewConfig): {
|
|
13
|
+
config: RevisionRegressionReviewConfig;
|
|
14
|
+
authority: RevisionRegressionAcceptanceAuthorityRef;
|
|
15
|
+
publicKey: string;
|
|
16
|
+
privateKey: ReturnType<typeof import('node:crypto').createPrivateKey>;
|
|
17
|
+
};
|
|
18
|
+
type RetainedCases = Readonly<{
|
|
19
|
+
certificate: PluginCreationVerificationCertificate;
|
|
20
|
+
discovery: unknown;
|
|
21
|
+
contract: unknown;
|
|
22
|
+
cases: Record<string, unknown>;
|
|
23
|
+
}>;
|
|
24
|
+
type ReadParentCases = (certificate: PluginCreationVerificationCertificate) => RetainedCases | undefined;
|
|
25
|
+
/** Independent paired Docker regression; this runtime has no LLM service and cannot switch a tool. */
|
|
26
|
+
export declare class RevisionRegressionReviewRuntime {
|
|
27
|
+
#private;
|
|
28
|
+
private readonly ctx;
|
|
29
|
+
private readonly readParentCases;
|
|
30
|
+
constructor(ctx: Context, input: RevisionRegressionReviewConfig, databasePath: string, readParentCases: ReadParentCases);
|
|
31
|
+
inspect(input: {
|
|
32
|
+
owner: RevisionRegressionReviewConfig['owner'];
|
|
33
|
+
}): RevisionRegressionReviewAuthorityInspection | undefined;
|
|
34
|
+
run(request: PluginRevisionRegressionRequest, external?: AbortSignal): Promise<PluginRevisionRegressionResult>;
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=revision-regression-review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-regression-review.d.ts","sourceRoot":"","sources":["../src/revision-regression-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAKL,KAAK,qCAAqC,EAC1C,KAAK,+BAA+B,EAAE,KAAK,8BAA8B,EAEzE,KAAK,wCAAwC,EAAE,MAAM,yCAAyC,CAAA;AAEhG,OAAO,EAC0C,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAQxG,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,eAAe,GAAG,iBAAiB,CAAC,CAAA;AACvH,MAAM,WAAW,2CAA2C;IAC1D,SAAS,EAAE,wCAAwC,CAAA;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,SAAS,EAAE,OAAO,CAAA;CACnB;AAcD,wBAAgB,sCAAsC,CAAC,KAAK,EAAE,8BAA8B,GAAG,8BAA8B,CAO5H;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,8BAA8B,GAAG;IAC5F,MAAM,EAAE,8BAA8B,CAAC;IAAC,SAAS,EAAE,wCAAwC,CAAC;IAC5F,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,UAAU,CAAC,cAAc,aAAa,EAAE,gBAAgB,CAAC,CAAA;CACzF,CAYA;AAkBD,KAAK,aAAa,GAAG,QAAQ,CAAC;IAAE,WAAW,EAAE,qCAAqC,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IACrG,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAAA;AACtD,KAAK,eAAe,GAAG,CAAC,WAAW,EAAE,qCAAqC,KAAK,aAAa,GAAG,SAAS,CAAA;AAgCxG,sGAAsG;AACtG,qBAAa,+BAA+B;;IAS9B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBADL,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,8BAA8B,EAAE,YAAY,EAAE,MAAM,EACnF,eAAe,EAAE,eAAe;IAenD,OAAO,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,8BAA8B,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,2CAA2C,GAAG,SAAS;IAQ3H,GAAG,CAAC,OAAO,EAAE,+BAA+B,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAoL9G,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAUvB"}
|