@sanctuary-framework/mcp-server 0.5.12 → 0.5.13
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/cli.cjs +53 -18
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +53 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +248 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +248 -168
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { randomBytes as randomBytes$1, createHmac } from 'crypto';
|
|
2
|
+
import { gcm } from '@noble/ciphers/aes.js';
|
|
1
3
|
import { sha256 } from '@noble/hashes/sha256';
|
|
2
4
|
import { hmac } from '@noble/hashes/hmac';
|
|
5
|
+
import { RistrettoPoint, ed25519 } from '@noble/curves/ed25519';
|
|
3
6
|
import { readFile, mkdir, writeFile, stat, unlink, readdir, chmod, access } from 'fs/promises';
|
|
4
7
|
import { join } from 'path';
|
|
5
8
|
import { platform, homedir } from 'os';
|
|
6
9
|
import { createRequire } from 'module';
|
|
7
|
-
import { randomBytes as randomBytes$1, createHmac } from 'crypto';
|
|
8
|
-
import { gcm } from '@noble/ciphers/aes.js';
|
|
9
|
-
import { RistrettoPoint, ed25519 } from '@noble/curves/ed25519';
|
|
10
10
|
import { argon2id } from 'hash-wasm';
|
|
11
11
|
import { hkdf } from '@noble/hashes/hkdf';
|
|
12
12
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
@@ -25,6 +25,26 @@ var __export = (target, all) => {
|
|
|
25
25
|
for (var name in all)
|
|
26
26
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
27
27
|
};
|
|
28
|
+
function randomBytes(length) {
|
|
29
|
+
if (length <= 0) {
|
|
30
|
+
throw new RangeError("Length must be positive");
|
|
31
|
+
}
|
|
32
|
+
const buf = randomBytes$1(length);
|
|
33
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
34
|
+
}
|
|
35
|
+
function generateIV() {
|
|
36
|
+
return randomBytes(12);
|
|
37
|
+
}
|
|
38
|
+
function generateSalt() {
|
|
39
|
+
return randomBytes(32);
|
|
40
|
+
}
|
|
41
|
+
function generateRandomKey() {
|
|
42
|
+
return randomBytes(32);
|
|
43
|
+
}
|
|
44
|
+
var init_random = __esm({
|
|
45
|
+
"src/core/random.ts"() {
|
|
46
|
+
}
|
|
47
|
+
});
|
|
28
48
|
|
|
29
49
|
// src/core/encoding.ts
|
|
30
50
|
var encoding_exports = {};
|
|
@@ -76,6 +96,42 @@ var init_encoding = __esm({
|
|
|
76
96
|
"src/core/encoding.ts"() {
|
|
77
97
|
}
|
|
78
98
|
});
|
|
99
|
+
function encrypt(plaintext, key, aad) {
|
|
100
|
+
if (key.length !== 32) {
|
|
101
|
+
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
102
|
+
}
|
|
103
|
+
const iv = generateIV();
|
|
104
|
+
const cipher = gcm(key, iv, aad);
|
|
105
|
+
const ciphertext = cipher.encrypt(plaintext);
|
|
106
|
+
return {
|
|
107
|
+
v: 1,
|
|
108
|
+
alg: "aes-256-gcm",
|
|
109
|
+
iv: toBase64url(iv),
|
|
110
|
+
ct: toBase64url(ciphertext),
|
|
111
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function decrypt(payload, key, aad) {
|
|
115
|
+
if (key.length !== 32) {
|
|
116
|
+
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
117
|
+
}
|
|
118
|
+
if (payload.v !== 1) {
|
|
119
|
+
throw new Error(`Unsupported payload version: ${payload.v}`);
|
|
120
|
+
}
|
|
121
|
+
if (payload.alg !== "aes-256-gcm") {
|
|
122
|
+
throw new Error(`Unsupported algorithm: ${payload.alg}`);
|
|
123
|
+
}
|
|
124
|
+
const iv = fromBase64url(payload.iv);
|
|
125
|
+
const ciphertext = fromBase64url(payload.ct);
|
|
126
|
+
const cipher = gcm(key, iv, aad);
|
|
127
|
+
return cipher.decrypt(ciphertext);
|
|
128
|
+
}
|
|
129
|
+
var init_encryption = __esm({
|
|
130
|
+
"src/core/encryption.ts"() {
|
|
131
|
+
init_random();
|
|
132
|
+
init_encoding();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
79
135
|
|
|
80
136
|
// src/core/hashing.ts
|
|
81
137
|
var hashing_exports = {};
|
|
@@ -204,6 +260,123 @@ var init_hashing = __esm({
|
|
|
204
260
|
init_encoding();
|
|
205
261
|
}
|
|
206
262
|
});
|
|
263
|
+
|
|
264
|
+
// src/core/identity.ts
|
|
265
|
+
var identity_exports = {};
|
|
266
|
+
__export(identity_exports, {
|
|
267
|
+
createIdentity: () => createIdentity,
|
|
268
|
+
generateIdentityId: () => generateIdentityId,
|
|
269
|
+
generateKeypair: () => generateKeypair,
|
|
270
|
+
publicKeyToDid: () => publicKeyToDid,
|
|
271
|
+
rotateKeys: () => rotateKeys,
|
|
272
|
+
sign: () => sign,
|
|
273
|
+
verify: () => verify
|
|
274
|
+
});
|
|
275
|
+
function generateKeypair() {
|
|
276
|
+
const privateKey = randomBytes(32);
|
|
277
|
+
const publicKey = ed25519.getPublicKey(privateKey);
|
|
278
|
+
return { publicKey, privateKey };
|
|
279
|
+
}
|
|
280
|
+
function publicKeyToDid(publicKey) {
|
|
281
|
+
const multicodec = new Uint8Array([237, 1, ...publicKey]);
|
|
282
|
+
return `did:key:z${toBase64url(multicodec)}`;
|
|
283
|
+
}
|
|
284
|
+
function generateIdentityId(publicKey) {
|
|
285
|
+
const keyHash = hash(publicKey);
|
|
286
|
+
return Array.from(keyHash.slice(0, 16)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
287
|
+
}
|
|
288
|
+
function createIdentity(label, encryptionKey, keyProtection) {
|
|
289
|
+
const { publicKey, privateKey } = generateKeypair();
|
|
290
|
+
const identityId = generateIdentityId(publicKey);
|
|
291
|
+
const did = publicKeyToDid(publicKey);
|
|
292
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
293
|
+
const encryptedPrivateKey = encrypt(privateKey, encryptionKey);
|
|
294
|
+
privateKey.fill(0);
|
|
295
|
+
const publicIdentity = {
|
|
296
|
+
identity_id: identityId,
|
|
297
|
+
label,
|
|
298
|
+
public_key: toBase64url(publicKey),
|
|
299
|
+
did,
|
|
300
|
+
created_at: now,
|
|
301
|
+
key_type: "ed25519",
|
|
302
|
+
key_protection: keyProtection
|
|
303
|
+
};
|
|
304
|
+
const storedIdentity = {
|
|
305
|
+
...publicIdentity,
|
|
306
|
+
encrypted_private_key: encryptedPrivateKey,
|
|
307
|
+
rotation_history: []
|
|
308
|
+
};
|
|
309
|
+
return { publicIdentity, storedIdentity };
|
|
310
|
+
}
|
|
311
|
+
function sign(payload, encryptedPrivateKey, encryptionKey) {
|
|
312
|
+
const privateKey = decrypt(encryptedPrivateKey, encryptionKey);
|
|
313
|
+
try {
|
|
314
|
+
return ed25519.sign(payload, privateKey);
|
|
315
|
+
} finally {
|
|
316
|
+
privateKey.fill(0);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function verify(payload, signature, publicKey) {
|
|
320
|
+
try {
|
|
321
|
+
return ed25519.verify(signature, payload, publicKey);
|
|
322
|
+
} catch {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function rotateKeys(storedIdentity, encryptionKey, reason) {
|
|
327
|
+
const { publicKey: newPublicKey, privateKey: newPrivateKey } = generateKeypair();
|
|
328
|
+
const newIdentityDid = publicKeyToDid(newPublicKey);
|
|
329
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
330
|
+
const eventData = JSON.stringify({
|
|
331
|
+
old_public_key: storedIdentity.public_key,
|
|
332
|
+
new_public_key: toBase64url(newPublicKey),
|
|
333
|
+
identity_id: storedIdentity.identity_id,
|
|
334
|
+
reason,
|
|
335
|
+
rotated_at: now
|
|
336
|
+
});
|
|
337
|
+
const eventBytes = new TextEncoder().encode(eventData);
|
|
338
|
+
const signature = sign(
|
|
339
|
+
eventBytes,
|
|
340
|
+
storedIdentity.encrypted_private_key,
|
|
341
|
+
encryptionKey
|
|
342
|
+
);
|
|
343
|
+
const rotationEvent = {
|
|
344
|
+
old_public_key: storedIdentity.public_key,
|
|
345
|
+
new_public_key: toBase64url(newPublicKey),
|
|
346
|
+
identity_id: storedIdentity.identity_id,
|
|
347
|
+
reason,
|
|
348
|
+
rotated_at: now,
|
|
349
|
+
signature: toBase64url(signature)
|
|
350
|
+
};
|
|
351
|
+
const encryptedNewPrivateKey = encrypt(newPrivateKey, encryptionKey);
|
|
352
|
+
newPrivateKey.fill(0);
|
|
353
|
+
const updatedIdentity = {
|
|
354
|
+
...storedIdentity,
|
|
355
|
+
public_key: toBase64url(newPublicKey),
|
|
356
|
+
did: newIdentityDid,
|
|
357
|
+
encrypted_private_key: encryptedNewPrivateKey,
|
|
358
|
+
rotation_history: [
|
|
359
|
+
...storedIdentity.rotation_history,
|
|
360
|
+
{
|
|
361
|
+
old_public_key: storedIdentity.public_key,
|
|
362
|
+
new_public_key: toBase64url(newPublicKey),
|
|
363
|
+
rotation_event: toBase64url(
|
|
364
|
+
new TextEncoder().encode(JSON.stringify(rotationEvent))
|
|
365
|
+
),
|
|
366
|
+
rotated_at: now
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
};
|
|
370
|
+
return { updatedIdentity, rotationEvent };
|
|
371
|
+
}
|
|
372
|
+
var init_identity = __esm({
|
|
373
|
+
"src/core/identity.ts"() {
|
|
374
|
+
init_encoding();
|
|
375
|
+
init_encryption();
|
|
376
|
+
init_hashing();
|
|
377
|
+
init_random();
|
|
378
|
+
}
|
|
379
|
+
});
|
|
207
380
|
var require2 = createRequire(import.meta.url);
|
|
208
381
|
var { version: PKG_VERSION } = require2("../package.json");
|
|
209
382
|
var SANCTUARY_VERSION = PKG_VERSION;
|
|
@@ -381,24 +554,9 @@ function deepMerge(base, override) {
|
|
|
381
554
|
}
|
|
382
555
|
return result;
|
|
383
556
|
}
|
|
384
|
-
function randomBytes(length) {
|
|
385
|
-
if (length <= 0) {
|
|
386
|
-
throw new RangeError("Length must be positive");
|
|
387
|
-
}
|
|
388
|
-
const buf = randomBytes$1(length);
|
|
389
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
390
|
-
}
|
|
391
|
-
function generateIV() {
|
|
392
|
-
return randomBytes(12);
|
|
393
|
-
}
|
|
394
|
-
function generateSalt() {
|
|
395
|
-
return randomBytes(32);
|
|
396
|
-
}
|
|
397
|
-
function generateRandomKey() {
|
|
398
|
-
return randomBytes(32);
|
|
399
|
-
}
|
|
400
557
|
|
|
401
558
|
// src/storage/filesystem.ts
|
|
559
|
+
init_random();
|
|
402
560
|
var FilesystemStorage = class {
|
|
403
561
|
basePath;
|
|
404
562
|
constructor(basePath) {
|
|
@@ -506,141 +664,14 @@ var FilesystemStorage = class {
|
|
|
506
664
|
return total;
|
|
507
665
|
}
|
|
508
666
|
};
|
|
509
|
-
init_encoding();
|
|
510
|
-
function encrypt(plaintext, key, aad) {
|
|
511
|
-
if (key.length !== 32) {
|
|
512
|
-
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
513
|
-
}
|
|
514
|
-
const iv = generateIV();
|
|
515
|
-
const cipher = gcm(key, iv, aad);
|
|
516
|
-
const ciphertext = cipher.encrypt(plaintext);
|
|
517
|
-
return {
|
|
518
|
-
v: 1,
|
|
519
|
-
alg: "aes-256-gcm",
|
|
520
|
-
iv: toBase64url(iv),
|
|
521
|
-
ct: toBase64url(ciphertext),
|
|
522
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
function decrypt(payload, key, aad) {
|
|
526
|
-
if (key.length !== 32) {
|
|
527
|
-
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
528
|
-
}
|
|
529
|
-
if (payload.v !== 1) {
|
|
530
|
-
throw new Error(`Unsupported payload version: ${payload.v}`);
|
|
531
|
-
}
|
|
532
|
-
if (payload.alg !== "aes-256-gcm") {
|
|
533
|
-
throw new Error(`Unsupported algorithm: ${payload.alg}`);
|
|
534
|
-
}
|
|
535
|
-
const iv = fromBase64url(payload.iv);
|
|
536
|
-
const ciphertext = fromBase64url(payload.ct);
|
|
537
|
-
const cipher = gcm(key, iv, aad);
|
|
538
|
-
return cipher.decrypt(ciphertext);
|
|
539
|
-
}
|
|
540
667
|
|
|
541
668
|
// src/l1-cognitive/state-store.ts
|
|
669
|
+
init_encryption();
|
|
542
670
|
init_hashing();
|
|
671
|
+
init_identity();
|
|
543
672
|
|
|
544
|
-
// src/core/
|
|
545
|
-
|
|
546
|
-
init_hashing();
|
|
547
|
-
function generateKeypair() {
|
|
548
|
-
const privateKey = randomBytes(32);
|
|
549
|
-
const publicKey = ed25519.getPublicKey(privateKey);
|
|
550
|
-
return { publicKey, privateKey };
|
|
551
|
-
}
|
|
552
|
-
function publicKeyToDid(publicKey) {
|
|
553
|
-
const multicodec = new Uint8Array([237, 1, ...publicKey]);
|
|
554
|
-
return `did:key:z${toBase64url(multicodec)}`;
|
|
555
|
-
}
|
|
556
|
-
function generateIdentityId(publicKey) {
|
|
557
|
-
const keyHash = hash(publicKey);
|
|
558
|
-
return Array.from(keyHash.slice(0, 16)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
559
|
-
}
|
|
560
|
-
function createIdentity(label, encryptionKey, keyProtection) {
|
|
561
|
-
const { publicKey, privateKey } = generateKeypair();
|
|
562
|
-
const identityId = generateIdentityId(publicKey);
|
|
563
|
-
const did = publicKeyToDid(publicKey);
|
|
564
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
565
|
-
const encryptedPrivateKey = encrypt(privateKey, encryptionKey);
|
|
566
|
-
privateKey.fill(0);
|
|
567
|
-
const publicIdentity = {
|
|
568
|
-
identity_id: identityId,
|
|
569
|
-
label,
|
|
570
|
-
public_key: toBase64url(publicKey),
|
|
571
|
-
did,
|
|
572
|
-
created_at: now,
|
|
573
|
-
key_type: "ed25519",
|
|
574
|
-
key_protection: keyProtection
|
|
575
|
-
};
|
|
576
|
-
const storedIdentity = {
|
|
577
|
-
...publicIdentity,
|
|
578
|
-
encrypted_private_key: encryptedPrivateKey,
|
|
579
|
-
rotation_history: []
|
|
580
|
-
};
|
|
581
|
-
return { publicIdentity, storedIdentity };
|
|
582
|
-
}
|
|
583
|
-
function sign(payload, encryptedPrivateKey, encryptionKey) {
|
|
584
|
-
const privateKey = decrypt(encryptedPrivateKey, encryptionKey);
|
|
585
|
-
try {
|
|
586
|
-
return ed25519.sign(payload, privateKey);
|
|
587
|
-
} finally {
|
|
588
|
-
privateKey.fill(0);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
function verify(payload, signature, publicKey) {
|
|
592
|
-
try {
|
|
593
|
-
return ed25519.verify(signature, payload, publicKey);
|
|
594
|
-
} catch {
|
|
595
|
-
return false;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
function rotateKeys(storedIdentity, encryptionKey, reason) {
|
|
599
|
-
const { publicKey: newPublicKey, privateKey: newPrivateKey } = generateKeypair();
|
|
600
|
-
const newIdentityDid = publicKeyToDid(newPublicKey);
|
|
601
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
602
|
-
const eventData = JSON.stringify({
|
|
603
|
-
old_public_key: storedIdentity.public_key,
|
|
604
|
-
new_public_key: toBase64url(newPublicKey),
|
|
605
|
-
identity_id: storedIdentity.identity_id,
|
|
606
|
-
reason,
|
|
607
|
-
rotated_at: now
|
|
608
|
-
});
|
|
609
|
-
const eventBytes = new TextEncoder().encode(eventData);
|
|
610
|
-
const signature = sign(
|
|
611
|
-
eventBytes,
|
|
612
|
-
storedIdentity.encrypted_private_key,
|
|
613
|
-
encryptionKey
|
|
614
|
-
);
|
|
615
|
-
const rotationEvent = {
|
|
616
|
-
old_public_key: storedIdentity.public_key,
|
|
617
|
-
new_public_key: toBase64url(newPublicKey),
|
|
618
|
-
identity_id: storedIdentity.identity_id,
|
|
619
|
-
reason,
|
|
620
|
-
rotated_at: now,
|
|
621
|
-
signature: toBase64url(signature)
|
|
622
|
-
};
|
|
623
|
-
const encryptedNewPrivateKey = encrypt(newPrivateKey, encryptionKey);
|
|
624
|
-
newPrivateKey.fill(0);
|
|
625
|
-
const updatedIdentity = {
|
|
626
|
-
...storedIdentity,
|
|
627
|
-
public_key: toBase64url(newPublicKey),
|
|
628
|
-
did: newIdentityDid,
|
|
629
|
-
encrypted_private_key: encryptedNewPrivateKey,
|
|
630
|
-
rotation_history: [
|
|
631
|
-
...storedIdentity.rotation_history,
|
|
632
|
-
{
|
|
633
|
-
old_public_key: storedIdentity.public_key,
|
|
634
|
-
new_public_key: toBase64url(newPublicKey),
|
|
635
|
-
rotation_event: toBase64url(
|
|
636
|
-
new TextEncoder().encode(JSON.stringify(rotationEvent))
|
|
637
|
-
),
|
|
638
|
-
rotated_at: now
|
|
639
|
-
}
|
|
640
|
-
]
|
|
641
|
-
};
|
|
642
|
-
return { updatedIdentity, rotationEvent };
|
|
643
|
-
}
|
|
673
|
+
// src/core/key-derivation.ts
|
|
674
|
+
init_random();
|
|
644
675
|
init_encoding();
|
|
645
676
|
var ARGON2_MEMORY_COST = 65536;
|
|
646
677
|
var ARGON2_TIME_COST = 3;
|
|
@@ -1238,7 +1269,9 @@ function toolResult(data) {
|
|
|
1238
1269
|
}
|
|
1239
1270
|
|
|
1240
1271
|
// src/l1-cognitive/tools.ts
|
|
1272
|
+
init_identity();
|
|
1241
1273
|
init_encoding();
|
|
1274
|
+
init_encryption();
|
|
1242
1275
|
init_encoding();
|
|
1243
1276
|
var RESERVED_NAMESPACE_PREFIXES2 = [
|
|
1244
1277
|
"_identities",
|
|
@@ -1745,6 +1778,7 @@ function createL1Tools(stateStore, storage, masterKey, keyProtection, auditLog)
|
|
|
1745
1778
|
}
|
|
1746
1779
|
|
|
1747
1780
|
// src/l2-operational/audit-log.ts
|
|
1781
|
+
init_encryption();
|
|
1748
1782
|
init_encoding();
|
|
1749
1783
|
var AuditLog = class {
|
|
1750
1784
|
storage;
|
|
@@ -1842,6 +1876,8 @@ var AuditLog = class {
|
|
|
1842
1876
|
// src/l3-disclosure/commitments.ts
|
|
1843
1877
|
init_hashing();
|
|
1844
1878
|
init_encoding();
|
|
1879
|
+
init_random();
|
|
1880
|
+
init_encryption();
|
|
1845
1881
|
init_encoding();
|
|
1846
1882
|
function createCommitment(value, blindingFactor) {
|
|
1847
1883
|
const blindingBytes = blindingFactor ? fromBase64url(blindingFactor) : randomBytes(32);
|
|
@@ -1922,7 +1958,9 @@ var CommitmentStore = class {
|
|
|
1922
1958
|
};
|
|
1923
1959
|
|
|
1924
1960
|
// src/l3-disclosure/policies.ts
|
|
1961
|
+
init_encryption();
|
|
1925
1962
|
init_encoding();
|
|
1963
|
+
init_random();
|
|
1926
1964
|
function evaluateDisclosure(policy, context, requestedFields) {
|
|
1927
1965
|
return requestedFields.map((field) => {
|
|
1928
1966
|
const exactRule = policy.rules.find((r) => r.context === context);
|
|
@@ -2053,6 +2091,9 @@ var PolicyStore = class {
|
|
|
2053
2091
|
);
|
|
2054
2092
|
}
|
|
2055
2093
|
};
|
|
2094
|
+
|
|
2095
|
+
// src/l3-disclosure/zk-proofs.ts
|
|
2096
|
+
init_random();
|
|
2056
2097
|
init_encoding();
|
|
2057
2098
|
var G = RistrettoPoint.BASE;
|
|
2058
2099
|
var H_INPUT = concatBytes(
|
|
@@ -2730,7 +2771,10 @@ function createL3Tools(storage, masterKey, auditLog) {
|
|
|
2730
2771
|
}
|
|
2731
2772
|
|
|
2732
2773
|
// src/l4-reputation/reputation-store.ts
|
|
2774
|
+
init_encryption();
|
|
2733
2775
|
init_encoding();
|
|
2776
|
+
init_random();
|
|
2777
|
+
init_identity();
|
|
2734
2778
|
function computeMedian(values) {
|
|
2735
2779
|
if (values.length === 0) return 0;
|
|
2736
2780
|
const sorted = [...values].sort((a, b) => a - b);
|
|
@@ -3625,6 +3669,24 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3625
3669
|
}
|
|
3626
3670
|
const publishType = args.type;
|
|
3627
3671
|
const veracoreUrl = args.verascore_url || "https://verascore.ai";
|
|
3672
|
+
const ALLOWED_VERASCORE_HOSTS = ["verascore.ai", "www.verascore.ai", "api.verascore.ai"];
|
|
3673
|
+
try {
|
|
3674
|
+
const parsed = new URL(veracoreUrl);
|
|
3675
|
+
if (parsed.protocol !== "https:") {
|
|
3676
|
+
return toolResult({
|
|
3677
|
+
error: `verascore_url must use HTTPS. Got: ${parsed.protocol}`
|
|
3678
|
+
});
|
|
3679
|
+
}
|
|
3680
|
+
if (!ALLOWED_VERASCORE_HOSTS.includes(parsed.hostname)) {
|
|
3681
|
+
return toolResult({
|
|
3682
|
+
error: `verascore_url must point to a known Verascore domain (${ALLOWED_VERASCORE_HOSTS.join(", ")}). Got: ${parsed.hostname}`
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
} catch {
|
|
3686
|
+
return toolResult({
|
|
3687
|
+
error: `verascore_url is not a valid URL: ${veracoreUrl}`
|
|
3688
|
+
});
|
|
3689
|
+
}
|
|
3628
3690
|
const agentId = args.verascore_agent_id || identity.did.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase();
|
|
3629
3691
|
let publishData;
|
|
3630
3692
|
if (args.data) {
|
|
@@ -3654,24 +3716,21 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3654
3716
|
return toolResult({ error: `Unknown publish type: ${publishType}` });
|
|
3655
3717
|
}
|
|
3656
3718
|
}
|
|
3657
|
-
const { sign:
|
|
3658
|
-
const payloadBytes =
|
|
3719
|
+
const { sign: identitySign } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
3720
|
+
const payloadBytes = new TextEncoder().encode(JSON.stringify(publishData));
|
|
3659
3721
|
let signatureB64;
|
|
3660
3722
|
try {
|
|
3661
|
-
const
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
]),
|
|
3668
|
-
format: "der",
|
|
3669
|
-
type: "pkcs8"
|
|
3670
|
-
});
|
|
3671
|
-
const sig = sign2(null, payloadBytes, privateKey);
|
|
3672
|
-
signatureB64 = sig.toString("base64url");
|
|
3723
|
+
const signingBytes = identitySign(
|
|
3724
|
+
payloadBytes,
|
|
3725
|
+
identity.encrypted_private_key,
|
|
3726
|
+
identityEncryptionKey
|
|
3727
|
+
);
|
|
3728
|
+
signatureB64 = toBase64url(signingBytes);
|
|
3673
3729
|
} catch (signError) {
|
|
3674
|
-
|
|
3730
|
+
return toolResult({
|
|
3731
|
+
error: "Failed to sign publish payload. Identity key may be corrupted.",
|
|
3732
|
+
details: signError instanceof Error ? signError.message : String(signError)
|
|
3733
|
+
});
|
|
3675
3734
|
}
|
|
3676
3735
|
const requestBody = {
|
|
3677
3736
|
agentId,
|
|
@@ -3750,7 +3809,9 @@ var DEFAULT_POLICY = {
|
|
|
3750
3809
|
"reputation_import",
|
|
3751
3810
|
"reputation_export",
|
|
3752
3811
|
"bootstrap_provide_guarantee",
|
|
3753
|
-
"decommission_certificate"
|
|
3812
|
+
"decommission_certificate",
|
|
3813
|
+
"reputation_publish"
|
|
3814
|
+
// SEC-039: Explicit Tier 1 — sends data to external API
|
|
3754
3815
|
],
|
|
3755
3816
|
tier2_anomaly: DEFAULT_TIER2,
|
|
3756
3817
|
tier3_always_allow: [
|
|
@@ -3802,7 +3863,9 @@ var DEFAULT_POLICY = {
|
|
|
3802
3863
|
"shr_gateway_export",
|
|
3803
3864
|
"bridge_commit",
|
|
3804
3865
|
"bridge_verify",
|
|
3805
|
-
"bridge_attest"
|
|
3866
|
+
"bridge_attest",
|
|
3867
|
+
"dashboard_open"
|
|
3868
|
+
// SEC-039: Explicit Tier 3 — only generates a URL
|
|
3806
3869
|
],
|
|
3807
3870
|
approval_channel: DEFAULT_CHANNEL
|
|
3808
3871
|
};
|
|
@@ -3910,6 +3973,7 @@ tier1_always_approve:
|
|
|
3910
3973
|
- reputation_import
|
|
3911
3974
|
- reputation_export
|
|
3912
3975
|
- bootstrap_provide_guarantee
|
|
3976
|
+
- reputation_publish
|
|
3913
3977
|
|
|
3914
3978
|
# \u2500\u2500\u2500 Tier 2: Behavioral Anomaly Detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3915
3979
|
# Triggers approval when agent behavior deviates from its baseline.
|
|
@@ -3972,6 +4036,7 @@ tier3_always_allow:
|
|
|
3972
4036
|
- bridge_commit
|
|
3973
4037
|
- bridge_verify
|
|
3974
4038
|
- bridge_attest
|
|
4039
|
+
- dashboard_open
|
|
3975
4040
|
|
|
3976
4041
|
# \u2500\u2500\u2500 Approval Channel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3977
4042
|
# How Sanctuary reaches you when approval is needed.
|
|
@@ -3999,6 +4064,7 @@ async function loadPrincipalPolicy(storagePath) {
|
|
|
3999
4064
|
}
|
|
4000
4065
|
|
|
4001
4066
|
// src/principal-policy/baseline.ts
|
|
4067
|
+
init_encryption();
|
|
4002
4068
|
init_encoding();
|
|
4003
4069
|
var BASELINE_NAMESPACE = "_principal";
|
|
4004
4070
|
var BASELINE_KEY = "session-baseline";
|
|
@@ -4224,6 +4290,7 @@ function canonicalizeForSigning(body) {
|
|
|
4224
4290
|
}
|
|
4225
4291
|
|
|
4226
4292
|
// src/shr/generator.ts
|
|
4293
|
+
init_identity();
|
|
4227
4294
|
init_encoding();
|
|
4228
4295
|
var DEFAULT_VALIDITY_MS = 60 * 60 * 1e3;
|
|
4229
4296
|
function generateSHR(identityId, opts) {
|
|
@@ -5604,7 +5671,9 @@ function generateDashboardHTML(options) {
|
|
|
5604
5671
|
|
|
5605
5672
|
<script>
|
|
5606
5673
|
// Constants
|
|
5607
|
-
|
|
5674
|
+
// SEC-038: Do NOT embed the long-lived auth token in page source.
|
|
5675
|
+
// Use only the session token stored in sessionStorage by the login flow.
|
|
5676
|
+
const AUTH_TOKEN = sessionStorage.getItem('authToken') || '';
|
|
5608
5677
|
const TIMEOUT_SECONDS = ${options.timeoutSeconds};
|
|
5609
5678
|
const API_BASE = '';
|
|
5610
5679
|
|
|
@@ -8117,6 +8186,7 @@ function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
|
8117
8186
|
}
|
|
8118
8187
|
|
|
8119
8188
|
// src/shr/verifier.ts
|
|
8189
|
+
init_identity();
|
|
8120
8190
|
init_encoding();
|
|
8121
8191
|
function verifySHR(shr, now) {
|
|
8122
8192
|
const errors = [];
|
|
@@ -8539,7 +8609,9 @@ function createSHRTools(config, identityManager, masterKey, auditLog) {
|
|
|
8539
8609
|
}
|
|
8540
8610
|
|
|
8541
8611
|
// src/handshake/protocol.ts
|
|
8612
|
+
init_identity();
|
|
8542
8613
|
init_encoding();
|
|
8614
|
+
init_random();
|
|
8543
8615
|
function generateNonce() {
|
|
8544
8616
|
return toBase64url(randomBytes(32));
|
|
8545
8617
|
}
|
|
@@ -8706,7 +8778,9 @@ function deriveTrustTier(level) {
|
|
|
8706
8778
|
}
|
|
8707
8779
|
|
|
8708
8780
|
// src/handshake/attestation.ts
|
|
8781
|
+
init_identity();
|
|
8709
8782
|
init_encoding();
|
|
8783
|
+
init_identity();
|
|
8710
8784
|
init_encoding();
|
|
8711
8785
|
var ATTESTATION_VERSION = "1.0";
|
|
8712
8786
|
function deriveTrustTier2(level) {
|
|
@@ -9499,10 +9573,13 @@ function createFederationTools(auditLog, handshakeResults) {
|
|
|
9499
9573
|
|
|
9500
9574
|
// src/bridge/tools.ts
|
|
9501
9575
|
init_encoding();
|
|
9576
|
+
init_encryption();
|
|
9502
9577
|
init_encoding();
|
|
9503
9578
|
|
|
9504
9579
|
// src/bridge/bridge.ts
|
|
9580
|
+
init_identity();
|
|
9505
9581
|
init_encoding();
|
|
9582
|
+
init_random();
|
|
9506
9583
|
init_hashing();
|
|
9507
9584
|
function canonicalize(outcome) {
|
|
9508
9585
|
return stringToBytes(stableStringify(outcome));
|
|
@@ -10653,7 +10730,9 @@ function createAuditTools(config) {
|
|
|
10653
10730
|
}
|
|
10654
10731
|
|
|
10655
10732
|
// src/l2-operational/context-gate.ts
|
|
10733
|
+
init_encryption();
|
|
10656
10734
|
init_encoding();
|
|
10735
|
+
init_random();
|
|
10657
10736
|
init_hashing();
|
|
10658
10737
|
var MAX_CONTEXT_FIELDS = 1e3;
|
|
10659
10738
|
var MAX_POLICY_RULES = 50;
|
|
@@ -12623,6 +12702,7 @@ function createL2HardeningTools(storagePath, auditLog) {
|
|
|
12623
12702
|
}
|
|
12624
12703
|
|
|
12625
12704
|
// src/index.ts
|
|
12705
|
+
init_random();
|
|
12626
12706
|
init_encoding();
|
|
12627
12707
|
|
|
12628
12708
|
// src/l2-operational/model-provenance.ts
|