@sanctuary-framework/mcp-server 0.5.12 → 0.5.14
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 +722 -22
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +722 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +937 -212
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +935 -213
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
var aes_js = require('@noble/ciphers/aes.js');
|
|
3
5
|
var sha256 = require('@noble/hashes/sha256');
|
|
4
6
|
var hmac = require('@noble/hashes/hmac');
|
|
7
|
+
var ed25519 = require('@noble/curves/ed25519');
|
|
5
8
|
var promises = require('fs/promises');
|
|
6
9
|
var path = require('path');
|
|
7
10
|
var os = require('os');
|
|
8
11
|
var module$1 = require('module');
|
|
9
|
-
var crypto = require('crypto');
|
|
10
|
-
var aes_js = require('@noble/ciphers/aes.js');
|
|
11
|
-
var ed25519 = require('@noble/curves/ed25519');
|
|
12
12
|
var hashWasm = require('hash-wasm');
|
|
13
13
|
var hkdf = require('@noble/hashes/hkdf');
|
|
14
14
|
var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
@@ -28,6 +28,26 @@ var __export = (target, all) => {
|
|
|
28
28
|
for (var name in all)
|
|
29
29
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
30
30
|
};
|
|
31
|
+
function randomBytes(length) {
|
|
32
|
+
if (length <= 0) {
|
|
33
|
+
throw new RangeError("Length must be positive");
|
|
34
|
+
}
|
|
35
|
+
const buf = crypto.randomBytes(length);
|
|
36
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
37
|
+
}
|
|
38
|
+
function generateIV() {
|
|
39
|
+
return randomBytes(12);
|
|
40
|
+
}
|
|
41
|
+
function generateSalt() {
|
|
42
|
+
return randomBytes(32);
|
|
43
|
+
}
|
|
44
|
+
function generateRandomKey() {
|
|
45
|
+
return randomBytes(32);
|
|
46
|
+
}
|
|
47
|
+
var init_random = __esm({
|
|
48
|
+
"src/core/random.ts"() {
|
|
49
|
+
}
|
|
50
|
+
});
|
|
31
51
|
|
|
32
52
|
// src/core/encoding.ts
|
|
33
53
|
var encoding_exports = {};
|
|
@@ -79,6 +99,42 @@ var init_encoding = __esm({
|
|
|
79
99
|
"src/core/encoding.ts"() {
|
|
80
100
|
}
|
|
81
101
|
});
|
|
102
|
+
function encrypt(plaintext, key, aad) {
|
|
103
|
+
if (key.length !== 32) {
|
|
104
|
+
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
105
|
+
}
|
|
106
|
+
const iv = generateIV();
|
|
107
|
+
const cipher = aes_js.gcm(key, iv, aad);
|
|
108
|
+
const ciphertext = cipher.encrypt(plaintext);
|
|
109
|
+
return {
|
|
110
|
+
v: 1,
|
|
111
|
+
alg: "aes-256-gcm",
|
|
112
|
+
iv: toBase64url(iv),
|
|
113
|
+
ct: toBase64url(ciphertext),
|
|
114
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function decrypt(payload, key, aad) {
|
|
118
|
+
if (key.length !== 32) {
|
|
119
|
+
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
120
|
+
}
|
|
121
|
+
if (payload.v !== 1) {
|
|
122
|
+
throw new Error(`Unsupported payload version: ${payload.v}`);
|
|
123
|
+
}
|
|
124
|
+
if (payload.alg !== "aes-256-gcm") {
|
|
125
|
+
throw new Error(`Unsupported algorithm: ${payload.alg}`);
|
|
126
|
+
}
|
|
127
|
+
const iv = fromBase64url(payload.iv);
|
|
128
|
+
const ciphertext = fromBase64url(payload.ct);
|
|
129
|
+
const cipher = aes_js.gcm(key, iv, aad);
|
|
130
|
+
return cipher.decrypt(ciphertext);
|
|
131
|
+
}
|
|
132
|
+
var init_encryption = __esm({
|
|
133
|
+
"src/core/encryption.ts"() {
|
|
134
|
+
init_random();
|
|
135
|
+
init_encoding();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
82
138
|
|
|
83
139
|
// src/core/hashing.ts
|
|
84
140
|
var hashing_exports = {};
|
|
@@ -207,6 +263,123 @@ var init_hashing = __esm({
|
|
|
207
263
|
init_encoding();
|
|
208
264
|
}
|
|
209
265
|
});
|
|
266
|
+
|
|
267
|
+
// src/core/identity.ts
|
|
268
|
+
var identity_exports = {};
|
|
269
|
+
__export(identity_exports, {
|
|
270
|
+
createIdentity: () => createIdentity,
|
|
271
|
+
generateIdentityId: () => generateIdentityId,
|
|
272
|
+
generateKeypair: () => generateKeypair,
|
|
273
|
+
publicKeyToDid: () => publicKeyToDid,
|
|
274
|
+
rotateKeys: () => rotateKeys,
|
|
275
|
+
sign: () => sign,
|
|
276
|
+
verify: () => verify
|
|
277
|
+
});
|
|
278
|
+
function generateKeypair() {
|
|
279
|
+
const privateKey = randomBytes(32);
|
|
280
|
+
const publicKey = ed25519.ed25519.getPublicKey(privateKey);
|
|
281
|
+
return { publicKey, privateKey };
|
|
282
|
+
}
|
|
283
|
+
function publicKeyToDid(publicKey) {
|
|
284
|
+
const multicodec = new Uint8Array([237, 1, ...publicKey]);
|
|
285
|
+
return `did:key:z${toBase64url(multicodec)}`;
|
|
286
|
+
}
|
|
287
|
+
function generateIdentityId(publicKey) {
|
|
288
|
+
const keyHash = hash(publicKey);
|
|
289
|
+
return Array.from(keyHash.slice(0, 16)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
290
|
+
}
|
|
291
|
+
function createIdentity(label, encryptionKey, keyProtection) {
|
|
292
|
+
const { publicKey, privateKey } = generateKeypair();
|
|
293
|
+
const identityId = generateIdentityId(publicKey);
|
|
294
|
+
const did = publicKeyToDid(publicKey);
|
|
295
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
296
|
+
const encryptedPrivateKey = encrypt(privateKey, encryptionKey);
|
|
297
|
+
privateKey.fill(0);
|
|
298
|
+
const publicIdentity = {
|
|
299
|
+
identity_id: identityId,
|
|
300
|
+
label,
|
|
301
|
+
public_key: toBase64url(publicKey),
|
|
302
|
+
did,
|
|
303
|
+
created_at: now,
|
|
304
|
+
key_type: "ed25519",
|
|
305
|
+
key_protection: keyProtection
|
|
306
|
+
};
|
|
307
|
+
const storedIdentity = {
|
|
308
|
+
...publicIdentity,
|
|
309
|
+
encrypted_private_key: encryptedPrivateKey,
|
|
310
|
+
rotation_history: []
|
|
311
|
+
};
|
|
312
|
+
return { publicIdentity, storedIdentity };
|
|
313
|
+
}
|
|
314
|
+
function sign(payload, encryptedPrivateKey, encryptionKey) {
|
|
315
|
+
const privateKey = decrypt(encryptedPrivateKey, encryptionKey);
|
|
316
|
+
try {
|
|
317
|
+
return ed25519.ed25519.sign(payload, privateKey);
|
|
318
|
+
} finally {
|
|
319
|
+
privateKey.fill(0);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function verify(payload, signature, publicKey) {
|
|
323
|
+
try {
|
|
324
|
+
return ed25519.ed25519.verify(signature, payload, publicKey);
|
|
325
|
+
} catch {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function rotateKeys(storedIdentity, encryptionKey, reason) {
|
|
330
|
+
const { publicKey: newPublicKey, privateKey: newPrivateKey } = generateKeypair();
|
|
331
|
+
const newIdentityDid = publicKeyToDid(newPublicKey);
|
|
332
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
333
|
+
const eventData = JSON.stringify({
|
|
334
|
+
old_public_key: storedIdentity.public_key,
|
|
335
|
+
new_public_key: toBase64url(newPublicKey),
|
|
336
|
+
identity_id: storedIdentity.identity_id,
|
|
337
|
+
reason,
|
|
338
|
+
rotated_at: now
|
|
339
|
+
});
|
|
340
|
+
const eventBytes = new TextEncoder().encode(eventData);
|
|
341
|
+
const signature = sign(
|
|
342
|
+
eventBytes,
|
|
343
|
+
storedIdentity.encrypted_private_key,
|
|
344
|
+
encryptionKey
|
|
345
|
+
);
|
|
346
|
+
const rotationEvent = {
|
|
347
|
+
old_public_key: storedIdentity.public_key,
|
|
348
|
+
new_public_key: toBase64url(newPublicKey),
|
|
349
|
+
identity_id: storedIdentity.identity_id,
|
|
350
|
+
reason,
|
|
351
|
+
rotated_at: now,
|
|
352
|
+
signature: toBase64url(signature)
|
|
353
|
+
};
|
|
354
|
+
const encryptedNewPrivateKey = encrypt(newPrivateKey, encryptionKey);
|
|
355
|
+
newPrivateKey.fill(0);
|
|
356
|
+
const updatedIdentity = {
|
|
357
|
+
...storedIdentity,
|
|
358
|
+
public_key: toBase64url(newPublicKey),
|
|
359
|
+
did: newIdentityDid,
|
|
360
|
+
encrypted_private_key: encryptedNewPrivateKey,
|
|
361
|
+
rotation_history: [
|
|
362
|
+
...storedIdentity.rotation_history,
|
|
363
|
+
{
|
|
364
|
+
old_public_key: storedIdentity.public_key,
|
|
365
|
+
new_public_key: toBase64url(newPublicKey),
|
|
366
|
+
rotation_event: toBase64url(
|
|
367
|
+
new TextEncoder().encode(JSON.stringify(rotationEvent))
|
|
368
|
+
),
|
|
369
|
+
rotated_at: now
|
|
370
|
+
}
|
|
371
|
+
]
|
|
372
|
+
};
|
|
373
|
+
return { updatedIdentity, rotationEvent };
|
|
374
|
+
}
|
|
375
|
+
var init_identity = __esm({
|
|
376
|
+
"src/core/identity.ts"() {
|
|
377
|
+
init_encoding();
|
|
378
|
+
init_encryption();
|
|
379
|
+
init_hashing();
|
|
380
|
+
init_random();
|
|
381
|
+
}
|
|
382
|
+
});
|
|
210
383
|
var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
211
384
|
var { version: PKG_VERSION } = require2("../package.json");
|
|
212
385
|
var SANCTUARY_VERSION = PKG_VERSION;
|
|
@@ -384,24 +557,9 @@ function deepMerge(base, override) {
|
|
|
384
557
|
}
|
|
385
558
|
return result;
|
|
386
559
|
}
|
|
387
|
-
function randomBytes(length) {
|
|
388
|
-
if (length <= 0) {
|
|
389
|
-
throw new RangeError("Length must be positive");
|
|
390
|
-
}
|
|
391
|
-
const buf = crypto.randomBytes(length);
|
|
392
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
393
|
-
}
|
|
394
|
-
function generateIV() {
|
|
395
|
-
return randomBytes(12);
|
|
396
|
-
}
|
|
397
|
-
function generateSalt() {
|
|
398
|
-
return randomBytes(32);
|
|
399
|
-
}
|
|
400
|
-
function generateRandomKey() {
|
|
401
|
-
return randomBytes(32);
|
|
402
|
-
}
|
|
403
560
|
|
|
404
561
|
// src/storage/filesystem.ts
|
|
562
|
+
init_random();
|
|
405
563
|
var FilesystemStorage = class {
|
|
406
564
|
basePath;
|
|
407
565
|
constructor(basePath) {
|
|
@@ -509,141 +667,14 @@ var FilesystemStorage = class {
|
|
|
509
667
|
return total;
|
|
510
668
|
}
|
|
511
669
|
};
|
|
512
|
-
init_encoding();
|
|
513
|
-
function encrypt(plaintext, key, aad) {
|
|
514
|
-
if (key.length !== 32) {
|
|
515
|
-
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
516
|
-
}
|
|
517
|
-
const iv = generateIV();
|
|
518
|
-
const cipher = aes_js.gcm(key, iv, aad);
|
|
519
|
-
const ciphertext = cipher.encrypt(plaintext);
|
|
520
|
-
return {
|
|
521
|
-
v: 1,
|
|
522
|
-
alg: "aes-256-gcm",
|
|
523
|
-
iv: toBase64url(iv),
|
|
524
|
-
ct: toBase64url(ciphertext),
|
|
525
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
function decrypt(payload, key, aad) {
|
|
529
|
-
if (key.length !== 32) {
|
|
530
|
-
throw new Error("Key must be exactly 32 bytes (256 bits)");
|
|
531
|
-
}
|
|
532
|
-
if (payload.v !== 1) {
|
|
533
|
-
throw new Error(`Unsupported payload version: ${payload.v}`);
|
|
534
|
-
}
|
|
535
|
-
if (payload.alg !== "aes-256-gcm") {
|
|
536
|
-
throw new Error(`Unsupported algorithm: ${payload.alg}`);
|
|
537
|
-
}
|
|
538
|
-
const iv = fromBase64url(payload.iv);
|
|
539
|
-
const ciphertext = fromBase64url(payload.ct);
|
|
540
|
-
const cipher = aes_js.gcm(key, iv, aad);
|
|
541
|
-
return cipher.decrypt(ciphertext);
|
|
542
|
-
}
|
|
543
670
|
|
|
544
671
|
// src/l1-cognitive/state-store.ts
|
|
672
|
+
init_encryption();
|
|
545
673
|
init_hashing();
|
|
674
|
+
init_identity();
|
|
546
675
|
|
|
547
|
-
// src/core/
|
|
548
|
-
|
|
549
|
-
init_hashing();
|
|
550
|
-
function generateKeypair() {
|
|
551
|
-
const privateKey = randomBytes(32);
|
|
552
|
-
const publicKey = ed25519.ed25519.getPublicKey(privateKey);
|
|
553
|
-
return { publicKey, privateKey };
|
|
554
|
-
}
|
|
555
|
-
function publicKeyToDid(publicKey) {
|
|
556
|
-
const multicodec = new Uint8Array([237, 1, ...publicKey]);
|
|
557
|
-
return `did:key:z${toBase64url(multicodec)}`;
|
|
558
|
-
}
|
|
559
|
-
function generateIdentityId(publicKey) {
|
|
560
|
-
const keyHash = hash(publicKey);
|
|
561
|
-
return Array.from(keyHash.slice(0, 16)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
562
|
-
}
|
|
563
|
-
function createIdentity(label, encryptionKey, keyProtection) {
|
|
564
|
-
const { publicKey, privateKey } = generateKeypair();
|
|
565
|
-
const identityId = generateIdentityId(publicKey);
|
|
566
|
-
const did = publicKeyToDid(publicKey);
|
|
567
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
568
|
-
const encryptedPrivateKey = encrypt(privateKey, encryptionKey);
|
|
569
|
-
privateKey.fill(0);
|
|
570
|
-
const publicIdentity = {
|
|
571
|
-
identity_id: identityId,
|
|
572
|
-
label,
|
|
573
|
-
public_key: toBase64url(publicKey),
|
|
574
|
-
did,
|
|
575
|
-
created_at: now,
|
|
576
|
-
key_type: "ed25519",
|
|
577
|
-
key_protection: keyProtection
|
|
578
|
-
};
|
|
579
|
-
const storedIdentity = {
|
|
580
|
-
...publicIdentity,
|
|
581
|
-
encrypted_private_key: encryptedPrivateKey,
|
|
582
|
-
rotation_history: []
|
|
583
|
-
};
|
|
584
|
-
return { publicIdentity, storedIdentity };
|
|
585
|
-
}
|
|
586
|
-
function sign(payload, encryptedPrivateKey, encryptionKey) {
|
|
587
|
-
const privateKey = decrypt(encryptedPrivateKey, encryptionKey);
|
|
588
|
-
try {
|
|
589
|
-
return ed25519.ed25519.sign(payload, privateKey);
|
|
590
|
-
} finally {
|
|
591
|
-
privateKey.fill(0);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
function verify(payload, signature, publicKey) {
|
|
595
|
-
try {
|
|
596
|
-
return ed25519.ed25519.verify(signature, payload, publicKey);
|
|
597
|
-
} catch {
|
|
598
|
-
return false;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
function rotateKeys(storedIdentity, encryptionKey, reason) {
|
|
602
|
-
const { publicKey: newPublicKey, privateKey: newPrivateKey } = generateKeypair();
|
|
603
|
-
const newIdentityDid = publicKeyToDid(newPublicKey);
|
|
604
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
605
|
-
const eventData = JSON.stringify({
|
|
606
|
-
old_public_key: storedIdentity.public_key,
|
|
607
|
-
new_public_key: toBase64url(newPublicKey),
|
|
608
|
-
identity_id: storedIdentity.identity_id,
|
|
609
|
-
reason,
|
|
610
|
-
rotated_at: now
|
|
611
|
-
});
|
|
612
|
-
const eventBytes = new TextEncoder().encode(eventData);
|
|
613
|
-
const signature = sign(
|
|
614
|
-
eventBytes,
|
|
615
|
-
storedIdentity.encrypted_private_key,
|
|
616
|
-
encryptionKey
|
|
617
|
-
);
|
|
618
|
-
const rotationEvent = {
|
|
619
|
-
old_public_key: storedIdentity.public_key,
|
|
620
|
-
new_public_key: toBase64url(newPublicKey),
|
|
621
|
-
identity_id: storedIdentity.identity_id,
|
|
622
|
-
reason,
|
|
623
|
-
rotated_at: now,
|
|
624
|
-
signature: toBase64url(signature)
|
|
625
|
-
};
|
|
626
|
-
const encryptedNewPrivateKey = encrypt(newPrivateKey, encryptionKey);
|
|
627
|
-
newPrivateKey.fill(0);
|
|
628
|
-
const updatedIdentity = {
|
|
629
|
-
...storedIdentity,
|
|
630
|
-
public_key: toBase64url(newPublicKey),
|
|
631
|
-
did: newIdentityDid,
|
|
632
|
-
encrypted_private_key: encryptedNewPrivateKey,
|
|
633
|
-
rotation_history: [
|
|
634
|
-
...storedIdentity.rotation_history,
|
|
635
|
-
{
|
|
636
|
-
old_public_key: storedIdentity.public_key,
|
|
637
|
-
new_public_key: toBase64url(newPublicKey),
|
|
638
|
-
rotation_event: toBase64url(
|
|
639
|
-
new TextEncoder().encode(JSON.stringify(rotationEvent))
|
|
640
|
-
),
|
|
641
|
-
rotated_at: now
|
|
642
|
-
}
|
|
643
|
-
]
|
|
644
|
-
};
|
|
645
|
-
return { updatedIdentity, rotationEvent };
|
|
646
|
-
}
|
|
676
|
+
// src/core/key-derivation.ts
|
|
677
|
+
init_random();
|
|
647
678
|
init_encoding();
|
|
648
679
|
var ARGON2_MEMORY_COST = 65536;
|
|
649
680
|
var ARGON2_TIME_COST = 3;
|
|
@@ -717,7 +748,9 @@ var RESERVED_NAMESPACE_PREFIXES = [
|
|
|
717
748
|
"_bridge",
|
|
718
749
|
"_federation",
|
|
719
750
|
"_handshake",
|
|
720
|
-
"_shr"
|
|
751
|
+
"_shr",
|
|
752
|
+
"_sovereignty_profile",
|
|
753
|
+
"_context_gate_policies"
|
|
721
754
|
];
|
|
722
755
|
var StateStore = class {
|
|
723
756
|
storage;
|
|
@@ -1241,7 +1274,9 @@ function toolResult(data) {
|
|
|
1241
1274
|
}
|
|
1242
1275
|
|
|
1243
1276
|
// src/l1-cognitive/tools.ts
|
|
1277
|
+
init_identity();
|
|
1244
1278
|
init_encoding();
|
|
1279
|
+
init_encryption();
|
|
1245
1280
|
init_encoding();
|
|
1246
1281
|
var RESERVED_NAMESPACE_PREFIXES2 = [
|
|
1247
1282
|
"_identities",
|
|
@@ -1256,7 +1291,9 @@ var RESERVED_NAMESPACE_PREFIXES2 = [
|
|
|
1256
1291
|
"_bridge",
|
|
1257
1292
|
"_federation",
|
|
1258
1293
|
"_handshake",
|
|
1259
|
-
"_shr"
|
|
1294
|
+
"_shr",
|
|
1295
|
+
"_sovereignty_profile",
|
|
1296
|
+
"_context_gate_policies"
|
|
1260
1297
|
];
|
|
1261
1298
|
function getReservedNamespaceViolation(namespace) {
|
|
1262
1299
|
for (const prefix of RESERVED_NAMESPACE_PREFIXES2) {
|
|
@@ -1748,6 +1785,7 @@ function createL1Tools(stateStore, storage, masterKey, keyProtection, auditLog)
|
|
|
1748
1785
|
}
|
|
1749
1786
|
|
|
1750
1787
|
// src/l2-operational/audit-log.ts
|
|
1788
|
+
init_encryption();
|
|
1751
1789
|
init_encoding();
|
|
1752
1790
|
var AuditLog = class {
|
|
1753
1791
|
storage;
|
|
@@ -1845,6 +1883,8 @@ var AuditLog = class {
|
|
|
1845
1883
|
// src/l3-disclosure/commitments.ts
|
|
1846
1884
|
init_hashing();
|
|
1847
1885
|
init_encoding();
|
|
1886
|
+
init_random();
|
|
1887
|
+
init_encryption();
|
|
1848
1888
|
init_encoding();
|
|
1849
1889
|
function createCommitment(value, blindingFactor) {
|
|
1850
1890
|
const blindingBytes = blindingFactor ? fromBase64url(blindingFactor) : randomBytes(32);
|
|
@@ -1925,7 +1965,9 @@ var CommitmentStore = class {
|
|
|
1925
1965
|
};
|
|
1926
1966
|
|
|
1927
1967
|
// src/l3-disclosure/policies.ts
|
|
1968
|
+
init_encryption();
|
|
1928
1969
|
init_encoding();
|
|
1970
|
+
init_random();
|
|
1929
1971
|
function evaluateDisclosure(policy, context, requestedFields) {
|
|
1930
1972
|
return requestedFields.map((field) => {
|
|
1931
1973
|
const exactRule = policy.rules.find((r) => r.context === context);
|
|
@@ -2056,6 +2098,9 @@ var PolicyStore = class {
|
|
|
2056
2098
|
);
|
|
2057
2099
|
}
|
|
2058
2100
|
};
|
|
2101
|
+
|
|
2102
|
+
// src/l3-disclosure/zk-proofs.ts
|
|
2103
|
+
init_random();
|
|
2059
2104
|
init_encoding();
|
|
2060
2105
|
var G = ed25519.RistrettoPoint.BASE;
|
|
2061
2106
|
var H_INPUT = concatBytes(
|
|
@@ -2733,7 +2778,10 @@ function createL3Tools(storage, masterKey, auditLog) {
|
|
|
2733
2778
|
}
|
|
2734
2779
|
|
|
2735
2780
|
// src/l4-reputation/reputation-store.ts
|
|
2781
|
+
init_encryption();
|
|
2736
2782
|
init_encoding();
|
|
2783
|
+
init_random();
|
|
2784
|
+
init_identity();
|
|
2737
2785
|
function computeMedian(values) {
|
|
2738
2786
|
if (values.length === 0) return 0;
|
|
2739
2787
|
const sorted = [...values].sort((a, b) => a - b);
|
|
@@ -3628,6 +3676,24 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3628
3676
|
}
|
|
3629
3677
|
const publishType = args.type;
|
|
3630
3678
|
const veracoreUrl = args.verascore_url || "https://verascore.ai";
|
|
3679
|
+
const ALLOWED_VERASCORE_HOSTS = ["verascore.ai", "www.verascore.ai", "api.verascore.ai"];
|
|
3680
|
+
try {
|
|
3681
|
+
const parsed = new URL(veracoreUrl);
|
|
3682
|
+
if (parsed.protocol !== "https:") {
|
|
3683
|
+
return toolResult({
|
|
3684
|
+
error: `verascore_url must use HTTPS. Got: ${parsed.protocol}`
|
|
3685
|
+
});
|
|
3686
|
+
}
|
|
3687
|
+
if (!ALLOWED_VERASCORE_HOSTS.includes(parsed.hostname)) {
|
|
3688
|
+
return toolResult({
|
|
3689
|
+
error: `verascore_url must point to a known Verascore domain (${ALLOWED_VERASCORE_HOSTS.join(", ")}). Got: ${parsed.hostname}`
|
|
3690
|
+
});
|
|
3691
|
+
}
|
|
3692
|
+
} catch {
|
|
3693
|
+
return toolResult({
|
|
3694
|
+
error: `verascore_url is not a valid URL: ${veracoreUrl}`
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3631
3697
|
const agentId = args.verascore_agent_id || identity.did.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase();
|
|
3632
3698
|
let publishData;
|
|
3633
3699
|
if (args.data) {
|
|
@@ -3657,24 +3723,21 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3657
3723
|
return toolResult({ error: `Unknown publish type: ${publishType}` });
|
|
3658
3724
|
}
|
|
3659
3725
|
}
|
|
3660
|
-
const { sign:
|
|
3661
|
-
const payloadBytes =
|
|
3726
|
+
const { sign: identitySign } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
3727
|
+
const payloadBytes = new TextEncoder().encode(JSON.stringify(publishData));
|
|
3662
3728
|
let signatureB64;
|
|
3663
3729
|
try {
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
]),
|
|
3671
|
-
format: "der",
|
|
3672
|
-
type: "pkcs8"
|
|
3673
|
-
});
|
|
3674
|
-
const sig = sign2(null, payloadBytes, privateKey);
|
|
3675
|
-
signatureB64 = sig.toString("base64url");
|
|
3730
|
+
const signingBytes = identitySign(
|
|
3731
|
+
payloadBytes,
|
|
3732
|
+
identity.encrypted_private_key,
|
|
3733
|
+
identityEncryptionKey
|
|
3734
|
+
);
|
|
3735
|
+
signatureB64 = toBase64url(signingBytes);
|
|
3676
3736
|
} catch (signError) {
|
|
3677
|
-
|
|
3737
|
+
return toolResult({
|
|
3738
|
+
error: "Failed to sign publish payload. Identity key may be corrupted.",
|
|
3739
|
+
details: signError instanceof Error ? signError.message : String(signError)
|
|
3740
|
+
});
|
|
3678
3741
|
}
|
|
3679
3742
|
const requestBody = {
|
|
3680
3743
|
agentId,
|
|
@@ -3753,7 +3816,11 @@ var DEFAULT_POLICY = {
|
|
|
3753
3816
|
"reputation_import",
|
|
3754
3817
|
"reputation_export",
|
|
3755
3818
|
"bootstrap_provide_guarantee",
|
|
3756
|
-
"decommission_certificate"
|
|
3819
|
+
"decommission_certificate",
|
|
3820
|
+
"reputation_publish",
|
|
3821
|
+
// SEC-039: Explicit Tier 1 — sends data to external API
|
|
3822
|
+
"sovereignty_profile_update"
|
|
3823
|
+
// Changes enforcement behavior — always requires approval
|
|
3757
3824
|
],
|
|
3758
3825
|
tier2_anomaly: DEFAULT_TIER2,
|
|
3759
3826
|
tier3_always_allow: [
|
|
@@ -3805,7 +3872,11 @@ var DEFAULT_POLICY = {
|
|
|
3805
3872
|
"shr_gateway_export",
|
|
3806
3873
|
"bridge_commit",
|
|
3807
3874
|
"bridge_verify",
|
|
3808
|
-
"bridge_attest"
|
|
3875
|
+
"bridge_attest",
|
|
3876
|
+
"dashboard_open",
|
|
3877
|
+
// SEC-039: Explicit Tier 3 — only generates a URL
|
|
3878
|
+
"sovereignty_profile_get",
|
|
3879
|
+
"sovereignty_profile_generate_prompt"
|
|
3809
3880
|
],
|
|
3810
3881
|
approval_channel: DEFAULT_CHANNEL
|
|
3811
3882
|
};
|
|
@@ -3913,6 +3984,8 @@ tier1_always_approve:
|
|
|
3913
3984
|
- reputation_import
|
|
3914
3985
|
- reputation_export
|
|
3915
3986
|
- bootstrap_provide_guarantee
|
|
3987
|
+
- reputation_publish
|
|
3988
|
+
- sovereignty_profile_update
|
|
3916
3989
|
|
|
3917
3990
|
# \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
|
|
3918
3991
|
# Triggers approval when agent behavior deviates from its baseline.
|
|
@@ -3975,6 +4048,9 @@ tier3_always_allow:
|
|
|
3975
4048
|
- bridge_commit
|
|
3976
4049
|
- bridge_verify
|
|
3977
4050
|
- bridge_attest
|
|
4051
|
+
- dashboard_open
|
|
4052
|
+
- sovereignty_profile_get
|
|
4053
|
+
- sovereignty_profile_generate_prompt
|
|
3978
4054
|
|
|
3979
4055
|
# \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
|
|
3980
4056
|
# How Sanctuary reaches you when approval is needed.
|
|
@@ -4002,6 +4078,7 @@ async function loadPrincipalPolicy(storagePath) {
|
|
|
4002
4078
|
}
|
|
4003
4079
|
|
|
4004
4080
|
// src/principal-policy/baseline.ts
|
|
4081
|
+
init_encryption();
|
|
4005
4082
|
init_encoding();
|
|
4006
4083
|
var BASELINE_NAMESPACE = "_principal";
|
|
4007
4084
|
var BASELINE_KEY = "session-baseline";
|
|
@@ -4227,6 +4304,7 @@ function canonicalizeForSigning(body) {
|
|
|
4227
4304
|
}
|
|
4228
4305
|
|
|
4229
4306
|
// src/shr/generator.ts
|
|
4307
|
+
init_identity();
|
|
4230
4308
|
init_encoding();
|
|
4231
4309
|
var DEFAULT_VALIDITY_MS = 60 * 60 * 1e3;
|
|
4232
4310
|
function generateSHR(identityId, opts) {
|
|
@@ -5179,73 +5257,200 @@ function generateDashboardHTML(options) {
|
|
|
5179
5257
|
right: 0;
|
|
5180
5258
|
}
|
|
5181
5259
|
|
|
5182
|
-
.pending-header {
|
|
5183
|
-
padding: 16px 20px;
|
|
5184
|
-
border-bottom: 1px solid var(--border);
|
|
5185
|
-
font-weight: 600;
|
|
5186
|
-
color: var(--text-primary);
|
|
5260
|
+
.pending-header {
|
|
5261
|
+
padding: 16px 20px;
|
|
5262
|
+
border-bottom: 1px solid var(--border);
|
|
5263
|
+
font-weight: 600;
|
|
5264
|
+
color: var(--text-primary);
|
|
5265
|
+
}
|
|
5266
|
+
|
|
5267
|
+
.pending-items {
|
|
5268
|
+
flex: 1;
|
|
5269
|
+
overflow-y: auto;
|
|
5270
|
+
padding: 16px;
|
|
5271
|
+
}
|
|
5272
|
+
|
|
5273
|
+
.pending-item {
|
|
5274
|
+
background-color: var(--bg);
|
|
5275
|
+
border: 1px solid var(--border);
|
|
5276
|
+
border-radius: 6px;
|
|
5277
|
+
padding: 16px;
|
|
5278
|
+
margin-bottom: 12px;
|
|
5279
|
+
}
|
|
5280
|
+
|
|
5281
|
+
.pending-title {
|
|
5282
|
+
font-weight: 600;
|
|
5283
|
+
color: var(--text-primary);
|
|
5284
|
+
margin-bottom: 8px;
|
|
5285
|
+
word-break: break-word;
|
|
5286
|
+
}
|
|
5287
|
+
|
|
5288
|
+
.pending-countdown {
|
|
5289
|
+
font-size: 12px;
|
|
5290
|
+
color: var(--amber);
|
|
5291
|
+
margin-bottom: 12px;
|
|
5292
|
+
font-weight: 500;
|
|
5293
|
+
}
|
|
5294
|
+
|
|
5295
|
+
.pending-actions {
|
|
5296
|
+
display: flex;
|
|
5297
|
+
gap: 8px;
|
|
5298
|
+
}
|
|
5299
|
+
|
|
5300
|
+
.pending-btn {
|
|
5301
|
+
flex: 1;
|
|
5302
|
+
padding: 8px 12px;
|
|
5303
|
+
border: none;
|
|
5304
|
+
border-radius: 4px;
|
|
5305
|
+
font-size: 12px;
|
|
5306
|
+
font-weight: 600;
|
|
5307
|
+
cursor: pointer;
|
|
5308
|
+
transition: background-color 0.2s;
|
|
5309
|
+
}
|
|
5310
|
+
|
|
5311
|
+
.pending-approve {
|
|
5312
|
+
background-color: var(--green);
|
|
5313
|
+
color: var(--bg);
|
|
5314
|
+
}
|
|
5315
|
+
|
|
5316
|
+
.pending-approve:hover {
|
|
5317
|
+
background-color: #3fa040;
|
|
5318
|
+
}
|
|
5319
|
+
|
|
5320
|
+
.pending-deny {
|
|
5321
|
+
background-color: var(--red);
|
|
5322
|
+
color: var(--bg);
|
|
5323
|
+
}
|
|
5324
|
+
|
|
5325
|
+
.pending-deny:hover {
|
|
5326
|
+
background-color: #e03c3c;
|
|
5327
|
+
}
|
|
5328
|
+
|
|
5329
|
+
/* Sovereignty Profile Panel */
|
|
5330
|
+
.profile-panel {
|
|
5331
|
+
background-color: var(--surface);
|
|
5332
|
+
border: 1px solid var(--border);
|
|
5333
|
+
border-radius: 8px;
|
|
5334
|
+
padding: 20px;
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
.profile-panel .panel-header {
|
|
5338
|
+
display: flex;
|
|
5339
|
+
justify-content: space-between;
|
|
5340
|
+
align-items: center;
|
|
5341
|
+
margin-bottom: 16px;
|
|
5342
|
+
}
|
|
5343
|
+
|
|
5344
|
+
.profile-panel .panel-title {
|
|
5345
|
+
font-size: 14px;
|
|
5346
|
+
font-weight: 600;
|
|
5347
|
+
color: var(--text-primary);
|
|
5348
|
+
}
|
|
5349
|
+
|
|
5350
|
+
.profile-cards {
|
|
5351
|
+
display: grid;
|
|
5352
|
+
grid-template-columns: repeat(5, 1fr);
|
|
5353
|
+
gap: 12px;
|
|
5354
|
+
margin-bottom: 16px;
|
|
5355
|
+
}
|
|
5356
|
+
|
|
5357
|
+
.profile-card {
|
|
5358
|
+
background-color: var(--bg);
|
|
5359
|
+
border: 1px solid var(--border);
|
|
5360
|
+
border-radius: 6px;
|
|
5361
|
+
padding: 14px;
|
|
5362
|
+
display: flex;
|
|
5363
|
+
flex-direction: column;
|
|
5364
|
+
gap: 8px;
|
|
5365
|
+
}
|
|
5366
|
+
|
|
5367
|
+
.profile-card-name {
|
|
5368
|
+
font-size: 12px;
|
|
5369
|
+
font-weight: 600;
|
|
5370
|
+
color: var(--text-primary);
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
.profile-card-desc {
|
|
5374
|
+
font-size: 11px;
|
|
5375
|
+
color: var(--text-secondary);
|
|
5376
|
+
line-height: 1.4;
|
|
5377
|
+
}
|
|
5378
|
+
|
|
5379
|
+
.profile-badge {
|
|
5380
|
+
display: inline-flex;
|
|
5381
|
+
align-items: center;
|
|
5382
|
+
gap: 4px;
|
|
5383
|
+
padding: 2px 8px;
|
|
5384
|
+
border-radius: 4px;
|
|
5385
|
+
font-size: 10px;
|
|
5386
|
+
font-weight: 600;
|
|
5387
|
+
width: fit-content;
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5390
|
+
.profile-badge.enabled {
|
|
5391
|
+
background-color: rgba(63, 185, 80, 0.15);
|
|
5392
|
+
color: var(--green);
|
|
5393
|
+
}
|
|
5394
|
+
|
|
5395
|
+
.profile-badge.disabled {
|
|
5396
|
+
background-color: rgba(139, 148, 158, 0.15);
|
|
5397
|
+
color: var(--text-secondary);
|
|
5187
5398
|
}
|
|
5188
5399
|
|
|
5189
|
-
.
|
|
5190
|
-
|
|
5191
|
-
overflow-y: auto;
|
|
5192
|
-
padding: 16px;
|
|
5400
|
+
.prompt-section {
|
|
5401
|
+
margin-top: 12px;
|
|
5193
5402
|
}
|
|
5194
5403
|
|
|
5195
|
-
.
|
|
5404
|
+
.prompt-textarea {
|
|
5405
|
+
width: 100%;
|
|
5406
|
+
min-height: 120px;
|
|
5196
5407
|
background-color: var(--bg);
|
|
5197
5408
|
border: 1px solid var(--border);
|
|
5198
5409
|
border-radius: 6px;
|
|
5199
|
-
padding: 16px;
|
|
5200
|
-
margin-bottom: 12px;
|
|
5201
|
-
}
|
|
5202
|
-
|
|
5203
|
-
.pending-title {
|
|
5204
|
-
font-weight: 600;
|
|
5205
5410
|
color: var(--text-primary);
|
|
5206
|
-
|
|
5207
|
-
word-break: break-word;
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
.pending-countdown {
|
|
5411
|
+
font-family: 'JetBrains Mono', monospace;
|
|
5211
5412
|
font-size: 12px;
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5413
|
+
padding: 12px;
|
|
5414
|
+
resize: vertical;
|
|
5415
|
+
margin-top: 8px;
|
|
5215
5416
|
}
|
|
5216
5417
|
|
|
5217
|
-
.
|
|
5418
|
+
.prompt-actions {
|
|
5218
5419
|
display: flex;
|
|
5219
5420
|
gap: 8px;
|
|
5421
|
+
margin-top: 8px;
|
|
5220
5422
|
}
|
|
5221
5423
|
|
|
5222
|
-
.
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
border: none;
|
|
5424
|
+
.prompt-btn {
|
|
5425
|
+
padding: 6px 12px;
|
|
5426
|
+
border: 1px solid var(--border);
|
|
5226
5427
|
border-radius: 4px;
|
|
5428
|
+
background-color: var(--surface);
|
|
5429
|
+
color: var(--text-primary);
|
|
5227
5430
|
font-size: 12px;
|
|
5228
|
-
font-weight: 600;
|
|
5229
5431
|
cursor: pointer;
|
|
5230
|
-
transition: background-color 0.2s;
|
|
5231
5432
|
}
|
|
5232
5433
|
|
|
5233
|
-
.
|
|
5234
|
-
background-color: var(--
|
|
5235
|
-
color: var(--bg);
|
|
5434
|
+
.prompt-btn:hover {
|
|
5435
|
+
background-color: var(--muted);
|
|
5236
5436
|
}
|
|
5237
5437
|
|
|
5238
|
-
.
|
|
5239
|
-
background-color:
|
|
5438
|
+
.prompt-btn.primary {
|
|
5439
|
+
background-color: var(--blue);
|
|
5440
|
+
color: var(--bg);
|
|
5441
|
+
border-color: var(--blue);
|
|
5240
5442
|
}
|
|
5241
5443
|
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5444
|
+
@media (max-width: 900px) {
|
|
5445
|
+
.profile-cards {
|
|
5446
|
+
grid-template-columns: repeat(2, 1fr);
|
|
5447
|
+
}
|
|
5245
5448
|
}
|
|
5246
5449
|
|
|
5247
|
-
|
|
5248
|
-
|
|
5450
|
+
@media (max-width: 500px) {
|
|
5451
|
+
.profile-cards {
|
|
5452
|
+
grid-template-columns: 1fr;
|
|
5453
|
+
}
|
|
5249
5454
|
}
|
|
5250
5455
|
|
|
5251
5456
|
/* Threat Panel */
|
|
@@ -5586,6 +5791,48 @@ function generateDashboardHTML(options) {
|
|
|
5586
5791
|
</div>
|
|
5587
5792
|
</div>
|
|
5588
5793
|
|
|
5794
|
+
<!-- Sovereignty Profile Panel -->
|
|
5795
|
+
<div class="profile-panel" id="sovereignty-profile-panel">
|
|
5796
|
+
<div class="panel-header">
|
|
5797
|
+
<div class="panel-title">Sovereignty Profile</div>
|
|
5798
|
+
<span class="card-value" id="profile-updated-at" style="font-size: 11px; color: var(--text-secondary);">\u2014</span>
|
|
5799
|
+
</div>
|
|
5800
|
+
<div class="profile-cards" id="profile-cards">
|
|
5801
|
+
<div class="profile-card" data-feature="audit_logging">
|
|
5802
|
+
<div class="profile-card-name">Audit Logging</div>
|
|
5803
|
+
<div class="profile-badge disabled" id="badge-audit_logging">OFF</div>
|
|
5804
|
+
<div class="profile-card-desc">Encrypted audit trail of all tool calls</div>
|
|
5805
|
+
</div>
|
|
5806
|
+
<div class="profile-card" data-feature="injection_detection">
|
|
5807
|
+
<div class="profile-card-name">Injection Detection</div>
|
|
5808
|
+
<div class="profile-badge disabled" id="badge-injection_detection">OFF</div>
|
|
5809
|
+
<div class="profile-card-desc">Scans tool arguments for prompt injection</div>
|
|
5810
|
+
</div>
|
|
5811
|
+
<div class="profile-card" data-feature="context_gating">
|
|
5812
|
+
<div class="profile-card-name">Context Gating</div>
|
|
5813
|
+
<div class="profile-badge disabled" id="badge-context_gating">OFF</div>
|
|
5814
|
+
<div class="profile-card-desc">Controls context flow to remote providers</div>
|
|
5815
|
+
</div>
|
|
5816
|
+
<div class="profile-card" data-feature="approval_gate">
|
|
5817
|
+
<div class="profile-card-name">Approval Gates</div>
|
|
5818
|
+
<div class="profile-badge disabled" id="badge-approval_gate">OFF</div>
|
|
5819
|
+
<div class="profile-card-desc">Human approval for high-risk operations</div>
|
|
5820
|
+
</div>
|
|
5821
|
+
<div class="profile-card" data-feature="zk_proofs">
|
|
5822
|
+
<div class="profile-card-name">ZK Proofs</div>
|
|
5823
|
+
<div class="profile-badge disabled" id="badge-zk_proofs">OFF</div>
|
|
5824
|
+
<div class="profile-card-desc">Prove claims without revealing data</div>
|
|
5825
|
+
</div>
|
|
5826
|
+
</div>
|
|
5827
|
+
<div class="prompt-section">
|
|
5828
|
+
<div class="prompt-actions">
|
|
5829
|
+
<button class="prompt-btn primary" id="generate-prompt-btn">Generate System Prompt</button>
|
|
5830
|
+
<button class="prompt-btn" id="copy-prompt-btn" style="display:none;">Copy</button>
|
|
5831
|
+
</div>
|
|
5832
|
+
<textarea class="prompt-textarea" id="system-prompt-output" readonly style="display:none;" placeholder="Click 'Generate System Prompt' to create an agent instruction snippet..."></textarea>
|
|
5833
|
+
</div>
|
|
5834
|
+
</div>
|
|
5835
|
+
|
|
5589
5836
|
<!-- Threat Panel -->
|
|
5590
5837
|
<div class="threat-panel collapsed">
|
|
5591
5838
|
<div class="threat-header">
|
|
@@ -5607,7 +5854,9 @@ function generateDashboardHTML(options) {
|
|
|
5607
5854
|
|
|
5608
5855
|
<script>
|
|
5609
5856
|
// Constants
|
|
5610
|
-
|
|
5857
|
+
// SEC-038: Do NOT embed the long-lived auth token in page source.
|
|
5858
|
+
// Use only the session token stored in sessionStorage by the login flow.
|
|
5859
|
+
const AUTH_TOKEN = sessionStorage.getItem('authToken') || '';
|
|
5611
5860
|
const TIMEOUT_SECONDS = ${options.timeoutSeconds};
|
|
5612
5861
|
const API_BASE = '';
|
|
5613
5862
|
|
|
@@ -5618,6 +5867,7 @@ function generateDashboardHTML(options) {
|
|
|
5618
5867
|
handshakes: [],
|
|
5619
5868
|
shr: null,
|
|
5620
5869
|
status: null,
|
|
5870
|
+
systemPrompt: null,
|
|
5621
5871
|
};
|
|
5622
5872
|
|
|
5623
5873
|
let pendingRequests = new Map();
|
|
@@ -6070,6 +6320,10 @@ function generateDashboardHTML(options) {
|
|
|
6070
6320
|
removePendingRequest(data.requestId);
|
|
6071
6321
|
});
|
|
6072
6322
|
|
|
6323
|
+
eventSource.addEventListener('sovereignty-profile-update', () => {
|
|
6324
|
+
updateSovereigntyProfile();
|
|
6325
|
+
});
|
|
6326
|
+
|
|
6073
6327
|
eventSource.onerror = () => {
|
|
6074
6328
|
console.error('SSE error');
|
|
6075
6329
|
setTimeout(setupSSE, 5000);
|
|
@@ -6226,6 +6480,58 @@ function generateDashboardHTML(options) {
|
|
|
6226
6480
|
document.getElementById('pending-overlay').classList.toggle('show');
|
|
6227
6481
|
});
|
|
6228
6482
|
|
|
6483
|
+
// Sovereignty Profile
|
|
6484
|
+
async function updateSovereigntyProfile() {
|
|
6485
|
+
try {
|
|
6486
|
+
const data = await fetchAPI('/api/sovereignty-profile');
|
|
6487
|
+
if (data && data.profile) {
|
|
6488
|
+
const features = data.profile.features;
|
|
6489
|
+
for (const [key, value] of Object.entries(features)) {
|
|
6490
|
+
const badge = document.getElementById('badge-' + key);
|
|
6491
|
+
if (badge) {
|
|
6492
|
+
const enabled = value && value.enabled;
|
|
6493
|
+
badge.textContent = enabled ? 'ON' : 'OFF';
|
|
6494
|
+
badge.className = 'profile-badge ' + (enabled ? 'enabled' : 'disabled');
|
|
6495
|
+
}
|
|
6496
|
+
}
|
|
6497
|
+
const updatedEl = document.getElementById('profile-updated-at');
|
|
6498
|
+
if (updatedEl && data.profile.updated_at) {
|
|
6499
|
+
updatedEl.textContent = 'Updated: ' + new Date(data.profile.updated_at).toLocaleString();
|
|
6500
|
+
}
|
|
6501
|
+
// Cache the prompt
|
|
6502
|
+
if (data.system_prompt) {
|
|
6503
|
+
apiState.systemPrompt = data.system_prompt;
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
} catch (e) {
|
|
6507
|
+
// Profile not available
|
|
6508
|
+
}
|
|
6509
|
+
}
|
|
6510
|
+
|
|
6511
|
+
document.getElementById('generate-prompt-btn').addEventListener('click', async () => {
|
|
6512
|
+
const data = await fetchAPI('/api/sovereignty-profile');
|
|
6513
|
+
if (data && data.system_prompt) {
|
|
6514
|
+
const textarea = document.getElementById('system-prompt-output');
|
|
6515
|
+
const copyBtn = document.getElementById('copy-prompt-btn');
|
|
6516
|
+
textarea.value = data.system_prompt;
|
|
6517
|
+
textarea.style.display = 'block';
|
|
6518
|
+
copyBtn.style.display = 'inline-flex';
|
|
6519
|
+
}
|
|
6520
|
+
});
|
|
6521
|
+
|
|
6522
|
+
document.getElementById('copy-prompt-btn').addEventListener('click', async () => {
|
|
6523
|
+
const textarea = document.getElementById('system-prompt-output');
|
|
6524
|
+
try {
|
|
6525
|
+
await navigator.clipboard.writeText(textarea.value);
|
|
6526
|
+
const btn = document.getElementById('copy-prompt-btn');
|
|
6527
|
+
const original = btn.textContent;
|
|
6528
|
+
btn.textContent = 'Copied!';
|
|
6529
|
+
setTimeout(() => { btn.textContent = original; }, 2000);
|
|
6530
|
+
} catch (err) {
|
|
6531
|
+
console.error('Copy failed:', err);
|
|
6532
|
+
}
|
|
6533
|
+
});
|
|
6534
|
+
|
|
6229
6535
|
// Initialize
|
|
6230
6536
|
async function initialize() {
|
|
6231
6537
|
if (!AUTH_TOKEN) {
|
|
@@ -6240,6 +6546,7 @@ function generateDashboardHTML(options) {
|
|
|
6240
6546
|
updateHandshakes(),
|
|
6241
6547
|
updateSHR(),
|
|
6242
6548
|
updateStatus(),
|
|
6549
|
+
updateSovereigntyProfile(),
|
|
6243
6550
|
]);
|
|
6244
6551
|
|
|
6245
6552
|
// Setup SSE for real-time updates
|
|
@@ -6256,6 +6563,80 @@ function generateDashboardHTML(options) {
|
|
|
6256
6563
|
</html>`;
|
|
6257
6564
|
}
|
|
6258
6565
|
|
|
6566
|
+
// src/system-prompt-generator.ts
|
|
6567
|
+
var FEATURE_INFO = {
|
|
6568
|
+
audit_logging: {
|
|
6569
|
+
name: "Audit Logging",
|
|
6570
|
+
activeDescription: "All your tool calls are logged to an encrypted audit trail. No action needed \u2014 this is automatic.",
|
|
6571
|
+
disabledDescription: "audit logging (sanctuary/monitor_audit_log)"
|
|
6572
|
+
},
|
|
6573
|
+
injection_detection: {
|
|
6574
|
+
name: "Injection Detection",
|
|
6575
|
+
activeDescription: "Your tool call arguments are scanned for prompt injection attempts. No action needed \u2014 this is automatic.",
|
|
6576
|
+
disabledDescription: "injection detection"
|
|
6577
|
+
},
|
|
6578
|
+
context_gating: {
|
|
6579
|
+
name: "Context Gating",
|
|
6580
|
+
activeDescription: "Before making outbound calls to remote providers, filter your context through sanctuary/context_gate_filter to ensure minimum-necessary disclosure.",
|
|
6581
|
+
toolNames: ["sanctuary/context_gate_filter", "sanctuary/context_gate_set_policy"],
|
|
6582
|
+
disabledDescription: "context gating (sanctuary/context_gate_filter)"
|
|
6583
|
+
},
|
|
6584
|
+
approval_gate: {
|
|
6585
|
+
name: "Approval Gates",
|
|
6586
|
+
activeDescription: "High-risk operations require human approval before execution. Tier 1 operations always require approval; Tier 2 operations trigger approval on anomaly detection.",
|
|
6587
|
+
disabledDescription: "approval gates"
|
|
6588
|
+
},
|
|
6589
|
+
zk_proofs: {
|
|
6590
|
+
name: "Zero-Knowledge Proofs",
|
|
6591
|
+
activeDescription: "You can prove claims about your data without revealing the underlying values. Use sanctuary/zk_commit to create commitments, sanctuary/zk_prove for proofs of knowledge, and sanctuary/zk_range_prove for range proofs.",
|
|
6592
|
+
toolNames: ["sanctuary/zk_commit", "sanctuary/zk_prove", "sanctuary/zk_range_prove"],
|
|
6593
|
+
disabledDescription: "zero-knowledge proofs (sanctuary/zk_commit, sanctuary/zk_prove)"
|
|
6594
|
+
}
|
|
6595
|
+
};
|
|
6596
|
+
function generateSystemPrompt(profile) {
|
|
6597
|
+
const activeFeatures = [];
|
|
6598
|
+
const inactiveFeatures = [];
|
|
6599
|
+
const featureKeys = [
|
|
6600
|
+
"audit_logging",
|
|
6601
|
+
"injection_detection",
|
|
6602
|
+
"context_gating",
|
|
6603
|
+
"approval_gate",
|
|
6604
|
+
"zk_proofs"
|
|
6605
|
+
];
|
|
6606
|
+
for (const key of featureKeys) {
|
|
6607
|
+
const featureConfig = profile.features[key];
|
|
6608
|
+
const info = FEATURE_INFO[key];
|
|
6609
|
+
if (featureConfig.enabled) {
|
|
6610
|
+
let desc = `- ${info.name}: ${info.activeDescription}`;
|
|
6611
|
+
if (key === "injection_detection" && "sensitivity" in featureConfig && featureConfig.sensitivity) {
|
|
6612
|
+
desc += ` Sensitivity: ${featureConfig.sensitivity}.`;
|
|
6613
|
+
}
|
|
6614
|
+
if (key === "context_gating" && "policy_id" in featureConfig && featureConfig.policy_id) {
|
|
6615
|
+
desc += ` Active policy: ${featureConfig.policy_id}.`;
|
|
6616
|
+
}
|
|
6617
|
+
activeFeatures.push(desc);
|
|
6618
|
+
} else {
|
|
6619
|
+
inactiveFeatures.push(info.disabledDescription);
|
|
6620
|
+
}
|
|
6621
|
+
}
|
|
6622
|
+
const lines = [
|
|
6623
|
+
"You are protected by Sanctuary sovereignty infrastructure. The following protections are active:",
|
|
6624
|
+
""
|
|
6625
|
+
];
|
|
6626
|
+
if (activeFeatures.length > 0) {
|
|
6627
|
+
lines.push(...activeFeatures);
|
|
6628
|
+
} else {
|
|
6629
|
+
lines.push("- No features are currently enabled. Contact your operator to configure protections.");
|
|
6630
|
+
}
|
|
6631
|
+
if (inactiveFeatures.length > 0) {
|
|
6632
|
+
lines.push("");
|
|
6633
|
+
lines.push(
|
|
6634
|
+
`Optional tools available but not currently enabled: ${inactiveFeatures.join(", ")}.`
|
|
6635
|
+
);
|
|
6636
|
+
}
|
|
6637
|
+
return lines.join("\n");
|
|
6638
|
+
}
|
|
6639
|
+
|
|
6259
6640
|
// src/principal-policy/dashboard.ts
|
|
6260
6641
|
var SESSION_TTL_REMOTE_MS = 5 * 60 * 1e3;
|
|
6261
6642
|
var SESSION_TTL_LOCAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6276,6 +6657,7 @@ var DashboardApprovalChannel = class {
|
|
|
6276
6657
|
handshakeResults = null;
|
|
6277
6658
|
shrOpts = null;
|
|
6278
6659
|
_sanctuaryConfig = null;
|
|
6660
|
+
profileStore = null;
|
|
6279
6661
|
dashboardHTML;
|
|
6280
6662
|
loginHTML;
|
|
6281
6663
|
authToken;
|
|
@@ -6315,6 +6697,7 @@ var DashboardApprovalChannel = class {
|
|
|
6315
6697
|
if (deps.handshakeResults) this.handshakeResults = deps.handshakeResults;
|
|
6316
6698
|
if (deps.shrOpts) this.shrOpts = deps.shrOpts;
|
|
6317
6699
|
if (deps.sanctuaryConfig) this._sanctuaryConfig = deps.sanctuaryConfig;
|
|
6700
|
+
if (deps.profileStore) this.profileStore = deps.profileStore;
|
|
6318
6701
|
}
|
|
6319
6702
|
/**
|
|
6320
6703
|
* Mark this dashboard as running in standalone mode.
|
|
@@ -6662,6 +7045,10 @@ var DashboardApprovalChannel = class {
|
|
|
6662
7045
|
this.handleHandshakes(res);
|
|
6663
7046
|
} else if (method === "GET" && url.pathname === "/api/shr") {
|
|
6664
7047
|
this.handleSHR(res);
|
|
7048
|
+
} else if (method === "GET" && url.pathname === "/api/sovereignty-profile") {
|
|
7049
|
+
this.handleSovereigntyProfileGet(res);
|
|
7050
|
+
} else if (method === "POST" && url.pathname === "/api/sovereignty-profile") {
|
|
7051
|
+
this.handleSovereigntyProfileUpdate(req, res);
|
|
6665
7052
|
} else if (method === "POST" && url.pathname.startsWith("/api/approve/")) {
|
|
6666
7053
|
if (!this.checkRateLimit(req, res, "decisions")) return;
|
|
6667
7054
|
const id = url.pathname.slice("/api/approve/".length);
|
|
@@ -6953,6 +7340,61 @@ data: ${JSON.stringify(initData)}
|
|
|
6953
7340
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6954
7341
|
res.end(JSON.stringify(shr));
|
|
6955
7342
|
}
|
|
7343
|
+
// ── Sovereignty Profile API ─────────────────────────────────────────
|
|
7344
|
+
handleSovereigntyProfileGet(res) {
|
|
7345
|
+
if (!this.profileStore) {
|
|
7346
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7347
|
+
res.end(JSON.stringify({ error: "Sovereignty Profile not available" }));
|
|
7348
|
+
return;
|
|
7349
|
+
}
|
|
7350
|
+
try {
|
|
7351
|
+
const profile = this.profileStore.get();
|
|
7352
|
+
const prompt = generateSystemPrompt(profile);
|
|
7353
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7354
|
+
res.end(JSON.stringify({ profile, system_prompt: prompt }));
|
|
7355
|
+
} catch {
|
|
7356
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
7357
|
+
res.end(JSON.stringify({ error: "Failed to read sovereignty profile" }));
|
|
7358
|
+
}
|
|
7359
|
+
}
|
|
7360
|
+
handleSovereigntyProfileUpdate(req, res) {
|
|
7361
|
+
if (!this.profileStore) {
|
|
7362
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
7363
|
+
res.end(JSON.stringify({ error: "Sovereignty Profile not available" }));
|
|
7364
|
+
return;
|
|
7365
|
+
}
|
|
7366
|
+
let body = "";
|
|
7367
|
+
let destroyed = false;
|
|
7368
|
+
req.on("data", (chunk) => {
|
|
7369
|
+
body += chunk.toString();
|
|
7370
|
+
if (body.length > 16384) {
|
|
7371
|
+
destroyed = true;
|
|
7372
|
+
res.writeHead(413, { "Content-Type": "application/json" });
|
|
7373
|
+
res.end(JSON.stringify({ error: "Request body too large" }));
|
|
7374
|
+
req.destroy();
|
|
7375
|
+
}
|
|
7376
|
+
});
|
|
7377
|
+
req.on("end", async () => {
|
|
7378
|
+
if (destroyed) return;
|
|
7379
|
+
try {
|
|
7380
|
+
const updates = JSON.parse(body);
|
|
7381
|
+
const updated = await this.profileStore.update(updates);
|
|
7382
|
+
const prompt = generateSystemPrompt(updated);
|
|
7383
|
+
if (this.auditLog) {
|
|
7384
|
+
this.auditLog.append("l2", "sovereignty_profile_update_dashboard", "dashboard", {
|
|
7385
|
+
changes: updates,
|
|
7386
|
+
features_enabled: Object.entries(updated.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
7387
|
+
});
|
|
7388
|
+
}
|
|
7389
|
+
this.broadcastSSE("sovereignty-profile-update", { profile: updated, system_prompt: prompt });
|
|
7390
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7391
|
+
res.end(JSON.stringify({ profile: updated, system_prompt: prompt }));
|
|
7392
|
+
} catch {
|
|
7393
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
7394
|
+
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
7395
|
+
}
|
|
7396
|
+
});
|
|
7397
|
+
}
|
|
6956
7398
|
// ── SSE Broadcasting ────────────────────────────────────────────────
|
|
6957
7399
|
broadcastSSE(event, data) {
|
|
6958
7400
|
const message = `event: ${event}
|
|
@@ -8120,6 +8562,7 @@ function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
|
8120
8562
|
}
|
|
8121
8563
|
|
|
8122
8564
|
// src/shr/verifier.ts
|
|
8565
|
+
init_identity();
|
|
8123
8566
|
init_encoding();
|
|
8124
8567
|
function verifySHR(shr, now) {
|
|
8125
8568
|
const errors = [];
|
|
@@ -8542,7 +8985,9 @@ function createSHRTools(config, identityManager, masterKey, auditLog) {
|
|
|
8542
8985
|
}
|
|
8543
8986
|
|
|
8544
8987
|
// src/handshake/protocol.ts
|
|
8988
|
+
init_identity();
|
|
8545
8989
|
init_encoding();
|
|
8990
|
+
init_random();
|
|
8546
8991
|
function generateNonce() {
|
|
8547
8992
|
return toBase64url(randomBytes(32));
|
|
8548
8993
|
}
|
|
@@ -8709,7 +9154,9 @@ function deriveTrustTier(level) {
|
|
|
8709
9154
|
}
|
|
8710
9155
|
|
|
8711
9156
|
// src/handshake/attestation.ts
|
|
9157
|
+
init_identity();
|
|
8712
9158
|
init_encoding();
|
|
9159
|
+
init_identity();
|
|
8713
9160
|
init_encoding();
|
|
8714
9161
|
var ATTESTATION_VERSION = "1.0";
|
|
8715
9162
|
function deriveTrustTier2(level) {
|
|
@@ -9502,10 +9949,13 @@ function createFederationTools(auditLog, handshakeResults) {
|
|
|
9502
9949
|
|
|
9503
9950
|
// src/bridge/tools.ts
|
|
9504
9951
|
init_encoding();
|
|
9952
|
+
init_encryption();
|
|
9505
9953
|
init_encoding();
|
|
9506
9954
|
|
|
9507
9955
|
// src/bridge/bridge.ts
|
|
9956
|
+
init_identity();
|
|
9508
9957
|
init_encoding();
|
|
9958
|
+
init_random();
|
|
9509
9959
|
init_hashing();
|
|
9510
9960
|
function canonicalize(outcome) {
|
|
9511
9961
|
return stringToBytes(stableStringify(outcome));
|
|
@@ -10656,7 +11106,9 @@ function createAuditTools(config) {
|
|
|
10656
11106
|
}
|
|
10657
11107
|
|
|
10658
11108
|
// src/l2-operational/context-gate.ts
|
|
11109
|
+
init_encryption();
|
|
10659
11110
|
init_encoding();
|
|
11111
|
+
init_random();
|
|
10660
11112
|
init_hashing();
|
|
10661
11113
|
var MAX_CONTEXT_FIELDS = 1e3;
|
|
10662
11114
|
var MAX_POLICY_RULES = 50;
|
|
@@ -12625,7 +13077,272 @@ function createL2HardeningTools(storagePath, auditLog) {
|
|
|
12625
13077
|
];
|
|
12626
13078
|
}
|
|
12627
13079
|
|
|
13080
|
+
// src/sovereignty-profile.ts
|
|
13081
|
+
init_encryption();
|
|
13082
|
+
init_encoding();
|
|
13083
|
+
var NAMESPACE = "_sovereignty_profile";
|
|
13084
|
+
var PROFILE_KEY = "active";
|
|
13085
|
+
var HKDF_DOMAIN = "sovereignty-profile";
|
|
13086
|
+
function createDefaultProfile() {
|
|
13087
|
+
return {
|
|
13088
|
+
version: 1,
|
|
13089
|
+
features: {
|
|
13090
|
+
audit_logging: { enabled: true },
|
|
13091
|
+
injection_detection: { enabled: true },
|
|
13092
|
+
context_gating: { enabled: false },
|
|
13093
|
+
approval_gate: { enabled: false },
|
|
13094
|
+
zk_proofs: { enabled: false }
|
|
13095
|
+
},
|
|
13096
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
13097
|
+
};
|
|
13098
|
+
}
|
|
13099
|
+
var SovereigntyProfileStore = class {
|
|
13100
|
+
storage;
|
|
13101
|
+
encryptionKey;
|
|
13102
|
+
profile = null;
|
|
13103
|
+
constructor(storage, masterKey) {
|
|
13104
|
+
this.storage = storage;
|
|
13105
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_DOMAIN);
|
|
13106
|
+
}
|
|
13107
|
+
/**
|
|
13108
|
+
* Load the active sovereignty profile from encrypted storage.
|
|
13109
|
+
* Creates the default profile on first run.
|
|
13110
|
+
*/
|
|
13111
|
+
async load() {
|
|
13112
|
+
if (this.profile) return this.profile;
|
|
13113
|
+
const raw = await this.storage.read(NAMESPACE, PROFILE_KEY);
|
|
13114
|
+
if (raw) {
|
|
13115
|
+
try {
|
|
13116
|
+
const encrypted = JSON.parse(bytesToString(raw));
|
|
13117
|
+
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
13118
|
+
this.profile = JSON.parse(bytesToString(decrypted));
|
|
13119
|
+
return this.profile;
|
|
13120
|
+
} catch {
|
|
13121
|
+
}
|
|
13122
|
+
}
|
|
13123
|
+
this.profile = createDefaultProfile();
|
|
13124
|
+
await this.persist();
|
|
13125
|
+
return this.profile;
|
|
13126
|
+
}
|
|
13127
|
+
/**
|
|
13128
|
+
* Get the current profile. Must call load() first.
|
|
13129
|
+
*/
|
|
13130
|
+
get() {
|
|
13131
|
+
if (!this.profile) {
|
|
13132
|
+
throw new Error("SovereigntyProfileStore: call load() before get()");
|
|
13133
|
+
}
|
|
13134
|
+
return this.profile;
|
|
13135
|
+
}
|
|
13136
|
+
/**
|
|
13137
|
+
* Apply a partial update to the profile.
|
|
13138
|
+
* Returns the updated profile.
|
|
13139
|
+
*/
|
|
13140
|
+
async update(updates) {
|
|
13141
|
+
if (!this.profile) {
|
|
13142
|
+
await this.load();
|
|
13143
|
+
}
|
|
13144
|
+
const features = this.profile.features;
|
|
13145
|
+
if (updates.audit_logging !== void 0) {
|
|
13146
|
+
if (updates.audit_logging.enabled !== void 0) {
|
|
13147
|
+
if (typeof updates.audit_logging.enabled !== "boolean") {
|
|
13148
|
+
throw new Error("audit_logging.enabled must be a boolean");
|
|
13149
|
+
}
|
|
13150
|
+
features.audit_logging.enabled = updates.audit_logging.enabled;
|
|
13151
|
+
}
|
|
13152
|
+
}
|
|
13153
|
+
if (updates.injection_detection !== void 0) {
|
|
13154
|
+
if (updates.injection_detection.enabled !== void 0) {
|
|
13155
|
+
if (typeof updates.injection_detection.enabled !== "boolean") {
|
|
13156
|
+
throw new Error("injection_detection.enabled must be a boolean");
|
|
13157
|
+
}
|
|
13158
|
+
features.injection_detection.enabled = updates.injection_detection.enabled;
|
|
13159
|
+
}
|
|
13160
|
+
if (updates.injection_detection.sensitivity !== void 0) {
|
|
13161
|
+
const valid = ["low", "medium", "high"];
|
|
13162
|
+
if (!valid.includes(updates.injection_detection.sensitivity)) {
|
|
13163
|
+
throw new Error("injection_detection.sensitivity must be low, medium, or high");
|
|
13164
|
+
}
|
|
13165
|
+
features.injection_detection.sensitivity = updates.injection_detection.sensitivity;
|
|
13166
|
+
}
|
|
13167
|
+
}
|
|
13168
|
+
if (updates.context_gating !== void 0) {
|
|
13169
|
+
if (updates.context_gating.enabled !== void 0) {
|
|
13170
|
+
if (typeof updates.context_gating.enabled !== "boolean") {
|
|
13171
|
+
throw new Error("context_gating.enabled must be a boolean");
|
|
13172
|
+
}
|
|
13173
|
+
features.context_gating.enabled = updates.context_gating.enabled;
|
|
13174
|
+
}
|
|
13175
|
+
if (updates.context_gating.policy_id !== void 0) {
|
|
13176
|
+
if (typeof updates.context_gating.policy_id !== "string" || updates.context_gating.policy_id.length > 256) {
|
|
13177
|
+
throw new Error("context_gating.policy_id must be a string of 256 characters or fewer");
|
|
13178
|
+
}
|
|
13179
|
+
features.context_gating.policy_id = updates.context_gating.policy_id;
|
|
13180
|
+
}
|
|
13181
|
+
}
|
|
13182
|
+
if (updates.approval_gate !== void 0) {
|
|
13183
|
+
if (updates.approval_gate.enabled !== void 0) {
|
|
13184
|
+
if (typeof updates.approval_gate.enabled !== "boolean") {
|
|
13185
|
+
throw new Error("approval_gate.enabled must be a boolean");
|
|
13186
|
+
}
|
|
13187
|
+
features.approval_gate.enabled = updates.approval_gate.enabled;
|
|
13188
|
+
}
|
|
13189
|
+
}
|
|
13190
|
+
if (updates.zk_proofs !== void 0) {
|
|
13191
|
+
if (updates.zk_proofs.enabled !== void 0) {
|
|
13192
|
+
if (typeof updates.zk_proofs.enabled !== "boolean") {
|
|
13193
|
+
throw new Error("zk_proofs.enabled must be a boolean");
|
|
13194
|
+
}
|
|
13195
|
+
features.zk_proofs.enabled = updates.zk_proofs.enabled;
|
|
13196
|
+
}
|
|
13197
|
+
}
|
|
13198
|
+
this.profile.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
13199
|
+
await this.persist();
|
|
13200
|
+
return this.profile;
|
|
13201
|
+
}
|
|
13202
|
+
/**
|
|
13203
|
+
* Persist the current profile to encrypted storage.
|
|
13204
|
+
*/
|
|
13205
|
+
async persist() {
|
|
13206
|
+
const serialized = stringToBytes(JSON.stringify(this.profile));
|
|
13207
|
+
const encrypted = encrypt(serialized, this.encryptionKey);
|
|
13208
|
+
await this.storage.write(
|
|
13209
|
+
NAMESPACE,
|
|
13210
|
+
PROFILE_KEY,
|
|
13211
|
+
stringToBytes(JSON.stringify(encrypted))
|
|
13212
|
+
);
|
|
13213
|
+
}
|
|
13214
|
+
};
|
|
13215
|
+
|
|
13216
|
+
// src/sovereignty-profile-tools.ts
|
|
13217
|
+
function createSovereigntyProfileTools(profileStore, auditLog) {
|
|
13218
|
+
const tools = [
|
|
13219
|
+
// ── Get Profile ──────────────────────────────────────────────────
|
|
13220
|
+
{
|
|
13221
|
+
name: "sanctuary/sovereignty_profile_get",
|
|
13222
|
+
description: "Get the current Sovereignty Profile \u2014 shows which Sanctuary features are active (audit logging, injection detection, context gating, approval gates, ZK proofs) and their configuration.",
|
|
13223
|
+
inputSchema: {
|
|
13224
|
+
type: "object",
|
|
13225
|
+
properties: {}
|
|
13226
|
+
},
|
|
13227
|
+
handler: async () => {
|
|
13228
|
+
const profile = profileStore.get();
|
|
13229
|
+
auditLog.append("l2", "sovereignty_profile_get", "system", {
|
|
13230
|
+
features_enabled: Object.entries(profile.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13231
|
+
});
|
|
13232
|
+
return toolResult({
|
|
13233
|
+
profile,
|
|
13234
|
+
message: "Current Sovereignty Profile. Use sovereignty_profile_update to change settings."
|
|
13235
|
+
});
|
|
13236
|
+
}
|
|
13237
|
+
},
|
|
13238
|
+
// ── Update Profile ───────────────────────────────────────────────
|
|
13239
|
+
{
|
|
13240
|
+
name: "sanctuary/sovereignty_profile_update",
|
|
13241
|
+
description: "Update the Sovereignty Profile feature toggles. This changes which Sanctuary protections are active. Requires human approval (Tier 1) because it modifies enforcement behavior. Pass only the features you want to change \u2014 unspecified features remain unchanged.",
|
|
13242
|
+
inputSchema: {
|
|
13243
|
+
type: "object",
|
|
13244
|
+
properties: {
|
|
13245
|
+
audit_logging: {
|
|
13246
|
+
type: "object",
|
|
13247
|
+
properties: {
|
|
13248
|
+
enabled: { type: "boolean" }
|
|
13249
|
+
},
|
|
13250
|
+
description: "Toggle audit logging on/off"
|
|
13251
|
+
},
|
|
13252
|
+
injection_detection: {
|
|
13253
|
+
type: "object",
|
|
13254
|
+
properties: {
|
|
13255
|
+
enabled: { type: "boolean" },
|
|
13256
|
+
sensitivity: {
|
|
13257
|
+
type: "string",
|
|
13258
|
+
enum: ["low", "medium", "high"],
|
|
13259
|
+
description: "Detection sensitivity threshold"
|
|
13260
|
+
}
|
|
13261
|
+
},
|
|
13262
|
+
description: "Toggle injection detection and set sensitivity"
|
|
13263
|
+
},
|
|
13264
|
+
context_gating: {
|
|
13265
|
+
type: "object",
|
|
13266
|
+
properties: {
|
|
13267
|
+
enabled: { type: "boolean" },
|
|
13268
|
+
policy_id: {
|
|
13269
|
+
type: "string",
|
|
13270
|
+
description: "ID of the context-gating policy to use"
|
|
13271
|
+
}
|
|
13272
|
+
},
|
|
13273
|
+
description: "Toggle context gating and set active policy"
|
|
13274
|
+
},
|
|
13275
|
+
approval_gate: {
|
|
13276
|
+
type: "object",
|
|
13277
|
+
properties: {
|
|
13278
|
+
enabled: { type: "boolean" }
|
|
13279
|
+
},
|
|
13280
|
+
description: "Toggle approval gates on/off"
|
|
13281
|
+
},
|
|
13282
|
+
zk_proofs: {
|
|
13283
|
+
type: "object",
|
|
13284
|
+
properties: {
|
|
13285
|
+
enabled: { type: "boolean" }
|
|
13286
|
+
},
|
|
13287
|
+
description: "Toggle zero-knowledge proofs on/off"
|
|
13288
|
+
}
|
|
13289
|
+
}
|
|
13290
|
+
},
|
|
13291
|
+
handler: async (args) => {
|
|
13292
|
+
const updates = {};
|
|
13293
|
+
if (args.audit_logging !== void 0) {
|
|
13294
|
+
updates.audit_logging = args.audit_logging;
|
|
13295
|
+
}
|
|
13296
|
+
if (args.injection_detection !== void 0) {
|
|
13297
|
+
updates.injection_detection = args.injection_detection;
|
|
13298
|
+
}
|
|
13299
|
+
if (args.context_gating !== void 0) {
|
|
13300
|
+
updates.context_gating = args.context_gating;
|
|
13301
|
+
}
|
|
13302
|
+
if (args.approval_gate !== void 0) {
|
|
13303
|
+
updates.approval_gate = args.approval_gate;
|
|
13304
|
+
}
|
|
13305
|
+
if (args.zk_proofs !== void 0) {
|
|
13306
|
+
updates.zk_proofs = args.zk_proofs;
|
|
13307
|
+
}
|
|
13308
|
+
const updated = await profileStore.update(updates);
|
|
13309
|
+
auditLog.append("l2", "sovereignty_profile_update", "system", {
|
|
13310
|
+
changes: updates,
|
|
13311
|
+
features_enabled: Object.entries(updated.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13312
|
+
});
|
|
13313
|
+
return toolResult({
|
|
13314
|
+
profile: updated,
|
|
13315
|
+
message: "Sovereignty Profile updated. Changes take effect immediately."
|
|
13316
|
+
});
|
|
13317
|
+
}
|
|
13318
|
+
},
|
|
13319
|
+
// ── Generate System Prompt ───────────────────────────────────────
|
|
13320
|
+
{
|
|
13321
|
+
name: "sanctuary/sovereignty_profile_generate_prompt",
|
|
13322
|
+
description: "Generate a system prompt snippet based on the active Sovereignty Profile. The snippet instructs an agent on which Sanctuary features are active and how to use them. Copy and paste this into your agent's system configuration.",
|
|
13323
|
+
inputSchema: {
|
|
13324
|
+
type: "object",
|
|
13325
|
+
properties: {}
|
|
13326
|
+
},
|
|
13327
|
+
handler: async () => {
|
|
13328
|
+
const profile = profileStore.get();
|
|
13329
|
+
const prompt = generateSystemPrompt(profile);
|
|
13330
|
+
auditLog.append("l2", "sovereignty_profile_generate_prompt", "system", {
|
|
13331
|
+
features_enabled: Object.entries(profile.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13332
|
+
});
|
|
13333
|
+
return toolResult({
|
|
13334
|
+
system_prompt: prompt,
|
|
13335
|
+
token_estimate: Math.ceil(prompt.length / 4),
|
|
13336
|
+
message: "Copy the system_prompt text above and paste it into your agent's system configuration. It will update dynamically as you toggle features."
|
|
13337
|
+
});
|
|
13338
|
+
}
|
|
13339
|
+
}
|
|
13340
|
+
];
|
|
13341
|
+
return { tools };
|
|
13342
|
+
}
|
|
13343
|
+
|
|
12628
13344
|
// src/index.ts
|
|
13345
|
+
init_random();
|
|
12629
13346
|
init_encoding();
|
|
12630
13347
|
|
|
12631
13348
|
// src/l2-operational/model-provenance.ts
|
|
@@ -13132,6 +13849,9 @@ async function createSanctuaryServer(options) {
|
|
|
13132
13849
|
const { tools: auditTools } = createAuditTools(config);
|
|
13133
13850
|
const { tools: contextGateTools, enforcer: contextGateEnforcer } = createContextGateTools(storage, masterKey, auditLog);
|
|
13134
13851
|
const hardeningTools = createL2HardeningTools(config.storage_path, auditLog);
|
|
13852
|
+
const profileStore = new SovereigntyProfileStore(storage, masterKey);
|
|
13853
|
+
await profileStore.load();
|
|
13854
|
+
const { tools: profileTools } = createSovereigntyProfileTools(profileStore, auditLog);
|
|
13135
13855
|
const policy = await loadPrincipalPolicy(config.storage_path);
|
|
13136
13856
|
const baseline = new BaselineTracker(storage, masterKey);
|
|
13137
13857
|
await baseline.load();
|
|
@@ -13159,7 +13879,8 @@ async function createSanctuaryServer(options) {
|
|
|
13159
13879
|
identityManager,
|
|
13160
13880
|
handshakeResults,
|
|
13161
13881
|
shrOpts: { config, identityManager, masterKey },
|
|
13162
|
-
sanctuaryConfig: config
|
|
13882
|
+
sanctuaryConfig: config,
|
|
13883
|
+
profileStore
|
|
13163
13884
|
});
|
|
13164
13885
|
await dashboard.start();
|
|
13165
13886
|
approvalChannel = dashboard;
|
|
@@ -13236,6 +13957,7 @@ async function createSanctuaryServer(options) {
|
|
|
13236
13957
|
...auditTools,
|
|
13237
13958
|
...contextGateTools,
|
|
13238
13959
|
...hardeningTools,
|
|
13960
|
+
...profileTools,
|
|
13239
13961
|
...dashboardTools,
|
|
13240
13962
|
manifestTool
|
|
13241
13963
|
];
|
|
@@ -13285,6 +14007,7 @@ exports.MODEL_PRESETS = MODEL_PRESETS;
|
|
|
13285
14007
|
exports.MemoryStorage = MemoryStorage;
|
|
13286
14008
|
exports.PolicyStore = PolicyStore;
|
|
13287
14009
|
exports.ReputationStore = ReputationStore;
|
|
14010
|
+
exports.SovereigntyProfileStore = SovereigntyProfileStore;
|
|
13288
14011
|
exports.StateStore = StateStore;
|
|
13289
14012
|
exports.StderrApprovalChannel = StderrApprovalChannel;
|
|
13290
14013
|
exports.TIER_WEIGHTS = TIER_WEIGHTS;
|
|
@@ -13294,6 +14017,7 @@ exports.classifyField = classifyField;
|
|
|
13294
14017
|
exports.completeHandshake = completeHandshake;
|
|
13295
14018
|
exports.computeWeightedScore = computeWeightedScore;
|
|
13296
14019
|
exports.createBridgeCommitment = createBridgeCommitment;
|
|
14020
|
+
exports.createDefaultProfile = createDefaultProfile;
|
|
13297
14021
|
exports.createPedersenCommitment = createPedersenCommitment;
|
|
13298
14022
|
exports.createProofOfKnowledge = createProofOfKnowledge;
|
|
13299
14023
|
exports.createRangeProof = createRangeProof;
|
|
@@ -13302,6 +14026,7 @@ exports.evaluateField = evaluateField;
|
|
|
13302
14026
|
exports.filterContext = filterContext;
|
|
13303
14027
|
exports.generateAttestation = generateAttestation;
|
|
13304
14028
|
exports.generateSHR = generateSHR;
|
|
14029
|
+
exports.generateSystemPrompt = generateSystemPrompt;
|
|
13305
14030
|
exports.getTemplate = getTemplate;
|
|
13306
14031
|
exports.initiateHandshake = initiateHandshake;
|
|
13307
14032
|
exports.listTemplateIds = listTemplateIds;
|