@sanctuary-framework/mcp-server 0.2.0 → 0.3.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.ts CHANGED
@@ -37,6 +37,29 @@ interface SanctuaryConfig {
37
37
  };
38
38
  transport: "stdio" | "http";
39
39
  http_port: number;
40
+ dashboard: {
41
+ enabled: boolean;
42
+ port: number;
43
+ host: string;
44
+ /** Bearer token for dashboard auth. If "auto", one is generated at startup. */
45
+ auth_token?: string;
46
+ /** TLS cert/key paths for HTTPS dashboard. */
47
+ tls?: {
48
+ cert_path: string;
49
+ key_path: string;
50
+ };
51
+ };
52
+ webhook: {
53
+ enabled: boolean;
54
+ /** URL to POST approval requests to */
55
+ url: string;
56
+ /** Shared secret for HMAC-SHA256 signatures */
57
+ secret: string;
58
+ /** Port for callback listener (receives approval responses) */
59
+ callback_port: number;
60
+ /** Host for callback listener */
61
+ callback_host: string;
62
+ };
40
63
  }
41
64
  /**
42
65
  * Load configuration from file, falling back to defaults.
@@ -347,6 +370,150 @@ declare class CommitmentStore {
347
370
  markRevealed(id: string): Promise<void>;
348
371
  }
349
372
 
373
+ /**
374
+ * Sanctuary MCP Server — L3 Selective Disclosure: Zero-Knowledge Proofs
375
+ *
376
+ * Upgrades the commitment-only L3 to support real zero-knowledge proofs.
377
+ * Uses Ristretto255 (prime-order curve group, no cofactor issues) for:
378
+ *
379
+ * 1. Pedersen commitments: C = v*G + b*H (computationally hiding, perfectly binding)
380
+ * 2. ZK proof of knowledge: Schnorr sigma protocol via Fiat-Shamir
381
+ * 3. ZK range proofs: Prove value ∈ [min, max] without revealing it
382
+ *
383
+ * Ristretto255 is available via @noble/curves/ed25519, which we already depend on.
384
+ * This is genuine zero-knowledge — proofs reveal nothing beyond the stated property.
385
+ *
386
+ * Architecture note:
387
+ * The existing commitment scheme (SHA-256 based) remains available for backward
388
+ * compatibility. The ZK proofs operate on a separate Pedersen commitment system
389
+ * that provides algebraic structure for proper ZK properties.
390
+ *
391
+ * Security invariants:
392
+ * - Generator H is derived via hash-to-curve (nothing-up-my-sleeve)
393
+ * - Blinding factors are cryptographically random (32 bytes)
394
+ * - Fiat-Shamir challenges use domain-separated hashing
395
+ * - Range proofs use a bit-decomposition approach (sound but logarithmic size)
396
+ */
397
+ /** A Pedersen commitment: C = v*G + b*H */
398
+ interface PedersenCommitment {
399
+ /** The commitment point (encoded as base64url) */
400
+ commitment: string;
401
+ /** The blinding factor b (base64url, 32 bytes) — keep secret */
402
+ blinding_factor: string;
403
+ /** When the commitment was created */
404
+ committed_at: string;
405
+ }
406
+ /** A non-interactive ZK proof of knowledge of a commitment's opening */
407
+ interface ZKProofOfKnowledge {
408
+ /** Proof type identifier */
409
+ type: "schnorr-pedersen-ristretto255";
410
+ /** The commitment this proof is for */
411
+ commitment: string;
412
+ /** Announcement point R (base64url) */
413
+ announcement: string;
414
+ /** Response scalar s_v (base64url) */
415
+ response_v: string;
416
+ /** Response scalar s_b (base64url) */
417
+ response_b: string;
418
+ /** Proof generated at */
419
+ generated_at: string;
420
+ }
421
+ /** A ZK range proof: proves value ∈ [min, max] */
422
+ interface ZKRangeProof {
423
+ /** Proof type identifier */
424
+ type: "range-pedersen-ristretto255";
425
+ /** The commitment this proof is for */
426
+ commitment: string;
427
+ /** Minimum value (inclusive) */
428
+ min: number;
429
+ /** Maximum value (inclusive) */
430
+ max: number;
431
+ /** Bit commitments for the shifted value (v - min) */
432
+ bit_commitments: string[];
433
+ /** Proofs that each bit commitment is 0 or 1 */
434
+ bit_proofs: Array<{
435
+ announcement_0: string;
436
+ announcement_1: string;
437
+ challenge_0: string;
438
+ challenge_1: string;
439
+ response_0: string;
440
+ response_1: string;
441
+ }>;
442
+ /** Sum proof: bit commitments sum to the value commitment */
443
+ sum_proof: {
444
+ announcement: string;
445
+ response: string;
446
+ };
447
+ /** Proof generated at */
448
+ generated_at: string;
449
+ }
450
+ /**
451
+ * Create a Pedersen commitment to a numeric value.
452
+ *
453
+ * C = v*G + b*H
454
+ *
455
+ * Properties:
456
+ * - Computationally hiding (under discrete log assumption)
457
+ * - Perfectly binding (information-theoretic)
458
+ * - Homomorphic: C(v1) + C(v2) = C(v1+v2) with adjusted blinding
459
+ *
460
+ * @param value - The value to commit to (integer)
461
+ * @returns The commitment and blinding factor
462
+ */
463
+ declare function createPedersenCommitment(value: number): PedersenCommitment;
464
+ /**
465
+ * Verify a Pedersen commitment against a revealed value and blinding factor.
466
+ *
467
+ * Recomputes C' = v*G + b*H and checks C' == C.
468
+ */
469
+ declare function verifyPedersenCommitment(commitment: string, value: number, blindingFactor: string): boolean;
470
+ /**
471
+ * Create a non-interactive ZK proof that you know the opening (v, b)
472
+ * of a Pedersen commitment C = v*G + b*H.
473
+ *
474
+ * Schnorr sigma protocol with Fiat-Shamir transform:
475
+ * 1. Pick random r_v, r_b
476
+ * 2. Compute R = r_v*G + r_b*H (announcement)
477
+ * 3. Compute e = H_FS(C || R) (challenge via Fiat-Shamir)
478
+ * 4. Compute s_v = r_v + e*v, s_b = r_b + e*b (responses)
479
+ * 5. Proof = (R, s_v, s_b)
480
+ *
481
+ * Zero-knowledge: the transcript (R, e, s_v, s_b) can be simulated
482
+ * without knowing (v, b), so it reveals nothing.
483
+ *
484
+ * @param value - The committed value
485
+ * @param blindingFactor - The blinding factor (base64url)
486
+ * @param commitment - The commitment (base64url)
487
+ */
488
+ declare function createProofOfKnowledge(value: number, blindingFactor: string, commitment: string): ZKProofOfKnowledge;
489
+ /**
490
+ * Verify a ZK proof of knowledge of a commitment's opening.
491
+ *
492
+ * Check: s_v*G + s_b*H == R + e*C
493
+ */
494
+ declare function verifyProofOfKnowledge(proof: ZKProofOfKnowledge): boolean;
495
+ /**
496
+ * Create a ZK range proof: prove value ∈ [min, max] without revealing value.
497
+ *
498
+ * Approach: bit-decomposition of (value - min) into n bits where 2^n > max - min.
499
+ * Each bit gets a Pedersen commitment and a proof it's 0 or 1.
500
+ * A sum proof shows the bit commitments reconstruct the original commitment
501
+ * (shifted by min).
502
+ *
503
+ * @param value - The committed value
504
+ * @param blindingFactor - The blinding factor (base64url)
505
+ * @param commitment - The commitment (base64url)
506
+ * @param min - Minimum value (inclusive)
507
+ * @param max - Maximum value (inclusive)
508
+ */
509
+ declare function createRangeProof(value: number, blindingFactor: string, commitment: string, min: number, max: number): ZKRangeProof | {
510
+ error: string;
511
+ };
512
+ /**
513
+ * Verify a ZK range proof.
514
+ */
515
+ declare function verifyRangeProof(proof: ZKRangeProof): boolean;
516
+
350
517
  /**
351
518
  * Sanctuary MCP Server — L3 Selective Disclosure: Disclosure Policies
352
519
  *
@@ -445,6 +612,225 @@ interface StoredIdentity extends PublicIdentity {
445
612
  }>;
446
613
  }
447
614
 
615
+ /**
616
+ * Sanctuary MCP Server — Sovereignty Health Report (SHR) Types
617
+ *
618
+ * Machine-readable, signed, versioned sovereignty capability advertisement.
619
+ * An agent presents its SHR to counterparties to prove its sovereignty posture.
620
+ * The SHR is signed by one of the instance's Ed25519 identities and can be
621
+ * independently verified by any party without trusting the presenter.
622
+ *
623
+ * SHR version: 1.0
624
+ */
625
+ type LayerStatus = "active" | "degraded" | "inactive";
626
+ type DegradationSeverity = "info" | "warning" | "critical";
627
+ type DegradationCode = "NO_TEE" | "PROCESS_ISOLATION_ONLY" | "COMMITMENT_ONLY" | "NO_ZK_PROOFS" | "SELF_REPORTED_ATTESTATION" | "NO_SELECTIVE_DISCLOSURE" | "BASIC_SYBIL_ONLY";
628
+ interface SHRLayerL1 {
629
+ status: LayerStatus;
630
+ encryption: string;
631
+ key_custody: "self" | "delegated" | "platform";
632
+ integrity: string;
633
+ identity_type: string;
634
+ state_portable: boolean;
635
+ }
636
+ interface SHRLayerL2 {
637
+ status: LayerStatus;
638
+ isolation_type: string;
639
+ attestation_available: boolean;
640
+ }
641
+ interface SHRLayerL3 {
642
+ status: LayerStatus;
643
+ proof_system: string;
644
+ selective_disclosure: boolean;
645
+ }
646
+ interface SHRLayerL4 {
647
+ status: LayerStatus;
648
+ reputation_mode: string;
649
+ attestation_format: string;
650
+ reputation_portable: boolean;
651
+ }
652
+ interface SHRDegradation {
653
+ layer: "l1" | "l2" | "l3" | "l4";
654
+ code: DegradationCode;
655
+ severity: DegradationSeverity;
656
+ description: string;
657
+ mitigation?: string;
658
+ }
659
+ interface SHRCapabilities {
660
+ handshake: boolean;
661
+ shr_exchange: boolean;
662
+ reputation_verify: boolean;
663
+ encrypted_channel: boolean;
664
+ }
665
+ /**
666
+ * The SHR body — the content that gets signed.
667
+ * Canonical form: JSON with sorted keys, no whitespace.
668
+ */
669
+ interface SHRBody {
670
+ shr_version: "1.0";
671
+ instance_id: string;
672
+ generated_at: string;
673
+ expires_at: string;
674
+ layers: {
675
+ l1: SHRLayerL1;
676
+ l2: SHRLayerL2;
677
+ l3: SHRLayerL3;
678
+ l4: SHRLayerL4;
679
+ };
680
+ capabilities: SHRCapabilities;
681
+ degradations: SHRDegradation[];
682
+ }
683
+ /**
684
+ * The complete signed SHR — body + signature envelope.
685
+ */
686
+ interface SignedSHR {
687
+ body: SHRBody;
688
+ signed_by: string;
689
+ signature: string;
690
+ }
691
+ interface SHRVerificationResult {
692
+ valid: boolean;
693
+ errors: string[];
694
+ warnings: string[];
695
+ sovereignty_level: "full" | "degraded" | "minimal";
696
+ counterparty_id: string;
697
+ expires_at: string;
698
+ }
699
+
700
+ /**
701
+ * Sanctuary MCP Server — Sovereignty Handshake Types
702
+ *
703
+ * The sovereignty handshake is a mutual verification protocol between
704
+ * two Sanctuary instances. Each party presents its SHR and proves
705
+ * liveness via nonce challenge-response.
706
+ *
707
+ * Protocol:
708
+ * A → B: HandshakeChallenge (A's SHR + nonce)
709
+ * B → A: HandshakeResponse (B's SHR + B's nonce + signature over A's nonce)
710
+ * A → B: HandshakeCompletion (signature over B's nonce)
711
+ * Result: Both hold a HandshakeResult with verified counterparty status
712
+ */
713
+
714
+ /** Trust tier derived from sovereignty handshake */
715
+ type TrustTier = "verified-sovereign" | "verified-degraded" | "unverified";
716
+ /** Sovereignty level from SHR assessment */
717
+ type SovereigntyLevel = "full" | "degraded" | "minimal" | "unverified";
718
+ /**
719
+ * Step 1: Initiator sends challenge
720
+ */
721
+ interface HandshakeChallenge {
722
+ protocol_version: "1.0";
723
+ shr: SignedSHR;
724
+ nonce: string;
725
+ initiated_at: string;
726
+ }
727
+ /**
728
+ * Step 2: Responder sends response
729
+ */
730
+ interface HandshakeResponse {
731
+ protocol_version: "1.0";
732
+ shr: SignedSHR;
733
+ responder_nonce: string;
734
+ initiator_nonce_signature: string;
735
+ responded_at: string;
736
+ }
737
+ /**
738
+ * Step 3: Initiator sends completion
739
+ */
740
+ interface HandshakeCompletion {
741
+ protocol_version: "1.0";
742
+ responder_nonce_signature: string;
743
+ completed_at: string;
744
+ }
745
+ /**
746
+ * Final result: both parties hold this after a successful handshake
747
+ */
748
+ interface HandshakeResult {
749
+ counterparty_id: string;
750
+ counterparty_shr: SignedSHR;
751
+ verified: boolean;
752
+ sovereignty_level: SovereigntyLevel;
753
+ trust_tier: TrustTier;
754
+ completed_at: string;
755
+ expires_at: string;
756
+ errors: string[];
757
+ }
758
+ /**
759
+ * In-progress handshake state (stored on initiator side)
760
+ */
761
+ interface HandshakeSession {
762
+ session_id: string;
763
+ role: "initiator" | "responder";
764
+ state: "initiated" | "responded" | "completed" | "failed";
765
+ our_nonce: string;
766
+ their_nonce?: string;
767
+ our_shr: SignedSHR;
768
+ their_shr?: SignedSHR;
769
+ initiated_at: string;
770
+ result?: HandshakeResult;
771
+ }
772
+
773
+ /**
774
+ * Sanctuary MCP Server — Sovereignty-Gated Reputation Tiers
775
+ *
776
+ * Attestations carry a sovereignty_tier field reflecting the signer's
777
+ * sovereignty posture at the time of recording. When querying or evaluating
778
+ * reputation, attestations from verified-sovereign agents carry more weight
779
+ * than those from unverified agents.
780
+ *
781
+ * Tier hierarchy (descending credibility):
782
+ * 1. "verified-sovereign" — signer completed a handshake with full sovereignty
783
+ * 2. "verified-degraded" — signer completed a handshake with degraded sovereignty
784
+ * 3. "self-attested" — signer has a Sanctuary identity but no handshake verification
785
+ * 4. "unverified" — no Sanctuary identity or sovereignty proof
786
+ *
787
+ * Weight multipliers are applied during reputation scoring. They are NOT
788
+ * gatekeeping — unverified attestations still count, just less.
789
+ */
790
+
791
+ type SovereigntyTier = "verified-sovereign" | "verified-degraded" | "self-attested" | "unverified";
792
+ /** Weight multipliers for each tier */
793
+ declare const TIER_WEIGHTS: Record<SovereigntyTier, number>;
794
+ /** Tier metadata embedded in attestations */
795
+ interface TierMetadata {
796
+ sovereignty_tier: SovereigntyTier;
797
+ /** If verified, the handshake that established it */
798
+ handshake_completed_at?: string;
799
+ /** Counterparty ID from handshake (if applicable) */
800
+ verified_by?: string;
801
+ }
802
+ /**
803
+ * Resolve the sovereignty tier for a counterparty based on handshake history.
804
+ *
805
+ * @param counterpartyId - The counterparty's instance ID
806
+ * @param handshakeResults - Map of counterparty ID → most recent handshake result
807
+ * @param hasSanctuaryIdentity - Whether the counterparty has a known Sanctuary identity
808
+ * @returns TierMetadata for embedding in attestations
809
+ */
810
+ declare function resolveTier(counterpartyId: string, handshakeResults: Map<string, HandshakeResult>, hasSanctuaryIdentity: boolean): TierMetadata;
811
+ /** An attestation with its tier for weighted scoring */
812
+ interface TieredAttestation {
813
+ /** The raw metric value */
814
+ value: number;
815
+ /** The sovereignty tier of the attestation signer */
816
+ tier: SovereigntyTier;
817
+ }
818
+ /**
819
+ * Compute a weighted reputation score from tiered attestations.
820
+ *
821
+ * Each attestation's contribution is multiplied by its tier weight.
822
+ * The result is normalized by total weight (not count), so adding
823
+ * low-tier attestations doesn't dilute high-tier ones.
824
+ *
825
+ * @param attestations - Array of value + tier pairs
826
+ * @returns Weighted score, or null if no attestations
827
+ */
828
+ declare function computeWeightedScore(attestations: TieredAttestation[]): number | null;
829
+ /**
830
+ * Compute a tier distribution summary for a set of attestations.
831
+ */
832
+ declare function tierDistribution(tiers: SovereigntyTier[]): Record<SovereigntyTier, number>;
833
+
448
834
  /**
449
835
  * Sanctuary MCP Server — L4 Verifiable Reputation: Reputation Store
450
836
  *
@@ -481,6 +867,8 @@ interface Attestation {
481
867
  metrics: Record<string, number>;
482
868
  context: string;
483
869
  timestamp: string;
870
+ /** Sovereignty tier of the signer at time of recording */
871
+ sovereignty_tier?: SovereigntyTier;
484
872
  };
485
873
  signature: string;
486
874
  signer: string;
@@ -552,7 +940,7 @@ declare class ReputationStore {
552
940
  /**
553
941
  * Record an interaction outcome as a signed attestation.
554
942
  */
555
- record(interactionId: string, counterpartyDid: string, outcome: InteractionOutcome, context: string, identity: StoredIdentity, identityEncryptionKey: Uint8Array, counterpartyAttestation?: string): Promise<StoredAttestation>;
943
+ record(interactionId: string, counterpartyDid: string, outcome: InteractionOutcome, context: string, identity: StoredIdentity, identityEncryptionKey: Uint8Array, counterpartyAttestation?: string, sovereigntyTier?: SovereigntyTier): Promise<StoredAttestation>;
556
944
  /**
557
945
  * Query reputation data with filtering.
558
946
  * Returns aggregates only — not raw interaction data.
@@ -593,37 +981,167 @@ declare class ReputationStore {
593
981
  * Create a principal's guarantee for a new agent.
594
982
  */
595
983
  createGuarantee(principalIdentity: StoredIdentity, agentDid: string, scope: string, durationSeconds: number, identityEncryptionKey: Uint8Array, maxLiability?: number): Promise<Guarantee>;
984
+ /**
985
+ * Load attestations for tier-weighted scoring.
986
+ * Applies basic context/counterparty filtering, returns full StoredAttestations
987
+ * so callers can access sovereignty_tier from attestation data.
988
+ */
989
+ loadAllForTierScoring(options?: {
990
+ context?: string;
991
+ counterparty_did?: string;
992
+ }): Promise<StoredAttestation[]>;
596
993
  private loadAll;
597
994
  }
598
995
 
599
996
  /**
600
- * Sanctuary MCP Server — In-Memory Storage Backend
997
+ * Sanctuary MCP Server — Federation Types
601
998
  *
602
- * Used for testing. Implements the same interface as filesystem storage
603
- * but stores everything in memory. Data does not persist across restarts.
999
+ * MCP-to-MCP federation enables two Sanctuary instances to:
1000
+ * 1. Discover each other's capabilities (SIM exchange)
1001
+ * 2. Establish mutual trust (sovereignty handshake)
1002
+ * 3. Exchange signed reputation attestations
1003
+ * 4. Evaluate trust for cross-instance interactions
1004
+ *
1005
+ * Federation operates as a protocol layer atop the handshake:
1006
+ * Handshake establishes trust → Federation uses that trust for ongoing operations.
1007
+ *
1008
+ * Key constraint: Federation MUST respect each party's sovereignty.
1009
+ * Neither party can compel the other to share data they haven't disclosed
1010
+ * via their disclosure policy.
604
1011
  */
605
1012
 
606
- declare class MemoryStorage implements StorageBackend {
607
- private store;
608
- private storageKey;
609
- write(namespace: string, key: string, data: Uint8Array): Promise<void>;
610
- read(namespace: string, key: string): Promise<Uint8Array | null>;
611
- delete(namespace: string, key: string, _secureOverwrite?: boolean): Promise<boolean>;
612
- list(namespace: string, prefix?: string): Promise<StorageEntryMeta[]>;
613
- exists(namespace: string, key: string): Promise<boolean>;
614
- totalSize(): Promise<number>;
615
- /** Clear all stored data (useful in tests) */
616
- clear(): void;
1013
+ /** A known federation peer */
1014
+ interface FederationPeer {
1015
+ /** The peer's instance ID (from their SHR) */
1016
+ peer_id: string;
1017
+ /** The peer's DID (identity) */
1018
+ peer_did: string;
1019
+ /** When this peer was first seen */
1020
+ first_seen: string;
1021
+ /** When last handshake completed */
1022
+ last_handshake: string;
1023
+ /** Current trust tier from most recent handshake */
1024
+ trust_tier: SovereigntyTier;
1025
+ /** Handshake result (for tier resolution) */
1026
+ handshake_result: HandshakeResult;
1027
+ /** Peer's advertised capabilities (from their SIM) */
1028
+ capabilities: FederationCapabilities;
1029
+ /** Whether we have a valid (non-expired) handshake */
1030
+ active: boolean;
1031
+ }
1032
+ /** Capabilities a peer advertises for federation */
1033
+ interface FederationCapabilities {
1034
+ /** Whether the peer supports reputation exchange */
1035
+ reputation_exchange: boolean;
1036
+ /** Whether the peer supports mutual attestation */
1037
+ mutual_attestation: boolean;
1038
+ /** Whether the peer supports encrypted channels */
1039
+ encrypted_channel: boolean;
1040
+ /** Supported attestation formats */
1041
+ attestation_formats: string[];
1042
+ }
1043
+ /** Trust evaluation result for a federation peer */
1044
+ interface PeerTrustEvaluation {
1045
+ peer_id: string;
1046
+ /** Current sovereignty tier (from handshake) */
1047
+ sovereignty_tier: SovereigntyTier;
1048
+ /** Whether handshake is current (not expired) */
1049
+ handshake_current: boolean;
1050
+ /** Reputation summary (if available) */
1051
+ reputation_score?: number;
1052
+ /** How many mutual attestations we share */
1053
+ mutual_attestation_count: number;
1054
+ /** Overall trust assessment */
1055
+ trust_level: "high" | "medium" | "low" | "none";
1056
+ /** Reasoning for the assessment */
1057
+ factors: string[];
1058
+ /** Evaluated at */
1059
+ evaluated_at: string;
617
1060
  }
618
1061
 
619
1062
  /**
620
- * Sanctuary MCP Server — Filesystem Storage Backend
1063
+ * Sanctuary MCP Server — Federation Peer Registry
621
1064
  *
622
- * Default storage backend using the local filesystem.
623
- * Files are stored as: {basePath}/{namespace}/{key}.enc
1065
+ * Manages known federation peers. Peers are discovered through handshakes
1066
+ * and tracked for ongoing federation operations.
1067
+ *
1068
+ * The registry is the source of truth for:
1069
+ * - Who we've federated with
1070
+ * - Current trust status of each peer
1071
+ * - Peer capabilities (what operations they support)
624
1072
  *
625
1073
  * Security invariants:
626
- * - Secure deletion overwrites file content with random bytes before unlinking
1074
+ * - Peers are ONLY added through completed handshakes (not self-registration)
1075
+ * - Trust tiers degrade automatically when handshakes expire
1076
+ * - Peer data is stored encrypted under L1 sovereignty
1077
+ */
1078
+
1079
+ declare class FederationRegistry {
1080
+ private peers;
1081
+ /**
1082
+ * Register or update a peer from a completed handshake.
1083
+ * This is the ONLY way peers enter the registry.
1084
+ */
1085
+ registerFromHandshake(result: HandshakeResult, peerDid: string, capabilities?: Partial<FederationCapabilities>): FederationPeer;
1086
+ /**
1087
+ * Get a peer by instance ID.
1088
+ * Automatically updates active status based on handshake expiry.
1089
+ */
1090
+ getPeer(peerId: string): FederationPeer | null;
1091
+ /**
1092
+ * List all known peers, optionally filtered by status.
1093
+ */
1094
+ listPeers(filter?: {
1095
+ active_only?: boolean;
1096
+ }): FederationPeer[];
1097
+ /**
1098
+ * Evaluate trust for a federation peer.
1099
+ *
1100
+ * Trust assessment considers:
1101
+ * - Handshake status (current vs expired)
1102
+ * - Sovereignty tier (verified-sovereign vs degraded vs unverified)
1103
+ * - Reputation data (if available)
1104
+ * - Mutual attestation history
1105
+ */
1106
+ evaluateTrust(peerId: string, mutualAttestationCount?: number, reputationScore?: number): PeerTrustEvaluation;
1107
+ /**
1108
+ * Remove a peer from the registry.
1109
+ */
1110
+ removePeer(peerId: string): boolean;
1111
+ /**
1112
+ * Get the handshake results map (for tier resolution integration).
1113
+ */
1114
+ getHandshakeResults(): Map<string, HandshakeResult>;
1115
+ }
1116
+
1117
+ /**
1118
+ * Sanctuary MCP Server — In-Memory Storage Backend
1119
+ *
1120
+ * Used for testing. Implements the same interface as filesystem storage
1121
+ * but stores everything in memory. Data does not persist across restarts.
1122
+ */
1123
+
1124
+ declare class MemoryStorage implements StorageBackend {
1125
+ private store;
1126
+ private storageKey;
1127
+ write(namespace: string, key: string, data: Uint8Array): Promise<void>;
1128
+ read(namespace: string, key: string): Promise<Uint8Array | null>;
1129
+ delete(namespace: string, key: string, _secureOverwrite?: boolean): Promise<boolean>;
1130
+ list(namespace: string, prefix?: string): Promise<StorageEntryMeta[]>;
1131
+ exists(namespace: string, key: string): Promise<boolean>;
1132
+ totalSize(): Promise<number>;
1133
+ /** Clear all stored data (useful in tests) */
1134
+ clear(): void;
1135
+ }
1136
+
1137
+ /**
1138
+ * Sanctuary MCP Server — Filesystem Storage Backend
1139
+ *
1140
+ * Default storage backend using the local filesystem.
1141
+ * Files are stored as: {basePath}/{namespace}/{key}.enc
1142
+ *
1143
+ * Security invariants:
1144
+ * - Secure deletion overwrites file content with random bytes before unlinking
627
1145
  * - Directory creation uses restrictive permissions (0o700)
628
1146
  * - File creation uses restrictive permissions (0o600)
629
1147
  */
@@ -915,6 +1433,197 @@ declare class ApprovalGate {
915
1433
  */
916
1434
  declare function loadPrincipalPolicy(storagePath: string): Promise<PrincipalPolicy>;
917
1435
 
1436
+ /**
1437
+ * Sanctuary MCP Server — Principal Dashboard
1438
+ *
1439
+ * HTTP-based approval channel that serves a real-time web dashboard
1440
+ * for human principals to approve/deny agent operations.
1441
+ *
1442
+ * Architecture:
1443
+ * - Node.js built-in `http`/`https` modules (no Express or external deps)
1444
+ * - SSE (Server-Sent Events) for real-time push to browser
1445
+ * - Pending approval requests block the MCP tool call via Promise
1446
+ * - Human clicks approve/deny in browser → POST /api/approve/:id → Promise resolves
1447
+ * - Timeout fallback: auto-deny (or auto-approve) if no response
1448
+ *
1449
+ * Security invariants:
1450
+ * - Binds to 127.0.0.1 by default (localhost only)
1451
+ * - Optional bearer token authentication for non-localhost deployments
1452
+ * - Optional TLS (HTTPS) via cert/key paths
1453
+ * - All decisions are audit-logged
1454
+ * - Agent cannot access the dashboard (it runs outside MCP stdin/stdout)
1455
+ */
1456
+
1457
+ interface DashboardConfig {
1458
+ port: number;
1459
+ host: string;
1460
+ timeout_seconds: number;
1461
+ auto_deny: boolean;
1462
+ /** Bearer token for API authentication. If omitted, auth is disabled. */
1463
+ auth_token?: string;
1464
+ /** TLS configuration for HTTPS. If omitted, plain HTTP is used. */
1465
+ tls?: {
1466
+ cert_path: string;
1467
+ key_path: string;
1468
+ };
1469
+ }
1470
+ declare class DashboardApprovalChannel implements ApprovalChannel {
1471
+ private config;
1472
+ private pending;
1473
+ private sseClients;
1474
+ private httpServer;
1475
+ private policy;
1476
+ private baseline;
1477
+ private auditLog;
1478
+ private dashboardHTML;
1479
+ private authToken;
1480
+ private useTLS;
1481
+ constructor(config: DashboardConfig);
1482
+ /**
1483
+ * Inject dependencies after construction.
1484
+ * Called from index.ts after all components are initialized.
1485
+ */
1486
+ setDependencies(deps: {
1487
+ policy: PrincipalPolicy;
1488
+ baseline: BaselineTracker;
1489
+ auditLog: AuditLog;
1490
+ }): void;
1491
+ /**
1492
+ * Start the HTTP(S) server for the dashboard.
1493
+ */
1494
+ start(): Promise<void>;
1495
+ /**
1496
+ * Stop the HTTP server and clean up.
1497
+ */
1498
+ stop(): Promise<void>;
1499
+ /**
1500
+ * Request approval from the human via the dashboard.
1501
+ * Blocks until the human approves/denies or timeout occurs.
1502
+ */
1503
+ requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
1504
+ /**
1505
+ * Verify bearer token authentication.
1506
+ * Checks Authorization header first, falls back to ?token= query param.
1507
+ * Returns true if auth passes, false if blocked (response already sent).
1508
+ */
1509
+ private checkAuth;
1510
+ private handleRequest;
1511
+ private serveDashboard;
1512
+ private handleSSE;
1513
+ private handleStatus;
1514
+ private handlePendingList;
1515
+ private handleAuditLog;
1516
+ private handleDecision;
1517
+ private broadcastSSE;
1518
+ /**
1519
+ * Broadcast an audit entry to connected dashboards.
1520
+ * Called externally when audit events happen.
1521
+ */
1522
+ broadcastAuditEntry(entry: {
1523
+ timestamp: string;
1524
+ layer: string;
1525
+ operation: string;
1526
+ identity_id: string;
1527
+ }): void;
1528
+ /**
1529
+ * Broadcast a baseline update to connected dashboards.
1530
+ * Called externally after baseline changes.
1531
+ */
1532
+ broadcastBaselineUpdate(): void;
1533
+ /** Get the number of pending requests */
1534
+ get pendingCount(): number;
1535
+ /** Get the number of connected SSE clients */
1536
+ get clientCount(): number;
1537
+ }
1538
+
1539
+ /**
1540
+ * Sanctuary MCP Server — Webhook Approval Channel
1541
+ *
1542
+ * Sends approval requests to an external webhook URL and listens for
1543
+ * callback responses. Enables integration with Slack, Discord, PagerDuty,
1544
+ * or any HTTP-based approval workflow.
1545
+ *
1546
+ * Architecture:
1547
+ * - Outbound: POST approval request to configured webhook_url
1548
+ * - Inbound: HTTP callback server listens for POST /webhook/respond/:id
1549
+ * - HMAC-SHA256 signatures on both outbound and inbound payloads
1550
+ * - Timeout fallback: auto-deny (or auto-approve) if no callback received
1551
+ *
1552
+ * Security invariants:
1553
+ * - All outbound payloads signed with HMAC-SHA256 (webhook_secret)
1554
+ * - All inbound callbacks verified with same HMAC-SHA256 signature
1555
+ * - Callback server binds to configurable host (default 127.0.0.1)
1556
+ * - Replay protection via request ID + pending map (can't approve twice)
1557
+ * - All decisions are audit-logged
1558
+ */
1559
+
1560
+ interface WebhookConfig {
1561
+ /** URL to POST approval requests to */
1562
+ webhook_url: string;
1563
+ /** Shared secret for HMAC-SHA256 signatures */
1564
+ webhook_secret: string;
1565
+ /** Port for the callback listener */
1566
+ callback_port: number;
1567
+ /** Host for the callback listener (default: 127.0.0.1) */
1568
+ callback_host: string;
1569
+ /** Seconds to wait for a callback before timeout */
1570
+ timeout_seconds: number;
1571
+ /** Whether to deny (true) or approve (false) on timeout */
1572
+ auto_deny: boolean;
1573
+ }
1574
+ /** Outbound webhook payload */
1575
+ interface WebhookPayload {
1576
+ /** Unique request ID */
1577
+ request_id: string;
1578
+ /** The approval request details */
1579
+ operation: string;
1580
+ tier: 1 | 2;
1581
+ reason: string;
1582
+ context: Record<string, unknown>;
1583
+ timestamp: string;
1584
+ /** URL to POST the response back to */
1585
+ callback_url: string;
1586
+ /** Seconds until auto-resolution */
1587
+ timeout_seconds: number;
1588
+ }
1589
+ /** Inbound callback payload */
1590
+ interface WebhookCallbackPayload {
1591
+ /** The request ID being responded to */
1592
+ request_id: string;
1593
+ /** The decision */
1594
+ decision: "approve" | "deny";
1595
+ }
1596
+ /**
1597
+ * Generate HMAC-SHA256 signature for a payload.
1598
+ */
1599
+ declare function signPayload(body: string, secret: string): string;
1600
+ /**
1601
+ * Verify HMAC-SHA256 signature. Uses timing-safe comparison.
1602
+ */
1603
+ declare function verifySignature(body: string, signature: string, secret: string): boolean;
1604
+ declare class WebhookApprovalChannel implements ApprovalChannel {
1605
+ private config;
1606
+ private pending;
1607
+ private callbackServer;
1608
+ constructor(config: WebhookConfig);
1609
+ /**
1610
+ * Start the callback listener server.
1611
+ */
1612
+ start(): Promise<void>;
1613
+ /**
1614
+ * Stop the callback server and clean up pending requests.
1615
+ */
1616
+ stop(): Promise<void>;
1617
+ /**
1618
+ * Request approval by POSTing to the webhook and waiting for a callback.
1619
+ */
1620
+ requestApproval(request: ApprovalRequest): Promise<ApprovalResponse>;
1621
+ private sendWebhook;
1622
+ private handleCallback;
1623
+ /** Get the number of pending requests */
1624
+ get pendingCount(): number;
1625
+ }
1626
+
918
1627
  /**
919
1628
  * Sanctuary MCP Server — L1 Cognitive Sovereignty: Tool Definitions
920
1629
  *
@@ -939,91 +1648,6 @@ declare class IdentityManager {
939
1648
  list(): PublicIdentity[];
940
1649
  }
941
1650
 
942
- /**
943
- * Sanctuary MCP Server — Sovereignty Health Report (SHR) Types
944
- *
945
- * Machine-readable, signed, versioned sovereignty capability advertisement.
946
- * An agent presents its SHR to counterparties to prove its sovereignty posture.
947
- * The SHR is signed by one of the instance's Ed25519 identities and can be
948
- * independently verified by any party without trusting the presenter.
949
- *
950
- * SHR version: 1.0
951
- */
952
- type LayerStatus = "active" | "degraded" | "inactive";
953
- type DegradationSeverity = "info" | "warning" | "critical";
954
- type DegradationCode = "NO_TEE" | "PROCESS_ISOLATION_ONLY" | "COMMITMENT_ONLY" | "NO_ZK_PROOFS" | "SELF_REPORTED_ATTESTATION" | "NO_SELECTIVE_DISCLOSURE" | "BASIC_SYBIL_ONLY";
955
- interface SHRLayerL1 {
956
- status: LayerStatus;
957
- encryption: string;
958
- key_custody: "self" | "delegated" | "platform";
959
- integrity: string;
960
- identity_type: string;
961
- state_portable: boolean;
962
- }
963
- interface SHRLayerL2 {
964
- status: LayerStatus;
965
- isolation_type: string;
966
- attestation_available: boolean;
967
- }
968
- interface SHRLayerL3 {
969
- status: LayerStatus;
970
- proof_system: string;
971
- selective_disclosure: boolean;
972
- }
973
- interface SHRLayerL4 {
974
- status: LayerStatus;
975
- reputation_mode: string;
976
- attestation_format: string;
977
- reputation_portable: boolean;
978
- }
979
- interface SHRDegradation {
980
- layer: "l1" | "l2" | "l3" | "l4";
981
- code: DegradationCode;
982
- severity: DegradationSeverity;
983
- description: string;
984
- mitigation?: string;
985
- }
986
- interface SHRCapabilities {
987
- handshake: boolean;
988
- shr_exchange: boolean;
989
- reputation_verify: boolean;
990
- encrypted_channel: boolean;
991
- }
992
- /**
993
- * The SHR body — the content that gets signed.
994
- * Canonical form: JSON with sorted keys, no whitespace.
995
- */
996
- interface SHRBody {
997
- shr_version: "1.0";
998
- instance_id: string;
999
- generated_at: string;
1000
- expires_at: string;
1001
- layers: {
1002
- l1: SHRLayerL1;
1003
- l2: SHRLayerL2;
1004
- l3: SHRLayerL3;
1005
- l4: SHRLayerL4;
1006
- };
1007
- capabilities: SHRCapabilities;
1008
- degradations: SHRDegradation[];
1009
- }
1010
- /**
1011
- * The complete signed SHR — body + signature envelope.
1012
- */
1013
- interface SignedSHR {
1014
- body: SHRBody;
1015
- signed_by: string;
1016
- signature: string;
1017
- }
1018
- interface SHRVerificationResult {
1019
- valid: boolean;
1020
- errors: string[];
1021
- warnings: string[];
1022
- sovereignty_level: "full" | "degraded" | "minimal";
1023
- counterparty_id: string;
1024
- expires_at: string;
1025
- }
1026
-
1027
1651
  /**
1028
1652
  * Sanctuary MCP Server — SHR Generator
1029
1653
  *
@@ -1066,79 +1690,6 @@ declare function generateSHR(identityId: string | undefined, opts: SHRGeneratorO
1066
1690
  */
1067
1691
  declare function verifySHR(shr: SignedSHR, now?: Date): SHRVerificationResult;
1068
1692
 
1069
- /**
1070
- * Sanctuary MCP Server — Sovereignty Handshake Types
1071
- *
1072
- * The sovereignty handshake is a mutual verification protocol between
1073
- * two Sanctuary instances. Each party presents its SHR and proves
1074
- * liveness via nonce challenge-response.
1075
- *
1076
- * Protocol:
1077
- * A → B: HandshakeChallenge (A's SHR + nonce)
1078
- * B → A: HandshakeResponse (B's SHR + B's nonce + signature over A's nonce)
1079
- * A → B: HandshakeCompletion (signature over B's nonce)
1080
- * Result: Both hold a HandshakeResult with verified counterparty status
1081
- */
1082
-
1083
- /** Trust tier derived from sovereignty handshake */
1084
- type TrustTier = "verified-sovereign" | "verified-degraded" | "unverified";
1085
- /** Sovereignty level from SHR assessment */
1086
- type SovereigntyLevel = "full" | "degraded" | "minimal" | "unverified";
1087
- /**
1088
- * Step 1: Initiator sends challenge
1089
- */
1090
- interface HandshakeChallenge {
1091
- protocol_version: "1.0";
1092
- shr: SignedSHR;
1093
- nonce: string;
1094
- initiated_at: string;
1095
- }
1096
- /**
1097
- * Step 2: Responder sends response
1098
- */
1099
- interface HandshakeResponse {
1100
- protocol_version: "1.0";
1101
- shr: SignedSHR;
1102
- responder_nonce: string;
1103
- initiator_nonce_signature: string;
1104
- responded_at: string;
1105
- }
1106
- /**
1107
- * Step 3: Initiator sends completion
1108
- */
1109
- interface HandshakeCompletion {
1110
- protocol_version: "1.0";
1111
- responder_nonce_signature: string;
1112
- completed_at: string;
1113
- }
1114
- /**
1115
- * Final result: both parties hold this after a successful handshake
1116
- */
1117
- interface HandshakeResult {
1118
- counterparty_id: string;
1119
- counterparty_shr: SignedSHR;
1120
- verified: boolean;
1121
- sovereignty_level: SovereigntyLevel;
1122
- trust_tier: TrustTier;
1123
- completed_at: string;
1124
- expires_at: string;
1125
- errors: string[];
1126
- }
1127
- /**
1128
- * In-progress handshake state (stored on initiator side)
1129
- */
1130
- interface HandshakeSession {
1131
- session_id: string;
1132
- role: "initiator" | "responder";
1133
- state: "initiated" | "responded" | "completed" | "failed";
1134
- our_nonce: string;
1135
- their_nonce?: string;
1136
- our_shr: SignedSHR;
1137
- their_shr?: SignedSHR;
1138
- initiated_at: string;
1139
- result?: HandshakeResult;
1140
- }
1141
-
1142
1693
  /**
1143
1694
  * Sanctuary MCP Server — Sovereignty Handshake Protocol
1144
1695
  *
@@ -1181,6 +1732,188 @@ declare function completeHandshake(response: HandshakeResponse, session: Handsha
1181
1732
  */
1182
1733
  declare function verifyCompletion(completion: HandshakeCompletion, session: HandshakeSession): HandshakeResult;
1183
1734
 
1735
+ /**
1736
+ * Sanctuary MCP Server — Concordia Bridge: Type Definitions
1737
+ *
1738
+ * Defines the interface contract between the Concordia negotiation protocol
1739
+ * and Sanctuary's sovereignty infrastructure. This is the Sanctuary side of
1740
+ * the bridge — when Concordia is present, its `accept` can trigger a
1741
+ * Sanctuary commitment for cryptographic binding. When Concordia is absent,
1742
+ * these types and tools still function independently.
1743
+ *
1744
+ * Design principle: the bridge is additive, never required. Sanctuary and
1745
+ * Concordia remain non-dependent. These types define the contract Concordia
1746
+ * implements against, not a dependency Sanctuary requires.
1747
+ */
1748
+
1749
+ /**
1750
+ * Concordia negotiation outcome — the data Concordia sends when an
1751
+ * `accept` triggers a Sanctuary commitment.
1752
+ *
1753
+ * This type is defined by Sanctuary (the receiver) to specify the
1754
+ * contract Concordia must fulfill. Field names align with Concordia's
1755
+ * protocol semantics.
1756
+ */
1757
+ interface ConcordiaOutcome {
1758
+ /** Concordia session identifier */
1759
+ session_id: string;
1760
+ /** Protocol version (e.g., "concordia-v1") */
1761
+ protocol_version: string;
1762
+ /** DID of the party who proposed the accepted terms */
1763
+ proposer_did: string;
1764
+ /** DID of the party who accepted */
1765
+ acceptor_did: string;
1766
+ /** The accepted terms — opaque to Sanctuary, meaningful to Concordia */
1767
+ terms: Record<string, unknown>;
1768
+ /** SHA-256 hash of the canonical terms serialization (computed by Concordia) */
1769
+ terms_hash: string;
1770
+ /** Number of rounds in the negotiation (propose/counter cycles) */
1771
+ rounds: number;
1772
+ /** ISO 8601 timestamp when accept was issued */
1773
+ accepted_at: string;
1774
+ /** Optional: Concordia session receipt (signed transcript) */
1775
+ session_receipt?: string;
1776
+ }
1777
+ /**
1778
+ * A Sanctuary commitment binding a Concordia negotiation outcome.
1779
+ *
1780
+ * This is the cryptographic anchor: a SHA-256 commitment over the
1781
+ * canonical serialization of the ConcordiaOutcome, plus a Pedersen
1782
+ * commitment if ZK proofs are needed (e.g., proving negotiation
1783
+ * took ≤ N rounds without revealing exact count).
1784
+ */
1785
+ interface BridgeCommitment {
1786
+ /** Unique bridge commitment identifier */
1787
+ bridge_commitment_id: string;
1788
+ /** The Concordia session this commitment binds */
1789
+ session_id: string;
1790
+ /** SHA-256 commitment: hash(canonical_outcome || blinding_factor) */
1791
+ sha256_commitment: string;
1792
+ /** Blinding factor for the SHA-256 commitment (base64url) */
1793
+ blinding_factor: string;
1794
+ /** DID of the Sanctuary identity that created this commitment */
1795
+ committer_did: string;
1796
+ /** Ed25519 signature over the commitment by the committer */
1797
+ signature: string;
1798
+ /** Optional: Pedersen commitment over the round count (for ZK range proofs) */
1799
+ pedersen_commitment?: {
1800
+ commitment: string;
1801
+ blinding_factor: string;
1802
+ };
1803
+ /** ISO 8601 timestamp */
1804
+ committed_at: string;
1805
+ /** Protocol metadata */
1806
+ bridge_version: "sanctuary-concordia-bridge-v1";
1807
+ }
1808
+ /** Result of verifying a bridge commitment against a revealed outcome */
1809
+ interface BridgeVerificationResult {
1810
+ /** Whether the commitment matches the revealed outcome */
1811
+ valid: boolean;
1812
+ /** Which checks passed/failed */
1813
+ checks: {
1814
+ sha256_match: boolean;
1815
+ signature_valid: boolean;
1816
+ session_id_match: boolean;
1817
+ terms_hash_match: boolean;
1818
+ pedersen_match?: boolean;
1819
+ };
1820
+ /** The commitment that was verified */
1821
+ bridge_commitment_id: string;
1822
+ /** ISO 8601 timestamp of verification */
1823
+ verified_at: string;
1824
+ }
1825
+ /**
1826
+ * A bridge attestation links a Concordia negotiation to Sanctuary's
1827
+ * L4 reputation system. When a negotiation completes successfully,
1828
+ * both the commitment (L3) and the reputation attestation (L4) are
1829
+ * recorded — the commitment proves the terms were agreed, the
1830
+ * attestation feeds the sovereignty-weighted reputation score.
1831
+ */
1832
+ interface BridgeAttestationRequest {
1833
+ /** The bridge commitment ID that anchors this attestation */
1834
+ bridge_commitment_id: string;
1835
+ /** Concordia session ID */
1836
+ session_id: string;
1837
+ /** DID of the counterparty in the negotiation */
1838
+ counterparty_did: string;
1839
+ /** Negotiation outcome for reputation scoring */
1840
+ outcome_result: "completed" | "partial" | "failed" | "disputed";
1841
+ /** Optional metrics (e.g., rounds, response_time_ms, terms_complexity) */
1842
+ metrics?: Record<string, number>;
1843
+ /** Identity to sign the attestation (uses default if omitted) */
1844
+ identity_id?: string;
1845
+ }
1846
+ /** Result of creating a bridge attestation */
1847
+ interface BridgeAttestationResult {
1848
+ /** The L4 attestation ID created */
1849
+ attestation_id: string;
1850
+ /** The bridge commitment ID that anchors it */
1851
+ bridge_commitment_id: string;
1852
+ /** Concordia session ID */
1853
+ session_id: string;
1854
+ /** Sovereignty tier applied to the attestation */
1855
+ sovereignty_tier: SovereigntyTier;
1856
+ /** ISO 8601 timestamp */
1857
+ attested_at: string;
1858
+ }
1859
+
1860
+ /**
1861
+ * Sanctuary MCP Server — Concordia Bridge: Core Module
1862
+ *
1863
+ * Implements the Sanctuary side of the Concordia bridge:
1864
+ * 1. bridge_commit — Create a cryptographic commitment binding a negotiation outcome
1865
+ * 2. bridge_verify — Verify a commitment against a revealed outcome
1866
+ * 3. bridge_attest — Link a negotiation to L4 reputation via the commitment
1867
+ *
1868
+ * The bridge composes L3 (selective disclosure) and L4 (verifiable reputation)
1869
+ * to serve negotiation-specific needs. It introduces no new cryptographic
1870
+ * primitives — everything delegates to the existing L3 commitment/ZK layer
1871
+ * and L4 reputation store.
1872
+ *
1873
+ * Non-dependency principle: this module can be used without Concordia
1874
+ * running. Any system that provides a ConcordiaOutcome-shaped object
1875
+ * can create bridge commitments. Concordia is the expected caller, but
1876
+ * the interface is protocol-agnostic.
1877
+ */
1878
+
1879
+ /**
1880
+ * Produce a canonical byte representation of a ConcordiaOutcome.
1881
+ * Sorts all keys recursively to ensure determinism.
1882
+ */
1883
+ declare function canonicalize(outcome: ConcordiaOutcome): Uint8Array;
1884
+ /**
1885
+ * Create a cryptographic commitment binding a Concordia negotiation outcome
1886
+ * to Sanctuary's L3 proof layer.
1887
+ *
1888
+ * Creates:
1889
+ * 1. A SHA-256 commitment over the canonical outcome (always)
1890
+ * 2. A Pedersen commitment over the round count (optional, for ZK range proofs)
1891
+ * 3. An Ed25519 signature over the commitment by the committer's identity
1892
+ *
1893
+ * @param outcome - The Concordia negotiation outcome to bind
1894
+ * @param identity - The Sanctuary identity creating the commitment
1895
+ * @param identityEncryptionKey - Key to decrypt the identity's private key
1896
+ * @param includePedersen - Whether to create a Pedersen commitment on round count
1897
+ * @returns The bridge commitment
1898
+ */
1899
+ declare function createBridgeCommitment(outcome: ConcordiaOutcome, identity: StoredIdentity, identityEncryptionKey: Uint8Array, includePedersen?: boolean): BridgeCommitment;
1900
+ /**
1901
+ * Verify a bridge commitment against a revealed Concordia outcome.
1902
+ *
1903
+ * Checks:
1904
+ * 1. SHA-256 commitment matches the canonical outcome + blinding factor
1905
+ * 2. Ed25519 signature is valid for the committer's public key
1906
+ * 3. Session IDs match
1907
+ * 4. Terms hash matches (Concordia's own hash of the terms)
1908
+ * 5. Pedersen commitment matches round count (if present)
1909
+ *
1910
+ * @param commitment - The bridge commitment to verify
1911
+ * @param outcome - The revealed Concordia outcome
1912
+ * @param committerPublicKey - The committer's Ed25519 public key
1913
+ * @returns Verification result with per-check detail
1914
+ */
1915
+ declare function verifyBridgeCommitment(commitment: BridgeCommitment, outcome: ConcordiaOutcome, committerPublicKey: Uint8Array): BridgeVerificationResult;
1916
+
1184
1917
  /**
1185
1918
  * Sanctuary MCP Server — Main Entry Point
1186
1919
  *
@@ -1204,4 +1937,4 @@ declare function createSanctuaryServer(options?: {
1204
1937
  storage?: StorageBackend;
1205
1938
  }): Promise<SanctuaryServer>;
1206
1939
 
1207
- export { ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, CallbackApprovalChannel, CommitmentStore, FilesystemStorage, type GateResult, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, MemoryStorage, PolicyStore, type PrincipalPolicy, ReputationStore, type SHRBody, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedSHR, StateStore, StderrApprovalChannel, completeHandshake, createSanctuaryServer, generateSHR, initiateHandshake, loadConfig, loadPrincipalPolicy, respondToHandshake, verifyCompletion, verifySHR };
1940
+ export { ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, type BridgeAttestationRequest, type BridgeAttestationResult, type BridgeCommitment, type BridgeVerificationResult, CallbackApprovalChannel, CommitmentStore, type ConcordiaOutcome, DashboardApprovalChannel, type DashboardConfig, type FederationCapabilities, type FederationPeer, FederationRegistry, FilesystemStorage, type GateResult, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, MemoryStorage, type PedersenCommitment, type PeerTrustEvaluation, PolicyStore, type PrincipalPolicy, ReputationStore, type SHRBody, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedSHR, type SovereigntyTier, StateStore, StderrApprovalChannel, TIER_WEIGHTS, type TierMetadata, type TieredAttestation, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, completeHandshake, computeWeightedScore, createBridgeCommitment, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, generateSHR, initiateHandshake, loadConfig, loadPrincipalPolicy, resolveTier, respondToHandshake, signPayload, tierDistribution, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };