@sanctuary-framework/mcp-server 0.7.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -6,7 +6,6 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
6
6
  interface SanctuaryConfig {
7
7
  version: string;
8
8
  storage_path: string;
9
- principal_id?: string;
10
9
  state: {
11
10
  encryption: "aes-256-gcm";
12
11
  key_protection: "passphrase" | "hardware-key" | "none";
@@ -127,157 +126,6 @@ interface StorageBackend {
127
126
  totalSize(): Promise<number>;
128
127
  }
129
128
 
130
- /**
131
- * Sanctuary MCP Server — AES-256-GCM Encryption
132
- *
133
- * All state encryption in Sanctuary uses AES-256-GCM (authenticated encryption).
134
- * This provides both confidentiality and integrity — a modified ciphertext will
135
- * fail authentication, detecting tampering.
136
- *
137
- * Security invariants:
138
- * - Every encryption uses a unique 12-byte IV (NIST SP 800-38D)
139
- * - The 16-byte authentication tag is always verified on decryption
140
- * - Keys are 256 bits (32 bytes)
141
- */
142
- /** Encrypted payload structure stored on disk */
143
- interface EncryptedPayload {
144
- /** Format version */
145
- v: number;
146
- /** Algorithm identifier */
147
- alg: "aes-256-gcm";
148
- /** Initialization vector (base64url) */
149
- iv: string;
150
- /** Ciphertext (base64url) */
151
- ct: string;
152
- /** Authentication tag (base64url) — included in ciphertext by @noble/ciphers */
153
- /** Timestamp */
154
- ts: string;
155
- }
156
-
157
- /**
158
- * Sanctuary MCP Server — L1 Cognitive Sovereignty: StateStore
159
- *
160
- * The encrypted state store is the foundation of Sanctuary.
161
- * Every read and write goes through here. All data is encrypted
162
- * with namespace-specific keys. All writes are signed by an identity.
163
- * All reads verify integrity via Merkle proofs.
164
- *
165
- * Security invariants:
166
- * - Plaintext never touches the filesystem
167
- * - Every write gets a unique IV
168
- * - Every write is signed (non-repudiation)
169
- * - Monotonic version numbers prevent rollback
170
- * - Merkle tree verifies namespace integrity
171
- * - Secure deletion overwrites before unlinking
172
- */
173
-
174
- /** Result of a state write operation */
175
- interface WriteResult {
176
- key: string;
177
- namespace: string;
178
- version: number;
179
- merkle_root: string;
180
- written_at: string;
181
- size_bytes: number;
182
- integrity_hash: string;
183
- }
184
- /** Result of a state read operation */
185
- interface ReadResult {
186
- key: string;
187
- namespace: string;
188
- value: string;
189
- version: number;
190
- integrity_verified: boolean;
191
- merkle_proof: string[];
192
- written_at: string;
193
- written_by: string;
194
- }
195
- /** Options for state write */
196
- interface WriteOptions {
197
- content_type?: string;
198
- ttl_seconds?: number;
199
- tags?: string[];
200
- }
201
- declare class StateStore {
202
- private storage;
203
- private masterKey;
204
- private versionCache;
205
- private contentHashes;
206
- constructor(storage: StorageBackend, masterKey: Uint8Array);
207
- private versionKey;
208
- /**
209
- * Get or initialize the content hash map for a namespace.
210
- */
211
- private getNamespaceHashes;
212
- /**
213
- * Write encrypted state.
214
- *
215
- * @param namespace - Logical grouping
216
- * @param key - State key
217
- * @param value - Plaintext value (will be encrypted)
218
- * @param identityId - Identity performing the write
219
- * @param encryptedPrivateKey - Identity's encrypted private key (for signing)
220
- * @param identityEncryptionKey - Key to decrypt the identity's private key
221
- * @param options - Optional metadata
222
- */
223
- write(namespace: string, key: string, value: string, identityId: string, encryptedPrivateKey: EncryptedPayload, identityEncryptionKey: Uint8Array, options?: WriteOptions): Promise<WriteResult>;
224
- /**
225
- * Read and decrypt state.
226
- *
227
- * @param namespace - Logical grouping
228
- * @param key - State key
229
- * @param signerPublicKey - Expected signer's public key (for signature verification)
230
- * @param verifyIntegrity - Whether to verify Merkle proof (default: true)
231
- */
232
- read(namespace: string, key: string, signerPublicKey?: Uint8Array, verifyIntegrity?: boolean): Promise<ReadResult | null>;
233
- /**
234
- * List keys in a namespace (metadata only — no decryption).
235
- */
236
- list(namespace: string, prefix?: string, tags?: string[], limit?: number, offset?: number): Promise<{
237
- keys: Array<{
238
- key: string;
239
- version: number;
240
- size_bytes: number;
241
- written_at: string;
242
- tags: string[];
243
- }>;
244
- total: number;
245
- merkle_root: string;
246
- }>;
247
- /**
248
- * Securely delete state (overwrite with random bytes before removal).
249
- */
250
- delete(namespace: string, key: string): Promise<{
251
- deleted: boolean;
252
- key: string;
253
- namespace: string;
254
- new_merkle_root: string;
255
- deleted_at: string;
256
- }>;
257
- /**
258
- * Export all state for a namespace as an encrypted bundle.
259
- */
260
- export(namespace?: string): Promise<{
261
- bundle: string;
262
- namespaces: string[];
263
- total_keys: number;
264
- bundle_hash: string;
265
- exported_at: string;
266
- }>;
267
- /**
268
- * Import a previously exported state bundle.
269
- */
270
- import(bundleBase64: string, conflictResolution: "skip" | "overwrite" | "version" | undefined, publicKeyResolver: (kid: string) => Uint8Array | null): Promise<{
271
- imported_keys: number;
272
- skipped_keys: number;
273
- skipped_invalid_sig: number;
274
- skipped_unknown_kid: number;
275
- conflicts: number;
276
- namespaces: string[];
277
- imported_at: string;
278
- }>;
279
- }
280
-
281
129
  /**
282
130
  * Sanctuary MCP Server — L2 Operational Isolation: Audit Log
283
131
  *
@@ -297,17 +145,31 @@ interface AuditEntry {
297
145
  result: "success" | "failure";
298
146
  details?: Record<string, unknown>;
299
147
  }
148
+ interface AuditLogConfig {
149
+ /** Maximum total size of stored audit entries in bytes. Default: 100 MB. */
150
+ maxTotalSizeBytes?: number;
151
+ /** Maximum number of stored audit entry files to retain. Default: 100_000. */
152
+ maxEntries?: number;
153
+ }
300
154
  declare class AuditLog {
301
155
  private storage;
302
156
  private encryptionKey;
303
157
  private entries;
304
158
  private counter;
305
- constructor(storage: StorageBackend, masterKey: Uint8Array);
159
+ private readonly maxTotalSizeBytes;
160
+ private readonly maxEntries;
161
+ private rotationInFlight;
162
+ constructor(storage: StorageBackend, masterKey: Uint8Array, config?: AuditLogConfig);
306
163
  /**
307
164
  * Append an audit entry.
308
165
  */
309
166
  append(layer: AuditEntry["layer"], operation: string, identityId: string, details?: Record<string, unknown>, result?: "success" | "failure"): void;
310
167
  private persistEntry;
168
+ /**
169
+ * Prune oldest audit entries when storage exceeds configured limits.
170
+ * Entries are sorted by key (timestamp-based) so oldest are pruned first.
171
+ */
172
+ private maybeRotate;
311
173
  /**
312
174
  * Query the audit log with filtering.
313
175
  */
@@ -328,942 +190,1010 @@ declare class AuditLog {
328
190
  }
329
191
 
330
192
  /**
331
- * Sanctuary MCP Server — L3 Selective Disclosure: Commitment Schemes
332
- *
333
- * Cryptographic commitments allow an agent to commit to a value
334
- * without revealing it, then later prove what was committed.
335
- *
336
- * This is the MVS approach to selective disclosure — simpler than
337
- * full ZK proofs but still cryptographically sound. The commitment
338
- * is SHA-256(value || blinding_factor), which is:
339
- * - Hiding: the commitment reveals nothing about the value
340
- * - Binding: the committer cannot change the value after committing
193
+ * Sanctuary MCP Server — Principal Policy Types
341
194
  *
342
- * Security invariants:
343
- * - Blinding factors are cryptographically random (32 bytes)
344
- * - Commitments are stored encrypted under L1 sovereignty
345
- * - Revealed values are verified via constant-time comparison
195
+ * Type definitions for the Principal Policy system.
196
+ * The Principal Policy is the human-controlled, agent-immutable
197
+ * configuration that gates operations through approval tiers.
346
198
  */
347
-
348
- /** A cryptographic commitment */
349
- interface Commitment {
350
- /** The commitment hash: SHA-256(value || blinding_factor) as base64url */
351
- commitment: string;
352
- /** The blinding factor (must be stored securely for later reveal) */
353
- blinding_factor: string;
354
- /** When the commitment was created */
355
- committed_at: string;
356
- }
357
- /** Stored commitment metadata (encrypted at rest) */
358
- interface StoredCommitment {
359
- commitment: string;
360
- blinding_factor: string;
361
- value: string;
362
- committed_at: string;
363
- revealed: boolean;
364
- revealed_at?: string;
199
+ /** Tier 2 anomaly action: what to do when an anomaly is detected */
200
+ type AnomalyAction = "approve" | "log" | "allow";
201
+ /** Tier 2 anomaly detection configuration */
202
+ interface Tier2Config {
203
+ /** Action when agent accesses a namespace it hasn't used before */
204
+ new_namespace_access: AnomalyAction;
205
+ /** Action when agent interacts with an unknown counterparty DID */
206
+ new_counterparty: AnomalyAction;
207
+ /** Tool call frequency multiplier that triggers anomaly */
208
+ frequency_spike_multiplier: number;
209
+ /** Maximum signing operations per minute before triggering */
210
+ max_signs_per_minute: number;
211
+ /** Reading more than N keys in a namespace within 60 seconds */
212
+ bulk_read_threshold: number;
213
+ /** Policy for first session when no baseline exists */
214
+ first_session_policy: AnomalyAction;
365
215
  }
366
- /**
367
- * Commitment store — manages commitments encrypted under L1 sovereignty.
368
- */
369
- declare class CommitmentStore {
370
- private storage;
371
- private encryptionKey;
372
- constructor(storage: StorageBackend, masterKey: Uint8Array);
373
- /**
374
- * Store a commitment (encrypted) for later reference.
375
- */
376
- store(commitment: Commitment, value: string): Promise<string>;
377
- /**
378
- * Retrieve a stored commitment by ID.
379
- */
380
- get(id: string): Promise<StoredCommitment | null>;
216
+ /** Approval channel configuration */
217
+ interface ApprovalChannelConfig {
218
+ type: "stderr" | "webhook" | "callback";
219
+ timeout_seconds: number;
381
220
  /**
382
- * Mark a commitment as revealed.
221
+ * SEC-002: auto_deny is hardcoded to true and not configurable.
222
+ * Timeout on any approval channel ALWAYS results in denial.
223
+ * This field is retained for backward compatibility with existing
224
+ * policy files but is ignored — timeout always denies.
383
225
  */
384
- markRevealed(id: string): Promise<void>;
226
+ auto_deny?: boolean;
227
+ webhook_url?: string;
228
+ webhook_secret?: string;
385
229
  }
386
-
387
- /**
388
- * Sanctuary MCP Server — L3 Selective Disclosure: Zero-Knowledge Proofs
389
- *
390
- * Upgrades the commitment-only L3 to support real zero-knowledge proofs.
391
- * Uses Ristretto255 (prime-order curve group, no cofactor issues) for:
392
- *
393
- * 1. Pedersen commitments: C = v*G + b*H (computationally hiding, perfectly binding)
394
- * 2. ZK proof of knowledge: Schnorr sigma protocol via Fiat-Shamir
395
- * 3. ZK range proofs: Prove value ∈ [min, max] without revealing it
396
- *
397
- * Ristretto255 is available via @noble/curves/ed25519, which we already depend on.
398
- * This is genuine zero-knowledge — proofs reveal nothing beyond the stated property.
399
- *
400
- * Architecture note:
401
- * The existing commitment scheme (SHA-256 based) remains available for backward
402
- * compatibility. The ZK proofs operate on a separate Pedersen commitment system
403
- * that provides algebraic structure for proper ZK properties.
404
- *
405
- * Security invariants:
406
- * - Generator H is derived via hash-to-curve (nothing-up-my-sleeve)
407
- * - Blinding factors are cryptographically random (32 bytes)
408
- * - Fiat-Shamir challenges use domain-separated hashing
409
- * - Range proofs use a bit-decomposition approach (sound but logarithmic size)
410
- */
411
- /** A Pedersen commitment: C = v*G + b*H */
412
- interface PedersenCommitment {
413
- /** The commitment point (encoded as base64url) */
414
- commitment: string;
415
- /** The blinding factor b (base64url, 32 bytes) — keep secret */
416
- blinding_factor: string;
417
- /** When the commitment was created */
418
- committed_at: string;
230
+ /** Complete Principal Policy */
231
+ interface PrincipalPolicy {
232
+ version: number;
233
+ /** Operations that always require human approval */
234
+ tier1_always_approve: string[];
235
+ /** Behavioral anomaly detection configuration */
236
+ tier2_anomaly: Tier2Config;
237
+ /** Operations that never require approval (audit only) */
238
+ tier3_always_allow: string[];
239
+ /** How approval requests reach the human */
240
+ approval_channel: ApprovalChannelConfig;
419
241
  }
420
- /** A non-interactive ZK proof of knowledge of a commitment's opening */
421
- interface ZKProofOfKnowledge {
422
- /** Proof type identifier */
423
- type: "schnorr-pedersen-ristretto255";
424
- /** The commitment this proof is for */
425
- commitment: string;
426
- /** Announcement point R (base64url) */
427
- announcement: string;
428
- /** Response scalar s_v (base64url) */
429
- response_v: string;
430
- /** Response scalar s_b (base64url) */
431
- response_b: string;
432
- /** Proof generated at */
433
- generated_at: string;
242
+ /** Approval request sent to the human */
243
+ interface ApprovalRequest {
244
+ operation: string;
245
+ tier: 1 | 2;
246
+ reason: string;
247
+ context: Record<string, unknown>;
248
+ timestamp: string;
434
249
  }
435
- /** A ZK range proof: proves value ∈ [min, max] */
436
- interface ZKRangeProof {
437
- /** Proof type identifier */
438
- type: "range-pedersen-ristretto255";
439
- /** The commitment this proof is for */
440
- commitment: string;
441
- /** Minimum value (inclusive) */
442
- min: number;
443
- /** Maximum value (inclusive) */
444
- max: number;
445
- /** Bit commitments for the shifted value (v - min) */
446
- bit_commitments: string[];
447
- /** Proofs that each bit commitment is 0 or 1 */
448
- bit_proofs: Array<{
449
- announcement_0: string;
450
- announcement_1: string;
451
- challenge_0: string;
452
- challenge_1: string;
453
- response_0: string;
454
- response_1: string;
455
- }>;
456
- /** Sum proof: bit commitments sum to the value commitment */
457
- sum_proof: {
458
- announcement: string;
459
- response: string;
460
- };
461
- /** Proof generated at */
462
- generated_at: string;
250
+ /** Approval response from the human */
251
+ interface ApprovalResponse {
252
+ decision: "approve" | "deny";
253
+ decided_at: string;
254
+ decided_by: "human" | "timeout" | "auto" | "stderr:non-interactive";
255
+ }
256
+ /** Result of the approval gate evaluation */
257
+ interface GateResult {
258
+ allowed: boolean;
259
+ tier: 1 | 2 | 3;
260
+ reason: string;
261
+ approval_required: boolean;
262
+ approval_response?: ApprovalResponse;
263
+ }
264
+ /** Behavioral baseline for anomaly detection */
265
+ interface SessionProfile {
266
+ /** Namespaces accessed (read or write) */
267
+ known_namespaces: string[];
268
+ /** Counterparty DIDs seen in reputation operations */
269
+ known_counterparties: string[];
270
+ /** Tool call counts per tool name (lifetime in session) */
271
+ tool_call_counts: Record<string, number>;
272
+ /** Whether this is the first session (no prior baseline) */
273
+ is_first_session: boolean;
274
+ /** Session start time */
275
+ started_at: string;
276
+ /** When the baseline was last saved */
277
+ saved_at?: string;
463
278
  }
279
+
464
280
  /**
465
- * Create a Pedersen commitment to a numeric value.
466
- *
467
- * C = v*G + b*H
468
- *
469
- * Properties:
470
- * - Computationally hiding (under discrete log assumption)
471
- * - Perfectly binding (information-theoretic)
472
- * - Homomorphic: C(v1) + C(v2) = C(v1+v2) with adjusted blinding
281
+ * Sanctuary MCP Server Approval Channel
473
282
  *
474
- * @param value - The value to commit to (integer)
475
- * @returns The commitment and blinding factor
476
- */
477
- declare function createPedersenCommitment(value: number): PedersenCommitment;
478
- /**
479
- * Verify a Pedersen commitment against a revealed value and blinding factor.
283
+ * Out-of-band communication with the human principal for operation approval.
284
+ * The default channel uses stderr (outside MCP's stdin/stdout protocol),
285
+ * ensuring the agent cannot intercept or forge approval responses.
480
286
  *
481
- * Recomputes C' = v*G + b*H and checks C' == C.
287
+ * Security invariant:
288
+ * - Approval prompts go through a channel the agent cannot access.
289
+ * - Timeouts result in denial by default (fail closed).
482
290
  */
483
- declare function verifyPedersenCommitment(commitment: string, value: number, blindingFactor: string): boolean;
291
+
292
+ /** Abstract approval channel interface */
293
+ interface ApprovalChannel {
294
+ requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
295
+ }
484
296
  /**
485
- * Create a non-interactive ZK proof that you know the opening (v, b)
486
- * of a Pedersen commitment C = v*G + b*H.
487
- *
488
- * Schnorr sigma protocol with Fiat-Shamir transform:
489
- * 1. Pick random r_v, r_b
490
- * 2. Compute R = r_v*G + r_b*H (announcement)
491
- * 3. Compute e = H_FS(C || R) (challenge via Fiat-Shamir)
492
- * 4. Compute s_v = r_v + e*v, s_b = r_b + e*b (responses)
493
- * 5. Proof = (R, s_v, s_b)
297
+ * Stderr approval channel — non-interactive informational channel.
494
298
  *
495
- * Zero-knowledge: the transcript (R, e, s_v, s_b) can be simulated
496
- * without knowing (v, b), so it reveals nothing.
299
+ * In the MCP stdio model:
300
+ * - stdin/stdout carry the MCP protocol (JSON-RPC)
301
+ * - stderr is available for out-of-band human communication
497
302
  *
498
- * @param value - The committed value
499
- * @param blindingFactor - The blinding factor (base64url)
500
- * @param commitment - The commitment (base64url)
501
- */
502
- declare function createProofOfKnowledge(value: number, blindingFactor: string, commitment: string): ZKProofOfKnowledge;
503
- /**
504
- * Verify a ZK proof of knowledge of a commitment's opening.
303
+ * Because stdin is consumed by the MCP JSON-RPC transport, this channel
304
+ * CANNOT read interactive human input. It is strictly informational:
305
+ * the prompt is displayed so the human sees what is happening, and the
306
+ * operation is denied immediately.
505
307
  *
506
- * Check: s_v*G + s_b*H == R + e*C
308
+ * SEC-002 + SEC-016 invariants:
309
+ * - This channel ALWAYS denies. No configuration can change this.
310
+ * - There is no timeout or async delay — denial is synchronous.
311
+ * - The `auto_deny` config field is ignored (SEC-002).
312
+ * - For interactive approval, use the dashboard or webhook channel.
507
313
  */
508
- declare function verifyProofOfKnowledge(proof: ZKProofOfKnowledge): boolean;
314
+ declare class StderrApprovalChannel implements ApprovalChannel {
315
+ constructor(_config: ApprovalChannelConfig);
316
+ requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
317
+ private formatPrompt;
318
+ }
509
319
  /**
510
- * Create a ZK range proof: prove value [min, max] without revealing value.
511
- *
512
- * Approach: bit-decomposition of (value - min) into n bits where 2^n > max - min.
513
- * Each bit gets a Pedersen commitment and a proof it's 0 or 1.
514
- * A sum proof shows the bit commitments reconstruct the original commitment
515
- * (shifted by min).
516
- *
517
- * @param value - The committed value
518
- * @param blindingFactor - The blinding factor (base64url)
519
- * @param commitment - The commitment (base64url)
520
- * @param min - Minimum value (inclusive)
521
- * @param max - Maximum value (inclusive)
320
+ * Programmatic approval channel for testing and API integration.
522
321
  */
523
- declare function createRangeProof(value: number, blindingFactor: string, commitment: string, min: number, max: number): ZKRangeProof | {
524
- error: string;
525
- };
322
+ declare class CallbackApprovalChannel implements ApprovalChannel {
323
+ private callback;
324
+ constructor(callback: (request: ApprovalRequest) => Promise<ApprovalResponse>);
325
+ requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
326
+ }
526
327
  /**
527
- * Verify a ZK range proof.
328
+ * Auto-approve channel for testing. Approves everything.
528
329
  */
529
- declare function verifyRangeProof(proof: ZKRangeProof): boolean;
330
+ declare class AutoApproveChannel implements ApprovalChannel {
331
+ requestApproval(_request: ApprovalRequest): Promise<ApprovalResponse>;
332
+ }
530
333
 
531
334
  /**
532
- * Sanctuary MCP Server — L3 Selective Disclosure: Disclosure Policies
533
- *
534
- * Disclosure policies define what an agent will and will not disclose
535
- * in different interaction contexts. Policies are evaluated against
536
- * incoming disclosure requests to produce per-field decisions.
335
+ * Sanctuary MCP Server — Behavioral Baseline Tracker
537
336
  *
538
- * This is the agent's "privacy preferences" layer it codifies the
539
- * human principal's intent about what information can flow where.
337
+ * Tracks the agent's behavioral profile during a session and persists
338
+ * it for cross-session anomaly detection. The baseline defines "normal"
339
+ * so that deviations can trigger Tier 2 approval.
540
340
  *
541
341
  * Security invariants:
542
- * - Policies are stored encrypted under L1 sovereignty
543
- * - Default action is always "withhold" unless explicitly overridden
544
- * - Policy evaluation is deterministic (same request same decision)
342
+ * - Baseline is stored encrypted under L1 sovereignty
343
+ * - Baseline changes are audit-logged
344
+ * - Baseline is integrity-verified via L1 Merkle tree
345
+ * - No MCP tool can directly modify the baseline
545
346
  */
546
347
 
547
- /** A single disclosure rule within a policy */
548
- interface DisclosureRule {
549
- /** Interaction context this rule applies to */
550
- context: string;
551
- /** Fields/claims the agent MAY disclose */
552
- disclose: string[];
553
- /** Fields/claims the agent MUST NOT disclose */
554
- withhold: string[];
555
- /** Fields that require proof rather than plain disclosure */
556
- proof_required: string[];
557
- }
558
- /** A complete disclosure policy */
559
- interface DisclosurePolicy {
560
- policy_id: string;
561
- policy_name: string;
562
- rules: DisclosureRule[];
563
- default_action: "withhold" | "ask-principal";
564
- identity_id?: string;
565
- created_at: string;
566
- updated_at: string;
567
- }
568
- /**
569
- * Policy store — manages disclosure policies encrypted under L1 sovereignty.
570
- */
571
- declare class PolicyStore {
348
+ declare class BaselineTracker {
572
349
  private storage;
573
350
  private encryptionKey;
574
- private policies;
351
+ private profile;
352
+ /** Sliding window: timestamps of tool calls per tool name (last 60s) */
353
+ private callWindows;
354
+ /** Sliding window: read counts per namespace (last 60s) */
355
+ private readWindows;
356
+ /** Sliding window: sign call timestamps (last 60s) */
357
+ private signWindow;
575
358
  constructor(storage: StorageBackend, masterKey: Uint8Array);
576
359
  /**
577
- * Create and store a new disclosure policy.
360
+ * Load the previous session's baseline from storage.
361
+ * If none exists, this is a first session.
578
362
  */
579
- create(policyName: string, rules: DisclosureRule[], defaultAction: "withhold" | "ask-principal", identityId?: string): Promise<DisclosurePolicy>;
363
+ load(): Promise<void>;
580
364
  /**
581
- * Get a policy by ID.
365
+ * Save the current baseline to storage (encrypted).
366
+ * Called at session end or periodically.
582
367
  */
583
- get(policyId: string): Promise<DisclosurePolicy | null>;
368
+ save(): Promise<void>;
584
369
  /**
585
- * List all policies.
370
+ * Record a tool call for baseline tracking.
371
+ * Returns anomaly information if applicable.
586
372
  */
587
- list(): Promise<DisclosurePolicy[]>;
373
+ recordToolCall(toolName: string): void;
588
374
  /**
589
- * Load all persisted policies into memory.
375
+ * Record a namespace access.
376
+ * @returns true if this is a new namespace (not in baseline)
590
377
  */
591
- private loadAll;
592
- private persist;
378
+ recordNamespaceAccess(namespace: string): boolean;
379
+ /**
380
+ * Record a namespace read for bulk-read detection.
381
+ * @returns the number of reads in the current 60-second window
382
+ */
383
+ recordNamespaceRead(namespace: string): number;
384
+ /**
385
+ * Record a counterparty DID interaction.
386
+ * @returns true if this is a new counterparty (not in baseline)
387
+ */
388
+ recordCounterparty(did: string): boolean;
389
+ /**
390
+ * Record a signing operation.
391
+ * @returns the number of signs in the current 60-second window
392
+ */
393
+ recordSign(): number;
394
+ /**
395
+ * Get the current call rate for a tool (calls per minute).
396
+ */
397
+ getCallRate(toolName: string): number;
398
+ /**
399
+ * Get the average call rate across all tools in the baseline.
400
+ */
401
+ getAverageCallRate(): number;
402
+ /** Whether this is the first session */
403
+ get isFirstSession(): boolean;
404
+ /** Get a read-only view of the current profile */
405
+ getProfile(): SessionProfile;
593
406
  }
594
407
 
595
408
  /**
596
- * Sanctuary MCP Server — Ed25519 Identity Management
597
- *
598
- * Sovereign identity based on Ed25519 keypairs.
599
- * Private keys are always encrypted at rest — never stored in plaintext.
409
+ * Sanctuary MCP Server — Prompt Injection Detection Layer
600
410
  *
601
- * Security invariants:
602
- * - Private keys never appear in any MCP tool response
603
- * - Private keys are encrypted with identity-specific keys derived from the master key
604
- * - Key rotation produces a signed rotation event (verifiable chain)
605
- */
606
-
607
- /** Public identity information (safe to share) */
608
- interface PublicIdentity {
609
- identity_id: string;
610
- label: string;
611
- public_key: string;
612
- did: string;
613
- created_at: string;
614
- key_type: "ed25519";
615
- key_protection: "passphrase" | "hardware-key" | "recovery-key";
616
- }
617
- /** Stored identity (private key is encrypted) */
618
- interface StoredIdentity extends PublicIdentity {
619
- encrypted_private_key: EncryptedPayload;
620
- /** Previous public keys (for rotation chain verification) */
621
- rotation_history: Array<{
622
- old_public_key: string;
623
- new_public_key: string;
624
- rotation_event: string;
625
- rotated_at: string;
626
- }>;
627
- }
628
-
629
- /**
630
- * Sanctuary MCP Server — Sovereignty Health Report (SHR) Types
411
+ * Fast, zero-dependency detection of common prompt injection patterns.
412
+ * Scans tool arguments for role override, security bypass, encoding evasion,
413
+ * data exfiltration, and prompt stuffing signals.
631
414
  *
632
- * Machine-readable, signed, versioned sovereignty capability advertisement.
633
- * An agent presents its SHR to counterparties to prove its sovereignty posture.
634
- * The SHR is signed by one of the instance's Ed25519 identities and can be
635
- * independently verified by any party without trusting the presenter.
415
+ * SEC-034/SEC-035: Enhanced with Unicode sanitization pre-pass, decoded content
416
+ * re-scanning, token budget analysis, and outbound content scanning.
636
417
  *
637
- * SHR version: 1.0
418
+ * Security invariants:
419
+ * - Always returns a result, never throws
420
+ * - Typical scan completes in < 5ms
421
+ * - False positives minimized via field-aware scanning
422
+ * - Recursive scanning of nested objects/arrays
423
+ * - Outbound scanning catches secret leaks and injection artifact survival
638
424
  */
639
- type LayerStatus = "active" | "degraded" | "inactive";
640
- type DegradationSeverity = "info" | "warning" | "critical";
641
- type DegradationCode = "NO_TEE" | "PROCESS_ISOLATION_ONLY" | "COMMITMENT_ONLY" | "NO_ZK_PROOFS" | "SELF_REPORTED_ATTESTATION" | "NO_SELECTIVE_DISCLOSURE" | "BASIC_SYBIL_ONLY";
642
- interface SHRLayerL1 {
643
- status: LayerStatus;
644
- encryption: string;
645
- key_custody: "self" | "delegated" | "platform";
646
- integrity: string;
647
- identity_type: string;
648
- state_portable: boolean;
649
- }
650
- interface SHRLayerL2 {
651
- status: LayerStatus;
652
- isolation_type: string;
653
- attestation_available: boolean;
654
- /** Model provenance: what inference model(s) power this agent */
655
- model_provenance?: {
656
- model_id: string;
657
- model_name: string;
658
- provider: string;
659
- open_weights: boolean;
660
- open_source: boolean;
661
- local_inference: boolean;
662
- weights_hash?: string;
663
- };
664
- }
665
- interface SHRLayerL3 {
666
- status: LayerStatus;
667
- proof_system: string;
668
- selective_disclosure: boolean;
669
- }
670
- interface SHRLayerL4 {
671
- status: LayerStatus;
672
- reputation_mode: string;
673
- attestation_format: string;
674
- reputation_portable: boolean;
425
+ interface InjectionDetectorConfig {
426
+ enabled: boolean;
427
+ sensitivity: "low" | "medium" | "high";
428
+ on_detection: "escalate" | "block" | "log";
429
+ custom_patterns?: string[];
675
430
  }
676
- interface SHRDegradation {
677
- layer: "l1" | "l2" | "l3" | "l4";
678
- code: DegradationCode;
679
- severity: DegradationSeverity;
680
- description: string;
681
- mitigation?: string;
431
+ interface InjectionSignal {
432
+ type: string;
433
+ pattern: string;
434
+ location: string;
435
+ severity: "low" | "medium" | "high";
682
436
  }
683
- interface SHRCapabilities {
684
- handshake: boolean;
685
- shr_exchange: boolean;
686
- reputation_verify: boolean;
687
- encrypted_channel: boolean;
437
+ interface DetectionResult {
438
+ flagged: boolean;
439
+ confidence: number;
440
+ signals: InjectionSignal[];
441
+ recommendation: "allow" | "escalate" | "block";
688
442
  }
689
- /**
690
- * The SHR body — the content that gets signed.
691
- * Canonical form: JSON with sorted keys, no whitespace.
692
- */
693
- interface SHRBody {
694
- shr_version: "1.0";
695
- implementation: {
696
- sanctuary_version: string;
697
- node_version: string;
698
- generated_by: string;
699
- };
700
- instance_id: string;
701
- generated_at: string;
702
- expires_at: string;
703
- layers: {
704
- l1: SHRLayerL1;
705
- l2: SHRLayerL2;
706
- l3: SHRLayerL3;
707
- l4: SHRLayerL4;
443
+ declare class InjectionDetector {
444
+ private config;
445
+ private stats;
446
+ constructor(config?: Partial<InjectionDetectorConfig>);
447
+ /**
448
+ * Scan tool arguments for injection signals.
449
+ * @param toolName Full tool name (e.g., "state_read")
450
+ * @param args Tool arguments
451
+ * @returns DetectionResult with all detected signals
452
+ */
453
+ scan(toolName: string, args: Record<string, unknown>): DetectionResult;
454
+ /**
455
+ * SEC-035: Scan outbound content for secret leaks, data exfiltration,
456
+ * internal path exposure, and injection artifact survival.
457
+ *
458
+ * @param content The outbound content string to scan
459
+ * @returns DetectionResult with outbound-specific signal types
460
+ */
461
+ scanOutbound(content: string): DetectionResult;
462
+ /**
463
+ * Recursively scan a value and all nested values.
464
+ */
465
+ private scanValue;
466
+ /**
467
+ * Scan a single string for injection signals.
468
+ */
469
+ private scanString;
470
+ /**
471
+ * Count invisible Unicode characters in a string.
472
+ * Includes zero-width chars, soft hyphens, directional marks,
473
+ * variation selectors, and other invisible categories.
474
+ */
475
+ private countInvisibleChars;
476
+ /**
477
+ * Strip invisible characters from a string for clean pattern matching.
478
+ * Returns a new string with all invisible chars removed.
479
+ */
480
+ private stripInvisibleChars;
481
+ /**
482
+ * SEC-034: Token budget attack detection.
483
+ * Some Unicode sequences expand dramatically during tokenization (e.g., CJK
484
+ * ideographs, combining characters, emoji sequences). If the estimated token
485
+ * cost per character is anomalously high, this may be a wallet-drain payload.
486
+ *
487
+ * Heuristic: count chars that typically tokenize into multiple tokens.
488
+ * If the ratio of estimated tokens to char count exceeds 3x, flag it.
489
+ */
490
+ private detectTokenBudgetAttack;
491
+ /**
492
+ * Detect encoded content (base64, hex, HTML entities, URL encoding),
493
+ * decode it, and re-scan the decoded content through injection patterns.
494
+ * If the decoded content contains injection patterns, flag as encoding_evasion.
495
+ */
496
+ private detectEncodedPayloads;
497
+ /**
498
+ * Check if a string contains any injection patterns (role override or security bypass).
499
+ */
500
+ private containsInjectionPatterns;
501
+ /**
502
+ * Safely decode a base64 string. Returns null if it's not valid base64
503
+ * or doesn't decode to a meaningful string.
504
+ */
505
+ private safeBase64Decode;
506
+ /**
507
+ * Safely decode a hex string. Returns null on failure.
508
+ */
509
+ private safeHexDecode;
510
+ /**
511
+ * Decode HTML numeric entities (&#xHH; and &#DDD;) in a string.
512
+ */
513
+ private decodeHtmlEntities;
514
+ /**
515
+ * Safely decode a URL-encoded string. Returns null on failure.
516
+ */
517
+ private safeUrlDecode;
518
+ /**
519
+ * Heuristic: does this look like readable text (vs. binary garbage)?
520
+ * Checks that most characters are printable ASCII or common Unicode.
521
+ */
522
+ private looksLikeText;
523
+ /**
524
+ * Detect API keys and secrets in outbound content.
525
+ */
526
+ private detectSecretPatterns;
527
+ /**
528
+ * Detect data exfiltration via markdown images with data-carrying query params.
529
+ */
530
+ private detectOutboundExfiltration;
531
+ /**
532
+ * Detect internal filesystem path leaks in outbound content.
533
+ */
534
+ private detectInternalPathLeaks;
535
+ /**
536
+ * Detect private IP addresses and localhost references in outbound content.
537
+ */
538
+ private detectPrivateNetworkLeaks;
539
+ /**
540
+ * Detect role markers / prompt template artifacts in outbound content.
541
+ * These should never appear in agent output — their presence indicates
542
+ * injection artifact survival.
543
+ */
544
+ private detectOutputRoleMarkers;
545
+ /**
546
+ * Detect base64 strings, base64url, and zero-width character evasion.
547
+ */
548
+ private detectEncodingEvasion;
549
+ /**
550
+ * Detect URLs and emails in fields that shouldn't have them.
551
+ */
552
+ private detectDataExfiltration;
553
+ /**
554
+ * Detect prompt stuffing: very large strings or high repetition.
555
+ */
556
+ private detectPromptStuffing;
557
+ /**
558
+ * Determine if this field is inherently safe from role override.
559
+ */
560
+ private isSafeField;
561
+ /**
562
+ * Determine if this is a tool name field (where tool refs are expected).
563
+ */
564
+ private isToolNameField;
565
+ /**
566
+ * Determine if this field is safe for URLs.
567
+ */
568
+ private isUrlSafeField;
569
+ /**
570
+ * Determine if this field is safe for emails.
571
+ */
572
+ private isEmailSafeField;
573
+ /**
574
+ * Determine if this field is safe for structured data (JSON/XML).
575
+ */
576
+ private isStructuredField;
577
+ /**
578
+ * SEC-032/SEC-034: Map common cross-script confusable characters to their
579
+ * Latin equivalents. NFKC normalization handles fullwidth and compatibility
580
+ * forms, but does NOT map Cyrillic/Greek/Armenian/Georgian lookalikes to
581
+ * Latin (they're distinct codepoints by design).
582
+ *
583
+ * Extended to 50+ confusable pairs covering Cyrillic, Greek, Armenian,
584
+ * Georgian, Cherokee, and mathematical/symbol lookalikes.
585
+ */
586
+ private normalizeConfusables;
587
+ /**
588
+ * Compute confidence score based on signals.
589
+ * More high-severity signals = higher confidence.
590
+ */
591
+ private computeConfidence;
592
+ /**
593
+ * Compute recommendation based on signals and sensitivity.
594
+ */
595
+ private computeRecommendation;
596
+ /**
597
+ * Get statistics about scans performed.
598
+ */
599
+ getStats(): {
600
+ total_scans: number;
601
+ total_flags: number;
602
+ total_blocks: number;
603
+ signals_by_type: Record<string, number>;
708
604
  };
709
- capabilities: SHRCapabilities;
710
- degradations: SHRDegradation[];
711
- }
712
- /**
713
- * The complete signed SHR — body + signature envelope.
714
- */
715
- interface SignedSHR {
716
- body: SHRBody;
717
- signed_by: string;
718
- signature: string;
719
- }
720
- interface SHRVerificationResult {
721
- valid: boolean;
722
- errors: string[];
723
- warnings: string[];
724
- sovereignty_level: "full" | "degraded" | "minimal";
725
- counterparty_id: string;
726
- expires_at: string;
727
- }
728
-
729
- /**
730
- * Sanctuary MCP Server — Sovereignty Handshake Types
731
- *
732
- * The sovereignty handshake is a mutual verification protocol between
733
- * two Sanctuary instances. Each party presents its SHR and proves
734
- * liveness via nonce challenge-response.
735
- *
736
- * Protocol:
737
- * A → B: HandshakeChallenge (A's SHR + nonce)
738
- * B → A: HandshakeResponse (B's SHR + B's nonce + signature over A's nonce)
739
- * A → B: HandshakeCompletion (signature over B's nonce)
740
- * Result: Both hold a HandshakeResult with verified counterparty status
741
- */
742
-
743
- /** Trust tier derived from sovereignty handshake */
744
- type TrustTier = "verified-sovereign" | "verified-degraded" | "unverified";
745
- /** Sovereignty level from SHR assessment */
746
- type SovereigntyLevel = "full" | "degraded" | "minimal" | "unverified";
747
- /**
748
- * Step 1: Initiator sends challenge
749
- */
750
- interface HandshakeChallenge {
751
- protocol_version: "1.0";
752
- shr: SignedSHR;
753
- nonce: string;
754
- initiated_at: string;
755
- }
756
- /**
757
- * Step 2: Responder sends response
758
- */
759
- interface HandshakeResponse {
760
- protocol_version: "1.0";
761
- shr: SignedSHR;
762
- responder_nonce: string;
763
- initiator_nonce_signature: string;
764
- responded_at: string;
765
- }
766
- /**
767
- * Step 3: Initiator sends completion
768
- */
769
- interface HandshakeCompletion {
770
- protocol_version: "1.0";
771
- responder_nonce_signature: string;
772
- completed_at: string;
773
- }
774
- /**
775
- * Final result: both parties hold this after a successful handshake
776
- */
777
- interface HandshakeResult {
778
- counterparty_id: string;
779
- counterparty_shr: SignedSHR;
780
- verified: boolean;
781
- sovereignty_level: SovereigntyLevel;
782
- trust_tier: TrustTier;
783
- completed_at: string;
784
- expires_at: string;
785
- errors: string[];
786
- }
787
- /**
788
- * In-progress handshake state (stored on initiator side)
789
- */
790
- interface HandshakeSession {
791
- session_id: string;
792
- role: "initiator" | "responder";
793
- state: "initiated" | "responded" | "completed" | "failed";
794
- our_nonce: string;
795
- their_nonce?: string;
796
- our_shr: SignedSHR;
797
- their_shr?: SignedSHR;
798
- initiated_at: string;
799
- result?: HandshakeResult;
605
+ /**
606
+ * Reset statistics.
607
+ */
608
+ resetStats(): void;
800
609
  }
801
610
 
802
611
  /**
803
- * Sanctuary MCP Server — Sovereignty-Gated Reputation Tiers
612
+ * Sanctuary MCP Server — Approval Gate
804
613
  *
805
- * Attestations carry a sovereignty_tier field reflecting the signer's
806
- * sovereignty posture at the time of recording. When querying or evaluating
807
- * reputation, attestations from verified-sovereign agents carry more weight
808
- * than those from unverified agents.
614
+ * The three-tier approval gate sits between the MCP router and tool handlers.
615
+ * Every tool call passes through the gate before execution.
809
616
  *
810
- * Tier hierarchy (descending credibility):
811
- * 1. "verified-sovereign" — signer completed a handshake with full sovereignty
812
- * 2. "verified-degraded" — signer completed a handshake with degraded sovereignty
813
- * 3. "self-attested" — signer has a Sanctuary identity but no handshake verification
814
- * 4. "unverified" — no Sanctuary identity or sovereignty proof
617
+ * Evaluation order:
618
+ * 1. Tier 1: Is this operation in the always-approve list? → Request approval.
619
+ * 2. Tier 2: Does this call represent a behavioral anomaly? Request approval.
620
+ * 3. Tier 3 / default: Allow with audit logging.
815
621
  *
816
- * Weight multipliers are applied during reputation scoring. They are NOT
817
- * gatekeepingunverified attestations still count, just less.
622
+ * Security invariants:
623
+ * - The gate cannot be bypassed it wraps every tool handler.
624
+ * - Denial responses do not reveal policy details to the agent.
625
+ * - All gate decisions (approve, deny, allow) are audit-logged.
818
626
  */
819
627
 
820
- type SovereigntyTier = "verified-sovereign" | "verified-degraded" | "self-attested" | "unverified";
821
- /** Weight multipliers for each tier */
822
- declare const TIER_WEIGHTS: Record<SovereigntyTier, number>;
823
- /** Tier metadata embedded in attestations */
824
- interface TierMetadata {
825
- sovereignty_tier: SovereigntyTier;
826
- /** If verified, the handshake that established it */
827
- handshake_completed_at?: string;
828
- /** Counterparty ID from handshake (if applicable) */
829
- verified_by?: string;
628
+ /** Callback invoked when an injection is detected, for dashboard broadcasting */
629
+ type InjectionAlertCallback = (alert: {
630
+ toolName: string;
631
+ result: DetectionResult;
632
+ timestamp: string;
633
+ }) => void;
634
+ /** Resolver for proxy tool tiers provided by the ProxyRouter */
635
+ type ProxyTierResolver = (toolName: string) => (1 | 2 | 3) | null;
636
+ declare class ApprovalGate {
637
+ private policy;
638
+ private baseline;
639
+ private channel;
640
+ private auditLog;
641
+ private injectionDetector;
642
+ private onInjectionAlert?;
643
+ private proxyTierResolver?;
644
+ constructor(policy: PrincipalPolicy, baseline: BaselineTracker, channel: ApprovalChannel, auditLog: AuditLog, injectionDetector?: InjectionDetector, onInjectionAlert?: InjectionAlertCallback);
645
+ /**
646
+ * Set the proxy tier resolver. Called after the proxy router is initialized.
647
+ */
648
+ setProxyTierResolver(resolver: ProxyTierResolver): void;
649
+ /**
650
+ * Evaluate a tool call against the Principal Policy.
651
+ *
652
+ * @param toolName - Full MCP tool name (e.g., "state_export")
653
+ * @param args - Tool call arguments (for context extraction)
654
+ * @returns GateResult indicating whether the call is allowed
655
+ */
656
+ evaluate(toolName: string, args: Record<string, unknown>): Promise<GateResult>;
657
+ /**
658
+ * Detect Tier 2 behavioral anomalies.
659
+ */
660
+ private detectAnomaly;
661
+ /**
662
+ * Request approval from the human principal.
663
+ */
664
+ private requestApproval;
665
+ /**
666
+ * Summarize tool arguments for the approval prompt.
667
+ * Strips potentially large values to keep the prompt readable.
668
+ */
669
+ private summarizeArgs;
670
+ /** Get the baseline tracker for saving at session end */
671
+ getBaseline(): BaselineTracker;
672
+ /** Get the injection detector for stats/configuration access */
673
+ getInjectionDetector(): InjectionDetector;
830
674
  }
675
+
831
676
  /**
832
- * Resolve the sovereignty tier for a counterparty based on handshake history.
677
+ * Sanctuary MCP Server Tool Router
833
678
  *
834
- * @param counterpartyId - The counterparty's instance ID
835
- * @param handshakeResults - Map of counterparty ID most recent handshake result
836
- * @param hasSanctuaryIdentity - Whether the counterparty has a known Sanctuary identity
837
- * @returns TierMetadata for embedding in attestations
679
+ * Routes sanctuary/* tool calls to their layer-specific handlers.
680
+ * Every tool call passes through schema validation and the ApprovalGate
681
+ * (if configured) before execution. Neither can be bypassed.
682
+ *
683
+ * This module is the abstraction boundary for MCP SDK version migration —
684
+ * if the SDK API changes, only this module needs updating.
838
685
  */
839
- declare function resolveTier(counterpartyId: string, handshakeResults: Map<string, HandshakeResult>, hasSanctuaryIdentity: boolean): TierMetadata;
840
- /** An attestation with its tier for weighted scoring */
841
- interface TieredAttestation {
842
- /** The raw metric value */
843
- value: number;
844
- /** The sovereignty tier of the attestation signer */
845
- tier: SovereigntyTier;
686
+
687
+ /** Tool handler function signature */
688
+ type ToolHandler = (args: Record<string, unknown>) => Promise<{
689
+ content: Array<{
690
+ type: "text";
691
+ text: string;
692
+ }>;
693
+ }>;
694
+ /** Tool definition for registration */
695
+ interface ToolDefinition {
696
+ name: string;
697
+ description: string;
698
+ inputSchema: Record<string, unknown>;
699
+ handler: ToolHandler;
846
700
  }
701
+
847
702
  /**
848
- * Compute a weighted reputation score from tiered attestations.
703
+ * Sanctuary MCP Server AES-256-GCM Encryption
849
704
  *
850
- * Each attestation's contribution is multiplied by its tier weight.
851
- * The result is normalized by total weight (not count), so adding
852
- * low-tier attestations doesn't dilute high-tier ones.
705
+ * All state encryption in Sanctuary uses AES-256-GCM (authenticated encryption).
706
+ * This provides both confidentiality and integrity a modified ciphertext will
707
+ * fail authentication, detecting tampering.
853
708
  *
854
- * @param attestations - Array of value + tier pairs
855
- * @returns Weighted score, or null if no attestations
856
- */
857
- declare function computeWeightedScore(attestations: TieredAttestation[]): number | null;
858
- /**
859
- * Compute a tier distribution summary for a set of attestations.
709
+ * Security invariants:
710
+ * - Every encryption uses a unique 12-byte IV (NIST SP 800-38D)
711
+ * - The 16-byte authentication tag is always verified on decryption
712
+ * - Keys are 256 bits (32 bytes)
860
713
  */
861
- declare function tierDistribution(tiers: SovereigntyTier[]): Record<SovereigntyTier, number>;
714
+ /** Encrypted payload structure stored on disk */
715
+ interface EncryptedPayload {
716
+ /** Format version */
717
+ v: number;
718
+ /** Algorithm identifier */
719
+ alg: "aes-256-gcm";
720
+ /** Initialization vector (base64url) */
721
+ iv: string;
722
+ /** Ciphertext (base64url) */
723
+ ct: string;
724
+ /** Authentication tag (base64url) — included in ciphertext by @noble/ciphers */
725
+ /** Timestamp */
726
+ ts: string;
727
+ }
862
728
 
863
729
  /**
864
- * Sanctuary MCP Server — L4 Verifiable Reputation: Reputation Store
865
- *
866
- * Records interaction outcomes as signed attestations, queries aggregated
867
- * reputation data, and supports export/import for cross-platform portability.
730
+ * Sanctuary MCP Server — L1 Cognitive Sovereignty: StateStore
868
731
  *
869
- * Attestation format is EAS-compatible (Ethereum Attestation Service) to
870
- * enable future on-chain anchoring without requiring blockchain for MVS.
732
+ * The encrypted state store is the foundation of Sanctuary.
733
+ * Every read and write goes through here. All data is encrypted
734
+ * with namespace-specific keys. All writes are signed by an identity.
735
+ * All reads verify integrity via Merkle proofs.
871
736
  *
872
737
  * Security invariants:
873
- * - All attestations are signed by the recording identity
874
- * - Attestations are stored encrypted under L1 sovereignty
875
- * - Reputation queries return aggregates, never raw interaction data
876
- * - Export bundles include all signatures for independent verification
877
- * - Import verifies every signature before accepting attestations
738
+ * - Plaintext never touches the filesystem
739
+ * - Every write gets a unique IV
740
+ * - Every write is signed (non-repudiation)
741
+ * - Monotonic version numbers prevent rollback
742
+ * - Merkle tree verifies namespace integrity
743
+ * - Secure deletion overwrites before unlinking
878
744
  */
879
745
 
880
- /** Interaction outcome for recording */
881
- interface InteractionOutcome {
882
- type: "transaction" | "negotiation" | "service" | "dispute" | "custom";
883
- result: "completed" | "partial" | "failed" | "disputed";
884
- metrics?: Record<string, number>;
885
- }
886
- /** A signed attestation of an interaction */
887
- interface Attestation {
888
- attestation_id: string;
889
- schema: "sanctuary-interaction-v1";
890
- data: {
891
- interaction_id: string;
892
- participant_did: string;
893
- counterparty_did: string;
894
- outcome_type: string;
895
- outcome_result: string;
896
- metrics: Record<string, number>;
897
- context: string;
898
- timestamp: string;
899
- /** Sovereignty tier of the signer at time of recording */
900
- sovereignty_tier?: SovereigntyTier;
901
- };
902
- signature: string;
903
- signer: string;
904
- }
905
- /** Stored attestation (encrypted at rest) */
906
- interface StoredAttestation {
907
- attestation: Attestation;
908
- counterparty_attestation?: string;
909
- counterparty_confirmed: boolean;
910
- recorded_at: string;
911
- }
912
- /** Aggregated metric statistics */
913
- interface MetricAggregate {
914
- mean: number;
915
- median: number;
916
- min: number;
917
- max: number;
918
- count: number;
919
- }
920
- /** Reputation query result */
921
- interface ReputationSummary {
922
- total_interactions: number;
923
- completed: number;
924
- partial: number;
925
- failed: number;
926
- disputed: number;
927
- contexts: string[];
928
- time_range: {
929
- start: string;
930
- end: string;
931
- };
932
- aggregate_metrics: Record<string, MetricAggregate>;
933
- }
934
- /** Portable reputation bundle */
935
- interface ReputationBundle {
936
- version: "SANCTUARY_REP_V1";
937
- attestations: Attestation[];
938
- exported_at: string;
939
- exporter_did: string;
940
- bundle_signature: string;
746
+ /** Result of a state write operation */
747
+ interface WriteResult {
748
+ key: string;
749
+ namespace: string;
750
+ version: number;
751
+ merkle_root: string;
752
+ written_at: string;
753
+ size_bytes: number;
754
+ integrity_hash: string;
941
755
  }
942
- /** Escrow for trust bootstrapping */
943
- interface Escrow {
944
- escrow_id: string;
945
- transaction_terms: string;
946
- terms_hash: string;
947
- collateral_amount?: number;
948
- counterparty_did: string;
949
- creator_did: string;
950
- created_at: string;
951
- expires_at: string;
952
- status: "pending" | "active" | "released" | "disputed" | "expired";
756
+ /** Result of a state read operation */
757
+ interface ReadResult {
758
+ key: string;
759
+ namespace: string;
760
+ value: string;
761
+ version: number;
762
+ integrity_verified: boolean;
763
+ merkle_proof: string[];
764
+ written_at: string;
765
+ written_by: string;
953
766
  }
954
- /** Principal guarantee for a new agent */
955
- interface Guarantee {
956
- guarantee_id: string;
957
- principal_did: string;
958
- agent_did: string;
959
- scope: string;
960
- max_liability?: number;
961
- valid_until: string;
962
- certificate: string;
963
- created_at: string;
767
+ /** Options for state write */
768
+ interface WriteOptions {
769
+ content_type?: string;
770
+ ttl_seconds?: number;
771
+ tags?: string[];
964
772
  }
965
- declare class ReputationStore {
773
+ declare class StateStore {
966
774
  private storage;
967
- private encryptionKey;
775
+ private masterKey;
776
+ private versionCache;
777
+ private contentHashes;
778
+ private namespaceKeyCache;
779
+ private static readonly KEY_CACHE_TTL_MS;
780
+ private static readonly KEY_CACHE_MAX_ENTRIES;
968
781
  constructor(storage: StorageBackend, masterKey: Uint8Array);
969
782
  /**
970
- * Record an interaction outcome as a signed attestation.
783
+ * Get or derive a namespace encryption key, with caching.
784
+ * Cache entries expire after 15 minutes and are evicted LRU when
785
+ * the cache exceeds 128 entries.
971
786
  */
972
- record(interactionId: string, counterpartyDid: string, outcome: InteractionOutcome, context: string, identity: StoredIdentity, identityEncryptionKey: Uint8Array, counterpartyAttestation?: string, sovereigntyTier?: SovereigntyTier): Promise<StoredAttestation>;
787
+ private getNamespaceKey;
788
+ /** Invalidate all cached namespace keys (call on master key rotation). */
789
+ invalidateKeyCache(): void;
790
+ private versionKey;
973
791
  /**
974
- * Query reputation data with filtering.
975
- * Returns aggregates only — not raw interaction data.
792
+ * Get or initialize the content hash map for a namespace.
976
793
  */
977
- query(options: {
978
- context?: string;
979
- time_range?: {
980
- start: string;
981
- end: string;
982
- };
983
- metrics?: string[];
984
- counterparty_did?: string;
985
- }): Promise<ReputationSummary>;
794
+ private getNamespaceHashes;
986
795
  /**
987
- * Export attestations as a portable reputation bundle.
796
+ * Write encrypted state.
797
+ *
798
+ * @param namespace - Logical grouping
799
+ * @param key - State key
800
+ * @param value - Plaintext value (will be encrypted)
801
+ * @param identityId - Identity performing the write
802
+ * @param encryptedPrivateKey - Identity's encrypted private key (for signing)
803
+ * @param identityEncryptionKey - Key to decrypt the identity's private key
804
+ * @param options - Optional metadata
988
805
  */
989
- exportBundle(identity: StoredIdentity, identityEncryptionKey: Uint8Array, context?: string): Promise<ReputationBundle>;
806
+ write(namespace: string, key: string, value: string, identityId: string, encryptedPrivateKey: EncryptedPayload, identityEncryptionKey: Uint8Array, options?: WriteOptions): Promise<WriteResult>;
990
807
  /**
991
- * Import attestations from a reputation bundle.
992
- * Verifies signatures if requested (default: true).
808
+ * Read and decrypt state.
993
809
  *
994
- * @param publicKeys - Map of DID → public key bytes for signature verification
810
+ * @param namespace - Logical grouping
811
+ * @param key - State key
812
+ * @param signerPublicKey - Expected signer's public key (for signature verification)
813
+ * @param verifyIntegrity - Whether to verify Merkle proof (default: true)
995
814
  */
996
- importBundle(bundle: ReputationBundle, verifySignatures: boolean, publicKeys: Map<string, Uint8Array>): Promise<{
997
- imported: number;
998
- invalid: number;
999
- contexts: string[];
1000
- }>;
815
+ read(namespace: string, key: string, signerPublicKey?: Uint8Array, verifyIntegrity?: boolean): Promise<ReadResult | null>;
1001
816
  /**
1002
- * Create an escrow for trust bootstrapping.
817
+ * List keys in a namespace (metadata only — no decryption).
1003
818
  */
1004
- createEscrow(transactionTerms: string, counterpartyDid: string, timeoutSeconds: number, creatorDid: string, collateralAmount?: number): Promise<Escrow>;
819
+ list(namespace: string, prefix?: string, tags?: string[], limit?: number, offset?: number): Promise<{
820
+ keys: Array<{
821
+ key: string;
822
+ version: number;
823
+ size_bytes: number;
824
+ written_at: string;
825
+ tags: string[];
826
+ }>;
827
+ total: number;
828
+ merkle_root: string;
829
+ }>;
1005
830
  /**
1006
- * Get an escrow by ID.
831
+ * Securely delete state (overwrite with random bytes before removal).
1007
832
  */
1008
- getEscrow(escrowId: string): Promise<Escrow | null>;
833
+ delete(namespace: string, key: string): Promise<{
834
+ deleted: boolean;
835
+ key: string;
836
+ namespace: string;
837
+ new_merkle_root: string;
838
+ deleted_at: string;
839
+ }>;
1009
840
  /**
1010
- * Create a principal's guarantee for a new agent.
841
+ * Export all state for a namespace as an encrypted bundle.
1011
842
  */
1012
- createGuarantee(principalIdentity: StoredIdentity, agentDid: string, scope: string, durationSeconds: number, identityEncryptionKey: Uint8Array, maxLiability?: number): Promise<Guarantee>;
843
+ export(namespace?: string): Promise<{
844
+ bundle: string;
845
+ namespaces: string[];
846
+ total_keys: number;
847
+ bundle_hash: string;
848
+ exported_at: string;
849
+ }>;
1013
850
  /**
1014
- * Load attestations for tier-weighted scoring.
1015
- * Applies basic context/counterparty filtering, returns full StoredAttestations
1016
- * so callers can access sovereignty_tier from attestation data.
851
+ * Import a previously exported state bundle.
1017
852
  */
1018
- loadAllForTierScoring(options?: {
1019
- context?: string;
1020
- counterparty_did?: string;
1021
- }): Promise<StoredAttestation[]>;
1022
- private loadAll;
853
+ import(bundleBase64: string, conflictResolution: "skip" | "overwrite" | "version" | undefined, publicKeyResolver: (kid: string) => Uint8Array | null): Promise<{
854
+ imported_keys: number;
855
+ skipped_keys: number;
856
+ skipped_invalid_sig: number;
857
+ skipped_unknown_kid: number;
858
+ conflicts: number;
859
+ namespaces: string[];
860
+ imported_at: string;
861
+ }>;
1023
862
  }
1024
863
 
1025
864
  /**
1026
- * Sanctuary MCP Server — Federation Types
1027
- *
1028
- * MCP-to-MCP federation enables two Sanctuary instances to:
1029
- * 1. Discover each other's capabilities (SIM exchange)
1030
- * 2. Establish mutual trust (sovereignty handshake)
1031
- * 3. Exchange signed reputation attestations
1032
- * 4. Evaluate trust for cross-instance interactions
865
+ * Sanctuary MCP Server — Ed25519 Identity Management
1033
866
  *
1034
- * Federation operates as a protocol layer atop the handshake:
1035
- * Handshake establishes trust Federation uses that trust for ongoing operations.
867
+ * Sovereign identity based on Ed25519 keypairs.
868
+ * Private keys are always encrypted at rest never stored in plaintext.
1036
869
  *
1037
- * Key constraint: Federation MUST respect each party's sovereignty.
1038
- * Neither party can compel the other to share data they haven't disclosed
1039
- * via their disclosure policy.
870
+ * Security invariants:
871
+ * - Private keys never appear in any MCP tool response
872
+ * - Private keys are encrypted with identity-specific keys derived from the master key
873
+ * - Key rotation produces a signed rotation event (verifiable chain)
1040
874
  */
1041
875
 
1042
- /** A known federation peer */
1043
- interface FederationPeer {
1044
- /** The peer's instance ID (from their SHR) */
1045
- peer_id: string;
1046
- /** The peer's DID (identity) */
1047
- peer_did: string;
1048
- /** When this peer was first seen */
1049
- first_seen: string;
1050
- /** When last handshake completed */
1051
- last_handshake: string;
1052
- /** Current trust tier from most recent handshake */
1053
- trust_tier: SovereigntyTier;
1054
- /** Handshake result (for tier resolution) */
1055
- handshake_result: HandshakeResult;
1056
- /** Peer's advertised capabilities (from their SIM) */
1057
- capabilities: FederationCapabilities;
1058
- /** Whether we have a valid (non-expired) handshake */
1059
- active: boolean;
876
+ /** Public identity information (safe to share) */
877
+ interface PublicIdentity {
878
+ identity_id: string;
879
+ label: string;
880
+ public_key: string;
881
+ did: string;
882
+ created_at: string;
883
+ key_type: "ed25519";
884
+ key_protection: "passphrase" | "hardware-key" | "recovery-key";
1060
885
  }
1061
- /** Capabilities a peer advertises for federation */
1062
- interface FederationCapabilities {
1063
- /** Whether the peer supports reputation exchange */
1064
- reputation_exchange: boolean;
1065
- /** Whether the peer supports mutual attestation */
1066
- mutual_attestation: boolean;
1067
- /** Whether the peer supports encrypted channels */
1068
- encrypted_channel: boolean;
1069
- /** Supported attestation formats */
1070
- attestation_formats: string[];
886
+ /** Stored identity (private key is encrypted) */
887
+ interface StoredIdentity extends PublicIdentity {
888
+ encrypted_private_key: EncryptedPayload;
889
+ /** Previous public keys (for rotation chain verification) */
890
+ rotation_history: Array<{
891
+ old_public_key: string;
892
+ new_public_key: string;
893
+ rotation_event: string;
894
+ rotated_at: string;
895
+ }>;
1071
896
  }
1072
- /** Trust evaluation result for a federation peer */
1073
- interface PeerTrustEvaluation {
1074
- peer_id: string;
1075
- /** Current sovereignty tier (from handshake) */
1076
- sovereignty_tier: SovereigntyTier;
1077
- /** Whether handshake is current (not expired) */
1078
- handshake_current: boolean;
1079
- /** Reputation summary (if available) */
1080
- reputation_score?: number;
1081
- /** How many mutual attestations we share */
1082
- mutual_attestation_count: number;
1083
- /** Overall trust assessment */
1084
- trust_level: "high" | "medium" | "low" | "none";
1085
- /** Reasoning for the assessment */
1086
- factors: string[];
1087
- /** Evaluated at */
1088
- evaluated_at: string;
897
+
898
+ /**
899
+ * Sanctuary MCP Server — L1 Cognitive Sovereignty: Tool Definitions
900
+ *
901
+ * MCP tool wrappers for StateStore and IdentityRoot operations.
902
+ * These tools are the public API that agents interact with.
903
+ */
904
+
905
+ /** Manages all identities — provides storage and retrieval */
906
+ declare class IdentityManager {
907
+ private storage;
908
+ private masterKey;
909
+ private identities;
910
+ private primaryIdentityId;
911
+ private metadataKey;
912
+ constructor(storage: StorageBackend, masterKey: Uint8Array);
913
+ private get encryptionKey();
914
+ /** Load identities from storage on startup.
915
+ * Returns { total: number of encrypted files found, loaded: number successfully decrypted }.
916
+ * A mismatch (total > 0, loaded === 0) indicates a wrong master key / missing passphrase.
917
+ */
918
+ load(): Promise<{
919
+ total: number;
920
+ loaded: number;
921
+ failed: number;
922
+ }>;
923
+ /** Save an identity to storage */
924
+ save(identity: StoredIdentity): Promise<void>;
925
+ /** Set which identity is the default/primary identity */
926
+ setPrimary(identityId: string): Promise<boolean>;
927
+ /** Persist the primary identity ID to storage */
928
+ private savePrimaryIdentityId;
929
+ get(id: string): StoredIdentity | undefined;
930
+ getDefault(): StoredIdentity | undefined;
931
+ getPrimaryIdentityId(): string | null;
932
+ list(): PublicIdentity[];
933
+ /** List identities with rotation count (for dashboard display). */
934
+ listWithRotationCount(): Array<PublicIdentity & {
935
+ rotation_count: number;
936
+ }>;
1089
937
  }
1090
938
 
1091
939
  /**
1092
- * Sanctuary MCP Server — Federation Peer Registry
940
+ * Sanctuary MCP Server — L3 Selective Disclosure: Commitment Schemes
1093
941
  *
1094
- * Manages known federation peers. Peers are discovered through handshakes
1095
- * and tracked for ongoing federation operations.
942
+ * Cryptographic commitments allow an agent to commit to a value
943
+ * without revealing it, then later prove what was committed.
1096
944
  *
1097
- * The registry is the source of truth for:
1098
- * - Who we've federated with
1099
- * - Current trust status of each peer
1100
- * - Peer capabilities (what operations they support)
945
+ * This is the MVS approach to selective disclosure — simpler than
946
+ * full ZK proofs but still cryptographically sound. The commitment
947
+ * is SHA-256(value || blinding_factor), which is:
948
+ * - Hiding: the commitment reveals nothing about the value
949
+ * - Binding: the committer cannot change the value after committing
1101
950
  *
1102
951
  * Security invariants:
1103
- * - Peers are ONLY added through completed handshakes (not self-registration)
1104
- * - Trust tiers degrade automatically when handshakes expire
1105
- * - Peer data is stored encrypted under L1 sovereignty
952
+ * - Blinding factors are cryptographically random (32 bytes)
953
+ * - Commitments are stored encrypted under L1 sovereignty
954
+ * - Revealed values are verified via constant-time comparison
955
+ */
956
+
957
+ /** A cryptographic commitment */
958
+ interface Commitment {
959
+ /** The commitment hash: SHA-256(value || blinding_factor) as base64url */
960
+ commitment: string;
961
+ /** The blinding factor (must be stored securely for later reveal) */
962
+ blinding_factor: string;
963
+ /** When the commitment was created */
964
+ committed_at: string;
965
+ }
966
+ /** Stored commitment metadata (encrypted at rest) */
967
+ interface StoredCommitment {
968
+ commitment: string;
969
+ blinding_factor: string;
970
+ value: string;
971
+ committed_at: string;
972
+ revealed: boolean;
973
+ revealed_at?: string;
974
+ }
975
+ /**
976
+ * Commitment store — manages commitments encrypted under L1 sovereignty.
1106
977
  */
1107
-
1108
- declare class FederationRegistry {
1109
- private peers;
1110
- /**
1111
- * Register or update a peer from a completed handshake.
1112
- * This is the ONLY way peers enter the registry.
1113
- */
1114
- registerFromHandshake(result: HandshakeResult, peerDid: string, capabilities?: Partial<FederationCapabilities>): FederationPeer;
1115
- /**
1116
- * Get a peer by instance ID.
1117
- * Automatically updates active status based on handshake expiry.
1118
- */
1119
- getPeer(peerId: string): FederationPeer | null;
1120
- /**
1121
- * List all known peers, optionally filtered by status.
1122
- */
1123
- listPeers(filter?: {
1124
- active_only?: boolean;
1125
- }): FederationPeer[];
978
+ declare class CommitmentStore {
979
+ private storage;
980
+ private encryptionKey;
981
+ constructor(storage: StorageBackend, masterKey: Uint8Array);
1126
982
  /**
1127
- * Evaluate trust for a federation peer.
1128
- *
1129
- * Trust assessment considers:
1130
- * - Handshake status (current vs expired)
1131
- * - Sovereignty tier (verified-sovereign vs degraded vs unverified)
1132
- * - Reputation data (if available)
1133
- * - Mutual attestation history
983
+ * Store a commitment (encrypted) for later reference.
1134
984
  */
1135
- evaluateTrust(peerId: string, mutualAttestationCount?: number, reputationScore?: number): PeerTrustEvaluation;
985
+ store(commitment: Commitment, value: string): Promise<string>;
1136
986
  /**
1137
- * Remove a peer from the registry.
987
+ * Retrieve a stored commitment by ID.
1138
988
  */
1139
- removePeer(peerId: string): boolean;
989
+ get(id: string): Promise<StoredCommitment | null>;
1140
990
  /**
1141
- * Get the handshake results map (for tier resolution integration).
991
+ * Mark a commitment as revealed.
1142
992
  */
1143
- getHandshakeResults(): Map<string, HandshakeResult>;
993
+ markRevealed(id: string): Promise<void>;
1144
994
  }
1145
995
 
1146
996
  /**
1147
- * Sanctuary MCP Server — L2 Operational Isolation: Context Gating
997
+ * Sanctuary MCP Server — L3 Selective Disclosure: Zero-Knowledge Proofs
1148
998
  *
1149
- * Context gating controls what information leaves the sovereignty boundary
1150
- * when an agent makes outbound calls especially inference calls to remote
1151
- * LLM providers. This is the "minimum-necessary context" enforcement layer.
999
+ * Upgrades the commitment-only L3 to support real zero-knowledge proofs.
1000
+ * Uses Ristretto255 (prime-order curve group, no cofactor issues) for:
1152
1001
  *
1153
- * The problem: When an agent sends a request to a remote LLM provider (Claude,
1154
- * GPT, etc.), most harnesses send the agent's full context conversation
1155
- * history, memory, tool results, preferences, internal reasoning. The agent
1156
- * has no control over what the provider sees.
1002
+ * 1. Pedersen commitments: C = v*G + b*H (computationally hiding, perfectly binding)
1003
+ * 2. ZK proof of knowledge: Schnorr sigma protocol via Fiat-Shamir
1004
+ * 3. ZK range proofs: Prove value ∈ [min, max] without revealing it
1157
1005
  *
1158
- * Context gating lets the agent define:
1159
- * - Provider categories (inference, tool-api, logging, analytics, etc.)
1160
- * - What fields/categories of context may flow to each provider type
1161
- * - What must always be redacted (secrets, internal reasoning, PII, etc.)
1162
- * - What requires transformation (hashing, summarizing, anonymizing)
1006
+ * Ristretto255 is available via @noble/curves/ed25519, which we already depend on.
1007
+ * This is genuine zero-knowledge proofs reveal nothing beyond the stated property.
1163
1008
  *
1164
- * This sits in L2 (Operational Isolation) because it controls information
1165
- * flow at the execution boundary. L3 (Selective Disclosure) handles agent-
1166
- * to-agent trust negotiation with cryptographic proofs; context gating
1167
- * handles agent-to-infrastructure information flow.
1009
+ * Architecture note:
1010
+ * The existing commitment scheme (SHA-256 based) remains available for backward
1011
+ * compatibility. The ZK proofs operate on a separate Pedersen commitment system
1012
+ * that provides algebraic structure for proper ZK properties.
1168
1013
  *
1169
1014
  * Security invariants:
1170
- * - Redact rules take absolute priority (like withhold in L3)
1171
- * - Policies are stored encrypted under L1 sovereignty
1172
- * - Every filter operation is audit-logged with a content hash
1173
- * (what was sent, what was redacted without storing the content itself)
1174
- * - Default policy: redact everything not explicitly allowed
1015
+ * - Generator H is derived via hash-to-curve (nothing-up-my-sleeve)
1016
+ * - Blinding factors are cryptographically random (32 bytes)
1017
+ * - Fiat-Shamir challenges use domain-separated hashing
1018
+ * - Range proofs use a bit-decomposition approach (sound but logarithmic size)
1175
1019
  */
1176
-
1177
- /** Provider categories that context may flow to */
1178
- type ProviderCategory = "inference" | "tool-api" | "logging" | "analytics" | "peer-agent" | "custom";
1179
- /** Actions that can be taken on a context field */
1180
- type ContextAction = "allow" | "redact" | "hash" | "summarize" | "deny";
1181
- /** A rule within a context-gating policy */
1182
- interface ContextGateRule {
1183
- /** Provider category this rule applies to */
1184
- provider: ProviderCategory | "*";
1185
- /** Fields/patterns that may pass through */
1186
- allow: string[];
1187
- /** Fields/patterns that must be redacted (highest priority) */
1188
- redact: string[];
1189
- /** Fields/patterns that should be hashed */
1190
- hash: string[];
1191
- /** Fields/patterns that should be summarized (advisory) */
1192
- summarize: string[];
1193
- }
1194
- /** A complete context-gating policy */
1195
- interface ContextGatePolicy {
1196
- policy_id: string;
1197
- policy_name: string;
1198
- rules: ContextGateRule[];
1199
- /** Default action when no rule matches a field */
1200
- default_action: "redact" | "deny";
1201
- /** Identity this policy is bound to (optional) */
1202
- identity_id?: string;
1203
- created_at: string;
1204
- updated_at: string;
1020
+ /** A Pedersen commitment: C = v*G + b*H */
1021
+ interface PedersenCommitment {
1022
+ /** The commitment point (encoded as base64url) */
1023
+ commitment: string;
1024
+ /** The blinding factor b (base64url, 32 bytes) keep secret */
1025
+ blinding_factor: string;
1026
+ /** When the commitment was created */
1027
+ committed_at: string;
1205
1028
  }
1206
- /** Result of filtering a single field */
1207
- interface FieldFilterResult {
1208
- field: string;
1209
- action: ContextAction;
1210
- reason: string;
1211
- /** If action is "hash", contains the hash */
1212
- hash_value?: string;
1029
+ /** A non-interactive ZK proof of knowledge of a commitment's opening */
1030
+ interface ZKProofOfKnowledge {
1031
+ /** Proof type identifier */
1032
+ type: "schnorr-pedersen-ristretto255";
1033
+ /** The commitment this proof is for */
1034
+ commitment: string;
1035
+ /** Announcement point R (base64url) */
1036
+ announcement: string;
1037
+ /** Response scalar s_v (base64url) */
1038
+ response_v: string;
1039
+ /** Response scalar s_b (base64url) */
1040
+ response_b: string;
1041
+ /** Proof generated at */
1042
+ generated_at: string;
1213
1043
  }
1214
- /** Result of a full context filter operation */
1215
- interface ContextFilterResult {
1216
- policy_id: string;
1217
- provider: ProviderCategory | string;
1218
- fields_allowed: number;
1219
- fields_redacted: number;
1220
- fields_hashed: number;
1221
- fields_summarized: number;
1222
- fields_denied: number;
1223
- decisions: FieldFilterResult[];
1224
- /** SHA-256 hash of the original context (for audit trail) */
1225
- original_context_hash: string;
1226
- /** SHA-256 hash of the filtered output (for audit trail) */
1227
- filtered_context_hash: string;
1228
- filtered_at: string;
1044
+ /** A ZK range proof: proves value [min, max] */
1045
+ interface ZKRangeProof {
1046
+ /** Proof type identifier */
1047
+ type: "range-pedersen-ristretto255";
1048
+ /** The commitment this proof is for */
1049
+ commitment: string;
1050
+ /** Minimum value (inclusive) */
1051
+ min: number;
1052
+ /** Maximum value (inclusive) */
1053
+ max: number;
1054
+ /** Bit commitments for the shifted value (v - min) */
1055
+ bit_commitments: string[];
1056
+ /** Proofs that each bit commitment is 0 or 1 */
1057
+ bit_proofs: Array<{
1058
+ announcement_0: string;
1059
+ announcement_1: string;
1060
+ challenge_0: string;
1061
+ challenge_1: string;
1062
+ response_0: string;
1063
+ response_1: string;
1064
+ }>;
1065
+ /** Sum proof: bit commitments sum to the value commitment */
1066
+ sum_proof: {
1067
+ announcement: string;
1068
+ response: string;
1069
+ };
1070
+ /** Proof generated at */
1071
+ generated_at: string;
1229
1072
  }
1230
1073
  /**
1231
- * Evaluate a context field against a policy for a given provider.
1074
+ * Create a Pedersen commitment to a numeric value.
1232
1075
  *
1233
- * Priority order (same as L3 disclosure):
1234
- * 1. Redact (blocks — highest priority)
1235
- * 2. Deny (blocks entire request)
1236
- * 3. Hash (transforms)
1237
- * 4. Summarize (advisory transform)
1238
- * 5. Allow (passes through)
1239
- * 6. Default action
1076
+ * C = v*G + b*H
1077
+ *
1078
+ * Properties:
1079
+ * - Computationally hiding (under discrete log assumption)
1080
+ * - Perfectly binding (information-theoretic)
1081
+ * - Homomorphic: C(v1) + C(v2) = C(v1+v2) with adjusted blinding
1082
+ *
1083
+ * @param value - The value to commit to (integer)
1084
+ * @returns The commitment and blinding factor
1240
1085
  */
1241
- declare function evaluateField(policy: ContextGatePolicy, provider: ProviderCategory | string, field: string): FieldFilterResult;
1086
+ declare function createPedersenCommitment(value: number): PedersenCommitment;
1087
+ /**
1088
+ * Verify a Pedersen commitment against a revealed value and blinding factor.
1089
+ *
1090
+ * Recomputes C' = v*G + b*H and checks C' == C.
1091
+ */
1092
+ declare function verifyPedersenCommitment(commitment: string, value: number, blindingFactor: string): boolean;
1093
+ /**
1094
+ * Create a non-interactive ZK proof that you know the opening (v, b)
1095
+ * of a Pedersen commitment C = v*G + b*H.
1096
+ *
1097
+ * Schnorr sigma protocol with Fiat-Shamir transform:
1098
+ * 1. Pick random r_v, r_b
1099
+ * 2. Compute R = r_v*G + r_b*H (announcement)
1100
+ * 3. Compute e = H_FS(C || R) (challenge via Fiat-Shamir)
1101
+ * 4. Compute s_v = r_v + e*v, s_b = r_b + e*b (responses)
1102
+ * 5. Proof = (R, s_v, s_b)
1103
+ *
1104
+ * Zero-knowledge: the transcript (R, e, s_v, s_b) can be simulated
1105
+ * without knowing (v, b), so it reveals nothing.
1106
+ *
1107
+ * @param value - The committed value
1108
+ * @param blindingFactor - The blinding factor (base64url)
1109
+ * @param commitment - The commitment (base64url)
1110
+ */
1111
+ declare function createProofOfKnowledge(value: number, blindingFactor: string, commitment: string): ZKProofOfKnowledge;
1112
+ /**
1113
+ * Verify a ZK proof of knowledge of a commitment's opening.
1114
+ *
1115
+ * Check: s_v*G + s_b*H == R + e*C
1116
+ */
1117
+ declare function verifyProofOfKnowledge(proof: ZKProofOfKnowledge): boolean;
1118
+ /**
1119
+ * Create a ZK range proof: prove value ∈ [min, max] without revealing value.
1120
+ *
1121
+ * Approach: bit-decomposition of (value - min) into n bits where 2^n > max - min.
1122
+ * Each bit gets a Pedersen commitment and a proof it's 0 or 1.
1123
+ * A sum proof shows the bit commitments reconstruct the original commitment
1124
+ * (shifted by min).
1125
+ *
1126
+ * @param value - The committed value
1127
+ * @param blindingFactor - The blinding factor (base64url)
1128
+ * @param commitment - The commitment (base64url)
1129
+ * @param min - Minimum value (inclusive)
1130
+ * @param max - Maximum value (inclusive)
1131
+ */
1132
+ declare function createRangeProof(value: number, blindingFactor: string, commitment: string, min: number, max: number): ZKRangeProof | {
1133
+ error: string;
1134
+ };
1135
+ /**
1136
+ * Verify a ZK range proof.
1137
+ */
1138
+ declare function verifyRangeProof(proof: ZKRangeProof): boolean;
1139
+
1242
1140
  /**
1243
- * Filter a full context object against a policy for a given provider.
1244
- * Returns per-field decisions and content hashes for the audit trail.
1141
+ * Sanctuary MCP Server L3 Selective Disclosure: Disclosure Policies
1142
+ *
1143
+ * Disclosure policies define what an agent will and will not disclose
1144
+ * in different interaction contexts. Policies are evaluated against
1145
+ * incoming disclosure requests to produce per-field decisions.
1146
+ *
1147
+ * This is the agent's "privacy preferences" layer — it codifies the
1148
+ * human principal's intent about what information can flow where.
1149
+ *
1150
+ * Security invariants:
1151
+ * - Policies are stored encrypted under L1 sovereignty
1152
+ * - Default action is always "withhold" unless explicitly overridden
1153
+ * - Policy evaluation is deterministic (same request → same decision)
1245
1154
  */
1246
- declare function filterContext(policy: ContextGatePolicy, provider: ProviderCategory | string, context: Record<string, unknown>): ContextFilterResult;
1155
+
1156
+ /** A single disclosure rule within a policy */
1157
+ interface DisclosureRule {
1158
+ /** Interaction context this rule applies to */
1159
+ context: string;
1160
+ /** Fields/claims the agent MAY disclose */
1161
+ disclose: string[];
1162
+ /** Fields/claims the agent MUST NOT disclose */
1163
+ withhold: string[];
1164
+ /** Fields that require proof rather than plain disclosure */
1165
+ proof_required: string[];
1166
+ }
1167
+ /** A complete disclosure policy */
1168
+ interface DisclosurePolicy {
1169
+ policy_id: string;
1170
+ policy_name: string;
1171
+ rules: DisclosureRule[];
1172
+ default_action: "withhold" | "ask-principal";
1173
+ identity_id?: string;
1174
+ created_at: string;
1175
+ updated_at: string;
1176
+ }
1247
1177
  /**
1248
- * Context gate policy store — encrypted under L1 sovereignty.
1178
+ * Policy store — manages disclosure policies encrypted under L1 sovereignty.
1249
1179
  */
1250
- declare class ContextGatePolicyStore {
1180
+ declare class PolicyStore {
1251
1181
  private storage;
1252
1182
  private encryptionKey;
1253
1183
  private policies;
1254
1184
  constructor(storage: StorageBackend, masterKey: Uint8Array);
1255
1185
  /**
1256
- * Create and store a new context-gating policy.
1186
+ * Create and store a new disclosure policy.
1257
1187
  */
1258
- create(policyName: string, rules: ContextGateRule[], defaultAction: "redact" | "deny", identityId?: string): Promise<ContextGatePolicy>;
1188
+ create(policyName: string, rules: DisclosureRule[], defaultAction: "withhold" | "ask-principal", identityId?: string): Promise<DisclosurePolicy>;
1259
1189
  /**
1260
1190
  * Get a policy by ID.
1261
1191
  */
1262
- get(policyId: string): Promise<ContextGatePolicy | null>;
1192
+ get(policyId: string): Promise<DisclosurePolicy | null>;
1263
1193
  /**
1264
- * List all context-gating policies.
1194
+ * List all policies.
1265
1195
  */
1266
- list(): Promise<ContextGatePolicy[]>;
1196
+ list(): Promise<DisclosurePolicy[]>;
1267
1197
  /**
1268
1198
  * Load all persisted policies into memory.
1269
1199
  */
@@ -1272,736 +1202,907 @@ declare class ContextGatePolicyStore {
1272
1202
  }
1273
1203
 
1274
1204
  /**
1275
- * Sanctuary MCP Server — L2 Context Gating: Starter Policy Templates
1276
- *
1277
- * Pre-built policies for common use cases. These are starting points —
1278
- * users should customize them for their specific context structure.
1279
- *
1280
- * Templates:
1281
- *
1282
- * inference-minimal
1283
- * Only the current task and query reach the LLM. Everything else
1284
- * is redacted. Secrets, PII, memory, reasoning, and history are
1285
- * all blocked. IDs are hashed. Maximum privacy, minimum context.
1286
- *
1287
- * inference-standard
1288
- * Task, query, and tool results pass through. Conversation history
1289
- * is flagged for summarization (compress before sending). Secrets,
1290
- * PII, and internal reasoning are redacted. IDs are hashed.
1291
- * Balanced: the LLM has enough context to be useful without seeing
1292
- * everything the agent knows.
1205
+ * Sanctuary MCP Server — Sovereignty Health Report (SHR) Types
1293
1206
  *
1294
- * logging-strict
1295
- * Redacts everything for logging/analytics providers. Only
1296
- * operation names and timestamps pass through. Use this for
1297
- * telemetry services where you want usage metrics without
1298
- * content exposure.
1207
+ * Machine-readable, signed, versioned sovereignty capability advertisement.
1208
+ * An agent presents its SHR to counterparties to prove its sovereignty posture.
1209
+ * The SHR is signed by one of the instance's Ed25519 identities and can be
1210
+ * independently verified by any party without trusting the presenter.
1299
1211
  *
1300
- * tool-api-scoped
1301
- * Allows tool-specific parameters and the current task, redacts
1302
- * memory, history, secrets, and PII. Hashes IDs. For outbound
1303
- * calls to external APIs (search, database, etc.) where you need
1304
- * to send query parameters but not your agent's full state.
1212
+ * SHR version: 1.0
1305
1213
  */
1306
-
1307
- /** A template definition ready to be applied via the policy store */
1308
- interface ContextGateTemplate {
1309
- /** Machine-readable template ID */
1310
- id: string;
1311
- /** Human-readable name */
1312
- name: string;
1313
- /** One-line description */
1214
+ type LayerStatus = "active" | "degraded" | "inactive";
1215
+ type DegradationSeverity = "info" | "warning" | "critical";
1216
+ type DegradationCode = "NO_TEE" | "PROCESS_ISOLATION_ONLY" | "COMMITMENT_ONLY" | "NO_ZK_PROOFS" | "SELF_REPORTED_ATTESTATION" | "NO_SELECTIVE_DISCLOSURE" | "BASIC_SYBIL_ONLY" | "NO_REPUTATION_HISTORY" | "LOW_TIER_DOMINANCE" | "STALE_REPUTATION" | "DISPUTE_ON_RECORD" | "NO_VERASCORE_LINK";
1217
+ interface SHRLayerL1 {
1218
+ status: LayerStatus;
1219
+ encryption: string;
1220
+ key_custody: "self" | "delegated" | "platform";
1221
+ integrity: string;
1222
+ identity_type: string;
1223
+ state_portable: boolean;
1224
+ }
1225
+ interface SHRLayerL2 {
1226
+ status: LayerStatus;
1227
+ isolation_type: string;
1228
+ attestation_available: boolean;
1229
+ /** Model provenance: what inference model(s) power this agent */
1230
+ model_provenance?: {
1231
+ model_id: string;
1232
+ model_name: string;
1233
+ provider: string;
1234
+ open_weights: boolean;
1235
+ open_source: boolean;
1236
+ local_inference: boolean;
1237
+ weights_hash?: string;
1238
+ };
1239
+ }
1240
+ interface SHRLayerL3 {
1241
+ status: LayerStatus;
1242
+ proof_system: string;
1243
+ selective_disclosure: boolean;
1244
+ }
1245
+ interface SHRLayerL4 {
1246
+ status: LayerStatus;
1247
+ reputation_mode: string;
1248
+ attestation_format: string;
1249
+ reputation_portable: boolean;
1250
+ }
1251
+ interface SHRDegradation {
1252
+ layer: "l1" | "l2" | "l3" | "l4";
1253
+ code: DegradationCode;
1254
+ severity: DegradationSeverity;
1314
1255
  description: string;
1315
- /** When to use this template */
1316
- use_when: string;
1317
- /** The rules that make up this template */
1318
- rules: ContextGateRule[];
1319
- /** Default action for unmatched fields */
1320
- default_action: "redact" | "deny";
1256
+ mitigation?: string;
1257
+ }
1258
+ interface SHRCapabilities {
1259
+ handshake: boolean;
1260
+ shr_exchange: boolean;
1261
+ reputation_verify: boolean;
1262
+ encrypted_channel: boolean;
1321
1263
  }
1322
- /** All available templates, keyed by ID */
1323
- declare const TEMPLATES: Record<string, ContextGateTemplate>;
1324
- /** List all available template IDs */
1325
- declare function listTemplateIds(): string[];
1326
- /** Get a template by ID (returns undefined if not found) */
1327
- declare function getTemplate(id: string): ContextGateTemplate | undefined;
1328
-
1329
1264
  /**
1330
- * Sanctuary MCP ServerL2 Context Gating: Policy Recommendation Engine
1331
- *
1332
- * Analyzes a sample context object and recommends a context-gating policy
1333
- * based on field name heuristics. The agent (or human) can then review,
1334
- * adjust, and apply the recommendation.
1335
- *
1336
- * This is deliberately conservative: when in doubt, it recommends redact.
1337
- * A false redaction is a usability issue; a false allow is a privacy leak.
1338
- *
1339
- * Classification heuristics:
1340
- * - Known secret patterns → redact (highest confidence)
1341
- * - Known PII patterns → redact (high confidence)
1342
- * - Known internal state patterns → redact (high confidence)
1343
- * - Known ID patterns → hash (medium confidence)
1344
- * - Known history patterns → summarize (medium confidence)
1345
- * - Known task/query patterns → allow (medium confidence)
1346
- * - Everything else → redact (conservative default)
1347
- *
1348
- * WARNING: Fields like 'tool_results' and 'tool_output' are classified as
1349
- * "allow" (medium confidence) but may contain sensitive data from external
1350
- * API responses, including auth tokens, user data, or PII. Always review
1351
- * recommendations before applying — the heuristic classifies by field NAME,
1352
- * not field CONTENT.
1265
+ * The SHR bodythe content that gets signed.
1266
+ * Canonical form: JSON with sorted keys, no whitespace.
1353
1267
  */
1354
- /** Classification result for a single field */
1355
- interface FieldClassification {
1356
- field: string;
1357
- recommended_action: "allow" | "redact" | "hash" | "summarize";
1358
- reason: string;
1359
- confidence: "high" | "medium" | "low";
1360
- /** Pattern that matched, if any */
1361
- matched_pattern: string | null;
1362
- }
1363
- /** Full recommendation result */
1364
- interface PolicyRecommendation {
1365
- provider: string;
1366
- classifications: FieldClassification[];
1367
- recommended_rules: {
1368
- allow: string[];
1369
- redact: string[];
1370
- hash: string[];
1371
- summarize: string[];
1268
+ interface SHRBody {
1269
+ shr_version: "1.0";
1270
+ implementation: {
1271
+ sanctuary_version: string;
1272
+ node_version: string;
1273
+ generated_by: string;
1372
1274
  };
1373
- default_action: "redact";
1374
- summary: {
1375
- total_fields: number;
1376
- allow: number;
1377
- redact: number;
1378
- hash: number;
1379
- summarize: number;
1275
+ instance_id: string;
1276
+ generated_at: string;
1277
+ expires_at: string;
1278
+ layers: {
1279
+ l1: SHRLayerL1;
1280
+ l2: SHRLayerL2;
1281
+ l3: SHRLayerL3;
1282
+ l4: SHRLayerL4;
1380
1283
  };
1284
+ capabilities: SHRCapabilities;
1285
+ degradations: SHRDegradation[];
1286
+ }
1287
+ /**
1288
+ * The complete signed SHR — body + signature envelope.
1289
+ */
1290
+ interface SignedSHR {
1291
+ body: SHRBody;
1292
+ signed_by: string;
1293
+ signature: string;
1294
+ }
1295
+ interface SHRVerificationResult {
1296
+ valid: boolean;
1297
+ errors: string[];
1381
1298
  warnings: string[];
1299
+ sovereignty_level: "full" | "degraded" | "minimal";
1300
+ counterparty_id: string;
1301
+ expires_at: string;
1302
+ }
1303
+
1304
+ /**
1305
+ * Sanctuary MCP Server — Sovereignty Handshake Types
1306
+ *
1307
+ * The sovereignty handshake is a mutual verification protocol between
1308
+ * two Sanctuary instances. Each party presents its SHR and proves
1309
+ * liveness via nonce challenge-response.
1310
+ *
1311
+ * Protocol:
1312
+ * A → B: HandshakeChallenge (A's SHR + nonce)
1313
+ * B → A: HandshakeResponse (B's SHR + B's nonce + signature over A's nonce)
1314
+ * A → B: HandshakeCompletion (signature over B's nonce)
1315
+ * Result: Both hold a HandshakeResult with verified counterparty status
1316
+ */
1317
+
1318
+ /** Trust tier derived from sovereignty handshake */
1319
+ type TrustTier = "verified-sovereign" | "verified-degraded" | "unverified";
1320
+ /** Sovereignty level from SHR assessment */
1321
+ type SovereigntyLevel = "full" | "degraded" | "minimal" | "unverified";
1322
+ /**
1323
+ * Step 1: Initiator sends challenge
1324
+ */
1325
+ interface HandshakeChallenge {
1326
+ protocol_version: "1.0";
1327
+ shr: SignedSHR;
1328
+ nonce: string;
1329
+ initiated_at: string;
1382
1330
  }
1383
1331
  /**
1384
- * Classify a single field name and return a recommendation.
1332
+ * Step 2: Responder sends response
1385
1333
  */
1386
- declare function classifyField(fieldName: string): FieldClassification;
1334
+ interface HandshakeResponse {
1335
+ protocol_version: "1.0";
1336
+ shr: SignedSHR;
1337
+ responder_nonce: string;
1338
+ initiator_nonce_signature: string;
1339
+ responded_at: string;
1340
+ }
1387
1341
  /**
1388
- * Analyze a full context object and recommend a policy.
1342
+ * Step 3: Initiator sends completion
1389
1343
  */
1390
- declare function recommendPolicy(context: Record<string, unknown>, provider?: string): PolicyRecommendation;
1344
+ interface HandshakeCompletion {
1345
+ protocol_version: "1.0";
1346
+ responder_nonce_signature: string;
1347
+ completed_at: string;
1348
+ }
1349
+ /**
1350
+ * Final result: both parties hold this after a successful handshake
1351
+ */
1352
+ interface HandshakeResult {
1353
+ counterparty_id: string;
1354
+ counterparty_shr: SignedSHR;
1355
+ verified: boolean;
1356
+ sovereignty_level: SovereigntyLevel;
1357
+ trust_tier: TrustTier;
1358
+ completed_at: string;
1359
+ expires_at: string;
1360
+ errors: string[];
1361
+ }
1362
+ /**
1363
+ * In-progress handshake state (stored on initiator side)
1364
+ */
1365
+ interface HandshakeSession {
1366
+ session_id: string;
1367
+ role: "initiator" | "responder";
1368
+ state: "initiated" | "responded" | "completed" | "failed";
1369
+ our_nonce: string;
1370
+ their_nonce?: string;
1371
+ our_shr: SignedSHR;
1372
+ their_shr?: SignedSHR;
1373
+ initiated_at: string;
1374
+ result?: HandshakeResult;
1375
+ }
1391
1376
 
1392
1377
  /**
1393
- * Sanctuary MCP Server — L2 Model Provenance
1394
- *
1395
- * Declares and attests to the model(s) powering this agent.
1378
+ * Sanctuary MCP Server — Sovereignty-Gated Reputation Tiers
1396
1379
  *
1397
- * Vitalik Buterin's "Secure LLM" post (April 2026) identified a critical gap:
1398
- * open-weights-but-not-open-source models can have trained-in backdoors. Model
1399
- * provenance declaration lets agents and their operators verify the integrity
1400
- * of the inference backbone.
1380
+ * Attestations carry a sovereignty_tier field reflecting the signer's
1381
+ * sovereignty posture at the time of recording. When querying or evaluating
1382
+ * reputation, attestations from verified-sovereign agents carry more weight
1383
+ * than those from unverified agents.
1401
1384
  *
1402
- * Tracks: model name, version, weights hash, license, open-source status,
1403
- * training data hash (if available). Included in SHR L2 section.
1385
+ * Tier hierarchy (descending credibility):
1386
+ * 1. "verified-sovereign" — signer completed a handshake with full sovereignty
1387
+ * 2. "verified-degraded" — signer completed a handshake with degraded sovereignty
1388
+ * 3. "self-attested" — signer has a Sanctuary identity but no handshake verification
1389
+ * 4. "unverified" — no Sanctuary identity or sovereignty proof
1404
1390
  *
1405
- * This sits in L2 (Operational Isolation) because it's part of the runtime
1406
- * attestation surface the agent declares what model(s) it's actually running.
1391
+ * Weight multipliers are applied during reputation scoring. They are NOT
1392
+ * gatekeepingunverified attestations still count, just less.
1407
1393
  */
1394
+
1395
+ type SovereigntyTier = "verified-sovereign" | "verified-degraded" | "self-attested" | "unverified";
1396
+ /** Weight multipliers for each tier */
1397
+ declare const TIER_WEIGHTS: Record<SovereigntyTier, number>;
1398
+ /** Tier metadata embedded in attestations */
1399
+ interface TierMetadata {
1400
+ sovereignty_tier: SovereigntyTier;
1401
+ /** If verified, the handshake that established it */
1402
+ handshake_completed_at?: string;
1403
+ /** Counterparty ID from handshake (if applicable) */
1404
+ verified_by?: string;
1405
+ }
1408
1406
  /**
1409
- * Metadata about a single model powering this agent.
1407
+ * Resolve the sovereignty tier for a counterparty based on handshake history.
1408
+ *
1409
+ * @param counterpartyId - The counterparty's instance ID
1410
+ * @param handshakeResults - Map of counterparty ID → most recent handshake result
1411
+ * @param hasSanctuaryIdentity - Whether the counterparty has a known Sanctuary identity
1412
+ * @returns TierMetadata for embedding in attestations
1410
1413
  */
1411
- interface ModelProvenance {
1412
- /** Machine-readable model ID (e.g., "qwen3.5-35b", "claude-opus-4", "llama-3.3-70b-instruct") */
1413
- model_id: string;
1414
- /** Human-readable model name (e.g., "Qwen 3.5", "Claude Opus 4", "Llama 3.3 70B Instruct") */
1415
- model_name: string;
1416
- /** Semantic version (e.g., "3.5", "4.0", "3.3") */
1417
- model_version: string;
1418
- /** Provider/vendor (e.g., "Alibaba Cloud", "Anthropic", "Meta", "local") */
1419
- provider: string;
1420
- /** SHA-256 of model weights file, if available and verifiable */
1421
- weights_hash?: string;
1422
- /** SHA-256 of training data manifest or metadata, if available */
1423
- training_data_hash?: string;
1424
- /** License identifier (e.g., "Apache-2.0", "CC-BY-4.0", "proprietary", "unknown") */
1425
- license: string;
1426
- /** True if model weights are publicly available (even if training is proprietary) */
1427
- open_weights: boolean;
1428
- /** True if full training code, data, and methodology are publicly available */
1429
- open_source: boolean;
1430
- /** True if inference runs on the local agent's hardware (not delegated to cloud API) */
1431
- local_inference: boolean;
1432
- /** ISO 8601 timestamp when this provenance was declared */
1433
- declared_at: string;
1414
+ declare function resolveTier(counterpartyId: string, handshakeResults: Map<string, HandshakeResult>, hasSanctuaryIdentity: boolean): TierMetadata;
1415
+ /** An attestation with its tier for weighted scoring */
1416
+ interface TieredAttestation {
1417
+ /** The raw metric value */
1418
+ value: number;
1419
+ /** The sovereignty tier of the attestation signer */
1420
+ tier: SovereigntyTier;
1434
1421
  }
1435
1422
  /**
1436
- * In-memory and persistent store for model provenance declarations.
1437
- * Declarations are encrypted under L1 sovereignty.
1423
+ * Compute a weighted reputation score from tiered attestations.
1424
+ *
1425
+ * Each attestation's contribution is multiplied by its tier weight.
1426
+ * The result is normalized by total weight (not count), so adding
1427
+ * low-tier attestations doesn't dilute high-tier ones.
1428
+ *
1429
+ * @param attestations - Array of value + tier pairs
1430
+ * @returns Weighted score, or null if no attestations
1438
1431
  */
1439
- interface ModelProvenanceStore {
1440
- /**
1441
- * Declare a model's provenance and add it to the store.
1442
- */
1443
- declare(provenance: ModelProvenance): void;
1444
- /**
1445
- * Retrieve a model's provenance by ID.
1446
- */
1447
- get(model_id: string): ModelProvenance | undefined;
1448
- /**
1449
- * List all declared models.
1450
- */
1451
- list(): ModelProvenance[];
1452
- /**
1453
- * Get the primary/main model (the one the agent uses by default for inference).
1454
- */
1455
- primary(): ModelProvenance | undefined;
1456
- /**
1457
- * Set which model is the primary.
1458
- */
1459
- setPrimary(model_id: string): void;
1460
- }
1432
+ declare function computeWeightedScore(attestations: TieredAttestation[]): number | null;
1461
1433
  /**
1462
- * In-memory implementation of ModelProvenanceStore.
1463
- * Suitable for most use cases. For encrypted persistence, integrate with L1 state store.
1434
+ * Compute a tier distribution summary for a set of attestations.
1464
1435
  */
1465
- declare class InMemoryModelProvenanceStore implements ModelProvenanceStore {
1466
- private models;
1467
- private primaryModelId;
1468
- declare(provenance: ModelProvenance): void;
1469
- get(model_id: string): ModelProvenance | undefined;
1470
- list(): ModelProvenance[];
1471
- primary(): ModelProvenance | undefined;
1472
- setPrimary(model_id: string): void;
1473
- }
1436
+ declare function tierDistribution(tiers: SovereigntyTier[]): Record<SovereigntyTier, number>;
1437
+
1474
1438
  /**
1475
- * Common model provenance presets for quick initialization.
1439
+ * Sanctuary MCP Server L4 Verifiable Reputation: Reputation Store
1440
+ *
1441
+ * Records interaction outcomes as signed attestations, queries aggregated
1442
+ * reputation data, and supports export/import for cross-platform portability.
1443
+ *
1444
+ * Attestation format is EAS-compatible (Ethereum Attestation Service) to
1445
+ * enable future on-chain anchoring without requiring blockchain for MVS.
1446
+ *
1447
+ * Security invariants:
1448
+ * - All attestations are signed by the recording identity
1449
+ * - Attestations are stored encrypted under L1 sovereignty
1450
+ * - Reputation queries return aggregates, never raw interaction data
1451
+ * - Export bundles include all signatures for independent verification
1452
+ * - Import verifies every signature before accepting attestations
1476
1453
  */
1477
- declare const MODEL_PRESETS: {
1478
- /**
1479
- * Claude Opus 4 via Anthropic API (cloud inference, closed weights/source)
1480
- */
1481
- claudeOpus4: () => ModelProvenance;
1482
- /**
1483
- * Qwen 3.5 via local inference (open weights, proprietary training)
1484
- */
1485
- qwen35Local: () => ModelProvenance;
1486
- /**
1487
- * Llama 3.3 70B via local inference (open weights and code)
1488
- */
1489
- llama33Local: () => ModelProvenance;
1490
- /**
1491
- * Mistral 7B (open weights, open code, local inference)
1492
- */
1493
- mistral7bLocal: () => ModelProvenance;
1494
- };
1495
1454
 
1455
+ /** Interaction outcome for recording */
1456
+ interface InteractionOutcome {
1457
+ type: "transaction" | "negotiation" | "service" | "dispute" | "custom";
1458
+ result: "completed" | "partial" | "failed" | "disputed";
1459
+ metrics?: Record<string, number>;
1460
+ }
1461
+ /** A signed attestation of an interaction */
1462
+ interface Attestation {
1463
+ attestation_id: string;
1464
+ schema: "sanctuary-interaction-v1";
1465
+ data: {
1466
+ interaction_id: string;
1467
+ participant_did: string;
1468
+ counterparty_did: string;
1469
+ outcome_type: string;
1470
+ outcome_result: string;
1471
+ metrics: Record<string, number>;
1472
+ context: string;
1473
+ timestamp: string;
1474
+ /** Sovereignty tier of the signer at time of recording */
1475
+ sovereignty_tier?: SovereigntyTier;
1476
+ };
1477
+ signature: string;
1478
+ signer: string;
1479
+ }
1480
+ /** Stored attestation (encrypted at rest) */
1481
+ interface StoredAttestation {
1482
+ attestation: Attestation;
1483
+ counterparty_attestation?: string;
1484
+ counterparty_confirmed: boolean;
1485
+ recorded_at: string;
1486
+ }
1487
+ /** Aggregated metric statistics */
1488
+ interface MetricAggregate {
1489
+ mean: number;
1490
+ median: number;
1491
+ min: number;
1492
+ max: number;
1493
+ count: number;
1494
+ }
1495
+ /** Reputation query result */
1496
+ interface ReputationSummary {
1497
+ total_interactions: number;
1498
+ completed: number;
1499
+ partial: number;
1500
+ failed: number;
1501
+ disputed: number;
1502
+ contexts: string[];
1503
+ time_range: {
1504
+ start: string;
1505
+ end: string;
1506
+ };
1507
+ aggregate_metrics: Record<string, MetricAggregate>;
1508
+ }
1496
1509
  /**
1497
- * Sanctuary MCP Server Prompt Injection Detection Layer
1498
- *
1499
- * Fast, zero-dependency detection of common prompt injection patterns.
1500
- * Scans tool arguments for role override, security bypass, encoding evasion,
1501
- * data exfiltration, and prompt stuffing signals.
1502
- *
1503
- * SEC-034/SEC-035: Enhanced with Unicode sanitization pre-pass, decoded content
1504
- * re-scanning, token budget analysis, and outbound content scanning.
1505
- *
1506
- * Security invariants:
1507
- * - Always returns a result, never throws
1508
- * - Typical scan completes in < 5ms
1509
- * - False positives minimized via field-aware scanning
1510
- * - Recursive scanning of nested objects/arrays
1511
- * - Outbound scanning catches secret leaks and injection artifact survival
1510
+ * L4 attestation evidence summary for the SHR degradation emitter and the
1511
+ * dashboard evidence widget. Derived from the stored attestations; does not
1512
+ * include Verascore-link state (tracked separately via audit log).
1512
1513
  */
1513
- interface InjectionDetectorConfig {
1514
- enabled: boolean;
1515
- sensitivity: "low" | "medium" | "high";
1516
- on_detection: "escalate" | "block" | "log";
1517
- custom_patterns?: string[];
1514
+ interface L4AttestationSummary {
1515
+ /** Total number of attestations covered by the summary */
1516
+ attestation_count: number;
1517
+ /** Count of attestations at each sovereignty tier */
1518
+ tier_distribution: Record<SovereigntyTier, number>;
1519
+ /** ISO timestamp of the most recent attestation, or null if none */
1520
+ most_recent_attestation_at: string | null;
1521
+ /** Count of attestations with outcome_result === "disputed" */
1522
+ dispute_count: number;
1523
+ /** Count of attestations per context label */
1524
+ context_breakdown: Record<string, number>;
1518
1525
  }
1519
- interface InjectionSignal {
1520
- type: string;
1521
- pattern: string;
1522
- location: string;
1523
- severity: "low" | "medium" | "high";
1526
+ /** Portable reputation bundle */
1527
+ interface ReputationBundle {
1528
+ version: "SANCTUARY_REP_V1";
1529
+ attestations: Attestation[];
1530
+ exported_at: string;
1531
+ exporter_did: string;
1532
+ bundle_signature: string;
1524
1533
  }
1525
- interface DetectionResult {
1526
- flagged: boolean;
1527
- confidence: number;
1528
- signals: InjectionSignal[];
1529
- recommendation: "allow" | "escalate" | "block";
1534
+ /** Escrow for trust bootstrapping */
1535
+ interface Escrow {
1536
+ escrow_id: string;
1537
+ transaction_terms: string;
1538
+ terms_hash: string;
1539
+ collateral_amount?: number;
1540
+ counterparty_did: string;
1541
+ creator_did: string;
1542
+ created_at: string;
1543
+ expires_at: string;
1544
+ status: "pending" | "active" | "released" | "disputed" | "expired";
1530
1545
  }
1531
- declare class InjectionDetector {
1532
- private config;
1533
- private stats;
1534
- constructor(config?: Partial<InjectionDetectorConfig>);
1535
- /**
1536
- * Scan tool arguments for injection signals.
1537
- * @param toolName Full tool name (e.g., "state_read")
1538
- * @param args Tool arguments
1539
- * @returns DetectionResult with all detected signals
1540
- */
1541
- scan(toolName: string, args: Record<string, unknown>): DetectionResult;
1542
- /**
1543
- * SEC-035: Scan outbound content for secret leaks, data exfiltration,
1544
- * internal path exposure, and injection artifact survival.
1545
- *
1546
- * @param content The outbound content string to scan
1547
- * @returns DetectionResult with outbound-specific signal types
1548
- */
1549
- scanOutbound(content: string): DetectionResult;
1550
- /**
1551
- * Recursively scan a value and all nested values.
1552
- */
1553
- private scanValue;
1546
+ /** Principal guarantee for a new agent */
1547
+ interface Guarantee {
1548
+ guarantee_id: string;
1549
+ principal_did: string;
1550
+ agent_did: string;
1551
+ scope: string;
1552
+ max_liability?: number;
1553
+ valid_until: string;
1554
+ certificate: string;
1555
+ created_at: string;
1556
+ }
1557
+ declare class ReputationStore {
1558
+ private storage;
1559
+ private encryptionKey;
1560
+ constructor(storage: StorageBackend, masterKey: Uint8Array);
1554
1561
  /**
1555
- * Scan a single string for injection signals.
1562
+ * Record an interaction outcome as a signed attestation.
1556
1563
  */
1557
- private scanString;
1564
+ record(interactionId: string, counterpartyDid: string, outcome: InteractionOutcome, context: string, identity: StoredIdentity, identityEncryptionKey: Uint8Array, counterpartyAttestation?: string, sovereigntyTier?: SovereigntyTier): Promise<StoredAttestation>;
1558
1565
  /**
1559
- * Count invisible Unicode characters in a string.
1560
- * Includes zero-width chars, soft hyphens, directional marks,
1561
- * variation selectors, and other invisible categories.
1566
+ * Query reputation data with filtering.
1567
+ * Returns aggregates only not raw interaction data.
1562
1568
  */
1563
- private countInvisibleChars;
1569
+ query(options: {
1570
+ context?: string;
1571
+ time_range?: {
1572
+ start: string;
1573
+ end: string;
1574
+ };
1575
+ metrics?: string[];
1576
+ counterparty_did?: string;
1577
+ }): Promise<ReputationSummary>;
1564
1578
  /**
1565
- * Strip invisible characters from a string for clean pattern matching.
1566
- * Returns a new string with all invisible chars removed.
1579
+ * Export attestations as a portable reputation bundle.
1567
1580
  */
1568
- private stripInvisibleChars;
1581
+ exportBundle(identity: StoredIdentity, identityEncryptionKey: Uint8Array, context?: string): Promise<ReputationBundle>;
1569
1582
  /**
1570
- * SEC-034: Token budget attack detection.
1571
- * Some Unicode sequences expand dramatically during tokenization (e.g., CJK
1572
- * ideographs, combining characters, emoji sequences). If the estimated token
1573
- * cost per character is anomalously high, this may be a wallet-drain payload.
1583
+ * Import attestations from a reputation bundle.
1584
+ * Verifies signatures if requested (default: true).
1574
1585
  *
1575
- * Heuristic: count chars that typically tokenize into multiple tokens.
1576
- * If the ratio of estimated tokens to char count exceeds 3x, flag it.
1577
- */
1578
- private detectTokenBudgetAttack;
1579
- /**
1580
- * Detect encoded content (base64, hex, HTML entities, URL encoding),
1581
- * decode it, and re-scan the decoded content through injection patterns.
1582
- * If the decoded content contains injection patterns, flag as encoding_evasion.
1583
- */
1584
- private detectEncodedPayloads;
1585
- /**
1586
- * Check if a string contains any injection patterns (role override or security bypass).
1587
- */
1588
- private containsInjectionPatterns;
1589
- /**
1590
- * Safely decode a base64 string. Returns null if it's not valid base64
1591
- * or doesn't decode to a meaningful string.
1592
- */
1593
- private safeBase64Decode;
1594
- /**
1595
- * Safely decode a hex string. Returns null on failure.
1596
- */
1597
- private safeHexDecode;
1598
- /**
1599
- * Decode HTML numeric entities (&#xHH; and &#DDD;) in a string.
1600
- */
1601
- private decodeHtmlEntities;
1602
- /**
1603
- * Safely decode a URL-encoded string. Returns null on failure.
1604
- */
1605
- private safeUrlDecode;
1606
- /**
1607
- * Heuristic: does this look like readable text (vs. binary garbage)?
1608
- * Checks that most characters are printable ASCII or common Unicode.
1609
- */
1610
- private looksLikeText;
1611
- /**
1612
- * Detect API keys and secrets in outbound content.
1613
- */
1614
- private detectSecretPatterns;
1615
- /**
1616
- * Detect data exfiltration via markdown images with data-carrying query params.
1617
- */
1618
- private detectOutboundExfiltration;
1619
- /**
1620
- * Detect internal filesystem path leaks in outbound content.
1621
- */
1622
- private detectInternalPathLeaks;
1623
- /**
1624
- * Detect private IP addresses and localhost references in outbound content.
1586
+ * @param publicKeys - Map of DID public key bytes for signature verification
1625
1587
  */
1626
- private detectPrivateNetworkLeaks;
1588
+ importBundle(bundle: ReputationBundle, verifySignatures: boolean, publicKeys: Map<string, Uint8Array>): Promise<{
1589
+ imported: number;
1590
+ invalid: number;
1591
+ contexts: string[];
1592
+ }>;
1627
1593
  /**
1628
- * Detect role markers / prompt template artifacts in outbound content.
1629
- * These should never appear in agent output — their presence indicates
1630
- * injection artifact survival.
1594
+ * Create an escrow for trust bootstrapping.
1631
1595
  */
1632
- private detectOutputRoleMarkers;
1596
+ createEscrow(transactionTerms: string, counterpartyDid: string, timeoutSeconds: number, creatorDid: string, collateralAmount?: number): Promise<Escrow>;
1633
1597
  /**
1634
- * Detect base64 strings, base64url, and zero-width character evasion.
1598
+ * Get an escrow by ID.
1635
1599
  */
1636
- private detectEncodingEvasion;
1600
+ getEscrow(escrowId: string): Promise<Escrow | null>;
1637
1601
  /**
1638
- * Detect URLs and emails in fields that shouldn't have them.
1602
+ * Create a principal's guarantee for a new agent.
1639
1603
  */
1640
- private detectDataExfiltration;
1604
+ createGuarantee(principalIdentity: StoredIdentity, agentDid: string, scope: string, durationSeconds: number, identityEncryptionKey: Uint8Array, maxLiability?: number): Promise<Guarantee>;
1641
1605
  /**
1642
- * Detect prompt stuffing: very large strings or high repetition.
1606
+ * Summarize attestations for the L4 degradation emitter and dashboard widget.
1607
+ *
1608
+ * Returns aggregate evidence about the identity's reputation state —
1609
+ * counts, tier distribution, recency, dispute counts, context coverage —
1610
+ * without exposing raw attestations. The caller combines this with an
1611
+ * audit-log check for Verascore link state to produce the final
1612
+ * `L4Evidence` struct consumed by the SHR generator.
1613
+ *
1614
+ * @param participantDid - If provided, only count attestations where the
1615
+ * `participant_did` matches. If omitted, covers all attestations in the
1616
+ * store.
1643
1617
  */
1644
- private detectPromptStuffing;
1618
+ summarizeForSHR(participantDid?: string): Promise<L4AttestationSummary>;
1645
1619
  /**
1646
- * Determine if this field is inherently safe from role override.
1620
+ * Load attestations for tier-weighted scoring.
1621
+ * Applies basic context/counterparty filtering, returns full StoredAttestations
1622
+ * so callers can access sovereignty_tier from attestation data.
1647
1623
  */
1648
- private isSafeField;
1624
+ loadAllForTierScoring(options?: {
1625
+ context?: string;
1626
+ counterparty_did?: string;
1627
+ }): Promise<StoredAttestation[]>;
1628
+ private loadAll;
1649
1629
  /**
1650
- * Determine if this is a tool name field (where tool refs are expected).
1630
+ * Cursor-based async iterator that loads attestations in pages.
1631
+ * Prevents OOM at 100K+ records by reading and decrypting in batches.
1651
1632
  */
1652
- private isToolNameField;
1633
+ loadAllPaginated(pageSize?: number): AsyncGenerator<StoredAttestation[]>;
1634
+ }
1635
+
1636
+ /**
1637
+ * Sanctuary MCP Server — Federation Types
1638
+ *
1639
+ * MCP-to-MCP federation enables two Sanctuary instances to:
1640
+ * 1. Discover each other's capabilities (SIM exchange)
1641
+ * 2. Establish mutual trust (sovereignty handshake)
1642
+ * 3. Exchange signed reputation attestations
1643
+ * 4. Evaluate trust for cross-instance interactions
1644
+ *
1645
+ * Federation operates as a protocol layer atop the handshake:
1646
+ * Handshake establishes trust → Federation uses that trust for ongoing operations.
1647
+ *
1648
+ * Key constraint: Federation MUST respect each party's sovereignty.
1649
+ * Neither party can compel the other to share data they haven't disclosed
1650
+ * via their disclosure policy.
1651
+ */
1652
+
1653
+ /** A known federation peer */
1654
+ interface FederationPeer {
1655
+ /** The peer's instance ID (from their SHR) */
1656
+ peer_id: string;
1657
+ /** The peer's DID (identity) */
1658
+ peer_did: string;
1659
+ /** When this peer was first seen */
1660
+ first_seen: string;
1661
+ /** When last handshake completed */
1662
+ last_handshake: string;
1663
+ /** Current trust tier from most recent handshake */
1664
+ trust_tier: SovereigntyTier;
1665
+ /** Handshake result (for tier resolution) */
1666
+ handshake_result: HandshakeResult;
1667
+ /** Peer's advertised capabilities (from their SIM) */
1668
+ capabilities: FederationCapabilities;
1669
+ /** Whether we have a valid (non-expired) handshake */
1670
+ active: boolean;
1671
+ }
1672
+ /** Capabilities a peer advertises for federation */
1673
+ interface FederationCapabilities {
1674
+ /** Whether the peer supports reputation exchange */
1675
+ reputation_exchange: boolean;
1676
+ /** Whether the peer supports mutual attestation */
1677
+ mutual_attestation: boolean;
1678
+ /** Whether the peer supports encrypted channels */
1679
+ encrypted_channel: boolean;
1680
+ /** Supported attestation formats */
1681
+ attestation_formats: string[];
1682
+ }
1683
+ /** Trust evaluation result for a federation peer */
1684
+ interface PeerTrustEvaluation {
1685
+ peer_id: string;
1686
+ /** Current sovereignty tier (from handshake) */
1687
+ sovereignty_tier: SovereigntyTier;
1688
+ /** Whether handshake is current (not expired) */
1689
+ handshake_current: boolean;
1690
+ /** Reputation summary (if available) */
1691
+ reputation_score?: number;
1692
+ /** How many mutual attestations we share */
1693
+ mutual_attestation_count: number;
1694
+ /** Overall trust assessment */
1695
+ trust_level: "high" | "medium" | "low" | "none";
1696
+ /** Reasoning for the assessment */
1697
+ factors: string[];
1698
+ /** Evaluated at */
1699
+ evaluated_at: string;
1700
+ }
1701
+
1702
+ /**
1703
+ * Sanctuary MCP Server — Federation Peer Registry
1704
+ *
1705
+ * Manages known federation peers. Peers are discovered through handshakes
1706
+ * and tracked for ongoing federation operations.
1707
+ *
1708
+ * The registry is the source of truth for:
1709
+ * - Who we've federated with
1710
+ * - Current trust status of each peer
1711
+ * - Peer capabilities (what operations they support)
1712
+ *
1713
+ * Security invariants:
1714
+ * - Peers are ONLY added through completed handshakes (not self-registration)
1715
+ * - Trust tiers degrade automatically when handshakes expire
1716
+ * - Peer data is stored encrypted under L1 sovereignty
1717
+ */
1718
+
1719
+ declare class FederationRegistry {
1720
+ private peers;
1653
1721
  /**
1654
- * Determine if this field is safe for URLs.
1722
+ * Register or update a peer from a completed handshake.
1723
+ * This is the ONLY way peers enter the registry.
1655
1724
  */
1656
- private isUrlSafeField;
1725
+ registerFromHandshake(result: HandshakeResult, peerDid: string, capabilities?: Partial<FederationCapabilities>): FederationPeer;
1657
1726
  /**
1658
- * Determine if this field is safe for emails.
1727
+ * Get a peer by instance ID.
1728
+ * Automatically updates active status based on handshake expiry.
1659
1729
  */
1660
- private isEmailSafeField;
1730
+ getPeer(peerId: string): FederationPeer | null;
1661
1731
  /**
1662
- * Determine if this field is safe for structured data (JSON/XML).
1732
+ * List all known peers, optionally filtered by status.
1663
1733
  */
1664
- private isStructuredField;
1734
+ listPeers(filter?: {
1735
+ active_only?: boolean;
1736
+ }): FederationPeer[];
1665
1737
  /**
1666
- * SEC-032/SEC-034: Map common cross-script confusable characters to their
1667
- * Latin equivalents. NFKC normalization handles fullwidth and compatibility
1668
- * forms, but does NOT map Cyrillic/Greek/Armenian/Georgian lookalikes to
1669
- * Latin (they're distinct codepoints by design).
1738
+ * Evaluate trust for a federation peer.
1670
1739
  *
1671
- * Extended to 50+ confusable pairs covering Cyrillic, Greek, Armenian,
1672
- * Georgian, Cherokee, and mathematical/symbol lookalikes.
1673
- */
1674
- private normalizeConfusables;
1675
- /**
1676
- * Compute confidence score based on signals.
1677
- * More high-severity signals = higher confidence.
1678
- */
1679
- private computeConfidence;
1680
- /**
1681
- * Compute recommendation based on signals and sensitivity.
1740
+ * Trust assessment considers:
1741
+ * - Handshake status (current vs expired)
1742
+ * - Sovereignty tier (verified-sovereign vs degraded vs unverified)
1743
+ * - Reputation data (if available)
1744
+ * - Mutual attestation history
1682
1745
  */
1683
- private computeRecommendation;
1746
+ evaluateTrust(peerId: string, mutualAttestationCount?: number, reputationScore?: number): PeerTrustEvaluation;
1684
1747
  /**
1685
- * Get statistics about scans performed.
1748
+ * Remove a peer from the registry.
1686
1749
  */
1687
- getStats(): {
1688
- total_scans: number;
1689
- total_flags: number;
1690
- total_blocks: number;
1691
- signals_by_type: Record<string, number>;
1692
- };
1750
+ removePeer(peerId: string): boolean;
1693
1751
  /**
1694
- * Reset statistics.
1752
+ * Get the handshake results map (for tier resolution integration).
1695
1753
  */
1696
- resetStats(): void;
1754
+ getHandshakeResults(): Map<string, HandshakeResult>;
1697
1755
  }
1698
1756
 
1699
1757
  /**
1700
- * Sanctuary MCP Server — Principal Policy Types
1758
+ * Sanctuary MCP Server — L2 Operational Isolation: Context Gating
1701
1759
  *
1702
- * Type definitions for the Principal Policy system.
1703
- * The Principal Policy is the human-controlled, agent-immutable
1704
- * configuration that gates operations through approval tiers.
1760
+ * Context gating controls what information leaves the sovereignty boundary
1761
+ * when an agent makes outbound calls — especially inference calls to remote
1762
+ * LLM providers. This is the "minimum-necessary context" enforcement layer.
1763
+ *
1764
+ * The problem: When an agent sends a request to a remote LLM provider (Claude,
1765
+ * GPT, etc.), most harnesses send the agent's full context — conversation
1766
+ * history, memory, tool results, preferences, internal reasoning. The agent
1767
+ * has no control over what the provider sees.
1768
+ *
1769
+ * Context gating lets the agent define:
1770
+ * - Provider categories (inference, tool-api, logging, analytics, etc.)
1771
+ * - What fields/categories of context may flow to each provider type
1772
+ * - What must always be redacted (secrets, internal reasoning, PII, etc.)
1773
+ * - What requires transformation (hashing, summarizing, anonymizing)
1774
+ *
1775
+ * This sits in L2 (Operational Isolation) because it controls information
1776
+ * flow at the execution boundary. L3 (Selective Disclosure) handles agent-
1777
+ * to-agent trust negotiation with cryptographic proofs; context gating
1778
+ * handles agent-to-infrastructure information flow.
1779
+ *
1780
+ * Security invariants:
1781
+ * - Redact rules take absolute priority (like withhold in L3)
1782
+ * - Policies are stored encrypted under L1 sovereignty
1783
+ * - Every filter operation is audit-logged with a content hash
1784
+ * (what was sent, what was redacted — without storing the content itself)
1785
+ * - Default policy: redact everything not explicitly allowed
1705
1786
  */
1706
- /** Tier 2 anomaly action: what to do when an anomaly is detected */
1707
- type AnomalyAction = "approve" | "log" | "allow";
1708
- /** Tier 2 anomaly detection configuration */
1709
- interface Tier2Config {
1710
- /** Action when agent accesses a namespace it hasn't used before */
1711
- new_namespace_access: AnomalyAction;
1712
- /** Action when agent interacts with an unknown counterparty DID */
1713
- new_counterparty: AnomalyAction;
1714
- /** Tool call frequency multiplier that triggers anomaly */
1715
- frequency_spike_multiplier: number;
1716
- /** Maximum signing operations per minute before triggering */
1717
- max_signs_per_minute: number;
1718
- /** Reading more than N keys in a namespace within 60 seconds */
1719
- bulk_read_threshold: number;
1720
- /** Policy for first session when no baseline exists */
1721
- first_session_policy: AnomalyAction;
1722
- }
1723
- /** Approval channel configuration */
1724
- interface ApprovalChannelConfig {
1725
- type: "stderr" | "webhook" | "callback";
1726
- timeout_seconds: number;
1727
- /**
1728
- * SEC-002: auto_deny is hardcoded to true and not configurable.
1729
- * Timeout on any approval channel ALWAYS results in denial.
1730
- * This field is retained for backward compatibility with existing
1731
- * policy files but is ignored — timeout always denies.
1732
- */
1733
- auto_deny?: boolean;
1734
- webhook_url?: string;
1735
- webhook_secret?: string;
1787
+
1788
+ /** Provider categories that context may flow to */
1789
+ type ProviderCategory = "inference" | "tool-api" | "logging" | "analytics" | "peer-agent" | "custom";
1790
+ /** Actions that can be taken on a context field */
1791
+ type ContextAction = "allow" | "redact" | "hash" | "summarize" | "deny";
1792
+ /** A rule within a context-gating policy */
1793
+ interface ContextGateRule {
1794
+ /** Provider category this rule applies to */
1795
+ provider: ProviderCategory | "*";
1796
+ /** Fields/patterns that may pass through */
1797
+ allow: string[];
1798
+ /** Fields/patterns that must be redacted (highest priority) */
1799
+ redact: string[];
1800
+ /** Fields/patterns that should be hashed */
1801
+ hash: string[];
1802
+ /** Fields/patterns that should be summarized (advisory) */
1803
+ summarize: string[];
1736
1804
  }
1737
- /** Complete Principal Policy */
1738
- interface PrincipalPolicy {
1739
- version: number;
1740
- /** Operations that always require human approval */
1741
- tier1_always_approve: string[];
1742
- /** Behavioral anomaly detection configuration */
1743
- tier2_anomaly: Tier2Config;
1744
- /** Operations that never require approval (audit only) */
1745
- tier3_always_allow: string[];
1746
- /** How approval requests reach the human */
1747
- approval_channel: ApprovalChannelConfig;
1805
+ /** A complete context-gating policy */
1806
+ interface ContextGatePolicy {
1807
+ policy_id: string;
1808
+ policy_name: string;
1809
+ rules: ContextGateRule[];
1810
+ /** Default action when no rule matches a field */
1811
+ default_action: "redact" | "deny";
1812
+ /** Identity this policy is bound to (optional) */
1813
+ identity_id?: string;
1814
+ created_at: string;
1815
+ updated_at: string;
1748
1816
  }
1749
- /** Approval request sent to the human */
1750
- interface ApprovalRequest {
1751
- operation: string;
1752
- tier: 1 | 2;
1817
+ /** Result of filtering a single field */
1818
+ interface FieldFilterResult {
1819
+ field: string;
1820
+ action: ContextAction;
1753
1821
  reason: string;
1754
- context: Record<string, unknown>;
1755
- timestamp: string;
1756
- }
1757
- /** Approval response from the human */
1758
- interface ApprovalResponse {
1759
- decision: "approve" | "deny";
1760
- decided_at: string;
1761
- decided_by: "human" | "timeout" | "auto" | "stderr:non-interactive";
1822
+ /** If action is "hash", contains the hash */
1823
+ hash_value?: string;
1762
1824
  }
1763
- /** Result of the approval gate evaluation */
1764
- interface GateResult {
1765
- allowed: boolean;
1766
- tier: 1 | 2 | 3;
1767
- reason: string;
1768
- approval_required: boolean;
1769
- approval_response?: ApprovalResponse;
1825
+ /** Result of a full context filter operation */
1826
+ interface ContextFilterResult {
1827
+ policy_id: string;
1828
+ provider: ProviderCategory | string;
1829
+ fields_allowed: number;
1830
+ fields_redacted: number;
1831
+ fields_hashed: number;
1832
+ fields_summarized: number;
1833
+ fields_denied: number;
1834
+ decisions: FieldFilterResult[];
1835
+ /** SHA-256 hash of the original context (for audit trail) */
1836
+ original_context_hash: string;
1837
+ /** SHA-256 hash of the filtered output (for audit trail) */
1838
+ filtered_context_hash: string;
1839
+ filtered_at: string;
1770
1840
  }
1771
- /** Behavioral baseline for anomaly detection */
1772
- interface SessionProfile {
1773
- /** Namespaces accessed (read or write) */
1774
- known_namespaces: string[];
1775
- /** Counterparty DIDs seen in reputation operations */
1776
- known_counterparties: string[];
1777
- /** Tool call counts per tool name (lifetime in session) */
1778
- tool_call_counts: Record<string, number>;
1779
- /** Whether this is the first session (no prior baseline) */
1780
- is_first_session: boolean;
1781
- /** Session start time */
1782
- started_at: string;
1783
- /** When the baseline was last saved */
1784
- saved_at?: string;
1841
+ /**
1842
+ * Evaluate a context field against a policy for a given provider.
1843
+ *
1844
+ * Priority order (same as L3 disclosure):
1845
+ * 1. Redact (blocks highest priority)
1846
+ * 2. Deny (blocks entire request)
1847
+ * 3. Hash (transforms)
1848
+ * 4. Summarize (advisory transform)
1849
+ * 5. Allow (passes through)
1850
+ * 6. Default action
1851
+ */
1852
+ declare function evaluateField(policy: ContextGatePolicy, provider: ProviderCategory | string, field: string): FieldFilterResult;
1853
+ /**
1854
+ * Filter a full context object against a policy for a given provider.
1855
+ * Returns per-field decisions and content hashes for the audit trail.
1856
+ */
1857
+ declare function filterContext(policy: ContextGatePolicy, provider: ProviderCategory | string, context: Record<string, unknown>): ContextFilterResult;
1858
+ /**
1859
+ * Context gate policy store — encrypted under L1 sovereignty.
1860
+ */
1861
+ declare class ContextGatePolicyStore {
1862
+ private storage;
1863
+ private encryptionKey;
1864
+ private policies;
1865
+ constructor(storage: StorageBackend, masterKey: Uint8Array);
1866
+ /**
1867
+ * Create and store a new context-gating policy.
1868
+ */
1869
+ create(policyName: string, rules: ContextGateRule[], defaultAction: "redact" | "deny", identityId?: string): Promise<ContextGatePolicy>;
1870
+ /**
1871
+ * Get a policy by ID.
1872
+ */
1873
+ get(policyId: string): Promise<ContextGatePolicy | null>;
1874
+ /**
1875
+ * List all context-gating policies.
1876
+ */
1877
+ list(): Promise<ContextGatePolicy[]>;
1878
+ /**
1879
+ * Load all persisted policies into memory.
1880
+ */
1881
+ private loadAll;
1882
+ private persist;
1785
1883
  }
1786
1884
 
1787
1885
  /**
1788
- * Sanctuary MCP Server — Approval Channel
1886
+ * Sanctuary MCP Server — L2 Context Gating: Starter Policy Templates
1789
1887
  *
1790
- * Out-of-band communication with the human principal for operation approval.
1791
- * The default channel uses stderr (outside MCP's stdin/stdout protocol),
1792
- * ensuring the agent cannot intercept or forge approval responses.
1888
+ * Pre-built policies for common use cases. These are starting points —
1889
+ * users should customize them for their specific context structure.
1793
1890
  *
1794
- * Security invariant:
1795
- * - Approval prompts go through a channel the agent cannot access.
1796
- * - Timeouts result in denial by default (fail closed).
1891
+ * Templates:
1892
+ *
1893
+ * inference-minimal
1894
+ * Only the current task and query reach the LLM. Everything else
1895
+ * is redacted. Secrets, PII, memory, reasoning, and history are
1896
+ * all blocked. IDs are hashed. Maximum privacy, minimum context.
1897
+ *
1898
+ * inference-standard
1899
+ * Task, query, and tool results pass through. Conversation history
1900
+ * is flagged for summarization (compress before sending). Secrets,
1901
+ * PII, and internal reasoning are redacted. IDs are hashed.
1902
+ * Balanced: the LLM has enough context to be useful without seeing
1903
+ * everything the agent knows.
1904
+ *
1905
+ * logging-strict
1906
+ * Redacts everything for logging/analytics providers. Only
1907
+ * operation names and timestamps pass through. Use this for
1908
+ * telemetry services where you want usage metrics without
1909
+ * content exposure.
1910
+ *
1911
+ * tool-api-scoped
1912
+ * Allows tool-specific parameters and the current task, redacts
1913
+ * memory, history, secrets, and PII. Hashes IDs. For outbound
1914
+ * calls to external APIs (search, database, etc.) where you need
1915
+ * to send query parameters but not your agent's full state.
1797
1916
  */
1798
1917
 
1799
- /** Abstract approval channel interface */
1800
- interface ApprovalChannel {
1801
- requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
1918
+ /** A template definition ready to be applied via the policy store */
1919
+ interface ContextGateTemplate {
1920
+ /** Machine-readable template ID */
1921
+ id: string;
1922
+ /** Human-readable name */
1923
+ name: string;
1924
+ /** One-line description */
1925
+ description: string;
1926
+ /** When to use this template */
1927
+ use_when: string;
1928
+ /** The rules that make up this template */
1929
+ rules: ContextGateRule[];
1930
+ /** Default action for unmatched fields */
1931
+ default_action: "redact" | "deny";
1802
1932
  }
1933
+ /** All available templates, keyed by ID */
1934
+ declare const TEMPLATES: Record<string, ContextGateTemplate>;
1935
+ /** List all available template IDs */
1936
+ declare function listTemplateIds(): string[];
1937
+ /** Get a template by ID (returns undefined if not found) */
1938
+ declare function getTemplate(id: string): ContextGateTemplate | undefined;
1939
+
1803
1940
  /**
1804
- * Stderr approval channelnon-interactive informational channel.
1941
+ * Sanctuary MCP ServerL2 Context Gating: Policy Recommendation Engine
1805
1942
  *
1806
- * In the MCP stdio model:
1807
- * - stdin/stdout carry the MCP protocol (JSON-RPC)
1808
- * - stderr is available for out-of-band human communication
1943
+ * Analyzes a sample context object and recommends a context-gating policy
1944
+ * based on field name heuristics. The agent (or human) can then review,
1945
+ * adjust, and apply the recommendation.
1809
1946
  *
1810
- * Because stdin is consumed by the MCP JSON-RPC transport, this channel
1811
- * CANNOT read interactive human input. It is strictly informational:
1812
- * the prompt is displayed so the human sees what is happening, and the
1813
- * operation is denied immediately.
1947
+ * This is deliberately conservative: when in doubt, it recommends redact.
1948
+ * A false redaction is a usability issue; a false allow is a privacy leak.
1814
1949
  *
1815
- * SEC-002 + SEC-016 invariants:
1816
- * - This channel ALWAYS denies. No configuration can change this.
1817
- * - There is no timeout or async delay — denial is synchronous.
1818
- * - The `auto_deny` config field is ignored (SEC-002).
1819
- * - For interactive approval, use the dashboard or webhook channel.
1950
+ * Classification heuristics:
1951
+ * - Known secret patterns redact (highest confidence)
1952
+ * - Known PII patterns redact (high confidence)
1953
+ * - Known internal state patterns redact (high confidence)
1954
+ * - Known ID patterns hash (medium confidence)
1955
+ * - Known history patterns → summarize (medium confidence)
1956
+ * - Known task/query patterns → allow (medium confidence)
1957
+ * - Everything else → redact (conservative default)
1958
+ *
1959
+ * WARNING: Fields like 'tool_results' and 'tool_output' are classified as
1960
+ * "allow" (medium confidence) but may contain sensitive data from external
1961
+ * API responses, including auth tokens, user data, or PII. Always review
1962
+ * recommendations before applying — the heuristic classifies by field NAME,
1963
+ * not field CONTENT.
1820
1964
  */
1821
- declare class StderrApprovalChannel implements ApprovalChannel {
1822
- constructor(_config: ApprovalChannelConfig);
1823
- requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
1824
- private formatPrompt;
1965
+ /** Classification result for a single field */
1966
+ interface FieldClassification {
1967
+ field: string;
1968
+ recommended_action: "allow" | "redact" | "hash" | "summarize";
1969
+ reason: string;
1970
+ confidence: "high" | "medium" | "low";
1971
+ /** Pattern that matched, if any */
1972
+ matched_pattern: string | null;
1973
+ }
1974
+ /** Full recommendation result */
1975
+ interface PolicyRecommendation {
1976
+ provider: string;
1977
+ classifications: FieldClassification[];
1978
+ recommended_rules: {
1979
+ allow: string[];
1980
+ redact: string[];
1981
+ hash: string[];
1982
+ summarize: string[];
1983
+ };
1984
+ default_action: "redact";
1985
+ summary: {
1986
+ total_fields: number;
1987
+ allow: number;
1988
+ redact: number;
1989
+ hash: number;
1990
+ summarize: number;
1991
+ };
1992
+ warnings: string[];
1825
1993
  }
1826
1994
  /**
1827
- * Programmatic approval channel for testing and API integration.
1995
+ * Classify a single field name and return a recommendation.
1828
1996
  */
1829
- declare class CallbackApprovalChannel implements ApprovalChannel {
1830
- private callback;
1831
- constructor(callback: (request: ApprovalRequest) => Promise<ApprovalResponse>);
1832
- requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
1833
- }
1997
+ declare function classifyField(fieldName: string): FieldClassification;
1834
1998
  /**
1835
- * Auto-approve channel for testing. Approves everything.
1999
+ * Analyze a full context object and recommend a policy.
1836
2000
  */
1837
- declare class AutoApproveChannel implements ApprovalChannel {
1838
- requestApproval(_request: ApprovalRequest): Promise<ApprovalResponse>;
1839
- }
2001
+ declare function recommendPolicy(context: Record<string, unknown>, provider?: string): PolicyRecommendation;
1840
2002
 
1841
2003
  /**
1842
- * Sanctuary MCP Server — Behavioral Baseline Tracker
2004
+ * Sanctuary MCP Server — L2 Model Provenance
1843
2005
  *
1844
- * Tracks the agent's behavioral profile during a session and persists
1845
- * it for cross-session anomaly detection. The baseline defines "normal"
1846
- * so that deviations can trigger Tier 2 approval.
2006
+ * Declares and attests to the model(s) powering this agent.
1847
2007
  *
1848
- * Security invariants:
1849
- * - Baseline is stored encrypted under L1 sovereignty
1850
- * - Baseline changes are audit-logged
1851
- * - Baseline is integrity-verified via L1 Merkle tree
1852
- * - No MCP tool can directly modify the baseline
2008
+ * Vitalik Buterin's "Secure LLM" post (April 2026) identified a critical gap:
2009
+ * open-weights-but-not-open-source models can have trained-in backdoors. Model
2010
+ * provenance declaration lets agents and their operators verify the integrity
2011
+ * of the inference backbone.
2012
+ *
2013
+ * Tracks: model name, version, weights hash, license, open-source status,
2014
+ * training data hash (if available). Included in SHR L2 section.
2015
+ *
2016
+ * This sits in L2 (Operational Isolation) because it's part of the runtime
2017
+ * attestation surface — the agent declares what model(s) it's actually running.
1853
2018
  */
1854
-
1855
- declare class BaselineTracker {
1856
- private storage;
1857
- private encryptionKey;
1858
- private profile;
1859
- /** Sliding window: timestamps of tool calls per tool name (last 60s) */
1860
- private callWindows;
1861
- /** Sliding window: read counts per namespace (last 60s) */
1862
- private readWindows;
1863
- /** Sliding window: sign call timestamps (last 60s) */
1864
- private signWindow;
1865
- constructor(storage: StorageBackend, masterKey: Uint8Array);
1866
- /**
1867
- * Load the previous session's baseline from storage.
1868
- * If none exists, this is a first session.
1869
- */
1870
- load(): Promise<void>;
1871
- /**
1872
- * Save the current baseline to storage (encrypted).
1873
- * Called at session end or periodically.
1874
- */
1875
- save(): Promise<void>;
1876
- /**
1877
- * Record a tool call for baseline tracking.
1878
- * Returns anomaly information if applicable.
1879
- */
1880
- recordToolCall(toolName: string): void;
1881
- /**
1882
- * Record a namespace access.
1883
- * @returns true if this is a new namespace (not in baseline)
1884
- */
1885
- recordNamespaceAccess(namespace: string): boolean;
2019
+ /**
2020
+ * Metadata about a single model powering this agent.
2021
+ */
2022
+ interface ModelProvenance {
2023
+ /** Machine-readable model ID (e.g., "qwen3.5-35b", "claude-opus-4", "llama-3.3-70b-instruct") */
2024
+ model_id: string;
2025
+ /** Human-readable model name (e.g., "Qwen 3.5", "Claude Opus 4", "Llama 3.3 70B Instruct") */
2026
+ model_name: string;
2027
+ /** Semantic version (e.g., "3.5", "4.0", "3.3") */
2028
+ model_version: string;
2029
+ /** Provider/vendor (e.g., "Alibaba Cloud", "Anthropic", "Meta", "local") */
2030
+ provider: string;
2031
+ /** SHA-256 of model weights file, if available and verifiable */
2032
+ weights_hash?: string;
2033
+ /** SHA-256 of training data manifest or metadata, if available */
2034
+ training_data_hash?: string;
2035
+ /** License identifier (e.g., "Apache-2.0", "CC-BY-4.0", "proprietary", "unknown") */
2036
+ license: string;
2037
+ /** True if model weights are publicly available (even if training is proprietary) */
2038
+ open_weights: boolean;
2039
+ /** True if full training code, data, and methodology are publicly available */
2040
+ open_source: boolean;
2041
+ /** True if inference runs on the local agent's hardware (not delegated to cloud API) */
2042
+ local_inference: boolean;
2043
+ /** ISO 8601 timestamp when this provenance was declared */
2044
+ declared_at: string;
2045
+ }
2046
+ /**
2047
+ * In-memory and persistent store for model provenance declarations.
2048
+ * Declarations are encrypted under L1 sovereignty.
2049
+ */
2050
+ interface ModelProvenanceStore {
1886
2051
  /**
1887
- * Record a namespace read for bulk-read detection.
1888
- * @returns the number of reads in the current 60-second window
2052
+ * Declare a model's provenance and add it to the store.
1889
2053
  */
1890
- recordNamespaceRead(namespace: string): number;
2054
+ declare(provenance: ModelProvenance): void;
1891
2055
  /**
1892
- * Record a counterparty DID interaction.
1893
- * @returns true if this is a new counterparty (not in baseline)
2056
+ * Retrieve a model's provenance by ID.
1894
2057
  */
1895
- recordCounterparty(did: string): boolean;
2058
+ get(model_id: string): ModelProvenance | undefined;
1896
2059
  /**
1897
- * Record a signing operation.
1898
- * @returns the number of signs in the current 60-second window
2060
+ * List all declared models.
1899
2061
  */
1900
- recordSign(): number;
2062
+ list(): ModelProvenance[];
1901
2063
  /**
1902
- * Get the current call rate for a tool (calls per minute).
2064
+ * Get the primary/main model (the one the agent uses by default for inference).
1903
2065
  */
1904
- getCallRate(toolName: string): number;
2066
+ primary(): ModelProvenance | undefined;
1905
2067
  /**
1906
- * Get the average call rate across all tools in the baseline.
2068
+ * Set which model is the primary.
1907
2069
  */
1908
- getAverageCallRate(): number;
1909
- /** Whether this is the first session */
1910
- get isFirstSession(): boolean;
1911
- /** Get a read-only view of the current profile */
1912
- getProfile(): SessionProfile;
2070
+ setPrimary(model_id: string): void;
1913
2071
  }
1914
-
1915
2072
  /**
1916
- * Sanctuary MCP Server — Approval Gate
1917
- *
1918
- * The three-tier approval gate sits between the MCP router and tool handlers.
1919
- * Every tool call passes through the gate before execution.
1920
- *
1921
- * Evaluation order:
1922
- * 1. Tier 1: Is this operation in the always-approve list? → Request approval.
1923
- * 2. Tier 2: Does this call represent a behavioral anomaly? → Request approval.
1924
- * 3. Tier 3 / default: Allow with audit logging.
1925
- *
1926
- * Security invariants:
1927
- * - The gate cannot be bypassed — it wraps every tool handler.
1928
- * - Denial responses do not reveal policy details to the agent.
1929
- * - All gate decisions (approve, deny, allow) are audit-logged.
2073
+ * In-memory implementation of ModelProvenanceStore.
2074
+ * Suitable for most use cases. For encrypted persistence, integrate with L1 state store.
1930
2075
  */
1931
-
1932
- /** Callback invoked when an injection is detected, for dashboard broadcasting */
1933
- type InjectionAlertCallback = (alert: {
1934
- toolName: string;
1935
- result: DetectionResult;
1936
- timestamp: string;
1937
- }) => void;
1938
- /** Resolver for proxy tool tiers — provided by the ProxyRouter */
1939
- type ProxyTierResolver = (toolName: string) => (1 | 2 | 3) | null;
1940
- declare class ApprovalGate {
1941
- private policy;
1942
- private baseline;
1943
- private channel;
1944
- private auditLog;
1945
- private injectionDetector;
1946
- private onInjectionAlert?;
1947
- private proxyTierResolver?;
1948
- constructor(policy: PrincipalPolicy, baseline: BaselineTracker, channel: ApprovalChannel, auditLog: AuditLog, injectionDetector?: InjectionDetector, onInjectionAlert?: InjectionAlertCallback);
1949
- /**
1950
- * Set the proxy tier resolver. Called after the proxy router is initialized.
1951
- */
1952
- setProxyTierResolver(resolver: ProxyTierResolver): void;
2076
+ declare class InMemoryModelProvenanceStore implements ModelProvenanceStore {
2077
+ private models;
2078
+ private primaryModelId;
2079
+ declare(provenance: ModelProvenance): void;
2080
+ get(model_id: string): ModelProvenance | undefined;
2081
+ list(): ModelProvenance[];
2082
+ primary(): ModelProvenance | undefined;
2083
+ setPrimary(model_id: string): void;
2084
+ }
2085
+ /**
2086
+ * Common model provenance presets for quick initialization.
2087
+ */
2088
+ declare const MODEL_PRESETS: {
1953
2089
  /**
1954
- * Evaluate a tool call against the Principal Policy.
1955
- *
1956
- * @param toolName - Full MCP tool name (e.g., "state_export")
1957
- * @param args - Tool call arguments (for context extraction)
1958
- * @returns GateResult indicating whether the call is allowed
2090
+ * Claude Opus 4 via Anthropic API (cloud inference, closed weights/source)
1959
2091
  */
1960
- evaluate(toolName: string, args: Record<string, unknown>): Promise<GateResult>;
2092
+ claudeOpus4: () => ModelProvenance;
1961
2093
  /**
1962
- * Detect Tier 2 behavioral anomalies.
2094
+ * Qwen 3.5 via local inference (open weights, proprietary training)
1963
2095
  */
1964
- private detectAnomaly;
2096
+ qwen35Local: () => ModelProvenance;
1965
2097
  /**
1966
- * Request approval from the human principal.
2098
+ * Llama 3.3 70B via local inference (open weights and code)
1967
2099
  */
1968
- private requestApproval;
2100
+ llama33Local: () => ModelProvenance;
1969
2101
  /**
1970
- * Summarize tool arguments for the approval prompt.
1971
- * Strips potentially large values to keep the prompt readable.
2102
+ * Mistral 7B (open weights, open code, local inference)
1972
2103
  */
1973
- private summarizeArgs;
1974
- /** Get the baseline tracker for saving at session end */
1975
- getBaseline(): BaselineTracker;
1976
- /** Get the injection detector for stats/configuration access */
1977
- getInjectionDetector(): InjectionDetector;
1978
- }
1979
-
1980
- /**
1981
- * Sanctuary MCP Server — Tool Router
1982
- *
1983
- * Routes sanctuary/* tool calls to their layer-specific handlers.
1984
- * Every tool call passes through schema validation and the ApprovalGate
1985
- * (if configured) before execution. Neither can be bypassed.
1986
- *
1987
- * This module is the abstraction boundary for MCP SDK version migration —
1988
- * if the SDK API changes, only this module needs updating.
1989
- */
1990
-
1991
- /** Tool handler function signature */
1992
- type ToolHandler = (args: Record<string, unknown>) => Promise<{
1993
- content: Array<{
1994
- type: "text";
1995
- text: string;
1996
- }>;
1997
- }>;
1998
- /** Tool definition for registration */
1999
- interface ToolDefinition {
2000
- name: string;
2001
- description: string;
2002
- inputSchema: Record<string, unknown>;
2003
- handler: ToolHandler;
2004
- }
2104
+ mistral7bLocal: () => ModelProvenance;
2105
+ };
2005
2106
 
2006
2107
  /**
2007
2108
  * Sanctuary MCP Server — L2 Context Gating: Automatic Enforcer
@@ -2620,37 +2721,6 @@ declare class FilesystemStorage implements StorageBackend {
2620
2721
  */
2621
2722
  declare function loadPrincipalPolicy(storagePath: string): Promise<PrincipalPolicy>;
2622
2723
 
2623
- /**
2624
- * Sanctuary MCP Server — L1 Cognitive Sovereignty: Tool Definitions
2625
- *
2626
- * MCP tool wrappers for StateStore and IdentityRoot operations.
2627
- * These tools are the public API that agents interact with.
2628
- */
2629
-
2630
- /** Manages all identities — provides storage and retrieval */
2631
- declare class IdentityManager {
2632
- private storage;
2633
- private masterKey;
2634
- private identities;
2635
- private primaryIdentityId;
2636
- constructor(storage: StorageBackend, masterKey: Uint8Array);
2637
- private get encryptionKey();
2638
- /** Load identities from storage on startup.
2639
- * Returns { total: number of encrypted files found, loaded: number successfully decrypted }.
2640
- * A mismatch (total > 0, loaded === 0) indicates a wrong master key / missing passphrase.
2641
- */
2642
- load(): Promise<{
2643
- total: number;
2644
- loaded: number;
2645
- failed: number;
2646
- }>;
2647
- /** Save an identity to storage */
2648
- save(identity: StoredIdentity): Promise<void>;
2649
- get(id: string): StoredIdentity | undefined;
2650
- getDefault(): StoredIdentity | undefined;
2651
- list(): PublicIdentity[];
2652
- }
2653
-
2654
2724
  /**
2655
2725
  * Sanctuary MCP Server — SHR Generator
2656
2726
  *
@@ -2658,12 +2728,56 @@ declare class IdentityManager {
2658
2728
  * signs it with a specified identity, and returns the complete signed SHR.
2659
2729
  */
2660
2730
 
2731
+ /**
2732
+ * Observed L4 reputation state used by the emitter. Callers gather these
2733
+ * facts from the reputation store + audit log; the emitter derives
2734
+ * degradations from them. Keeping evidence as plain data keeps the
2735
+ * generator synchronous and easy to test.
2736
+ */
2737
+ interface L4Evidence {
2738
+ /** Total attestations attributed to the signing identity */
2739
+ attestation_count: number;
2740
+ /** Count of attestations at each sovereignty tier */
2741
+ tier_distribution: Record<SovereigntyTier, number>;
2742
+ /** ISO timestamp of most recent attestation, or null when none exist */
2743
+ most_recent_attestation_at: string | null;
2744
+ /** Count of attestations with outcome_result === "disputed" */
2745
+ dispute_count: number;
2746
+ /** Attestation count per context label (optional; used by dashboard) */
2747
+ context_breakdown?: Record<string, number>;
2748
+ /**
2749
+ * True iff the `reputation_publish` tool has been successfully invoked
2750
+ * for this identity (i.e., there is at least one success audit entry).
2751
+ */
2752
+ verascore_linked: boolean;
2753
+ /**
2754
+ * Optional overrides for the emitter thresholds. Defaults apply when
2755
+ * omitted or when a field is missing.
2756
+ */
2757
+ thresholds?: {
2758
+ freshness_window_days?: number;
2759
+ low_tier_dominance_threshold?: number;
2760
+ };
2761
+ }
2661
2762
  interface SHRGeneratorOptions {
2662
2763
  config: SanctuaryConfig;
2663
2764
  identityManager: IdentityManager;
2664
2765
  masterKey: Uint8Array;
2665
2766
  /** Override validity window (milliseconds). Default: 1 hour. */
2666
2767
  validityMs?: number;
2768
+ /**
2769
+ * Optional L4 reputation evidence. When provided, the generator emits
2770
+ * L4 degradations (NO_REPUTATION_HISTORY, LOW_TIER_DOMINANCE,
2771
+ * STALE_REPUTATION, DISPUTE_ON_RECORD, NO_VERASCORE_LINK) accordingly
2772
+ * and downgrades `layers.l4.status` to `degraded` when any fire.
2773
+ * When omitted, L4 is left at "active" (backward-compatible).
2774
+ */
2775
+ l4Evidence?: L4Evidence;
2776
+ /**
2777
+ * Clock override for deterministic testing of staleness behavior.
2778
+ * Defaults to the current wall clock.
2779
+ */
2780
+ now?: Date;
2667
2781
  }
2668
2782
  /**
2669
2783
  * Generate and sign a Sovereignty Health Report.
@@ -3358,6 +3472,279 @@ declare function createBridgeCommitment(outcome: ConcordiaOutcome, identity: Sto
3358
3472
  */
3359
3473
  declare function verifyBridgeCommitment(commitment: BridgeCommitment, outcome: ConcordiaOutcome, committerPublicKey: Uint8Array): BridgeVerificationResult;
3360
3474
 
3475
+ /**
3476
+ * Sanctuary Dashboard — Protection Snapshot Aggregator
3477
+ *
3478
+ * Pulls unified protection state from the existing subsystems
3479
+ * (IdentityManager, AuditLog, ClientManager, BaselineTracker, policy)
3480
+ * and returns a single typed snapshot consumed by the API + HTML.
3481
+ *
3482
+ * The aggregator is the single source of truth for dashboard state.
3483
+ * It is pure (no I/O beyond what the injected sources already do) and
3484
+ * safe to call repeatedly — callers control freshness.
3485
+ */
3486
+
3487
+ type LayerState = "full" | "degraded" | "compromised";
3488
+ type OverallStatus = "healthy" | "degraded" | "compromised";
3489
+ interface AgentInfo {
3490
+ display_name: string;
3491
+ did: string | null;
3492
+ did_fingerprint: string | null;
3493
+ identity_count: number;
3494
+ primary_identity_id: string | null;
3495
+ }
3496
+ interface L1Status {
3497
+ label: string;
3498
+ state: LayerState;
3499
+ headline: string;
3500
+ encryption: string;
3501
+ injection_blocked_today: number;
3502
+ memory_attest_ready: boolean;
3503
+ }
3504
+ interface L2Status {
3505
+ label: string;
3506
+ state: LayerState;
3507
+ headline: string;
3508
+ isolation_type: string;
3509
+ tee_available: boolean;
3510
+ tee_status: string;
3511
+ sandbox_status: string;
3512
+ }
3513
+ interface L3Status {
3514
+ label: string;
3515
+ state: LayerState;
3516
+ headline: string;
3517
+ did_active: boolean;
3518
+ vc_count: number;
3519
+ proofs_today: number;
3520
+ }
3521
+ /** A single L4 degradation surfaced to the dashboard widget. */
3522
+ interface L4ActiveDegradation {
3523
+ code: string;
3524
+ severity: "info" | "warning" | "critical";
3525
+ description: string;
3526
+ mitigation?: string;
3527
+ }
3528
+ interface L4Status {
3529
+ label: string;
3530
+ state: LayerState;
3531
+ headline: string;
3532
+ score: number | null;
3533
+ profile_url: string | null;
3534
+ claim_cta: string | null;
3535
+ /**
3536
+ * Evidence surfaced under the L4 tile so users can tell what underlies
3537
+ * the reputation state. Null when no reputation store is wired in
3538
+ * (standalone mode, some tests).
3539
+ */
3540
+ evidence?: {
3541
+ attestation_count: number;
3542
+ tier_distribution: Record<SovereigntyTier, number>;
3543
+ most_recent_attestation_at: string | null;
3544
+ dispute_count: number;
3545
+ context_breakdown: Record<string, number>;
3546
+ verascore_linked: boolean;
3547
+ };
3548
+ /**
3549
+ * SHR-aligned L4 layer score (0-100) when evidence is available.
3550
+ * Computed with the same scoring model the gateway adapter uses so
3551
+ * counterparties and the dashboard agree on the number.
3552
+ */
3553
+ layer_score?: number;
3554
+ /** Active L4 degradations rendered under the widget. */
3555
+ active_degradations?: L4ActiveDegradation[];
3556
+ }
3557
+ interface ActivityEntry {
3558
+ timestamp: string;
3559
+ tool: string;
3560
+ server: string;
3561
+ tier: 1 | 2 | 3;
3562
+ result: "allowed" | "denied" | "approved" | "pending";
3563
+ }
3564
+ interface PendingApproval {
3565
+ id: string;
3566
+ operation: string;
3567
+ tier: 1 | 2;
3568
+ reason: string;
3569
+ created_at: string;
3570
+ }
3571
+ interface UpstreamServerStatus {
3572
+ name: string;
3573
+ state: string;
3574
+ tool_count: number;
3575
+ error?: string;
3576
+ }
3577
+ interface ProtectionSnapshot {
3578
+ overall: {
3579
+ status: OverallStatus;
3580
+ light: "green" | "yellow" | "red";
3581
+ headline: string;
3582
+ };
3583
+ agent: AgentInfo;
3584
+ layers: {
3585
+ l1: L1Status;
3586
+ l2: L2Status;
3587
+ l3: L3Status;
3588
+ l4: L4Status;
3589
+ };
3590
+ activity: ActivityEntry[];
3591
+ pending_approvals: PendingApproval[];
3592
+ audit: AuditEntry[];
3593
+ upstream_servers: UpstreamServerStatus[];
3594
+ mode: "co-located" | "standalone";
3595
+ server_version: string;
3596
+ generated_at: string;
3597
+ }
3598
+ interface ReputationLookup {
3599
+ score: number | null;
3600
+ profile_url: string | null;
3601
+ }
3602
+ interface AggregatorSources {
3603
+ mode: "co-located" | "standalone";
3604
+ server_version: string;
3605
+ identityManager?: IdentityManager;
3606
+ auditLog?: AuditLog;
3607
+ clientManager?: ClientManager;
3608
+ baseline?: BaselineTracker;
3609
+ policy?: PrincipalPolicy;
3610
+ activity?: ActivityEntry[];
3611
+ pendingApprovals?: PendingApproval[];
3612
+ reputation?: ReputationLookup;
3613
+ teeAvailable?: boolean;
3614
+ /**
3615
+ * Pre-computed L4 reputation evidence for the primary identity. When
3616
+ * present the dashboard renders the evidence widget under the L4 tile
3617
+ * and computes an SHR-aligned L4 layer score. Providers build this
3618
+ * via `gatherL4Evidence` from `shr/tools.ts`.
3619
+ */
3620
+ l4Evidence?: L4Evidence;
3621
+ /** Clock override for deterministic staleness rendering in tests. */
3622
+ l4Now?: Date;
3623
+ }
3624
+ /**
3625
+ * Pull a unified protection snapshot from the injected sources.
3626
+ *
3627
+ * Any missing source degrades gracefully — standalone mode may have
3628
+ * no ClientManager or live activity feed, for example, and the
3629
+ * aggregator returns a coherent snapshot with empty arrays rather
3630
+ * than throwing.
3631
+ */
3632
+ declare function getProtectionSnapshot(sources: AggregatorSources): Promise<ProtectionSnapshot>;
3633
+
3634
+ /**
3635
+ * Sanctuary Dashboard — HTTP API + SSE
3636
+ *
3637
+ * Request router for the unified dashboard. Pure functions that
3638
+ * take a request + sources and produce a response so the transport
3639
+ * layer (node:http) and tests can exercise the same code paths.
3640
+ */
3641
+
3642
+ interface ApprovalHandlers {
3643
+ allow: (id: string) => Promise<boolean>;
3644
+ deny: (id: string) => Promise<boolean>;
3645
+ }
3646
+ interface StreamEvent {
3647
+ type: "snapshot" | "activity" | "approval";
3648
+ data: unknown;
3649
+ }
3650
+
3651
+ /**
3652
+ * Sanctuary Dashboard — HTTP Server
3653
+ *
3654
+ * Thin wrapper around node:http that wires the request handler
3655
+ * from api.ts. No Express. Listens on 127.0.0.1 by default.
3656
+ *
3657
+ * Exposes a minimal event emitter (publish / subscribe) so callers
3658
+ * can push live activity + approval events to SSE clients without
3659
+ * the server layer needing to know about aggregator internals.
3660
+ */
3661
+
3662
+ interface DashboardServerOptions {
3663
+ port?: number;
3664
+ host?: string;
3665
+ authToken?: string;
3666
+ mode: "co-located" | "standalone";
3667
+ sources: AggregatorSources;
3668
+ approvals?: ApprovalHandlers;
3669
+ }
3670
+ interface DashboardHandle {
3671
+ url: string;
3672
+ port: number;
3673
+ host: string;
3674
+ stop: () => Promise<void>;
3675
+ /** Push an event to all connected SSE clients. */
3676
+ publish: (event: StreamEvent) => void;
3677
+ /**
3678
+ * Push a fresh activity entry. Exposes a simple shortcut so callers
3679
+ * (e.g. the Sanctuary proxy / upstream clients) can report tool calls
3680
+ * without constructing a StreamEvent themselves.
3681
+ */
3682
+ publishActivity: (entry: ActivityEntry) => void;
3683
+ /** Push a new pending approval (already added by the approval channel). */
3684
+ publishApproval: (approval: PendingApproval) => void;
3685
+ }
3686
+ declare function startDashboardServer(options: DashboardServerOptions): Promise<DashboardHandle>;
3687
+
3688
+ /**
3689
+ * Sanctuary Dashboard — Single-Page HTML
3690
+ *
3691
+ * Hero shield + four layer cards + live activity feed + approval queue +
3692
+ * audit trail. Vanilla HTML/CSS/JS in one string, matching the convention
3693
+ * established by server/src/cocoon/fortress-view.ts.
3694
+ *
3695
+ * The initial snapshot is embedded server-side so the page renders
3696
+ * correctly without JavaScript. Live updates layer on via SSE + REST.
3697
+ */
3698
+
3699
+ /** Hero copy. Change here if we ever A/B test. */
3700
+ declare const HERO_COPY = "Your agent is protected.";
3701
+ interface DashboardHTMLOptions {
3702
+ snapshot: ProtectionSnapshot;
3703
+ authToken?: string;
3704
+ }
3705
+ declare function renderDashboardHTML(options: DashboardHTMLOptions): string;
3706
+
3707
+ /**
3708
+ * Sanctuary Sovereignty Dashboard — public surface.
3709
+ *
3710
+ * Consumers import `startDashboard` to bring up the hero-shield UI
3711
+ * on port 3501 (default). The rest of the exports are types + utilities
3712
+ * for tests and callers that want to wire in live events.
3713
+ */
3714
+
3715
+ interface StartDashboardOptions {
3716
+ port?: number;
3717
+ host?: string;
3718
+ authToken?: string;
3719
+ mode: "co-located" | "standalone";
3720
+ serverVersion: string;
3721
+ auditLog?: AuditLog;
3722
+ identityManager?: IdentityManager;
3723
+ clientManager?: ClientManager;
3724
+ baseline?: BaselineTracker;
3725
+ policy?: PrincipalPolicy;
3726
+ reputation?: ReputationLookup;
3727
+ teeAvailable?: boolean;
3728
+ approvals?: ApprovalHandlers;
3729
+ /** Seed activity entries (most recent first). Runtime entries arrive via publishActivity. */
3730
+ initialActivity?: ActivityEntry[];
3731
+ /** Seed pending approvals. Runtime approvals arrive via publishApproval. */
3732
+ initialPendingApprovals?: PendingApproval[];
3733
+ /**
3734
+ * Pre-computed L4 reputation evidence. When provided the dashboard
3735
+ * renders the L4 evidence widget (attestation count, tier distribution,
3736
+ * disputes, freshness, active degradations). Typically supplied by the
3737
+ * server after L4 tools are constructed.
3738
+ */
3739
+ l4Evidence?: L4Evidence;
3740
+ }
3741
+ /**
3742
+ * High-level entry point used by callers (CLI, standalone service).
3743
+ * Returns a DashboardHandle that exposes `stop()` and `publish*`
3744
+ * helpers for driving live updates.
3745
+ */
3746
+ declare function startDashboard(options: StartDashboardOptions): Promise<DashboardHandle>;
3747
+
3361
3748
  /**
3362
3749
  * Sanctuary MCP Server — Main Entry Point
3363
3750
  *
@@ -3368,6 +3755,16 @@ declare function verifyBridgeCommitment(commitment: BridgeCommitment, outcome: C
3368
3755
  interface SanctuaryServer {
3369
3756
  server: Server;
3370
3757
  config: SanctuaryConfig;
3758
+ /**
3759
+ * Runtime dependencies exposed for embedding callers that need
3760
+ * direct access to the Sanctuary substrate (e.g., the EU AI Act
3761
+ * compliance CLI subcommand). Most callers only use `server` and
3762
+ * `config`; these are optional-usage extras.
3763
+ */
3764
+ identityManager: IdentityManager;
3765
+ masterKey: Uint8Array;
3766
+ auditLog: AuditLog;
3767
+ policy: PrincipalPolicy;
3371
3768
  }
3372
3769
  /**
3373
3770
  * Initialize the Sanctuary MCP Server.
@@ -3381,4 +3778,4 @@ declare function createSanctuaryServer(options?: {
3381
3778
  storage?: StorageBackend;
3382
3779
  }): Promise<SanctuaryServer>;
3383
3780
 
3384
- export { ATTESTATION_VERSION, ApprovalGate, type AttestationBody, type AttestationVerificationResult, AuditLog, AutoApproveChannel, BaselineTracker, type BridgeAttestationRequest, type BridgeAttestationResult, type BridgeCommitment, type BridgeVerificationResult, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, ClientManager, CommitmentStore, type ConcordiaOutcome, type ConnectionState, type ContextAction, type ContextFilterResult, ContextGateEnforcer, type ContextGatePolicy, ContextGatePolicyStore, type ContextGateRule, type ContextGateTemplate, DashboardApprovalChannel, type DashboardConfig, type DetectionResult, type EnforcerConfig, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, MODEL_PRESETS, MemoryStorage, type ModelProvenance, type ModelProvenanceStore, type PedersenCommitment, type PeerTrustEvaluation, type PolicyRecommendation, PolicyStore, type PrincipalPolicy, type ProviderCategory, ProxyRouter, type ProxyRouterOptions, ReputationStore, type SHRBody, type SHRGeneratorOptions, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedAttestation, type SignedSHR, type SovereigntyProfile, SovereigntyProfileStore, type SovereigntyProfileUpdate, type SovereigntyTier, StateStore, StderrApprovalChannel, TIER_WEIGHTS, type TierMetadata, type TieredAttestation, type UpstreamConnection, type UpstreamServer, type UpstreamTool, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, 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 };
3781
+ export { ATTESTATION_VERSION, type ActivityEntry, type AggregatorSources, ApprovalGate, type ApprovalHandlers, type AttestationBody, type AttestationVerificationResult, AuditLog, AutoApproveChannel, BaselineTracker, type BridgeAttestationRequest, type BridgeAttestationResult, type BridgeCommitment, type BridgeVerificationResult, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, ClientManager, CommitmentStore, type ConcordiaOutcome, type ConnectionState, type ContextAction, type ContextFilterResult, ContextGateEnforcer, type ContextGatePolicy, ContextGatePolicyStore, type ContextGateRule, type ContextGateTemplate, DashboardApprovalChannel, type DashboardConfig, type DashboardHandle, type DashboardServerOptions, type DetectionResult, type EnforcerConfig, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, HERO_COPY, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, type L1Status, type L2Status, type L3Status, type L4Status, MODEL_PRESETS, MemoryStorage, type ModelProvenance, type ModelProvenanceStore, type PedersenCommitment, type PeerTrustEvaluation, type PendingApproval, type PolicyRecommendation, PolicyStore, type PrincipalPolicy, type ProtectionSnapshot, type ProviderCategory, ProxyRouter, type ProxyRouterOptions, type ReputationLookup, ReputationStore, type SHRBody, type SHRGeneratorOptions, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedAttestation, type SignedSHR, type SovereigntyProfile, SovereigntyProfileStore, type SovereigntyProfileUpdate, type SovereigntyTier, type StartDashboardOptions, StateStore, StderrApprovalChannel, type StreamEvent, TIER_WEIGHTS, type TierMetadata, type TieredAttestation, type UpstreamConnection, type UpstreamServer, type UpstreamTool, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getProtectionSnapshot, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, renderDashboardHTML, resolveTier, respondToHandshake, signPayload, startDashboard, startDashboardServer, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };