@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.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;
|
|
@@ -714,7 +745,9 @@ var RESERVED_NAMESPACE_PREFIXES = [
|
|
|
714
745
|
"_bridge",
|
|
715
746
|
"_federation",
|
|
716
747
|
"_handshake",
|
|
717
|
-
"_shr"
|
|
748
|
+
"_shr",
|
|
749
|
+
"_sovereignty_profile",
|
|
750
|
+
"_context_gate_policies"
|
|
718
751
|
];
|
|
719
752
|
var StateStore = class {
|
|
720
753
|
storage;
|
|
@@ -1238,7 +1271,9 @@ function toolResult(data) {
|
|
|
1238
1271
|
}
|
|
1239
1272
|
|
|
1240
1273
|
// src/l1-cognitive/tools.ts
|
|
1274
|
+
init_identity();
|
|
1241
1275
|
init_encoding();
|
|
1276
|
+
init_encryption();
|
|
1242
1277
|
init_encoding();
|
|
1243
1278
|
var RESERVED_NAMESPACE_PREFIXES2 = [
|
|
1244
1279
|
"_identities",
|
|
@@ -1253,7 +1288,9 @@ var RESERVED_NAMESPACE_PREFIXES2 = [
|
|
|
1253
1288
|
"_bridge",
|
|
1254
1289
|
"_federation",
|
|
1255
1290
|
"_handshake",
|
|
1256
|
-
"_shr"
|
|
1291
|
+
"_shr",
|
|
1292
|
+
"_sovereignty_profile",
|
|
1293
|
+
"_context_gate_policies"
|
|
1257
1294
|
];
|
|
1258
1295
|
function getReservedNamespaceViolation(namespace) {
|
|
1259
1296
|
for (const prefix of RESERVED_NAMESPACE_PREFIXES2) {
|
|
@@ -1745,6 +1782,7 @@ function createL1Tools(stateStore, storage, masterKey, keyProtection, auditLog)
|
|
|
1745
1782
|
}
|
|
1746
1783
|
|
|
1747
1784
|
// src/l2-operational/audit-log.ts
|
|
1785
|
+
init_encryption();
|
|
1748
1786
|
init_encoding();
|
|
1749
1787
|
var AuditLog = class {
|
|
1750
1788
|
storage;
|
|
@@ -1842,6 +1880,8 @@ var AuditLog = class {
|
|
|
1842
1880
|
// src/l3-disclosure/commitments.ts
|
|
1843
1881
|
init_hashing();
|
|
1844
1882
|
init_encoding();
|
|
1883
|
+
init_random();
|
|
1884
|
+
init_encryption();
|
|
1845
1885
|
init_encoding();
|
|
1846
1886
|
function createCommitment(value, blindingFactor) {
|
|
1847
1887
|
const blindingBytes = blindingFactor ? fromBase64url(blindingFactor) : randomBytes(32);
|
|
@@ -1922,7 +1962,9 @@ var CommitmentStore = class {
|
|
|
1922
1962
|
};
|
|
1923
1963
|
|
|
1924
1964
|
// src/l3-disclosure/policies.ts
|
|
1965
|
+
init_encryption();
|
|
1925
1966
|
init_encoding();
|
|
1967
|
+
init_random();
|
|
1926
1968
|
function evaluateDisclosure(policy, context, requestedFields) {
|
|
1927
1969
|
return requestedFields.map((field) => {
|
|
1928
1970
|
const exactRule = policy.rules.find((r) => r.context === context);
|
|
@@ -2053,6 +2095,9 @@ var PolicyStore = class {
|
|
|
2053
2095
|
);
|
|
2054
2096
|
}
|
|
2055
2097
|
};
|
|
2098
|
+
|
|
2099
|
+
// src/l3-disclosure/zk-proofs.ts
|
|
2100
|
+
init_random();
|
|
2056
2101
|
init_encoding();
|
|
2057
2102
|
var G = RistrettoPoint.BASE;
|
|
2058
2103
|
var H_INPUT = concatBytes(
|
|
@@ -2730,7 +2775,10 @@ function createL3Tools(storage, masterKey, auditLog) {
|
|
|
2730
2775
|
}
|
|
2731
2776
|
|
|
2732
2777
|
// src/l4-reputation/reputation-store.ts
|
|
2778
|
+
init_encryption();
|
|
2733
2779
|
init_encoding();
|
|
2780
|
+
init_random();
|
|
2781
|
+
init_identity();
|
|
2734
2782
|
function computeMedian(values) {
|
|
2735
2783
|
if (values.length === 0) return 0;
|
|
2736
2784
|
const sorted = [...values].sort((a, b) => a - b);
|
|
@@ -3625,6 +3673,24 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3625
3673
|
}
|
|
3626
3674
|
const publishType = args.type;
|
|
3627
3675
|
const veracoreUrl = args.verascore_url || "https://verascore.ai";
|
|
3676
|
+
const ALLOWED_VERASCORE_HOSTS = ["verascore.ai", "www.verascore.ai", "api.verascore.ai"];
|
|
3677
|
+
try {
|
|
3678
|
+
const parsed = new URL(veracoreUrl);
|
|
3679
|
+
if (parsed.protocol !== "https:") {
|
|
3680
|
+
return toolResult({
|
|
3681
|
+
error: `verascore_url must use HTTPS. Got: ${parsed.protocol}`
|
|
3682
|
+
});
|
|
3683
|
+
}
|
|
3684
|
+
if (!ALLOWED_VERASCORE_HOSTS.includes(parsed.hostname)) {
|
|
3685
|
+
return toolResult({
|
|
3686
|
+
error: `verascore_url must point to a known Verascore domain (${ALLOWED_VERASCORE_HOSTS.join(", ")}). Got: ${parsed.hostname}`
|
|
3687
|
+
});
|
|
3688
|
+
}
|
|
3689
|
+
} catch {
|
|
3690
|
+
return toolResult({
|
|
3691
|
+
error: `verascore_url is not a valid URL: ${veracoreUrl}`
|
|
3692
|
+
});
|
|
3693
|
+
}
|
|
3628
3694
|
const agentId = args.verascore_agent_id || identity.did.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase();
|
|
3629
3695
|
let publishData;
|
|
3630
3696
|
if (args.data) {
|
|
@@ -3654,24 +3720,21 @@ function createL4Tools(storage, masterKey, identityManager, auditLog, handshakeR
|
|
|
3654
3720
|
return toolResult({ error: `Unknown publish type: ${publishType}` });
|
|
3655
3721
|
}
|
|
3656
3722
|
}
|
|
3657
|
-
const { sign:
|
|
3658
|
-
const payloadBytes =
|
|
3723
|
+
const { sign: identitySign } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
3724
|
+
const payloadBytes = new TextEncoder().encode(JSON.stringify(publishData));
|
|
3659
3725
|
let signatureB64;
|
|
3660
3726
|
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");
|
|
3727
|
+
const signingBytes = identitySign(
|
|
3728
|
+
payloadBytes,
|
|
3729
|
+
identity.encrypted_private_key,
|
|
3730
|
+
identityEncryptionKey
|
|
3731
|
+
);
|
|
3732
|
+
signatureB64 = toBase64url(signingBytes);
|
|
3673
3733
|
} catch (signError) {
|
|
3674
|
-
|
|
3734
|
+
return toolResult({
|
|
3735
|
+
error: "Failed to sign publish payload. Identity key may be corrupted.",
|
|
3736
|
+
details: signError instanceof Error ? signError.message : String(signError)
|
|
3737
|
+
});
|
|
3675
3738
|
}
|
|
3676
3739
|
const requestBody = {
|
|
3677
3740
|
agentId,
|
|
@@ -3750,7 +3813,11 @@ var DEFAULT_POLICY = {
|
|
|
3750
3813
|
"reputation_import",
|
|
3751
3814
|
"reputation_export",
|
|
3752
3815
|
"bootstrap_provide_guarantee",
|
|
3753
|
-
"decommission_certificate"
|
|
3816
|
+
"decommission_certificate",
|
|
3817
|
+
"reputation_publish",
|
|
3818
|
+
// SEC-039: Explicit Tier 1 — sends data to external API
|
|
3819
|
+
"sovereignty_profile_update"
|
|
3820
|
+
// Changes enforcement behavior — always requires approval
|
|
3754
3821
|
],
|
|
3755
3822
|
tier2_anomaly: DEFAULT_TIER2,
|
|
3756
3823
|
tier3_always_allow: [
|
|
@@ -3802,7 +3869,11 @@ var DEFAULT_POLICY = {
|
|
|
3802
3869
|
"shr_gateway_export",
|
|
3803
3870
|
"bridge_commit",
|
|
3804
3871
|
"bridge_verify",
|
|
3805
|
-
"bridge_attest"
|
|
3872
|
+
"bridge_attest",
|
|
3873
|
+
"dashboard_open",
|
|
3874
|
+
// SEC-039: Explicit Tier 3 — only generates a URL
|
|
3875
|
+
"sovereignty_profile_get",
|
|
3876
|
+
"sovereignty_profile_generate_prompt"
|
|
3806
3877
|
],
|
|
3807
3878
|
approval_channel: DEFAULT_CHANNEL
|
|
3808
3879
|
};
|
|
@@ -3910,6 +3981,8 @@ tier1_always_approve:
|
|
|
3910
3981
|
- reputation_import
|
|
3911
3982
|
- reputation_export
|
|
3912
3983
|
- bootstrap_provide_guarantee
|
|
3984
|
+
- reputation_publish
|
|
3985
|
+
- sovereignty_profile_update
|
|
3913
3986
|
|
|
3914
3987
|
# \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
3988
|
# Triggers approval when agent behavior deviates from its baseline.
|
|
@@ -3972,6 +4045,9 @@ tier3_always_allow:
|
|
|
3972
4045
|
- bridge_commit
|
|
3973
4046
|
- bridge_verify
|
|
3974
4047
|
- bridge_attest
|
|
4048
|
+
- dashboard_open
|
|
4049
|
+
- sovereignty_profile_get
|
|
4050
|
+
- sovereignty_profile_generate_prompt
|
|
3975
4051
|
|
|
3976
4052
|
# \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
4053
|
# How Sanctuary reaches you when approval is needed.
|
|
@@ -3999,6 +4075,7 @@ async function loadPrincipalPolicy(storagePath) {
|
|
|
3999
4075
|
}
|
|
4000
4076
|
|
|
4001
4077
|
// src/principal-policy/baseline.ts
|
|
4078
|
+
init_encryption();
|
|
4002
4079
|
init_encoding();
|
|
4003
4080
|
var BASELINE_NAMESPACE = "_principal";
|
|
4004
4081
|
var BASELINE_KEY = "session-baseline";
|
|
@@ -4224,6 +4301,7 @@ function canonicalizeForSigning(body) {
|
|
|
4224
4301
|
}
|
|
4225
4302
|
|
|
4226
4303
|
// src/shr/generator.ts
|
|
4304
|
+
init_identity();
|
|
4227
4305
|
init_encoding();
|
|
4228
4306
|
var DEFAULT_VALIDITY_MS = 60 * 60 * 1e3;
|
|
4229
4307
|
function generateSHR(identityId, opts) {
|
|
@@ -5176,73 +5254,200 @@ function generateDashboardHTML(options) {
|
|
|
5176
5254
|
right: 0;
|
|
5177
5255
|
}
|
|
5178
5256
|
|
|
5179
|
-
.pending-header {
|
|
5180
|
-
padding: 16px 20px;
|
|
5181
|
-
border-bottom: 1px solid var(--border);
|
|
5182
|
-
font-weight: 600;
|
|
5183
|
-
color: var(--text-primary);
|
|
5257
|
+
.pending-header {
|
|
5258
|
+
padding: 16px 20px;
|
|
5259
|
+
border-bottom: 1px solid var(--border);
|
|
5260
|
+
font-weight: 600;
|
|
5261
|
+
color: var(--text-primary);
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5264
|
+
.pending-items {
|
|
5265
|
+
flex: 1;
|
|
5266
|
+
overflow-y: auto;
|
|
5267
|
+
padding: 16px;
|
|
5268
|
+
}
|
|
5269
|
+
|
|
5270
|
+
.pending-item {
|
|
5271
|
+
background-color: var(--bg);
|
|
5272
|
+
border: 1px solid var(--border);
|
|
5273
|
+
border-radius: 6px;
|
|
5274
|
+
padding: 16px;
|
|
5275
|
+
margin-bottom: 12px;
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
.pending-title {
|
|
5279
|
+
font-weight: 600;
|
|
5280
|
+
color: var(--text-primary);
|
|
5281
|
+
margin-bottom: 8px;
|
|
5282
|
+
word-break: break-word;
|
|
5283
|
+
}
|
|
5284
|
+
|
|
5285
|
+
.pending-countdown {
|
|
5286
|
+
font-size: 12px;
|
|
5287
|
+
color: var(--amber);
|
|
5288
|
+
margin-bottom: 12px;
|
|
5289
|
+
font-weight: 500;
|
|
5290
|
+
}
|
|
5291
|
+
|
|
5292
|
+
.pending-actions {
|
|
5293
|
+
display: flex;
|
|
5294
|
+
gap: 8px;
|
|
5295
|
+
}
|
|
5296
|
+
|
|
5297
|
+
.pending-btn {
|
|
5298
|
+
flex: 1;
|
|
5299
|
+
padding: 8px 12px;
|
|
5300
|
+
border: none;
|
|
5301
|
+
border-radius: 4px;
|
|
5302
|
+
font-size: 12px;
|
|
5303
|
+
font-weight: 600;
|
|
5304
|
+
cursor: pointer;
|
|
5305
|
+
transition: background-color 0.2s;
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
.pending-approve {
|
|
5309
|
+
background-color: var(--green);
|
|
5310
|
+
color: var(--bg);
|
|
5311
|
+
}
|
|
5312
|
+
|
|
5313
|
+
.pending-approve:hover {
|
|
5314
|
+
background-color: #3fa040;
|
|
5315
|
+
}
|
|
5316
|
+
|
|
5317
|
+
.pending-deny {
|
|
5318
|
+
background-color: var(--red);
|
|
5319
|
+
color: var(--bg);
|
|
5320
|
+
}
|
|
5321
|
+
|
|
5322
|
+
.pending-deny:hover {
|
|
5323
|
+
background-color: #e03c3c;
|
|
5324
|
+
}
|
|
5325
|
+
|
|
5326
|
+
/* Sovereignty Profile Panel */
|
|
5327
|
+
.profile-panel {
|
|
5328
|
+
background-color: var(--surface);
|
|
5329
|
+
border: 1px solid var(--border);
|
|
5330
|
+
border-radius: 8px;
|
|
5331
|
+
padding: 20px;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
.profile-panel .panel-header {
|
|
5335
|
+
display: flex;
|
|
5336
|
+
justify-content: space-between;
|
|
5337
|
+
align-items: center;
|
|
5338
|
+
margin-bottom: 16px;
|
|
5339
|
+
}
|
|
5340
|
+
|
|
5341
|
+
.profile-panel .panel-title {
|
|
5342
|
+
font-size: 14px;
|
|
5343
|
+
font-weight: 600;
|
|
5344
|
+
color: var(--text-primary);
|
|
5345
|
+
}
|
|
5346
|
+
|
|
5347
|
+
.profile-cards {
|
|
5348
|
+
display: grid;
|
|
5349
|
+
grid-template-columns: repeat(5, 1fr);
|
|
5350
|
+
gap: 12px;
|
|
5351
|
+
margin-bottom: 16px;
|
|
5352
|
+
}
|
|
5353
|
+
|
|
5354
|
+
.profile-card {
|
|
5355
|
+
background-color: var(--bg);
|
|
5356
|
+
border: 1px solid var(--border);
|
|
5357
|
+
border-radius: 6px;
|
|
5358
|
+
padding: 14px;
|
|
5359
|
+
display: flex;
|
|
5360
|
+
flex-direction: column;
|
|
5361
|
+
gap: 8px;
|
|
5362
|
+
}
|
|
5363
|
+
|
|
5364
|
+
.profile-card-name {
|
|
5365
|
+
font-size: 12px;
|
|
5366
|
+
font-weight: 600;
|
|
5367
|
+
color: var(--text-primary);
|
|
5368
|
+
}
|
|
5369
|
+
|
|
5370
|
+
.profile-card-desc {
|
|
5371
|
+
font-size: 11px;
|
|
5372
|
+
color: var(--text-secondary);
|
|
5373
|
+
line-height: 1.4;
|
|
5374
|
+
}
|
|
5375
|
+
|
|
5376
|
+
.profile-badge {
|
|
5377
|
+
display: inline-flex;
|
|
5378
|
+
align-items: center;
|
|
5379
|
+
gap: 4px;
|
|
5380
|
+
padding: 2px 8px;
|
|
5381
|
+
border-radius: 4px;
|
|
5382
|
+
font-size: 10px;
|
|
5383
|
+
font-weight: 600;
|
|
5384
|
+
width: fit-content;
|
|
5385
|
+
}
|
|
5386
|
+
|
|
5387
|
+
.profile-badge.enabled {
|
|
5388
|
+
background-color: rgba(63, 185, 80, 0.15);
|
|
5389
|
+
color: var(--green);
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5392
|
+
.profile-badge.disabled {
|
|
5393
|
+
background-color: rgba(139, 148, 158, 0.15);
|
|
5394
|
+
color: var(--text-secondary);
|
|
5184
5395
|
}
|
|
5185
5396
|
|
|
5186
|
-
.
|
|
5187
|
-
|
|
5188
|
-
overflow-y: auto;
|
|
5189
|
-
padding: 16px;
|
|
5397
|
+
.prompt-section {
|
|
5398
|
+
margin-top: 12px;
|
|
5190
5399
|
}
|
|
5191
5400
|
|
|
5192
|
-
.
|
|
5401
|
+
.prompt-textarea {
|
|
5402
|
+
width: 100%;
|
|
5403
|
+
min-height: 120px;
|
|
5193
5404
|
background-color: var(--bg);
|
|
5194
5405
|
border: 1px solid var(--border);
|
|
5195
5406
|
border-radius: 6px;
|
|
5196
|
-
padding: 16px;
|
|
5197
|
-
margin-bottom: 12px;
|
|
5198
|
-
}
|
|
5199
|
-
|
|
5200
|
-
.pending-title {
|
|
5201
|
-
font-weight: 600;
|
|
5202
5407
|
color: var(--text-primary);
|
|
5203
|
-
|
|
5204
|
-
word-break: break-word;
|
|
5205
|
-
}
|
|
5206
|
-
|
|
5207
|
-
.pending-countdown {
|
|
5408
|
+
font-family: 'JetBrains Mono', monospace;
|
|
5208
5409
|
font-size: 12px;
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5410
|
+
padding: 12px;
|
|
5411
|
+
resize: vertical;
|
|
5412
|
+
margin-top: 8px;
|
|
5212
5413
|
}
|
|
5213
5414
|
|
|
5214
|
-
.
|
|
5415
|
+
.prompt-actions {
|
|
5215
5416
|
display: flex;
|
|
5216
5417
|
gap: 8px;
|
|
5418
|
+
margin-top: 8px;
|
|
5217
5419
|
}
|
|
5218
5420
|
|
|
5219
|
-
.
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
border: none;
|
|
5421
|
+
.prompt-btn {
|
|
5422
|
+
padding: 6px 12px;
|
|
5423
|
+
border: 1px solid var(--border);
|
|
5223
5424
|
border-radius: 4px;
|
|
5425
|
+
background-color: var(--surface);
|
|
5426
|
+
color: var(--text-primary);
|
|
5224
5427
|
font-size: 12px;
|
|
5225
|
-
font-weight: 600;
|
|
5226
5428
|
cursor: pointer;
|
|
5227
|
-
transition: background-color 0.2s;
|
|
5228
5429
|
}
|
|
5229
5430
|
|
|
5230
|
-
.
|
|
5231
|
-
background-color: var(--
|
|
5232
|
-
color: var(--bg);
|
|
5431
|
+
.prompt-btn:hover {
|
|
5432
|
+
background-color: var(--muted);
|
|
5233
5433
|
}
|
|
5234
5434
|
|
|
5235
|
-
.
|
|
5236
|
-
background-color:
|
|
5435
|
+
.prompt-btn.primary {
|
|
5436
|
+
background-color: var(--blue);
|
|
5437
|
+
color: var(--bg);
|
|
5438
|
+
border-color: var(--blue);
|
|
5237
5439
|
}
|
|
5238
5440
|
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5441
|
+
@media (max-width: 900px) {
|
|
5442
|
+
.profile-cards {
|
|
5443
|
+
grid-template-columns: repeat(2, 1fr);
|
|
5444
|
+
}
|
|
5242
5445
|
}
|
|
5243
5446
|
|
|
5244
|
-
|
|
5245
|
-
|
|
5447
|
+
@media (max-width: 500px) {
|
|
5448
|
+
.profile-cards {
|
|
5449
|
+
grid-template-columns: 1fr;
|
|
5450
|
+
}
|
|
5246
5451
|
}
|
|
5247
5452
|
|
|
5248
5453
|
/* Threat Panel */
|
|
@@ -5583,6 +5788,48 @@ function generateDashboardHTML(options) {
|
|
|
5583
5788
|
</div>
|
|
5584
5789
|
</div>
|
|
5585
5790
|
|
|
5791
|
+
<!-- Sovereignty Profile Panel -->
|
|
5792
|
+
<div class="profile-panel" id="sovereignty-profile-panel">
|
|
5793
|
+
<div class="panel-header">
|
|
5794
|
+
<div class="panel-title">Sovereignty Profile</div>
|
|
5795
|
+
<span class="card-value" id="profile-updated-at" style="font-size: 11px; color: var(--text-secondary);">\u2014</span>
|
|
5796
|
+
</div>
|
|
5797
|
+
<div class="profile-cards" id="profile-cards">
|
|
5798
|
+
<div class="profile-card" data-feature="audit_logging">
|
|
5799
|
+
<div class="profile-card-name">Audit Logging</div>
|
|
5800
|
+
<div class="profile-badge disabled" id="badge-audit_logging">OFF</div>
|
|
5801
|
+
<div class="profile-card-desc">Encrypted audit trail of all tool calls</div>
|
|
5802
|
+
</div>
|
|
5803
|
+
<div class="profile-card" data-feature="injection_detection">
|
|
5804
|
+
<div class="profile-card-name">Injection Detection</div>
|
|
5805
|
+
<div class="profile-badge disabled" id="badge-injection_detection">OFF</div>
|
|
5806
|
+
<div class="profile-card-desc">Scans tool arguments for prompt injection</div>
|
|
5807
|
+
</div>
|
|
5808
|
+
<div class="profile-card" data-feature="context_gating">
|
|
5809
|
+
<div class="profile-card-name">Context Gating</div>
|
|
5810
|
+
<div class="profile-badge disabled" id="badge-context_gating">OFF</div>
|
|
5811
|
+
<div class="profile-card-desc">Controls context flow to remote providers</div>
|
|
5812
|
+
</div>
|
|
5813
|
+
<div class="profile-card" data-feature="approval_gate">
|
|
5814
|
+
<div class="profile-card-name">Approval Gates</div>
|
|
5815
|
+
<div class="profile-badge disabled" id="badge-approval_gate">OFF</div>
|
|
5816
|
+
<div class="profile-card-desc">Human approval for high-risk operations</div>
|
|
5817
|
+
</div>
|
|
5818
|
+
<div class="profile-card" data-feature="zk_proofs">
|
|
5819
|
+
<div class="profile-card-name">ZK Proofs</div>
|
|
5820
|
+
<div class="profile-badge disabled" id="badge-zk_proofs">OFF</div>
|
|
5821
|
+
<div class="profile-card-desc">Prove claims without revealing data</div>
|
|
5822
|
+
</div>
|
|
5823
|
+
</div>
|
|
5824
|
+
<div class="prompt-section">
|
|
5825
|
+
<div class="prompt-actions">
|
|
5826
|
+
<button class="prompt-btn primary" id="generate-prompt-btn">Generate System Prompt</button>
|
|
5827
|
+
<button class="prompt-btn" id="copy-prompt-btn" style="display:none;">Copy</button>
|
|
5828
|
+
</div>
|
|
5829
|
+
<textarea class="prompt-textarea" id="system-prompt-output" readonly style="display:none;" placeholder="Click 'Generate System Prompt' to create an agent instruction snippet..."></textarea>
|
|
5830
|
+
</div>
|
|
5831
|
+
</div>
|
|
5832
|
+
|
|
5586
5833
|
<!-- Threat Panel -->
|
|
5587
5834
|
<div class="threat-panel collapsed">
|
|
5588
5835
|
<div class="threat-header">
|
|
@@ -5604,7 +5851,9 @@ function generateDashboardHTML(options) {
|
|
|
5604
5851
|
|
|
5605
5852
|
<script>
|
|
5606
5853
|
// Constants
|
|
5607
|
-
|
|
5854
|
+
// SEC-038: Do NOT embed the long-lived auth token in page source.
|
|
5855
|
+
// Use only the session token stored in sessionStorage by the login flow.
|
|
5856
|
+
const AUTH_TOKEN = sessionStorage.getItem('authToken') || '';
|
|
5608
5857
|
const TIMEOUT_SECONDS = ${options.timeoutSeconds};
|
|
5609
5858
|
const API_BASE = '';
|
|
5610
5859
|
|
|
@@ -5615,6 +5864,7 @@ function generateDashboardHTML(options) {
|
|
|
5615
5864
|
handshakes: [],
|
|
5616
5865
|
shr: null,
|
|
5617
5866
|
status: null,
|
|
5867
|
+
systemPrompt: null,
|
|
5618
5868
|
};
|
|
5619
5869
|
|
|
5620
5870
|
let pendingRequests = new Map();
|
|
@@ -6067,6 +6317,10 @@ function generateDashboardHTML(options) {
|
|
|
6067
6317
|
removePendingRequest(data.requestId);
|
|
6068
6318
|
});
|
|
6069
6319
|
|
|
6320
|
+
eventSource.addEventListener('sovereignty-profile-update', () => {
|
|
6321
|
+
updateSovereigntyProfile();
|
|
6322
|
+
});
|
|
6323
|
+
|
|
6070
6324
|
eventSource.onerror = () => {
|
|
6071
6325
|
console.error('SSE error');
|
|
6072
6326
|
setTimeout(setupSSE, 5000);
|
|
@@ -6223,6 +6477,58 @@ function generateDashboardHTML(options) {
|
|
|
6223
6477
|
document.getElementById('pending-overlay').classList.toggle('show');
|
|
6224
6478
|
});
|
|
6225
6479
|
|
|
6480
|
+
// Sovereignty Profile
|
|
6481
|
+
async function updateSovereigntyProfile() {
|
|
6482
|
+
try {
|
|
6483
|
+
const data = await fetchAPI('/api/sovereignty-profile');
|
|
6484
|
+
if (data && data.profile) {
|
|
6485
|
+
const features = data.profile.features;
|
|
6486
|
+
for (const [key, value] of Object.entries(features)) {
|
|
6487
|
+
const badge = document.getElementById('badge-' + key);
|
|
6488
|
+
if (badge) {
|
|
6489
|
+
const enabled = value && value.enabled;
|
|
6490
|
+
badge.textContent = enabled ? 'ON' : 'OFF';
|
|
6491
|
+
badge.className = 'profile-badge ' + (enabled ? 'enabled' : 'disabled');
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
const updatedEl = document.getElementById('profile-updated-at');
|
|
6495
|
+
if (updatedEl && data.profile.updated_at) {
|
|
6496
|
+
updatedEl.textContent = 'Updated: ' + new Date(data.profile.updated_at).toLocaleString();
|
|
6497
|
+
}
|
|
6498
|
+
// Cache the prompt
|
|
6499
|
+
if (data.system_prompt) {
|
|
6500
|
+
apiState.systemPrompt = data.system_prompt;
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
} catch (e) {
|
|
6504
|
+
// Profile not available
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
|
|
6508
|
+
document.getElementById('generate-prompt-btn').addEventListener('click', async () => {
|
|
6509
|
+
const data = await fetchAPI('/api/sovereignty-profile');
|
|
6510
|
+
if (data && data.system_prompt) {
|
|
6511
|
+
const textarea = document.getElementById('system-prompt-output');
|
|
6512
|
+
const copyBtn = document.getElementById('copy-prompt-btn');
|
|
6513
|
+
textarea.value = data.system_prompt;
|
|
6514
|
+
textarea.style.display = 'block';
|
|
6515
|
+
copyBtn.style.display = 'inline-flex';
|
|
6516
|
+
}
|
|
6517
|
+
});
|
|
6518
|
+
|
|
6519
|
+
document.getElementById('copy-prompt-btn').addEventListener('click', async () => {
|
|
6520
|
+
const textarea = document.getElementById('system-prompt-output');
|
|
6521
|
+
try {
|
|
6522
|
+
await navigator.clipboard.writeText(textarea.value);
|
|
6523
|
+
const btn = document.getElementById('copy-prompt-btn');
|
|
6524
|
+
const original = btn.textContent;
|
|
6525
|
+
btn.textContent = 'Copied!';
|
|
6526
|
+
setTimeout(() => { btn.textContent = original; }, 2000);
|
|
6527
|
+
} catch (err) {
|
|
6528
|
+
console.error('Copy failed:', err);
|
|
6529
|
+
}
|
|
6530
|
+
});
|
|
6531
|
+
|
|
6226
6532
|
// Initialize
|
|
6227
6533
|
async function initialize() {
|
|
6228
6534
|
if (!AUTH_TOKEN) {
|
|
@@ -6237,6 +6543,7 @@ function generateDashboardHTML(options) {
|
|
|
6237
6543
|
updateHandshakes(),
|
|
6238
6544
|
updateSHR(),
|
|
6239
6545
|
updateStatus(),
|
|
6546
|
+
updateSovereigntyProfile(),
|
|
6240
6547
|
]);
|
|
6241
6548
|
|
|
6242
6549
|
// Setup SSE for real-time updates
|
|
@@ -6253,6 +6560,80 @@ function generateDashboardHTML(options) {
|
|
|
6253
6560
|
</html>`;
|
|
6254
6561
|
}
|
|
6255
6562
|
|
|
6563
|
+
// src/system-prompt-generator.ts
|
|
6564
|
+
var FEATURE_INFO = {
|
|
6565
|
+
audit_logging: {
|
|
6566
|
+
name: "Audit Logging",
|
|
6567
|
+
activeDescription: "All your tool calls are logged to an encrypted audit trail. No action needed \u2014 this is automatic.",
|
|
6568
|
+
disabledDescription: "audit logging (sanctuary/monitor_audit_log)"
|
|
6569
|
+
},
|
|
6570
|
+
injection_detection: {
|
|
6571
|
+
name: "Injection Detection",
|
|
6572
|
+
activeDescription: "Your tool call arguments are scanned for prompt injection attempts. No action needed \u2014 this is automatic.",
|
|
6573
|
+
disabledDescription: "injection detection"
|
|
6574
|
+
},
|
|
6575
|
+
context_gating: {
|
|
6576
|
+
name: "Context Gating",
|
|
6577
|
+
activeDescription: "Before making outbound calls to remote providers, filter your context through sanctuary/context_gate_filter to ensure minimum-necessary disclosure.",
|
|
6578
|
+
toolNames: ["sanctuary/context_gate_filter", "sanctuary/context_gate_set_policy"],
|
|
6579
|
+
disabledDescription: "context gating (sanctuary/context_gate_filter)"
|
|
6580
|
+
},
|
|
6581
|
+
approval_gate: {
|
|
6582
|
+
name: "Approval Gates",
|
|
6583
|
+
activeDescription: "High-risk operations require human approval before execution. Tier 1 operations always require approval; Tier 2 operations trigger approval on anomaly detection.",
|
|
6584
|
+
disabledDescription: "approval gates"
|
|
6585
|
+
},
|
|
6586
|
+
zk_proofs: {
|
|
6587
|
+
name: "Zero-Knowledge Proofs",
|
|
6588
|
+
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.",
|
|
6589
|
+
toolNames: ["sanctuary/zk_commit", "sanctuary/zk_prove", "sanctuary/zk_range_prove"],
|
|
6590
|
+
disabledDescription: "zero-knowledge proofs (sanctuary/zk_commit, sanctuary/zk_prove)"
|
|
6591
|
+
}
|
|
6592
|
+
};
|
|
6593
|
+
function generateSystemPrompt(profile) {
|
|
6594
|
+
const activeFeatures = [];
|
|
6595
|
+
const inactiveFeatures = [];
|
|
6596
|
+
const featureKeys = [
|
|
6597
|
+
"audit_logging",
|
|
6598
|
+
"injection_detection",
|
|
6599
|
+
"context_gating",
|
|
6600
|
+
"approval_gate",
|
|
6601
|
+
"zk_proofs"
|
|
6602
|
+
];
|
|
6603
|
+
for (const key of featureKeys) {
|
|
6604
|
+
const featureConfig = profile.features[key];
|
|
6605
|
+
const info = FEATURE_INFO[key];
|
|
6606
|
+
if (featureConfig.enabled) {
|
|
6607
|
+
let desc = `- ${info.name}: ${info.activeDescription}`;
|
|
6608
|
+
if (key === "injection_detection" && "sensitivity" in featureConfig && featureConfig.sensitivity) {
|
|
6609
|
+
desc += ` Sensitivity: ${featureConfig.sensitivity}.`;
|
|
6610
|
+
}
|
|
6611
|
+
if (key === "context_gating" && "policy_id" in featureConfig && featureConfig.policy_id) {
|
|
6612
|
+
desc += ` Active policy: ${featureConfig.policy_id}.`;
|
|
6613
|
+
}
|
|
6614
|
+
activeFeatures.push(desc);
|
|
6615
|
+
} else {
|
|
6616
|
+
inactiveFeatures.push(info.disabledDescription);
|
|
6617
|
+
}
|
|
6618
|
+
}
|
|
6619
|
+
const lines = [
|
|
6620
|
+
"You are protected by Sanctuary sovereignty infrastructure. The following protections are active:",
|
|
6621
|
+
""
|
|
6622
|
+
];
|
|
6623
|
+
if (activeFeatures.length > 0) {
|
|
6624
|
+
lines.push(...activeFeatures);
|
|
6625
|
+
} else {
|
|
6626
|
+
lines.push("- No features are currently enabled. Contact your operator to configure protections.");
|
|
6627
|
+
}
|
|
6628
|
+
if (inactiveFeatures.length > 0) {
|
|
6629
|
+
lines.push("");
|
|
6630
|
+
lines.push(
|
|
6631
|
+
`Optional tools available but not currently enabled: ${inactiveFeatures.join(", ")}.`
|
|
6632
|
+
);
|
|
6633
|
+
}
|
|
6634
|
+
return lines.join("\n");
|
|
6635
|
+
}
|
|
6636
|
+
|
|
6256
6637
|
// src/principal-policy/dashboard.ts
|
|
6257
6638
|
var SESSION_TTL_REMOTE_MS = 5 * 60 * 1e3;
|
|
6258
6639
|
var SESSION_TTL_LOCAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6273,6 +6654,7 @@ var DashboardApprovalChannel = class {
|
|
|
6273
6654
|
handshakeResults = null;
|
|
6274
6655
|
shrOpts = null;
|
|
6275
6656
|
_sanctuaryConfig = null;
|
|
6657
|
+
profileStore = null;
|
|
6276
6658
|
dashboardHTML;
|
|
6277
6659
|
loginHTML;
|
|
6278
6660
|
authToken;
|
|
@@ -6312,6 +6694,7 @@ var DashboardApprovalChannel = class {
|
|
|
6312
6694
|
if (deps.handshakeResults) this.handshakeResults = deps.handshakeResults;
|
|
6313
6695
|
if (deps.shrOpts) this.shrOpts = deps.shrOpts;
|
|
6314
6696
|
if (deps.sanctuaryConfig) this._sanctuaryConfig = deps.sanctuaryConfig;
|
|
6697
|
+
if (deps.profileStore) this.profileStore = deps.profileStore;
|
|
6315
6698
|
}
|
|
6316
6699
|
/**
|
|
6317
6700
|
* Mark this dashboard as running in standalone mode.
|
|
@@ -6659,6 +7042,10 @@ var DashboardApprovalChannel = class {
|
|
|
6659
7042
|
this.handleHandshakes(res);
|
|
6660
7043
|
} else if (method === "GET" && url.pathname === "/api/shr") {
|
|
6661
7044
|
this.handleSHR(res);
|
|
7045
|
+
} else if (method === "GET" && url.pathname === "/api/sovereignty-profile") {
|
|
7046
|
+
this.handleSovereigntyProfileGet(res);
|
|
7047
|
+
} else if (method === "POST" && url.pathname === "/api/sovereignty-profile") {
|
|
7048
|
+
this.handleSovereigntyProfileUpdate(req, res);
|
|
6662
7049
|
} else if (method === "POST" && url.pathname.startsWith("/api/approve/")) {
|
|
6663
7050
|
if (!this.checkRateLimit(req, res, "decisions")) return;
|
|
6664
7051
|
const id = url.pathname.slice("/api/approve/".length);
|
|
@@ -6950,6 +7337,61 @@ data: ${JSON.stringify(initData)}
|
|
|
6950
7337
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6951
7338
|
res.end(JSON.stringify(shr));
|
|
6952
7339
|
}
|
|
7340
|
+
// ── Sovereignty Profile API ─────────────────────────────────────────
|
|
7341
|
+
handleSovereigntyProfileGet(res) {
|
|
7342
|
+
if (!this.profileStore) {
|
|
7343
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7344
|
+
res.end(JSON.stringify({ error: "Sovereignty Profile not available" }));
|
|
7345
|
+
return;
|
|
7346
|
+
}
|
|
7347
|
+
try {
|
|
7348
|
+
const profile = this.profileStore.get();
|
|
7349
|
+
const prompt = generateSystemPrompt(profile);
|
|
7350
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7351
|
+
res.end(JSON.stringify({ profile, system_prompt: prompt }));
|
|
7352
|
+
} catch {
|
|
7353
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
7354
|
+
res.end(JSON.stringify({ error: "Failed to read sovereignty profile" }));
|
|
7355
|
+
}
|
|
7356
|
+
}
|
|
7357
|
+
handleSovereigntyProfileUpdate(req, res) {
|
|
7358
|
+
if (!this.profileStore) {
|
|
7359
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
7360
|
+
res.end(JSON.stringify({ error: "Sovereignty Profile not available" }));
|
|
7361
|
+
return;
|
|
7362
|
+
}
|
|
7363
|
+
let body = "";
|
|
7364
|
+
let destroyed = false;
|
|
7365
|
+
req.on("data", (chunk) => {
|
|
7366
|
+
body += chunk.toString();
|
|
7367
|
+
if (body.length > 16384) {
|
|
7368
|
+
destroyed = true;
|
|
7369
|
+
res.writeHead(413, { "Content-Type": "application/json" });
|
|
7370
|
+
res.end(JSON.stringify({ error: "Request body too large" }));
|
|
7371
|
+
req.destroy();
|
|
7372
|
+
}
|
|
7373
|
+
});
|
|
7374
|
+
req.on("end", async () => {
|
|
7375
|
+
if (destroyed) return;
|
|
7376
|
+
try {
|
|
7377
|
+
const updates = JSON.parse(body);
|
|
7378
|
+
const updated = await this.profileStore.update(updates);
|
|
7379
|
+
const prompt = generateSystemPrompt(updated);
|
|
7380
|
+
if (this.auditLog) {
|
|
7381
|
+
this.auditLog.append("l2", "sovereignty_profile_update_dashboard", "dashboard", {
|
|
7382
|
+
changes: updates,
|
|
7383
|
+
features_enabled: Object.entries(updated.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
7384
|
+
});
|
|
7385
|
+
}
|
|
7386
|
+
this.broadcastSSE("sovereignty-profile-update", { profile: updated, system_prompt: prompt });
|
|
7387
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
7388
|
+
res.end(JSON.stringify({ profile: updated, system_prompt: prompt }));
|
|
7389
|
+
} catch {
|
|
7390
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
7391
|
+
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
7392
|
+
}
|
|
7393
|
+
});
|
|
7394
|
+
}
|
|
6953
7395
|
// ── SSE Broadcasting ────────────────────────────────────────────────
|
|
6954
7396
|
broadcastSSE(event, data) {
|
|
6955
7397
|
const message = `event: ${event}
|
|
@@ -8117,6 +8559,7 @@ function createPrincipalPolicyTools(policy, baseline, auditLog) {
|
|
|
8117
8559
|
}
|
|
8118
8560
|
|
|
8119
8561
|
// src/shr/verifier.ts
|
|
8562
|
+
init_identity();
|
|
8120
8563
|
init_encoding();
|
|
8121
8564
|
function verifySHR(shr, now) {
|
|
8122
8565
|
const errors = [];
|
|
@@ -8539,7 +8982,9 @@ function createSHRTools(config, identityManager, masterKey, auditLog) {
|
|
|
8539
8982
|
}
|
|
8540
8983
|
|
|
8541
8984
|
// src/handshake/protocol.ts
|
|
8985
|
+
init_identity();
|
|
8542
8986
|
init_encoding();
|
|
8987
|
+
init_random();
|
|
8543
8988
|
function generateNonce() {
|
|
8544
8989
|
return toBase64url(randomBytes(32));
|
|
8545
8990
|
}
|
|
@@ -8706,7 +9151,9 @@ function deriveTrustTier(level) {
|
|
|
8706
9151
|
}
|
|
8707
9152
|
|
|
8708
9153
|
// src/handshake/attestation.ts
|
|
9154
|
+
init_identity();
|
|
8709
9155
|
init_encoding();
|
|
9156
|
+
init_identity();
|
|
8710
9157
|
init_encoding();
|
|
8711
9158
|
var ATTESTATION_VERSION = "1.0";
|
|
8712
9159
|
function deriveTrustTier2(level) {
|
|
@@ -9499,10 +9946,13 @@ function createFederationTools(auditLog, handshakeResults) {
|
|
|
9499
9946
|
|
|
9500
9947
|
// src/bridge/tools.ts
|
|
9501
9948
|
init_encoding();
|
|
9949
|
+
init_encryption();
|
|
9502
9950
|
init_encoding();
|
|
9503
9951
|
|
|
9504
9952
|
// src/bridge/bridge.ts
|
|
9953
|
+
init_identity();
|
|
9505
9954
|
init_encoding();
|
|
9955
|
+
init_random();
|
|
9506
9956
|
init_hashing();
|
|
9507
9957
|
function canonicalize(outcome) {
|
|
9508
9958
|
return stringToBytes(stableStringify(outcome));
|
|
@@ -10653,7 +11103,9 @@ function createAuditTools(config) {
|
|
|
10653
11103
|
}
|
|
10654
11104
|
|
|
10655
11105
|
// src/l2-operational/context-gate.ts
|
|
11106
|
+
init_encryption();
|
|
10656
11107
|
init_encoding();
|
|
11108
|
+
init_random();
|
|
10657
11109
|
init_hashing();
|
|
10658
11110
|
var MAX_CONTEXT_FIELDS = 1e3;
|
|
10659
11111
|
var MAX_POLICY_RULES = 50;
|
|
@@ -12622,7 +13074,272 @@ function createL2HardeningTools(storagePath, auditLog) {
|
|
|
12622
13074
|
];
|
|
12623
13075
|
}
|
|
12624
13076
|
|
|
13077
|
+
// src/sovereignty-profile.ts
|
|
13078
|
+
init_encryption();
|
|
13079
|
+
init_encoding();
|
|
13080
|
+
var NAMESPACE = "_sovereignty_profile";
|
|
13081
|
+
var PROFILE_KEY = "active";
|
|
13082
|
+
var HKDF_DOMAIN = "sovereignty-profile";
|
|
13083
|
+
function createDefaultProfile() {
|
|
13084
|
+
return {
|
|
13085
|
+
version: 1,
|
|
13086
|
+
features: {
|
|
13087
|
+
audit_logging: { enabled: true },
|
|
13088
|
+
injection_detection: { enabled: true },
|
|
13089
|
+
context_gating: { enabled: false },
|
|
13090
|
+
approval_gate: { enabled: false },
|
|
13091
|
+
zk_proofs: { enabled: false }
|
|
13092
|
+
},
|
|
13093
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
13094
|
+
};
|
|
13095
|
+
}
|
|
13096
|
+
var SovereigntyProfileStore = class {
|
|
13097
|
+
storage;
|
|
13098
|
+
encryptionKey;
|
|
13099
|
+
profile = null;
|
|
13100
|
+
constructor(storage, masterKey) {
|
|
13101
|
+
this.storage = storage;
|
|
13102
|
+
this.encryptionKey = derivePurposeKey(masterKey, HKDF_DOMAIN);
|
|
13103
|
+
}
|
|
13104
|
+
/**
|
|
13105
|
+
* Load the active sovereignty profile from encrypted storage.
|
|
13106
|
+
* Creates the default profile on first run.
|
|
13107
|
+
*/
|
|
13108
|
+
async load() {
|
|
13109
|
+
if (this.profile) return this.profile;
|
|
13110
|
+
const raw = await this.storage.read(NAMESPACE, PROFILE_KEY);
|
|
13111
|
+
if (raw) {
|
|
13112
|
+
try {
|
|
13113
|
+
const encrypted = JSON.parse(bytesToString(raw));
|
|
13114
|
+
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
13115
|
+
this.profile = JSON.parse(bytesToString(decrypted));
|
|
13116
|
+
return this.profile;
|
|
13117
|
+
} catch {
|
|
13118
|
+
}
|
|
13119
|
+
}
|
|
13120
|
+
this.profile = createDefaultProfile();
|
|
13121
|
+
await this.persist();
|
|
13122
|
+
return this.profile;
|
|
13123
|
+
}
|
|
13124
|
+
/**
|
|
13125
|
+
* Get the current profile. Must call load() first.
|
|
13126
|
+
*/
|
|
13127
|
+
get() {
|
|
13128
|
+
if (!this.profile) {
|
|
13129
|
+
throw new Error("SovereigntyProfileStore: call load() before get()");
|
|
13130
|
+
}
|
|
13131
|
+
return this.profile;
|
|
13132
|
+
}
|
|
13133
|
+
/**
|
|
13134
|
+
* Apply a partial update to the profile.
|
|
13135
|
+
* Returns the updated profile.
|
|
13136
|
+
*/
|
|
13137
|
+
async update(updates) {
|
|
13138
|
+
if (!this.profile) {
|
|
13139
|
+
await this.load();
|
|
13140
|
+
}
|
|
13141
|
+
const features = this.profile.features;
|
|
13142
|
+
if (updates.audit_logging !== void 0) {
|
|
13143
|
+
if (updates.audit_logging.enabled !== void 0) {
|
|
13144
|
+
if (typeof updates.audit_logging.enabled !== "boolean") {
|
|
13145
|
+
throw new Error("audit_logging.enabled must be a boolean");
|
|
13146
|
+
}
|
|
13147
|
+
features.audit_logging.enabled = updates.audit_logging.enabled;
|
|
13148
|
+
}
|
|
13149
|
+
}
|
|
13150
|
+
if (updates.injection_detection !== void 0) {
|
|
13151
|
+
if (updates.injection_detection.enabled !== void 0) {
|
|
13152
|
+
if (typeof updates.injection_detection.enabled !== "boolean") {
|
|
13153
|
+
throw new Error("injection_detection.enabled must be a boolean");
|
|
13154
|
+
}
|
|
13155
|
+
features.injection_detection.enabled = updates.injection_detection.enabled;
|
|
13156
|
+
}
|
|
13157
|
+
if (updates.injection_detection.sensitivity !== void 0) {
|
|
13158
|
+
const valid = ["low", "medium", "high"];
|
|
13159
|
+
if (!valid.includes(updates.injection_detection.sensitivity)) {
|
|
13160
|
+
throw new Error("injection_detection.sensitivity must be low, medium, or high");
|
|
13161
|
+
}
|
|
13162
|
+
features.injection_detection.sensitivity = updates.injection_detection.sensitivity;
|
|
13163
|
+
}
|
|
13164
|
+
}
|
|
13165
|
+
if (updates.context_gating !== void 0) {
|
|
13166
|
+
if (updates.context_gating.enabled !== void 0) {
|
|
13167
|
+
if (typeof updates.context_gating.enabled !== "boolean") {
|
|
13168
|
+
throw new Error("context_gating.enabled must be a boolean");
|
|
13169
|
+
}
|
|
13170
|
+
features.context_gating.enabled = updates.context_gating.enabled;
|
|
13171
|
+
}
|
|
13172
|
+
if (updates.context_gating.policy_id !== void 0) {
|
|
13173
|
+
if (typeof updates.context_gating.policy_id !== "string" || updates.context_gating.policy_id.length > 256) {
|
|
13174
|
+
throw new Error("context_gating.policy_id must be a string of 256 characters or fewer");
|
|
13175
|
+
}
|
|
13176
|
+
features.context_gating.policy_id = updates.context_gating.policy_id;
|
|
13177
|
+
}
|
|
13178
|
+
}
|
|
13179
|
+
if (updates.approval_gate !== void 0) {
|
|
13180
|
+
if (updates.approval_gate.enabled !== void 0) {
|
|
13181
|
+
if (typeof updates.approval_gate.enabled !== "boolean") {
|
|
13182
|
+
throw new Error("approval_gate.enabled must be a boolean");
|
|
13183
|
+
}
|
|
13184
|
+
features.approval_gate.enabled = updates.approval_gate.enabled;
|
|
13185
|
+
}
|
|
13186
|
+
}
|
|
13187
|
+
if (updates.zk_proofs !== void 0) {
|
|
13188
|
+
if (updates.zk_proofs.enabled !== void 0) {
|
|
13189
|
+
if (typeof updates.zk_proofs.enabled !== "boolean") {
|
|
13190
|
+
throw new Error("zk_proofs.enabled must be a boolean");
|
|
13191
|
+
}
|
|
13192
|
+
features.zk_proofs.enabled = updates.zk_proofs.enabled;
|
|
13193
|
+
}
|
|
13194
|
+
}
|
|
13195
|
+
this.profile.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
13196
|
+
await this.persist();
|
|
13197
|
+
return this.profile;
|
|
13198
|
+
}
|
|
13199
|
+
/**
|
|
13200
|
+
* Persist the current profile to encrypted storage.
|
|
13201
|
+
*/
|
|
13202
|
+
async persist() {
|
|
13203
|
+
const serialized = stringToBytes(JSON.stringify(this.profile));
|
|
13204
|
+
const encrypted = encrypt(serialized, this.encryptionKey);
|
|
13205
|
+
await this.storage.write(
|
|
13206
|
+
NAMESPACE,
|
|
13207
|
+
PROFILE_KEY,
|
|
13208
|
+
stringToBytes(JSON.stringify(encrypted))
|
|
13209
|
+
);
|
|
13210
|
+
}
|
|
13211
|
+
};
|
|
13212
|
+
|
|
13213
|
+
// src/sovereignty-profile-tools.ts
|
|
13214
|
+
function createSovereigntyProfileTools(profileStore, auditLog) {
|
|
13215
|
+
const tools = [
|
|
13216
|
+
// ── Get Profile ──────────────────────────────────────────────────
|
|
13217
|
+
{
|
|
13218
|
+
name: "sanctuary/sovereignty_profile_get",
|
|
13219
|
+
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.",
|
|
13220
|
+
inputSchema: {
|
|
13221
|
+
type: "object",
|
|
13222
|
+
properties: {}
|
|
13223
|
+
},
|
|
13224
|
+
handler: async () => {
|
|
13225
|
+
const profile = profileStore.get();
|
|
13226
|
+
auditLog.append("l2", "sovereignty_profile_get", "system", {
|
|
13227
|
+
features_enabled: Object.entries(profile.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13228
|
+
});
|
|
13229
|
+
return toolResult({
|
|
13230
|
+
profile,
|
|
13231
|
+
message: "Current Sovereignty Profile. Use sovereignty_profile_update to change settings."
|
|
13232
|
+
});
|
|
13233
|
+
}
|
|
13234
|
+
},
|
|
13235
|
+
// ── Update Profile ───────────────────────────────────────────────
|
|
13236
|
+
{
|
|
13237
|
+
name: "sanctuary/sovereignty_profile_update",
|
|
13238
|
+
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.",
|
|
13239
|
+
inputSchema: {
|
|
13240
|
+
type: "object",
|
|
13241
|
+
properties: {
|
|
13242
|
+
audit_logging: {
|
|
13243
|
+
type: "object",
|
|
13244
|
+
properties: {
|
|
13245
|
+
enabled: { type: "boolean" }
|
|
13246
|
+
},
|
|
13247
|
+
description: "Toggle audit logging on/off"
|
|
13248
|
+
},
|
|
13249
|
+
injection_detection: {
|
|
13250
|
+
type: "object",
|
|
13251
|
+
properties: {
|
|
13252
|
+
enabled: { type: "boolean" },
|
|
13253
|
+
sensitivity: {
|
|
13254
|
+
type: "string",
|
|
13255
|
+
enum: ["low", "medium", "high"],
|
|
13256
|
+
description: "Detection sensitivity threshold"
|
|
13257
|
+
}
|
|
13258
|
+
},
|
|
13259
|
+
description: "Toggle injection detection and set sensitivity"
|
|
13260
|
+
},
|
|
13261
|
+
context_gating: {
|
|
13262
|
+
type: "object",
|
|
13263
|
+
properties: {
|
|
13264
|
+
enabled: { type: "boolean" },
|
|
13265
|
+
policy_id: {
|
|
13266
|
+
type: "string",
|
|
13267
|
+
description: "ID of the context-gating policy to use"
|
|
13268
|
+
}
|
|
13269
|
+
},
|
|
13270
|
+
description: "Toggle context gating and set active policy"
|
|
13271
|
+
},
|
|
13272
|
+
approval_gate: {
|
|
13273
|
+
type: "object",
|
|
13274
|
+
properties: {
|
|
13275
|
+
enabled: { type: "boolean" }
|
|
13276
|
+
},
|
|
13277
|
+
description: "Toggle approval gates on/off"
|
|
13278
|
+
},
|
|
13279
|
+
zk_proofs: {
|
|
13280
|
+
type: "object",
|
|
13281
|
+
properties: {
|
|
13282
|
+
enabled: { type: "boolean" }
|
|
13283
|
+
},
|
|
13284
|
+
description: "Toggle zero-knowledge proofs on/off"
|
|
13285
|
+
}
|
|
13286
|
+
}
|
|
13287
|
+
},
|
|
13288
|
+
handler: async (args) => {
|
|
13289
|
+
const updates = {};
|
|
13290
|
+
if (args.audit_logging !== void 0) {
|
|
13291
|
+
updates.audit_logging = args.audit_logging;
|
|
13292
|
+
}
|
|
13293
|
+
if (args.injection_detection !== void 0) {
|
|
13294
|
+
updates.injection_detection = args.injection_detection;
|
|
13295
|
+
}
|
|
13296
|
+
if (args.context_gating !== void 0) {
|
|
13297
|
+
updates.context_gating = args.context_gating;
|
|
13298
|
+
}
|
|
13299
|
+
if (args.approval_gate !== void 0) {
|
|
13300
|
+
updates.approval_gate = args.approval_gate;
|
|
13301
|
+
}
|
|
13302
|
+
if (args.zk_proofs !== void 0) {
|
|
13303
|
+
updates.zk_proofs = args.zk_proofs;
|
|
13304
|
+
}
|
|
13305
|
+
const updated = await profileStore.update(updates);
|
|
13306
|
+
auditLog.append("l2", "sovereignty_profile_update", "system", {
|
|
13307
|
+
changes: updates,
|
|
13308
|
+
features_enabled: Object.entries(updated.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13309
|
+
});
|
|
13310
|
+
return toolResult({
|
|
13311
|
+
profile: updated,
|
|
13312
|
+
message: "Sovereignty Profile updated. Changes take effect immediately."
|
|
13313
|
+
});
|
|
13314
|
+
}
|
|
13315
|
+
},
|
|
13316
|
+
// ── Generate System Prompt ───────────────────────────────────────
|
|
13317
|
+
{
|
|
13318
|
+
name: "sanctuary/sovereignty_profile_generate_prompt",
|
|
13319
|
+
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.",
|
|
13320
|
+
inputSchema: {
|
|
13321
|
+
type: "object",
|
|
13322
|
+
properties: {}
|
|
13323
|
+
},
|
|
13324
|
+
handler: async () => {
|
|
13325
|
+
const profile = profileStore.get();
|
|
13326
|
+
const prompt = generateSystemPrompt(profile);
|
|
13327
|
+
auditLog.append("l2", "sovereignty_profile_generate_prompt", "system", {
|
|
13328
|
+
features_enabled: Object.entries(profile.features).filter(([, v]) => v.enabled).map(([k]) => k)
|
|
13329
|
+
});
|
|
13330
|
+
return toolResult({
|
|
13331
|
+
system_prompt: prompt,
|
|
13332
|
+
token_estimate: Math.ceil(prompt.length / 4),
|
|
13333
|
+
message: "Copy the system_prompt text above and paste it into your agent's system configuration. It will update dynamically as you toggle features."
|
|
13334
|
+
});
|
|
13335
|
+
}
|
|
13336
|
+
}
|
|
13337
|
+
];
|
|
13338
|
+
return { tools };
|
|
13339
|
+
}
|
|
13340
|
+
|
|
12625
13341
|
// src/index.ts
|
|
13342
|
+
init_random();
|
|
12626
13343
|
init_encoding();
|
|
12627
13344
|
|
|
12628
13345
|
// src/l2-operational/model-provenance.ts
|
|
@@ -13129,6 +13846,9 @@ async function createSanctuaryServer(options) {
|
|
|
13129
13846
|
const { tools: auditTools } = createAuditTools(config);
|
|
13130
13847
|
const { tools: contextGateTools, enforcer: contextGateEnforcer } = createContextGateTools(storage, masterKey, auditLog);
|
|
13131
13848
|
const hardeningTools = createL2HardeningTools(config.storage_path, auditLog);
|
|
13849
|
+
const profileStore = new SovereigntyProfileStore(storage, masterKey);
|
|
13850
|
+
await profileStore.load();
|
|
13851
|
+
const { tools: profileTools } = createSovereigntyProfileTools(profileStore, auditLog);
|
|
13132
13852
|
const policy = await loadPrincipalPolicy(config.storage_path);
|
|
13133
13853
|
const baseline = new BaselineTracker(storage, masterKey);
|
|
13134
13854
|
await baseline.load();
|
|
@@ -13156,7 +13876,8 @@ async function createSanctuaryServer(options) {
|
|
|
13156
13876
|
identityManager,
|
|
13157
13877
|
handshakeResults,
|
|
13158
13878
|
shrOpts: { config, identityManager, masterKey },
|
|
13159
|
-
sanctuaryConfig: config
|
|
13879
|
+
sanctuaryConfig: config,
|
|
13880
|
+
profileStore
|
|
13160
13881
|
});
|
|
13161
13882
|
await dashboard.start();
|
|
13162
13883
|
approvalChannel = dashboard;
|
|
@@ -13233,6 +13954,7 @@ async function createSanctuaryServer(options) {
|
|
|
13233
13954
|
...auditTools,
|
|
13234
13955
|
...contextGateTools,
|
|
13235
13956
|
...hardeningTools,
|
|
13957
|
+
...profileTools,
|
|
13236
13958
|
...dashboardTools,
|
|
13237
13959
|
manifestTool
|
|
13238
13960
|
];
|
|
@@ -13263,6 +13985,6 @@ async function createSanctuaryServer(options) {
|
|
|
13263
13985
|
return { server, config };
|
|
13264
13986
|
}
|
|
13265
13987
|
|
|
13266
|
-
export { ATTESTATION_VERSION, ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, CommitmentStore, ContextGateEnforcer, ContextGatePolicyStore, DashboardApprovalChannel, FederationRegistry, FilesystemStorage, InMemoryModelProvenanceStore, InjectionDetector, MODEL_PRESETS, MemoryStorage, PolicyStore, ReputationStore, StateStore, StderrApprovalChannel, TIER_WEIGHTS, WebhookApprovalChannel, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateAttestation, generateSHR, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, resolveTier, respondToHandshake, signPayload, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|
|
13988
|
+
export { ATTESTATION_VERSION, ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, CommitmentStore, ContextGateEnforcer, ContextGatePolicyStore, DashboardApprovalChannel, FederationRegistry, FilesystemStorage, InMemoryModelProvenanceStore, InjectionDetector, MODEL_PRESETS, MemoryStorage, PolicyStore, ReputationStore, SovereigntyProfileStore, StateStore, StderrApprovalChannel, TIER_WEIGHTS, WebhookApprovalChannel, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, resolveTier, respondToHandshake, signPayload, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|
|
13267
13989
|
//# sourceMappingURL=index.js.map
|
|
13268
13990
|
//# sourceMappingURL=index.js.map
|