@sanctuary-framework/mcp-server 1.2.3 → 1.2.5

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
@@ -252,6 +252,43 @@ interface ApprovalChannelConfig {
252
252
  webhook_url?: string;
253
253
  webhook_secret?: string;
254
254
  }
255
+ /**
256
+ * WP-V1.3-10 Upsilon-2: cross-harness approval-redirect mode.
257
+ *
258
+ * `mode` selects how the underlying channel and the aggregator interact when
259
+ * a Tier 1/2 approval fires for a wrapped agent:
260
+ *
261
+ * - `replace`: the underlying channel is bypassed; the gate's
262
+ * `requestApproval()` blocks awaiting the operator's decision through
263
+ * the aggregator HTTP `approve`/`deny` routes (or any other surface that
264
+ * calls `aggregator.resolve()`). Default behavior when redirect is
265
+ * enabled.
266
+ * - `notify`: both the underlying channel AND the aggregator run; the
267
+ * first decision wins. Right shape for harnesses (e.g. Mastra) where
268
+ * full local-prompt suppression is not viable, so the operator still
269
+ * sees the prompt locally but ALSO can resolve from the unified inbox.
270
+ *
271
+ * `per_agent` is a stub for v1.4 multi-agent fortresses: a map of
272
+ * `agent_id -> {enabled, mode}` overrides. v1.x ignores this field; the
273
+ * fortress-level `enabled` + `mode` apply to every wrapped agent in the
274
+ * fortress (which is currently single-agent in practice). v1.4 adds
275
+ * agent-id propagation through the gate signature and consults this map.
276
+ */
277
+ interface ApprovalRedirectPerAgentOverride {
278
+ enabled?: boolean;
279
+ mode?: "replace" | "notify";
280
+ }
281
+ interface ApprovalRedirectConfig {
282
+ /** Master toggle. When false, redirect-mode is off across the fortress. */
283
+ enabled: boolean;
284
+ /** How the underlying channel and the aggregator coexist. */
285
+ mode: "replace" | "notify";
286
+ /**
287
+ * Per-agent overrides. v1.x stub — populated entries are validated and
288
+ * persisted but not enforced. Reserved for v1.4 multi-agent fortresses.
289
+ */
290
+ per_agent?: Record<string, ApprovalRedirectPerAgentOverride>;
291
+ }
255
292
  /** Complete Principal Policy */
256
293
  interface PrincipalPolicy {
257
294
  version: number;
@@ -263,6 +300,20 @@ interface PrincipalPolicy {
263
300
  tier3_always_allow: string[];
264
301
  /** How approval requests reach the human */
265
302
  approval_channel: ApprovalChannelConfig;
303
+ /**
304
+ * WP-V1.3-9 Tau-1: operator-tunable retention window (days) for the
305
+ * concierge memory store. Per-turn `retention_until` is stamped at
306
+ * append time; cocoon-unlock pruning drops expired turns. Default 30
307
+ * days when absent; values <= 0 fall back to the default.
308
+ */
309
+ concierge_memory_retention_days?: number;
310
+ /**
311
+ * WP-V1.3-10 Upsilon-2: cross-harness approval-redirect mode. Optional;
312
+ * defaults to `{ enabled: false, mode: "replace" }` (preserves legacy
313
+ * behavior). Operator-toggled via `sanctuary agents config <tenant>
314
+ * --approval-redirect=<bool>` or by editing principal-policy.yaml.
315
+ */
316
+ approval_redirect?: ApprovalRedirectConfig;
266
317
  }
267
318
  /** Approval request sent to the human */
268
319
  interface ApprovalRequest {
@@ -276,7 +327,7 @@ interface ApprovalRequest {
276
327
  interface ApprovalResponse {
277
328
  decision: "approve" | "deny";
278
329
  decided_at: string;
279
- decided_by: "human" | "timeout" | "auto" | "stderr:non-interactive";
330
+ decided_by: "human" | "timeout" | "auto" | "stderr:non-interactive" | "channel_failure";
280
331
  }
281
332
  /** Result of the approval gate evaluation */
282
333
  interface GateResult {
@@ -658,6 +709,31 @@ type InjectionAlertCallback = (alert: {
658
709
  }) => void;
659
710
  /** Resolver for proxy tool tiers — provided by the ProxyRouter */
660
711
  type ProxyTierResolver = (toolName: string) => (1 | 2 | 3) | null;
712
+ /**
713
+ * Approval-lifecycle callback. Wired in v1.3 Upsilon-1 by the Cross-
714
+ * Harness Approval Inbox aggregator. The gate fires this callback before
715
+ * `channel.requestApproval()` (phase = "requested") and after the channel
716
+ * resolves or fails (phase = "resolved"). The callback is fire-and-forget;
717
+ * exceptions are swallowed so a broken aggregator never blocks the gate.
718
+ *
719
+ * The callback shape is import-free here so the principal-policy module
720
+ * keeps no dependency on the aggregator (the aggregator imports the gate,
721
+ * not vice versa).
722
+ */
723
+ type ApprovalEventCallback = (event: {
724
+ phase: "requested" | "resolved";
725
+ operation: string;
726
+ tier: 1 | 2;
727
+ reason: string;
728
+ context: Record<string, unknown>;
729
+ request_timestamp: string;
730
+ resolution?: {
731
+ decision: "approve" | "deny";
732
+ decided_at: string;
733
+ decided_by: string;
734
+ };
735
+ correlation_id: string;
736
+ }) => void;
661
737
  declare class ApprovalGate {
662
738
  private policy;
663
739
  private baseline;
@@ -665,8 +741,16 @@ declare class ApprovalGate {
665
741
  private auditLog;
666
742
  private injectionDetector;
667
743
  private onInjectionAlert?;
744
+ private onApprovalEvent?;
668
745
  private proxyTierResolver?;
669
- constructor(policy: PrincipalPolicy, baseline: BaselineTracker, channel: ApprovalChannel, auditLog: AuditLog, injectionDetector?: InjectionDetector, onInjectionAlert?: InjectionAlertCallback);
746
+ constructor(policy: PrincipalPolicy, baseline: BaselineTracker, channel: ApprovalChannel, auditLog: AuditLog, injectionDetector?: InjectionDetector, onInjectionAlert?: InjectionAlertCallback, onApprovalEvent?: ApprovalEventCallback);
747
+ /**
748
+ * Set the approval-event callback after construction. Used by the
749
+ * Upsilon-1 wire-up when the aggregator is constructed alongside the
750
+ * gate. The aggregator subscribes through this setter rather than the
751
+ * constructor so existing call sites continue to work unchanged.
752
+ */
753
+ setApprovalEventCallback(cb: ApprovalEventCallback | undefined): void;
670
754
  /**
671
755
  * Set the proxy tier resolver. Called after the proxy router is initialized.
672
756
  */
@@ -685,6 +769,13 @@ declare class ApprovalGate {
685
769
  private detectAnomaly;
686
770
  /**
687
771
  * Request approval from the human principal.
772
+ *
773
+ * Fail-closed contract (full-sweep #49): if the channel throws (network
774
+ * down, callback unreachable, dashboard SSE peer dropped, webhook DNS
775
+ * failure, etc.), the gate denies the operation and audit-logs the cause.
776
+ * Channel-internal timeouts already resolve with decision: "deny" per
777
+ * SEC-002; this catch covers the remaining "channel raised" path so an
778
+ * unhandled rejection cannot turn into an indeterminate state at the gate.
688
779
  */
689
780
  private requestApproval;
690
781
  /**
@@ -3537,7 +3628,7 @@ interface ExitBundleVerifierResult {
3537
3628
  * Coarse failure-class enum, when `passed` is false. Distinct from a free-text
3538
3629
  * error message so import commands can branch.
3539
3630
  */
3540
- failure_class?: "manifest_signature_invalid" | "manifest_unknown_version" | "manifest_signature_scheme_invalid" | "artifact_hash_mismatch" | "artifact_missing" | "artifact_size_mismatch" | "aggregate_hash_mismatch" | "artifact_path_unsafe" | "artifact_path_duplicate" | "artifact_path_escapes_root" | "archive_contains_symlink" | "private_material_present" | "other";
3631
+ failure_class?: "manifest_signature_invalid" | "manifest_unknown_version" | "manifest_signature_scheme_invalid" | "artifact_hash_mismatch" | "artifact_missing" | "artifact_size_mismatch" | "aggregate_hash_mismatch" | "artifact_path_unsafe" | "artifact_path_duplicate" | "artifact_path_escapes_root" | "archive_contains_symlink" | "private_material_present" | "identity_signature_invalid" | "reputation_bundle_signature_invalid" | "reputation_attestation_signature_invalid" | "reputation_unverifiable_attestations" | "other";
3541
3632
  }
3542
3633
 
3543
3634
  /**
@@ -4104,21 +4195,35 @@ interface ExitCommandArgs {
4104
4195
  declare function runExitCommand(args: ExitCommandArgs): Promise<number>;
4105
4196
 
4106
4197
  /**
4107
- * Sanctuary MCP Server Principal Policy Loader
4198
+ * Sanctuary MCP Server -- Principal Policy Loader
4108
4199
  *
4109
4200
  * Loads the Principal Policy from a YAML file at server startup.
4110
- * The policy is immutable at runtime no MCP tool can modify it.
4201
+ * The policy is immutable at runtime -- no MCP tool can modify it.
4111
4202
  *
4112
4203
  * Security invariant:
4113
4204
  * - The policy is loaded ONCE at startup and frozen.
4114
4205
  * - No code path exists to modify the policy during a session.
4115
4206
  * - If no policy file exists, a sensible default is generated and saved.
4207
+ * - If the policy file exists but is malformed, the server refuses to start
4208
+ * rather than silently substituting a default (operator intent preservation).
4116
4209
  */
4117
4210
 
4211
+ /**
4212
+ * Thrown when a principal-policy.yaml file exists on disk but cannot be
4213
+ * parsed or validated. Sanctuary refuses to substitute a default policy
4214
+ * when an existing file is present, to avoid silently overriding operator
4215
+ * intent.
4216
+ */
4217
+ declare class MalformedPrincipalPolicyError extends Error {
4218
+ readonly policyPath: string;
4219
+ readonly reason: string;
4220
+ constructor(policyPath: string, reason: string);
4221
+ }
4118
4222
  /**
4119
4223
  * Load the Principal Policy from disk.
4120
4224
  * If no policy file exists, generate the default and save it.
4121
- * The returned policy is frozen immutable at runtime.
4225
+ * If the file exists but is malformed, throw MalformedPrincipalPolicyError.
4226
+ * The returned policy is frozen -- immutable at runtime.
4122
4227
  */
4123
4228
  declare function loadPrincipalPolicy(storagePath: string): Promise<PrincipalPolicy>;
4124
4229
 
@@ -5045,6 +5150,171 @@ declare class OperatorChatStore {
5045
5150
  deleteThread(surface: OperatorChatSurface, threadKey: string): Promise<void>;
5046
5151
  }
5047
5152
 
5153
+ /**
5154
+ * Sanctuary MCP Server — Concierge Memory Store (WP-V1.3-9 Tau-1)
5155
+ *
5156
+ * Per-fortress, encrypted-at-rest, cocoon-bound persistence for
5157
+ * concierge conversation turns. Distinct from the v1.2 OperatorChatStore
5158
+ * (single fortress-scoped thread, capped FIFO, no retention) — this
5159
+ * store is the foundation for v1.3 conversational sovereignty depth:
5160
+ * multi-thread enumeration, per-turn retention, scrollable history.
5161
+ *
5162
+ * Storage layout:
5163
+ * namespace: `_chat` (existing reserved L1 namespace)
5164
+ * key: `concierge_memory.{thread_id}` (one record per thread)
5165
+ * payload: AES-256-GCM ciphertext of the JSON-serialised turns bundle.
5166
+ * key: `concierge-memory-store-v1` HKDF subkey of fortress master.
5167
+ * AAD: UTF-8 bytes of `thread_id` — swapping records across
5168
+ * threads breaks the auth tag. Castle-walking discipline:
5169
+ * the encryption boundary holds even against on-disk shuffle.
5170
+ *
5171
+ * Concurrency:
5172
+ * Per-thread async lock serializes appendTurn calls within the same
5173
+ * store instance. Cross-process locking is out of scope (single-process
5174
+ * Sanctuary server).
5175
+ *
5176
+ * Retention:
5177
+ * Each turn carries an ISO-8601 `retention_until`. `pruneExpired()`
5178
+ * iterates threads and drops turns whose retention_until is in the
5179
+ * past. Empty bundles are deleted entirely. Caller wires this into
5180
+ * the cocoon-unlock initialization path (the wiring layer fires it
5181
+ * once the store is constructed).
5182
+ *
5183
+ * Multi-fortress isolation:
5184
+ * The HKDF subkey is derived from the fortress master key. Two
5185
+ * fortresses never produce identical encryption keys for identical
5186
+ * thread_ids. The `fortress_id` field on each turn is metadata for
5187
+ * audit clarity; isolation is enforced cryptographically.
5188
+ */
5189
+
5190
+ /** One turn in a concierge thread. */
5191
+ interface ConciergeTurn {
5192
+ /** UUID of the thread this turn belongs to. */
5193
+ thread_id: string;
5194
+ /** Stable fortress id (audit metadata; isolation is keyed). */
5195
+ fortress_id: string;
5196
+ /** Monotonic turn number within thread, starting at 1. */
5197
+ turn_id: number;
5198
+ /** Sender role. */
5199
+ role: "user" | "assistant";
5200
+ /** Cleartext at runtime; AES-256-GCM at rest. */
5201
+ content: string;
5202
+ /** ISO-8601 timestamp of turn creation. */
5203
+ created_at: string;
5204
+ /** ISO-8601 timestamp after which prune drops this turn. */
5205
+ retention_until: string;
5206
+ }
5207
+ /** Operator-facing summary surfaced by `listThreads`. */
5208
+ interface ConciergeThreadSummary {
5209
+ thread_id: string;
5210
+ created_at: string;
5211
+ last_turn_at: string;
5212
+ turn_count: number;
5213
+ }
5214
+ interface ConciergeMemoryStoreOptions {
5215
+ /** Storage backend that persists the encrypted bundles. */
5216
+ storage: StorageBackend;
5217
+ /** 32-byte fortress master key. */
5218
+ masterKey: Uint8Array;
5219
+ /** Stable fortress id stamped on every turn for audit clarity. */
5220
+ fortressId: string;
5221
+ /** Operator-tunable retention window. Default 30 days. */
5222
+ retentionDays?: number;
5223
+ }
5224
+ interface ReadThreadOptions {
5225
+ /** Return only turns with turn_id strictly greater than this. */
5226
+ sinceTurnId?: number;
5227
+ /** Cap the number of turns returned (oldest-first within the bundle). */
5228
+ limit?: number;
5229
+ }
5230
+ /**
5231
+ * Stable failure-reason enum for `readThreadStrict` (WP-V1.3-9 Tau-2).
5232
+ * Mirrors the shape carried by `operator_concierge_memory_read_failed`
5233
+ * audit payloads so the service emits the cause verbatim.
5234
+ */
5235
+ type ConciergeMemoryReadFailure = "decrypt_failed" | "schema_mismatch" | "oversize_bundle" | "io_failed" | "unknown";
5236
+ /**
5237
+ * Discriminated result for `readThreadStrict`. The fold-read path uses
5238
+ * this so an empty thread (no bundle) does not look the same as a
5239
+ * corrupted bundle (which must trigger graceful degradation).
5240
+ */
5241
+ type ReadThreadStrictResult = {
5242
+ ok: true;
5243
+ turns: ConciergeTurn[];
5244
+ } | {
5245
+ ok: false;
5246
+ reason: ConciergeMemoryReadFailure;
5247
+ };
5248
+ interface ListThreadsOptions {
5249
+ /** Cap the number of summaries returned. */
5250
+ limit?: number;
5251
+ }
5252
+ /**
5253
+ * Encrypted, AAD-bound, retention-aware concierge memory persistence.
5254
+ */
5255
+ declare class ConciergeMemoryStore {
5256
+ private storage;
5257
+ private encryptionKey;
5258
+ private fortressId;
5259
+ private retentionDays;
5260
+ private locks;
5261
+ constructor(opts: ConciergeMemoryStoreOptions);
5262
+ /**
5263
+ * Append a turn to the named thread, creating the bundle if no record
5264
+ * exists. Returns the persisted turn (with assigned turn_id +
5265
+ * retention_until). Per-thread serialisation guarantees turn_id
5266
+ * monotonicity even under concurrent callers.
5267
+ */
5268
+ appendTurn(threadId: string, role: "user" | "assistant", content: string): Promise<ConciergeTurn>;
5269
+ /**
5270
+ * Read turns from a thread, oldest-first. Returns an empty array if
5271
+ * the thread does not exist or its bundle is corrupt. Does not emit
5272
+ * audit events; the caller (HTTP route handler) owns audit semantics.
5273
+ */
5274
+ readThread(threadId: string, opts?: ReadThreadOptions): Promise<ConciergeTurn[]>;
5275
+ /**
5276
+ * Read turns with explicit failure surfacing (WP-V1.3-9 Tau-2). Where
5277
+ * `readThread` collapses every failure mode to an empty array, this
5278
+ * variant returns a discriminated result so the multi-turn fold path
5279
+ * can degrade cleanly + emit `operator_concierge_memory_read_failed`
5280
+ * with a concrete cause.
5281
+ *
5282
+ * - No bundle on disk → `{ ok: true, turns: [] }` (a fresh thread).
5283
+ * - Bundle present, decode + decrypt + schema check pass → ok with turns.
5284
+ * - Bundle present, oversize → `{ ok: false, reason: "oversize_bundle" }`.
5285
+ * - Bundle present, decryption fails → `{ ok: false, reason: "decrypt_failed" }`.
5286
+ * - Bundle present, schema mismatch (version / thread_id) → `schema_mismatch`.
5287
+ * - Storage IO error → `io_failed`.
5288
+ */
5289
+ readThreadStrict(threadId: string, opts?: ReadThreadOptions): Promise<ReadThreadStrictResult>;
5290
+ /**
5291
+ * Enumerate concierge threads in this fortress with summary metadata.
5292
+ * Sorted newest-first by last_turn_at.
5293
+ */
5294
+ listThreads(opts?: ListThreadsOptions): Promise<ConciergeThreadSummary[]>;
5295
+ /**
5296
+ * Delete a thread's bundle. Returns true if the bundle existed and
5297
+ * was removed; false if no bundle was present. Audit emission is the
5298
+ * caller's responsibility.
5299
+ */
5300
+ deleteThread(threadId: string): Promise<boolean>;
5301
+ /**
5302
+ * Drop expired turns across all threads. Threads emptied by pruning
5303
+ * are removed entirely. Returns the count of turns pruned.
5304
+ */
5305
+ pruneExpired(now?: Date): Promise<{
5306
+ pruned: number;
5307
+ }>;
5308
+ private loadBundle;
5309
+ private saveBundle;
5310
+ /**
5311
+ * Run `task` while holding the per-thread async lock. Lock is released
5312
+ * once the task settles (success or failure). Generic helper so
5313
+ * appendTurn / deleteThread / pruneExpired share serialisation.
5314
+ */
5315
+ private withLock;
5316
+ }
5317
+
5048
5318
  /**
5049
5319
  * Sanctuary MCP Server — Operator Chat Service
5050
5320
  *
@@ -5146,6 +5416,51 @@ interface OperatorChatServiceDeps {
5146
5416
  * summary). Operator-tunable via dashboard config.
5147
5417
  */
5148
5418
  conciergeMaxTokens?: number;
5419
+ /**
5420
+ * WP-V1.3-9 Tau-1: optional foundation memory store. When wired,
5421
+ * `sendConcierge` dual-writes each operator+concierge turn pair into
5422
+ * the memory store under a session-scoped thread_id. Tau-2 adds a
5423
+ * read-fold path that surfaces the prior turns to the substrate so
5424
+ * the concierge maintains coherence across a multi-turn session.
5425
+ *
5426
+ * Omit at construction time to disable memory-side persistence; the
5427
+ * existing `OperatorChatStore` write keeps working unchanged.
5428
+ */
5429
+ conciergeMemory?: ConciergeMemoryStore;
5430
+ /**
5431
+ * WP-V1.3-9 Tau-2: maximum prior turns folded into the substrate
5432
+ * context per round-trip. Defaults to
5433
+ * `DEFAULT_CONCIERGE_HISTORY_WINDOW_TURNS` (10). The current operator
5434
+ * turn is always present; this caps history only.
5435
+ */
5436
+ conciergeHistoryWindowTurns?: number;
5437
+ /**
5438
+ * WP-V1.3-9 Tau-2: prior turns older than this many milliseconds are
5439
+ * excluded from the active fold even when they remain on disk.
5440
+ * Defaults to `DEFAULT_CONCIERGE_HISTORY_FRESHNESS_MS` (24h).
5441
+ */
5442
+ conciergeHistoryFreshnessMs?: number;
5443
+ /**
5444
+ * WP-V1.3-9 Tau-2: rough token budget for the prior-conversation
5445
+ * portion of the substrate context. Estimated as ~4 chars per token.
5446
+ * Defaults to `DEFAULT_CONCIERGE_HISTORY_TOKEN_BUDGET` (500). The
5447
+ * static reference block + fortress sections are NOT subject to this
5448
+ * budget; only the prior-conversation fold is pruned oldest-first.
5449
+ */
5450
+ conciergeHistoryTokenBudget?: number;
5451
+ /**
5452
+ * WP-V1.3-9 Tau-2: how long an active session may stay quiet before
5453
+ * the next `sendConcierge` allocates a fresh thread_id. Defaults to
5454
+ * `DEFAULT_CONCIERGE_SESSION_TTL_MS` (24h). Does not delete the prior
5455
+ * thread; it remains readable through the memory store.
5456
+ */
5457
+ conciergeSessionTtlMs?: number;
5458
+ /**
5459
+ * Optional clock for the session-TTL + freshness checks. Tests inject
5460
+ * a deterministic clock; production lets the default `Date.now`-based
5461
+ * implementation run.
5462
+ */
5463
+ conciergeClock?: () => number;
5149
5464
  }
5150
5465
  declare class OperatorChatService {
5151
5466
  private store;
@@ -5155,6 +5470,27 @@ declare class OperatorChatService {
5155
5470
  private contextProviders?;
5156
5471
  private piiFilter?;
5157
5472
  private conciergeMaxTokens;
5473
+ private memory?;
5474
+ private historyWindowTurns;
5475
+ private historyFreshnessMs;
5476
+ private historyTokenBudget;
5477
+ private sessionTtlMs;
5478
+ private clock;
5479
+ /**
5480
+ * In-memory thread_id assigned to the active concierge session.
5481
+ * The first sendConcierge call after construction allocates a fresh
5482
+ * UUID; subsequent calls reuse it so multi-turn coherence (Tau-2)
5483
+ * folds the prior turns into context. Cleared by `resetConciergeMemoryThread`.
5484
+ */
5485
+ private activeMemoryThreadId?;
5486
+ /**
5487
+ * Wall-clock ms of the most recent sendConcierge that touched the
5488
+ * active session thread. Drives the WP-V1.3-9 Tau-2 session-TTL
5489
+ * check: a fresh sendConcierge after `sessionTtlMs` of quiet
5490
+ * allocates a new thread_id even though the prior one is still
5491
+ * readable from the memory store.
5492
+ */
5493
+ private lastInteractionAt?;
5158
5494
  constructor(deps: OperatorChatServiceDeps);
5159
5495
  /**
5160
5496
  * Operator submit on the concierge surface. Persists the operator's
@@ -5167,11 +5503,47 @@ declare class OperatorChatService {
5167
5503
  * operator sees on the page (no silent dropping).
5168
5504
  */
5169
5505
  sendConcierge(query: string): Promise<ConciergeResponse>;
5506
+ /**
5507
+ * Emit the WP-V1.3-9 Tau-2 graceful-degradation audit event. Pulled
5508
+ * out of `sendConcierge` so the read-fold path stays readable. Emits
5509
+ * with `result: "failure"` since the concierge fell back to
5510
+ * single-turn mode for this round-trip.
5511
+ */
5512
+ private emitMemoryReadFailed;
5170
5513
  /**
5171
5514
  * Read the persisted concierge thread, oldest message first. Returns
5172
5515
  * an empty array when no thread exists yet.
5173
5516
  */
5174
5517
  getConciergeHistory(): Promise<OperatorChatMessage[]>;
5518
+ /**
5519
+ * Whether the foundation memory store is wired. Routes use this to
5520
+ * 503 cleanly when called against an unwired service.
5521
+ */
5522
+ hasConciergeMemory(): boolean;
5523
+ /**
5524
+ * List concierge memory threads, newest-first. Emits the
5525
+ * `operator_concierge_history_read` audit event with `thread_id="*"`.
5526
+ */
5527
+ listConciergeMemoryThreads(opts?: ListThreadsOptions): Promise<ConciergeThreadSummary[]>;
5528
+ /**
5529
+ * Read a concierge memory thread, oldest turn first. Emits the
5530
+ * `operator_concierge_history_read` audit event with the named
5531
+ * thread_id and the count of turns surfaced.
5532
+ */
5533
+ readConciergeMemoryThread(threadId: string, opts?: ReadThreadOptions): Promise<ConciergeTurn[]>;
5534
+ /**
5535
+ * Delete a concierge memory thread. Emits
5536
+ * `operator_concierge_thread_deleted` only when a bundle was actually
5537
+ * removed; absent threads return false without an audit event.
5538
+ */
5539
+ deleteConciergeMemoryThread(threadId: string): Promise<boolean>;
5540
+ /**
5541
+ * Reset the active session memory thread. Subsequent sendConcierge
5542
+ * calls allocate a fresh thread_id. Surfaced for tests + future "new
5543
+ * conversation" affordance; not currently called by the dashboard.
5544
+ */
5545
+ resetConciergeMemoryThread(): void;
5546
+ private ensureActiveMemoryThread;
5175
5547
  /**
5176
5548
  * Stitch fortress state into a single context blob the substrate
5177
5549
  * folds into its summarization prompt.
@@ -5184,6 +5556,11 @@ declare class OperatorChatService {
5184
5556
  * ## Sanctuary reference
5185
5557
  * <static domain reference block>
5186
5558
  *
5559
+ * ## Prior conversation ← WP-V1.3-9 Tau-2, when present
5560
+ * OPERATOR: ...
5561
+ * CONCIERGE: ...
5562
+ * ---
5563
+ *
5187
5564
  * ## Recent activity
5188
5565
  * <recentActivity output>
5189
5566
  *
@@ -5193,8 +5570,22 @@ declare class OperatorChatService {
5193
5570
  * ## Open inbox
5194
5571
  * <openInbox output>
5195
5572
  * ```
5573
+ *
5574
+ * The substrate selector ships a `context: string` shape (not a
5575
+ * messages array), so multi-turn coherence is folded as a structured
5576
+ * prior-conversation section with explicit OPERATOR / CONCIERGE
5577
+ * boundaries. Coordinator-CTO guidance: prefer messages-array shape
5578
+ * if available; the v1.2 selector does not expose one, so structured
5579
+ * serialization is the canonical path for v1.3.
5196
5580
  */
5197
5581
  private assembleConciergeContext;
5582
+ /**
5583
+ * Render the prior-conversation section with token-budget enforcement
5584
+ * (WP-V1.3-9 Tau-2). Drops oldest turns first when the rendered
5585
+ * section exceeds `historyTokenBudget`. Returns an empty string when
5586
+ * the input is empty or when the budget excludes every turn.
5587
+ */
5588
+ private formatPriorTurnsSection;
5198
5589
  private emit;
5199
5590
  }
5200
5591
 
@@ -5603,6 +5994,15 @@ declare class HubService {
5603
5994
  * Read the persisted concierge thread.
5604
5995
  */
5605
5996
  getConciergeHistory(): Promise<OperatorChatMessage[]>;
5997
+ /**
5998
+ * Whether the operator-chat service has the WP-V1.3-9 memory store
5999
+ * wired. Routes use this to 503 cleanly when the foundation memory
6000
+ * surface is unavailable on a given fortress.
6001
+ */
6002
+ hasConciergeMemory(): boolean;
6003
+ listConciergeMemoryThreads(opts?: ListThreadsOptions): Promise<ConciergeThreadSummary[]>;
6004
+ readConciergeMemoryThread(threadId: string, opts?: ReadThreadOptions): Promise<ConciergeTurn[]>;
6005
+ deleteConciergeMemoryThread(threadId: string): Promise<boolean>;
5606
6006
  /**
5607
6007
  * Open the click-to-inspect/approve panel for a wrapped agent. The
5608
6008
  * panel surfaces recent activity routed through this agent, pending
@@ -5669,6 +6069,268 @@ interface V11Bindings {
5669
6069
  operatorChatService?: OperatorChatService;
5670
6070
  }
5671
6071
 
6072
+ /**
6073
+ * Sanctuary v1.3 WP-V1.3-10 Cross-Harness Approval Inbox Upsilon-1
6074
+ *
6075
+ * The aggregator is a passive subscriber to the existing ApprovalGate
6076
+ * lifecycle. On each `gate-request` event it normalizes the payload into a
6077
+ * stable `AggregatedApproval` record, dedupes against prior emissions of
6078
+ * the same `(source_harness, source_agent_id, audit_log_entry_id)` tuple,
6079
+ * persists the record under the reserved `_approval_aggregator` namespace,
6080
+ * and exposes a query + resolve API.
6081
+ *
6082
+ * Scope of Upsilon-1:
6083
+ * - Aggregator module + storage + resolve API.
6084
+ * - Wired into the gate via an additive callback. The gate's blocking
6085
+ * deny/accept logic is unchanged; the aggregator never fails the gate
6086
+ * (callback exceptions are swallowed and audit-logged).
6087
+ * - HTTP route surface and three audit event names are owned by the
6088
+ * sibling `approval-aggregator-routes.ts` module + the gate wire-up.
6089
+ *
6090
+ * Out of scope (carries to Upsilon-2..4):
6091
+ * - Per-harness wrapped-agent approval-redirect mode.
6092
+ * - Operator decisions through the aggregator's HTTP `approve`/`deny`
6093
+ * routes flowing back to a blocked `channel.requestApproval()` call;
6094
+ * Upsilon-1 records the decision on the aggregator entry only.
6095
+ * - Provenance + replay UX.
6096
+ * - Mobile companion preview hook.
6097
+ */
6098
+
6099
+ /**
6100
+ * Lifecycle status of an aggregated approval entry.
6101
+ * - `pending`: ingest fired, gate is awaiting a channel decision.
6102
+ * - `approved` / `denied`: gate's channel returned a decision OR the
6103
+ * operator resolved through the HTTP surface.
6104
+ * - `timeout`: the channel reported a timeout (decided_by ===
6105
+ * 'channel_failure' OR explicit timeout reason).
6106
+ * - `expired`: pending past TTL on a `list()` poll without a resolution.
6107
+ */
6108
+ type AggregatedApprovalStatus = "pending" | "approved" | "denied" | "timeout" | "expired";
6109
+ /**
6110
+ * Normalized record the aggregator stores per approval. Field set is
6111
+ * additive-stable; new fields go behind `?` so existing dashboards keep
6112
+ * rendering unchanged. Raw request payloads are not stored on the record;
6113
+ * only a SHA-256 hash and the original payload pulled separately via
6114
+ * `getFullPayload()`.
6115
+ */
6116
+ interface AggregatedApproval {
6117
+ /** Stable per-fortress aggregator id (UUID v4). */
6118
+ aggregator_id: string;
6119
+ /** Harness the source approval came from (claude-code, cline, cursor, etc). */
6120
+ source_harness: string;
6121
+ /** Wrapped-agent identifier. Ed25519 pubkey hex or label. */
6122
+ source_agent_id: string;
6123
+ /**
6124
+ * Audit-log entry id this approval correlates to. Used as the
6125
+ * deduplication key alongside source_harness and source_agent_id.
6126
+ * Format: `<iso-timestamp>:<operation>` so two different requests on the
6127
+ * same operation in the same millisecond are still distinguishable.
6128
+ */
6129
+ audit_log_entry_id: string;
6130
+ /** Policy rule that fired (`tier1_<operation>`, `tier2_<anomaly>`, etc.). */
6131
+ policy_rule_id: string;
6132
+ /** Operator-friendly one-line summary, derived from gate context. */
6133
+ action_summary: string;
6134
+ /** SHA-256 hex of the canonicalized request payload. */
6135
+ request_payload_hash: string;
6136
+ /** Lifecycle status. */
6137
+ status: AggregatedApprovalStatus;
6138
+ /** ISO 8601 timestamp the aggregator first ingested the request. */
6139
+ created_at: string;
6140
+ /** ISO 8601 timestamp the status left `pending`. */
6141
+ resolved_at?: string;
6142
+ /** Operator identity that resolved the entry, if applicable. */
6143
+ resolved_by?: string;
6144
+ /** ISO 8601 deadline. Defaults to created_at + DEFAULT_PENDING_TTL_MS. */
6145
+ expires_at: string;
6146
+ /**
6147
+ * Optional cross-link to a v1.1 hub inbox item id. When set, the
6148
+ * dashboard renderer SHOULD suppress the duplicate hub card so the
6149
+ * operator sees one card per approval. Hub inbox surface is unchanged
6150
+ * (the cross-link signal lives on the aggregator side only).
6151
+ */
6152
+ hub_inbox_item_id?: string;
6153
+ }
6154
+ /**
6155
+ * Source-context resolver. Called once per ingest to map gate context to
6156
+ * the aggregator's harness + agent_id fields. Default impl reads the
6157
+ * fortress identity (single-agent fortresses) and returns `unknown` when
6158
+ * the gate context does not name an agent.
6159
+ */
6160
+ interface ApprovalSourceContext {
6161
+ source_harness: string;
6162
+ source_agent_id: string;
6163
+ }
6164
+ /**
6165
+ * Event the gate emits per approval lifecycle transition.
6166
+ */
6167
+ interface ApprovalGateEvent {
6168
+ /** `requested` on initial gate entry; `resolved` when channel returns. */
6169
+ phase: "requested" | "resolved";
6170
+ /** Operation name from the policy gate. */
6171
+ operation: string;
6172
+ /** Tier the gate decided on. */
6173
+ tier: 1 | 2;
6174
+ /** Human-readable reason from the gate (audit log only; not user-facing). */
6175
+ reason: string;
6176
+ /** Sanitized context map the gate captured. */
6177
+ context: Record<string, unknown>;
6178
+ /** ISO 8601 timestamp the gate entered `requestApproval()`. */
6179
+ request_timestamp: string;
6180
+ /**
6181
+ * On `resolved` only. Channel decision plus decided_by metadata. When
6182
+ * `decision === 'deny'` and `decided_by === 'channel_failure'`, the
6183
+ * aggregator records `status: 'timeout'` (Castle-walking discipline:
6184
+ * fail-closed at the gate flows through to the inbox).
6185
+ */
6186
+ resolution?: {
6187
+ decision: "approve" | "deny";
6188
+ decided_at: string;
6189
+ decided_by: string;
6190
+ };
6191
+ /**
6192
+ * Stable correlation id the gate emits BOTH on `requested` and on
6193
+ * `resolved`. The aggregator uses this to update the same entry on the
6194
+ * resolution event. Format: `<iso-ms-timestamp>:<operation>:<random4>`.
6195
+ */
6196
+ correlation_id: string;
6197
+ }
6198
+ /**
6199
+ * Listener subscription returned by `onEvent`. Call to unsubscribe.
6200
+ */
6201
+ type ApprovalAggregatorUnsubscribe = () => void;
6202
+ /**
6203
+ * Event emitted to subscribers. Mirrors the lifecycle transitions the
6204
+ * aggregator records. SSE listeners surface these to the dashboard.
6205
+ */
6206
+ interface ApprovalAggregatorEmit {
6207
+ /**
6208
+ * `aggregated` on first ingest, `resolved` on a status leaving pending,
6209
+ * `deduped` when an ingest dropped because the same dedup key was seen.
6210
+ */
6211
+ type: "aggregated" | "resolved" | "deduped";
6212
+ entry: AggregatedApproval;
6213
+ }
6214
+ /**
6215
+ * Constructor dependencies. `pendingTtlMs` and `maxListLimit` default to
6216
+ * coordinator-CTO defaults; tests pass overrides for deterministic timing.
6217
+ */
6218
+ interface ApprovalAggregatorDeps {
6219
+ storage: StorageBackend;
6220
+ masterKey: Uint8Array;
6221
+ auditLog: AuditLog;
6222
+ /** Operator identity id. Recorded on the audit entries. */
6223
+ identityId: string;
6224
+ /** Stable fortress id. Drives the source-context default values. */
6225
+ fortressId: string;
6226
+ /** Optional override for the pending TTL. */
6227
+ pendingTtlMs?: number;
6228
+ /** Optional override for the maximum list limit. */
6229
+ maxListLimit?: number;
6230
+ /** Optional clock override for deterministic tests. Defaults to `() => new Date()`. */
6231
+ now?: () => Date;
6232
+ /** Optional source-context resolver. Defaults to fortress identifiers. */
6233
+ resolveSourceContext?: (event: ApprovalGateEvent) => ApprovalSourceContext;
6234
+ /**
6235
+ * Optional cross-link resolver. Returns the v1.1 hub inbox item id that
6236
+ * shadows the same approval, when known. Default returns undefined and
6237
+ * the dashboard renders both surfaces. Upsilon-2 wires this through the
6238
+ * hub inbox store.
6239
+ */
6240
+ resolveHubInboxItemId?: (event: ApprovalGateEvent) => string | undefined;
6241
+ }
6242
+ /**
6243
+ * Aggregator state. The map is hydrated lazily from the encrypted
6244
+ * namespace on first read; subsequent reads are served from memory.
6245
+ */
6246
+ declare class ApprovalAggregator {
6247
+ private readonly storage;
6248
+ private readonly encryptionKey;
6249
+ private readonly auditLog;
6250
+ private readonly identityId;
6251
+ private readonly fortressId;
6252
+ private readonly pendingTtlMs;
6253
+ private readonly maxListLimit;
6254
+ private readonly now;
6255
+ private readonly resolveSourceContext;
6256
+ private readonly resolveHubInboxItemId;
6257
+ /** Cached entries by `aggregator_id`. */
6258
+ private readonly entries;
6259
+ /** Dedup index: `${harness}|${agent}|${audit_id}` -> aggregator_id. */
6260
+ private readonly dedupIndex;
6261
+ /** Correlation index: gate `correlation_id` -> aggregator_id. */
6262
+ private readonly correlationIndex;
6263
+ /** Original request payloads kept in-memory for `getFullPayload()`. */
6264
+ private readonly fullPayloads;
6265
+ /** Has the aggregator hydrated persisted entries on this process? */
6266
+ private hydrated;
6267
+ /** Active SSE listeners. */
6268
+ private readonly listeners;
6269
+ constructor(deps: ApprovalAggregatorDeps);
6270
+ /**
6271
+ * Subscribe an event listener. Returns an unsubscribe fn. SSE handlers
6272
+ * use this to forward aggregator emissions to the dashboard.
6273
+ */
6274
+ onEvent(listener: (event: ApprovalAggregatorEmit) => void): ApprovalAggregatorUnsubscribe;
6275
+ /**
6276
+ * Ingest a gate event. Returns the aggregator entry on first sight,
6277
+ * `null` when deduped. Resolution events update the existing record;
6278
+ * unmatched resolutions are dropped silently (caller's gate emitted a
6279
+ * resolved-without-requested pair, which the aggregator does not invent
6280
+ * a record for).
6281
+ */
6282
+ ingest(event: ApprovalGateEvent): Promise<AggregatedApproval | null>;
6283
+ /**
6284
+ * List pending or recently resolved entries. Pending entries past TTL
6285
+ * are lazily transitioned to `expired` and persisted before the list
6286
+ * snapshot is returned.
6287
+ */
6288
+ list(opts?: {
6289
+ status?: AggregatedApprovalStatus;
6290
+ sinceTs?: string;
6291
+ limit?: number;
6292
+ }): Promise<AggregatedApproval[]>;
6293
+ /**
6294
+ * Return the original (unhashed) request payload for the entry. Returns
6295
+ * `null` when the entry is unknown or the payload was evicted (e.g. the
6296
+ * process restarted; payloads are in-memory only at v1.3 Upsilon-1).
6297
+ */
6298
+ getFullPayload(aggregatorId: string): Promise<unknown>;
6299
+ /**
6300
+ * Resolve an entry. Used by both:
6301
+ * 1. The gate wire-up on channel-decision return.
6302
+ * 2. The HTTP `approve`/`deny` routes when an operator clicks.
6303
+ *
6304
+ * Idempotent: resolving an already-resolved entry is a no-op (the record
6305
+ * keeps its first decision and the audit log is not double-fired).
6306
+ * Unknown ids throw `Error("approval-aggregator: not_found")` so HTTP
6307
+ * routes return 404.
6308
+ */
6309
+ resolve(aggregatorId: string, decision: "approved" | "denied", operatorId: string): Promise<AggregatedApproval>;
6310
+ private ingestRequested;
6311
+ private ingestResolved;
6312
+ /**
6313
+ * Audit-log entry id for the dedup tuple. The audit log itself does not
6314
+ * surface a stable per-entry id (counter-prefixed keys are internal); the
6315
+ * aggregator uses the request timestamp + operation, which together pin
6316
+ * the audit entry the gate appended on the same call.
6317
+ */
6318
+ private auditEntryIdForEvent;
6319
+ private derivePolicyRuleId;
6320
+ private deriveActionSummary;
6321
+ /**
6322
+ * Canonical SHA-256 of the request context. Sorted-keys serialization so
6323
+ * identical payloads always hash the same, even when key insertion order
6324
+ * varies. Defends against payload-replay smuggling (the aggregator can
6325
+ * tell the same payload was seen twice without storing it cleartext).
6326
+ */
6327
+ private hashPayload;
6328
+ private emit;
6329
+ private expireStale;
6330
+ private persist;
6331
+ private hydrate;
6332
+ }
6333
+
5672
6334
  /**
5673
6335
  * Sanctuary MCP Server — Principal Dashboard
5674
6336
  *
@@ -5758,6 +6420,14 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
5758
6420
  * regardless. Default route flip is deferred to v1.2.
5759
6421
  */
5760
6422
  private v11Bindings;
6423
+ /**
6424
+ * v1.3 WP-V1.3-10 Cross-Harness Approval Inbox aggregator. Mounted
6425
+ * additively at `/api/approval-inbox/*` when set. Legacy approval
6426
+ * routes at `/api/approvals/:id/(allow|deny)` continue to serve. The
6427
+ * aggregator is a passive subscriber to the gate; the routes here are
6428
+ * the operator-facing query / decision surface.
6429
+ */
6430
+ private approvalAggregator;
5761
6431
  constructor(config: DashboardConfig);
5762
6432
  /**
5763
6433
  * Inject dependencies after construction.
@@ -5788,6 +6458,18 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
5788
6458
  * Pass `null` to detach the bindings (used by tests and during shutdown).
5789
6459
  */
5790
6460
  setV11Bindings(bindings: V11Bindings | null): void;
6461
+ /**
6462
+ * v1.3 WP-V1.3-10 Upsilon-1: bind the cross-harness approval inbox
6463
+ * aggregator. Once set, requests to `/api/approval-inbox/*` route
6464
+ * through `handleApprovalInboxRoute`. Pass `null` to detach (used by
6465
+ * tests + during shutdown).
6466
+ */
6467
+ setApprovalAggregator(aggregator: ApprovalAggregator | null): void;
6468
+ /**
6469
+ * v1.3 WP-V1.3-10 dispatch entry point. Called from `handleRequest`
6470
+ * before the legacy approval route table. Returns true when served.
6471
+ */
6472
+ private dispatchApprovalInbox;
5791
6473
  /**
5792
6474
  * v1.1 dispatch entry point. Called from `handleRequest` before the
5793
6475
  * legacy route table. Returns true when the request was served by v1.1
@@ -6772,4 +7454,4 @@ declare function createSanctuaryServer(options?: {
6772
7454
  storage?: StorageBackend;
6773
7455
  }): Promise<SanctuaryServer>;
6774
7456
 
6775
- 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 ExitAuditReceiptsArtifact, type ExitBundleDetailedVerifierResult, ExitBundleImportError, type ExitCommandArgs, type ExitCommitmentsArtifact, type ExitEncryptedStateBundle, type ExitPlaceholderVaultMetadataArtifact, type ExitPolicySetArtifact, type ExitPublicIdentityArtifact, type ExportExitBundleOptions, type ExportExitBundleResult, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, HERO_COPY, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, type ImportExitBundleOptions, type ImportExitBundleResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, type L1Status, type L2Status, type L3Status, type L4Status, type LoadedExitArtifact, 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, type VerifyExitBundleOptions, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, exitBundleManifestShape, exportExitBundle, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getProtectionSnapshot, getTemplate, importExitBundle, initiateHandshake, listTemplateIds, loadConfig, loadExitArtifact, loadPrincipalPolicy, readManifest, recommendPolicy, renderDashboardHTML, resolveTier, respondToHandshake, runExitCommand, signPayload, startDashboard, startDashboardServer, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyExitBundle, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
7457
+ 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 ExitAuditReceiptsArtifact, type ExitBundleDetailedVerifierResult, ExitBundleImportError, type ExitCommandArgs, type ExitCommitmentsArtifact, type ExitEncryptedStateBundle, type ExitPlaceholderVaultMetadataArtifact, type ExitPolicySetArtifact, type ExitPublicIdentityArtifact, type ExportExitBundleOptions, type ExportExitBundleResult, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, HERO_COPY, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, type ImportExitBundleOptions, type ImportExitBundleResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, type L1Status, type L2Status, type L3Status, type L4Status, type LoadedExitArtifact, MODEL_PRESETS, MalformedPrincipalPolicyError, 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, type VerifyExitBundleOptions, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, exitBundleManifestShape, exportExitBundle, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getProtectionSnapshot, getTemplate, importExitBundle, initiateHandshake, listTemplateIds, loadConfig, loadExitArtifact, loadPrincipalPolicy, readManifest, recommendPolicy, renderDashboardHTML, resolveTier, respondToHandshake, runExitCommand, signPayload, startDashboard, startDashboardServer, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyExitBundle, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };