@sanctuary-framework/mcp-server 1.0.0-rc.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +21551 -15416
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21558 -15423
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +19607 -14493
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1759 -3
- package/dist/index.d.ts +1759 -3
- package/dist/index.js +19603 -14496
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
2
2
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
3
3
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
4
4
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
5
|
+
import { Writable } from 'node:stream';
|
|
5
6
|
|
|
6
7
|
interface SanctuaryConfig {
|
|
7
8
|
version: string;
|
|
@@ -68,6 +69,12 @@ interface SanctuaryConfig {
|
|
|
68
69
|
/** Whether to auto-publish on successful handshake_respond calls. */
|
|
69
70
|
auto_publish_handshakes: boolean;
|
|
70
71
|
};
|
|
72
|
+
privacy_filter: {
|
|
73
|
+
mode: "local" | "opf" | "off";
|
|
74
|
+
fail_mode: "closed" | "fallback";
|
|
75
|
+
command: string;
|
|
76
|
+
timeout_ms: number;
|
|
77
|
+
};
|
|
71
78
|
}
|
|
72
79
|
/**
|
|
73
80
|
* Load configuration from file, falling back to defaults.
|
|
@@ -761,6 +768,28 @@ interface EncryptedPayload {
|
|
|
761
768
|
* - Secure deletion overwrites before unlinking
|
|
762
769
|
*/
|
|
763
770
|
|
|
771
|
+
/** On-disk format for an encrypted state entry */
|
|
772
|
+
interface StateEntry {
|
|
773
|
+
/** Format version */
|
|
774
|
+
v: number;
|
|
775
|
+
/** Encrypted payload */
|
|
776
|
+
payload: EncryptedPayload;
|
|
777
|
+
/** Version number (monotonically increasing) */
|
|
778
|
+
ver: number;
|
|
779
|
+
/** Signature over ciphertext by the writing identity (base64url) */
|
|
780
|
+
sig: string;
|
|
781
|
+
/** Identity that wrote this entry */
|
|
782
|
+
kid: string;
|
|
783
|
+
/** SHA-256 of the plaintext value (base64url, for client-side verification) */
|
|
784
|
+
integrity_hash: string;
|
|
785
|
+
/** Metadata */
|
|
786
|
+
metadata: {
|
|
787
|
+
content_type?: string;
|
|
788
|
+
ttl_seconds?: number;
|
|
789
|
+
tags?: string[];
|
|
790
|
+
written_at: string;
|
|
791
|
+
};
|
|
792
|
+
}
|
|
764
793
|
/** Result of a state write operation */
|
|
765
794
|
interface WriteResult {
|
|
766
795
|
key: string;
|
|
@@ -2122,6 +2151,124 @@ declare const MODEL_PRESETS: {
|
|
|
2122
2151
|
mistral7bLocal: () => ModelProvenance;
|
|
2123
2152
|
};
|
|
2124
2153
|
|
|
2154
|
+
/**
|
|
2155
|
+
* Signature scheme identifier embedded on every signed v1.1 record.
|
|
2156
|
+
*
|
|
2157
|
+
* v1.1 only accepts "ed25519-v1". Mirrors the mesh module: this field is the
|
|
2158
|
+
* forward-compat hinge for v1.4+ post-quantum migration. Verifiers MUST reject
|
|
2159
|
+
* unknown schemes. Do not optimize this field away.
|
|
2160
|
+
*
|
|
2161
|
+
* Mirror of: server/src/mesh/constants.ts SignatureScheme.
|
|
2162
|
+
*/
|
|
2163
|
+
type SignatureScheme = "ed25519-v1";
|
|
2164
|
+
/**
|
|
2165
|
+
* Detector classes for the privacy filter. Workstreams MUST use this enum so
|
|
2166
|
+
* the dashboard privacy panel and audit consumers can group consistently.
|
|
2167
|
+
*
|
|
2168
|
+
* "custom" is reserved for operator-defined detectors via policy.
|
|
2169
|
+
*/
|
|
2170
|
+
declare const PRIVACY_DETECTOR_CLASSES: readonly ["person", "client", "project", "secret", "credential", "account", "file_path", "domain_term", "custom"];
|
|
2171
|
+
type PrivacyDetectorClass = (typeof PRIVACY_DETECTOR_CLASSES)[number];
|
|
2172
|
+
/**
|
|
2173
|
+
* Outbound destination categories. The privacy filter and the remote-bound
|
|
2174
|
+
* enforcement workstream agree on this enum so events compose end-to-end.
|
|
2175
|
+
*
|
|
2176
|
+
* Categories deliberately mirror the L2 `ProviderCategory` taxonomy in
|
|
2177
|
+
* `server/src/l2-operational/context-gate.ts` (hyphen form) so JSON-stable
|
|
2178
|
+
* strings flow through both layers without translation. If the L2 category
|
|
2179
|
+
* set grows, keep this v1.1 list in lockstep through coordinator review.
|
|
2180
|
+
*/
|
|
2181
|
+
declare const PRIVACY_DESTINATION_CATEGORIES: readonly ["inference", "tool-api", "logging", "analytics", "peer-agent", "custom"];
|
|
2182
|
+
type PrivacyDestinationCategory = (typeof PRIVACY_DESTINATION_CATEGORIES)[number];
|
|
2183
|
+
/**
|
|
2184
|
+
* Privacy actions taken on a single field. Uses the L2 vocabulary.
|
|
2185
|
+
*
|
|
2186
|
+
* "rehydrate" is v1.1-new and applies to inbound responses, not outbound calls.
|
|
2187
|
+
*/
|
|
2188
|
+
declare const PRIVACY_ACTIONS: readonly ["allow", "redact", "hash", "summarize", "deny", "rehydrate"];
|
|
2189
|
+
type PrivacyAction = (typeof PRIVACY_ACTIONS)[number];
|
|
2190
|
+
/**
|
|
2191
|
+
* Hash algorithm identifier embedded in every privacy event content_hash.
|
|
2192
|
+
*
|
|
2193
|
+
* v1.1 ships ONLY `hmac-sha256-fortress-keyed-v1`: HMAC-SHA-256 over the
|
|
2194
|
+
* raw field value, using a per-fortress secret derived from the master key
|
|
2195
|
+
* via HKDF info string `sanctuary-v1.1-privacy-content-hmac`. Plain SHA-256
|
|
2196
|
+
* is NOT permitted because privacy field values (PII, project names, client
|
|
2197
|
+
* names, file paths) are low-entropy and dictionary-attackable. The keyed
|
|
2198
|
+
* hash makes content hashes meaningful for equality checks across events
|
|
2199
|
+
* within a fortress while remaining opaque to anyone without the per-
|
|
2200
|
+
* fortress key.
|
|
2201
|
+
*
|
|
2202
|
+
* Forward-compat: a future v1.x privacy hardening pass may add ML-DSA-keyed
|
|
2203
|
+
* variants. Verifiers MUST reject unknown algorithms.
|
|
2204
|
+
*/
|
|
2205
|
+
declare const PRIVACY_HASH_ALGS: readonly ["hmac-sha256-fortress-keyed-v1"];
|
|
2206
|
+
type PrivacyHashAlg = (typeof PRIVACY_HASH_ALGS)[number];
|
|
2207
|
+
/**
|
|
2208
|
+
* Hub inbox item kinds. Hub API and dashboard consume the same enum so the
|
|
2209
|
+
* unified inbox renders without inventing new categories per surface.
|
|
2210
|
+
*/
|
|
2211
|
+
declare const HUB_INBOX_KINDS: readonly ["approval_pending", "blocked_egress", "privacy_event", "budget_warning", "recovery_prompt", "agent_error"];
|
|
2212
|
+
type HubInboxKind = (typeof HUB_INBOX_KINDS)[number];
|
|
2213
|
+
/**
|
|
2214
|
+
* Agent lifecycle states surfaced to the operator hub.
|
|
2215
|
+
*
|
|
2216
|
+
* Underlying harness capability dictates which transitions are reachable; the
|
|
2217
|
+
* hub API surfaces unsupported transitions as "not_supported" rather than
|
|
2218
|
+
* faking them.
|
|
2219
|
+
*/
|
|
2220
|
+
declare const HUB_AGENT_STATUSES: readonly ["active", "paused", "restarting", "locked_down", "unwrapping", "error", "unknown"];
|
|
2221
|
+
type HubAgentStatus = (typeof HUB_AGENT_STATUSES)[number];
|
|
2222
|
+
/**
|
|
2223
|
+
* Exit-bundle manifest version. v1 is the only valid value at v1.1 ship.
|
|
2224
|
+
* v1.x bumps require coordinator-approved manifest amendment.
|
|
2225
|
+
*/
|
|
2226
|
+
declare const EXIT_BUNDLE_MANIFEST_VERSION: "SANCTUARY_EXIT_BUNDLE_V1";
|
|
2227
|
+
type ExitBundleManifestVersion = typeof EXIT_BUNDLE_MANIFEST_VERSION;
|
|
2228
|
+
/**
|
|
2229
|
+
* Artifact kinds enumerated by the exit-bundle manifest. The export command
|
|
2230
|
+
* MUST list every included artifact under one of these kinds. The verifier
|
|
2231
|
+
* CLI rejects unknown kinds.
|
|
2232
|
+
*/
|
|
2233
|
+
declare const EXIT_BUNDLE_ARTIFACT_KINDS: readonly ["public_identity", "encrypted_state", "policy_set", "audit_receipts", "reputation_bundle", "commitments", "placeholder_vault_metadata"];
|
|
2234
|
+
type ExitBundleArtifactKind = (typeof EXIT_BUNDLE_ARTIFACT_KINDS)[number];
|
|
2235
|
+
|
|
2236
|
+
/**
|
|
2237
|
+
* Lightweight local privacy filter for outbound context.
|
|
2238
|
+
*
|
|
2239
|
+
* This is not a replacement for a full detector such as OpenAI privacy-filter.
|
|
2240
|
+
* It gives Sanctuary a deterministic baseline that catches common high-risk
|
|
2241
|
+
* spans inside otherwise-allowed fields, so policy gates are not limited to
|
|
2242
|
+
* top-level field names.
|
|
2243
|
+
*/
|
|
2244
|
+
|
|
2245
|
+
type PrivacySpanClass = "email" | "phone" | "ssn" | "credit_card" | "secret_assignment" | "secret" | "credential" | "account_number" | "address" | "person" | "client" | "project" | "file_path" | "domain_term" | "url" | "date" | "custom";
|
|
2246
|
+
declare class PrivacyPlaceholderVault {
|
|
2247
|
+
private storage;
|
|
2248
|
+
private encryptionKey;
|
|
2249
|
+
private lookupKey;
|
|
2250
|
+
private cache;
|
|
2251
|
+
private pathCache;
|
|
2252
|
+
constructor(storage: StorageBackend, masterKey: Uint8Array);
|
|
2253
|
+
placeholderFor(spanClass: PrivacySpanClass, rawValue: string, scope?: string): Promise<string>;
|
|
2254
|
+
resolvePlaceholder(placeholder: string, scope?: string): Promise<string | null>;
|
|
2255
|
+
aliasForFieldPath(path: string, scope?: string): Promise<string>;
|
|
2256
|
+
resolveFieldPathAlias(alias: string, scope?: string): Promise<string | null>;
|
|
2257
|
+
private recordKey;
|
|
2258
|
+
private indexKey;
|
|
2259
|
+
private pathRecordKey;
|
|
2260
|
+
private pathIndexKey;
|
|
2261
|
+
private readIndex;
|
|
2262
|
+
private writeIndex;
|
|
2263
|
+
private readRecord;
|
|
2264
|
+
private writeRecord;
|
|
2265
|
+
private readPathIndex;
|
|
2266
|
+
private writePathIndex;
|
|
2267
|
+
private readPathRecord;
|
|
2268
|
+
private writePathRecord;
|
|
2269
|
+
private hmacString;
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2125
2272
|
/**
|
|
2126
2273
|
* Sanctuary MCP Server — L2 Context Gating: Automatic Enforcer
|
|
2127
2274
|
*
|
|
@@ -2170,9 +2317,10 @@ interface EnforcerStatus {
|
|
|
2170
2317
|
declare class ContextGateEnforcer {
|
|
2171
2318
|
private policyStore;
|
|
2172
2319
|
private auditLog;
|
|
2320
|
+
private privacyVault?;
|
|
2173
2321
|
private config;
|
|
2174
2322
|
private stats;
|
|
2175
|
-
constructor(policyStore: ContextGatePolicyStore, auditLog: AuditLog, config: EnforcerConfig);
|
|
2323
|
+
constructor(policyStore: ContextGatePolicyStore, auditLog: AuditLog, config: EnforcerConfig, privacyVault?: PrivacyPlaceholderVault);
|
|
2176
2324
|
/**
|
|
2177
2325
|
* Wrap a tool handler to apply automatic context gating.
|
|
2178
2326
|
*
|
|
@@ -2274,6 +2422,9 @@ interface UpstreamServer {
|
|
|
2274
2422
|
tool_overrides?: Record<string, {
|
|
2275
2423
|
tier: 1 | 2 | 3;
|
|
2276
2424
|
}>;
|
|
2425
|
+
destination_category?: "inference" | "tool-api" | "logging" | "analytics" | "peer-agent" | "custom";
|
|
2426
|
+
privacy_policy_id?: string;
|
|
2427
|
+
privacy_identity_id?: string;
|
|
2277
2428
|
}
|
|
2278
2429
|
interface SovereigntyProfile {
|
|
2279
2430
|
version: 1;
|
|
@@ -2581,6 +2732,887 @@ declare class CallGovernor {
|
|
|
2581
2732
|
private pruneDuplicateCache;
|
|
2582
2733
|
}
|
|
2583
2734
|
|
|
2735
|
+
/**
|
|
2736
|
+
* Sanctuary v1.1 — Privacy Audit Payload Contracts
|
|
2737
|
+
*
|
|
2738
|
+
* Shared payload shapes emitted by the privacy core (Prompt 3) and consumed by
|
|
2739
|
+
* the remote-bound enforcement workstream (Prompt 4), the operator hub API
|
|
2740
|
+
* (Prompt 5), and the dashboard privacy panel (Prompt 8).
|
|
2741
|
+
*
|
|
2742
|
+
* Local-only invariant:
|
|
2743
|
+
* Payloads describe outbound traffic from a single fortress on a single
|
|
2744
|
+
* operator's machine. v1.1 ships local-only, single-operator scope.
|
|
2745
|
+
*
|
|
2746
|
+
* Enclosure-and-signing model:
|
|
2747
|
+
* Privacy events are NOT signed objects on their own. They are payloads
|
|
2748
|
+
* carried inside an enclosing audit-chain entry (`l2-operational/audit-log`
|
|
2749
|
+
* AuditEntry encrypted-at-rest under L1, plus `mesh/audit-batch`
|
|
2750
|
+
* SignedAuditBatch where federation propagation applies). The enclosing
|
|
2751
|
+
* audit entry carries the signature scheme; this file deliberately does not
|
|
2752
|
+
* declare a signature field on any payload type.
|
|
2753
|
+
*
|
|
2754
|
+
* When an enforcement path emits a privacy event:
|
|
2755
|
+
* 1. Build a `PrivacyAuditPayload` from this file.
|
|
2756
|
+
* 2. Append it as the `details` (or equivalent payload field) of an
|
|
2757
|
+
* `AuditEntry` in the L2 audit log.
|
|
2758
|
+
* 3. The mesh-layer batch envelope (`SIGNATURE_SCHEME_V1`) signs the
|
|
2759
|
+
* batch that carries this entry.
|
|
2760
|
+
*
|
|
2761
|
+
* Safe-metadata invariant:
|
|
2762
|
+
* Raw sensitive content MUST NEVER appear in any field of any payload defined
|
|
2763
|
+
* in this file. Only safe metadata is permitted: detector class, field path,
|
|
2764
|
+
* action, content hash, policy id, destination category, identity id,
|
|
2765
|
+
* placeholder labels.
|
|
2766
|
+
*
|
|
2767
|
+
* If a future workstream needs to surface a sensitive value to the operator,
|
|
2768
|
+
* it MUST go through the encrypted placeholder vault — not through these
|
|
2769
|
+
* payload shapes.
|
|
2770
|
+
*/
|
|
2771
|
+
|
|
2772
|
+
/**
|
|
2773
|
+
* Common metadata header on every v1.1 privacy audit payload.
|
|
2774
|
+
*
|
|
2775
|
+
* `event_id` is the audit-chain id assigned by the enclosing AuditEntry.
|
|
2776
|
+
* `policy_id` is the bound privacy policy that produced the decision.
|
|
2777
|
+
* `identity_id` is the operator identity the policy is bound to.
|
|
2778
|
+
*/
|
|
2779
|
+
interface PrivacyAuditPayloadHeader {
|
|
2780
|
+
/** v1.1 payload-shape version. */
|
|
2781
|
+
version: "1.1";
|
|
2782
|
+
/** Unique event id; SHOULD match the enclosing audit-chain id. */
|
|
2783
|
+
event_id: string;
|
|
2784
|
+
/** ISO8601 timestamp of the decision. */
|
|
2785
|
+
emitted_at: string;
|
|
2786
|
+
/** Policy id that produced this decision. */
|
|
2787
|
+
policy_id: string;
|
|
2788
|
+
/** Identity the policy is bound to. */
|
|
2789
|
+
identity_id: string;
|
|
2790
|
+
/** Wrapped agent the outbound traffic originates from. */
|
|
2791
|
+
agent_id: string;
|
|
2792
|
+
/** Destination category for the outbound payload. */
|
|
2793
|
+
destination_category: PrivacyDestinationCategory;
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* Per-field decision recorded inside a privacy audit payload. Field-level
|
|
2797
|
+
* decisions bubble up into the rolled-up payload kinds below.
|
|
2798
|
+
*
|
|
2799
|
+
* Path-and-hash safety:
|
|
2800
|
+
* `field_path` MUST be sanitized — see `PRIVACY_FIELD_PATH_PATTERN` in
|
|
2801
|
+
* constants.ts. Raw object keys (which can themselves leak sensitive
|
|
2802
|
+
* information) MUST NOT appear on the wire. `content_hash` MUST use a keyed
|
|
2803
|
+
* hash algorithm (`hmac-sha256-fortress-keyed-v1` at v1.1) to defeat
|
|
2804
|
+
* dictionary attacks against low-entropy field values.
|
|
2805
|
+
*/
|
|
2806
|
+
interface PrivacyFieldDecision {
|
|
2807
|
+
/**
|
|
2808
|
+
* Sanitized field path. Conforms to `PRIVACY_FIELD_PATH_PATTERN`:
|
|
2809
|
+
* positional references like "$0" / "$1.$2" or typed positional like
|
|
2810
|
+
* "obj:0" / "key:1.val:0". The fortress-local mapping back to the real
|
|
2811
|
+
* path is held in the placeholder vault. Real object keys MUST NOT
|
|
2812
|
+
* appear here.
|
|
2813
|
+
*/
|
|
2814
|
+
field_path: string;
|
|
2815
|
+
/** Detector class that fired on this field. */
|
|
2816
|
+
detector_class: PrivacyDetectorClass;
|
|
2817
|
+
/** Action taken on this field. */
|
|
2818
|
+
action: PrivacyAction;
|
|
2819
|
+
/**
|
|
2820
|
+
* Keyed hash of the original field value. Hex-encoded.
|
|
2821
|
+
* Algorithm pinned via `hash_alg`; v1.1 only accepts
|
|
2822
|
+
* `hmac-sha256-fortress-keyed-v1`. The HMAC key is fortress-local
|
|
2823
|
+
* (HKDF-derived from the master key); equality of two `content_hash`
|
|
2824
|
+
* values within the same fortress means equal field values, but the
|
|
2825
|
+
* hash is opaque to any verifier outside the fortress and resists
|
|
2826
|
+
* dictionary attacks against low-entropy values. Plain SHA-256 is NOT
|
|
2827
|
+
* permitted. The original value MUST NOT appear anywhere in the payload.
|
|
2828
|
+
*/
|
|
2829
|
+
content_hash: string;
|
|
2830
|
+
/** Hash algorithm identifier. v1.1 only accepts the keyed HMAC variant. */
|
|
2831
|
+
hash_alg: PrivacyHashAlg;
|
|
2832
|
+
/**
|
|
2833
|
+
* Stable placeholder label this field was substituted with on the outbound
|
|
2834
|
+
* payload, if applicable. Examples: "PERSON_1", "CLIENT_3", "SECRET_2".
|
|
2835
|
+
*/
|
|
2836
|
+
placeholder_label?: string;
|
|
2837
|
+
}
|
|
2838
|
+
/**
|
|
2839
|
+
* Outbound payload was filtered. At least one field was redacted, hashed, or
|
|
2840
|
+
* substituted with a placeholder, and the call proceeded.
|
|
2841
|
+
*/
|
|
2842
|
+
interface PrivacyFilteredPayload extends PrivacyAuditPayloadHeader {
|
|
2843
|
+
kind: "filtered";
|
|
2844
|
+
field_decisions: PrivacyFieldDecision[];
|
|
2845
|
+
/**
|
|
2846
|
+
* Keyed hash of the canonicalized outbound payload after filtering.
|
|
2847
|
+
* Same `hash_alg` constraint as `PrivacyFieldDecision.content_hash`.
|
|
2848
|
+
*/
|
|
2849
|
+
outbound_payload_hash: string;
|
|
2850
|
+
/** Hash algorithm. v1.1 only accepts `hmac-sha256-fortress-keyed-v1`. */
|
|
2851
|
+
payload_hash_alg: PrivacyHashAlg;
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Outbound payload was allowed unchanged. No detector fired, or every fired
|
|
2855
|
+
* detector resolved to "allow" under the bound policy.
|
|
2856
|
+
*/
|
|
2857
|
+
interface PrivacyAllowedPayload extends PrivacyAuditPayloadHeader {
|
|
2858
|
+
kind: "allowed";
|
|
2859
|
+
/**
|
|
2860
|
+
* Keyed hash of the canonicalized outbound payload.
|
|
2861
|
+
* Same `hash_alg` constraint as `PrivacyFieldDecision.content_hash`.
|
|
2862
|
+
*/
|
|
2863
|
+
outbound_payload_hash: string;
|
|
2864
|
+
/** Hash algorithm. v1.1 only accepts `hmac-sha256-fortress-keyed-v1`. */
|
|
2865
|
+
payload_hash_alg: PrivacyHashAlg;
|
|
2866
|
+
}
|
|
2867
|
+
/**
|
|
2868
|
+
* Outbound payload was denied. Either a "deny" rule fired on a field, or the
|
|
2869
|
+
* fail-closed default applied because the policy or vault was unavailable.
|
|
2870
|
+
*
|
|
2871
|
+
* The `denial_reason_class` is a machine-friendly label, NOT a free-text
|
|
2872
|
+
* explanation. Operator-facing UIs may render a generic message keyed by this
|
|
2873
|
+
* label; raw policy-rule details MUST NOT be revealed.
|
|
2874
|
+
*/
|
|
2875
|
+
interface PrivacyDeniedPayload extends PrivacyAuditPayloadHeader {
|
|
2876
|
+
kind: "denied";
|
|
2877
|
+
/**
|
|
2878
|
+
* Coarse denial reason class. Permitted values:
|
|
2879
|
+
* - "policy_deny_rule" — at least one field had a deny rule
|
|
2880
|
+
* - "fail_closed_no_policy" — fail-closed because policy missing
|
|
2881
|
+
* - "fail_closed_filter_error" — fail-closed because filter raised
|
|
2882
|
+
* - "fail_closed_vault_error" — fail-closed because vault unavailable
|
|
2883
|
+
* - "operator_override_denied" — explicit operator override path failed
|
|
2884
|
+
*/
|
|
2885
|
+
denial_reason_class: "policy_deny_rule" | "fail_closed_no_policy" | "fail_closed_filter_error" | "fail_closed_vault_error" | "operator_override_denied";
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* Privacy filter raised an unrecoverable error and outbound traffic failed
|
|
2889
|
+
* closed. Distinct from PrivacyDeniedPayload because the operator may want to
|
|
2890
|
+
* surface error events as alerts rather than as policy decisions.
|
|
2891
|
+
*/
|
|
2892
|
+
interface PrivacyErrorPayload extends PrivacyAuditPayloadHeader {
|
|
2893
|
+
kind: "error";
|
|
2894
|
+
/** Stable error code. Implementation-specific catalog. No raw stack traces. */
|
|
2895
|
+
error_code: string;
|
|
2896
|
+
}
|
|
2897
|
+
/**
|
|
2898
|
+
* Inbound provider response was rehydrated using the placeholder vault. Only
|
|
2899
|
+
* fires when the bound policy permits rehydration for the destination category.
|
|
2900
|
+
*/
|
|
2901
|
+
interface PrivacyRehydratedPayload extends PrivacyAuditPayloadHeader {
|
|
2902
|
+
kind: "rehydrated";
|
|
2903
|
+
/**
|
|
2904
|
+
* Number of placeholders successfully rehydrated. The placeholders themselves
|
|
2905
|
+
* are NOT logged.
|
|
2906
|
+
*/
|
|
2907
|
+
rehydrated_count: number;
|
|
2908
|
+
/** Number of placeholders that could not be rehydrated (e.g., vault entry expired). */
|
|
2909
|
+
unresolvable_count: number;
|
|
2910
|
+
/**
|
|
2911
|
+
* Keyed hash of the canonicalized rehydrated response.
|
|
2912
|
+
* Same `hash_alg` constraint as `PrivacyFieldDecision.content_hash`.
|
|
2913
|
+
*/
|
|
2914
|
+
response_hash: string;
|
|
2915
|
+
/** Hash algorithm. v1.1 only accepts `hmac-sha256-fortress-keyed-v1`. */
|
|
2916
|
+
response_hash_alg: PrivacyHashAlg;
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* Discriminated union of every v1.1 privacy audit payload. The hub API and
|
|
2920
|
+
* dashboard privacy panel switch on `kind`. Integrity of these payloads
|
|
2921
|
+
* derives from the enclosing audit entry (encrypted-at-rest, plus signed at
|
|
2922
|
+
* the mesh-batch layer where applicable). No payload in this file carries a
|
|
2923
|
+
* self-signature.
|
|
2924
|
+
*/
|
|
2925
|
+
type PrivacyAuditPayload = PrivacyFilteredPayload | PrivacyAllowedPayload | PrivacyDeniedPayload | PrivacyErrorPayload | PrivacyRehydratedPayload;
|
|
2926
|
+
|
|
2927
|
+
/**
|
|
2928
|
+
* Sanctuary v1.1 — Operator Hub Event Contracts
|
|
2929
|
+
*
|
|
2930
|
+
* Shared shapes for the unified inbox, the activity feed, and the per-agent
|
|
2931
|
+
* status panels. The operator hub API workstream (Prompt 5) emits these; the
|
|
2932
|
+
* dashboard UI workstream (Prompt 8) consumes them. v1.2 mobile companion
|
|
2933
|
+
* planning will evaluate these shapes when it scopes a phone surface, but
|
|
2934
|
+
* v1.1 does not commit to mobile compatibility — these contracts are
|
|
2935
|
+
* tuned for the local dashboard surface only.
|
|
2936
|
+
*
|
|
2937
|
+
* Local-only invariant:
|
|
2938
|
+
* Every event in this file describes activity inside a single fortress on a
|
|
2939
|
+
* single operator's machine. Cross-fortress, fleet, and public-federation
|
|
2940
|
+
* events are out of scope.
|
|
2941
|
+
*
|
|
2942
|
+
* Safe-metadata invariant:
|
|
2943
|
+
* No raw sensitive content in any field. Inbox cards may carry display titles
|
|
2944
|
+
* and subtitles, but those titles MUST be derived from policy templates and
|
|
2945
|
+
* MUST NOT contain raw query text, tool args, filenames, client names,
|
|
2946
|
+
* passphrases, or secrets.
|
|
2947
|
+
*/
|
|
2948
|
+
|
|
2949
|
+
/**
|
|
2950
|
+
* Allowed value space for `display_template_args`. Only safe primitives plus
|
|
2951
|
+
* a small enumerated value set are permitted. Free-form strings ARE NOT
|
|
2952
|
+
* accepted; the dashboard rejects rendering on any value outside this union.
|
|
2953
|
+
*
|
|
2954
|
+
* The renderer treats every value as data to interpolate into a fixed
|
|
2955
|
+
* template registered under `template_id` — never as raw content. This
|
|
2956
|
+
* defends against secrets, query text, file paths, and client names leaking
|
|
2957
|
+
* into inbox cards via stringly-typed display fields.
|
|
2958
|
+
*/
|
|
2959
|
+
type HubDisplayTemplateArg = {
|
|
2960
|
+
kind: "agent_id";
|
|
2961
|
+
value: string;
|
|
2962
|
+
} | {
|
|
2963
|
+
kind: "identity_id";
|
|
2964
|
+
value: string;
|
|
2965
|
+
} | {
|
|
2966
|
+
kind: "policy_id";
|
|
2967
|
+
value: string;
|
|
2968
|
+
} | {
|
|
2969
|
+
kind: "destination_category";
|
|
2970
|
+
value: PrivacyDestinationCategory;
|
|
2971
|
+
} | {
|
|
2972
|
+
kind: "tier";
|
|
2973
|
+
value: "tier1" | "tier2" | "tier3";
|
|
2974
|
+
} | {
|
|
2975
|
+
kind: "count";
|
|
2976
|
+
value: number;
|
|
2977
|
+
} | {
|
|
2978
|
+
kind: "iso8601";
|
|
2979
|
+
value: string;
|
|
2980
|
+
} | {
|
|
2981
|
+
kind: "duration_ms";
|
|
2982
|
+
value: number;
|
|
2983
|
+
};
|
|
2984
|
+
/**
|
|
2985
|
+
* Common header on every v1.1 hub inbox item.
|
|
2986
|
+
*
|
|
2987
|
+
* Display rendering uses a `template_id` plus typed args, NOT free-form
|
|
2988
|
+
* strings. The dashboard owns the template registry; backends only emit the
|
|
2989
|
+
* id and the args. This makes secret-leakage into inbox copy structurally
|
|
2990
|
+
* impossible: a backend cannot smuggle raw query content into a card by
|
|
2991
|
+
* accident, because there is no free-text channel.
|
|
2992
|
+
*/
|
|
2993
|
+
interface HubInboxItemHeader {
|
|
2994
|
+
/** v1.1 event-shape version. */
|
|
2995
|
+
version: "1.1";
|
|
2996
|
+
/** Stable inbox-item id. SHOULD reference an audit-chain id where applicable. */
|
|
2997
|
+
item_id: string;
|
|
2998
|
+
/** Inbox kind discriminator. */
|
|
2999
|
+
kind: HubInboxKind;
|
|
3000
|
+
/** ISO8601 timestamp the item was created. */
|
|
3001
|
+
created_at: string;
|
|
3002
|
+
/** Wrapped agent id this item refers to, if applicable. */
|
|
3003
|
+
agent_id?: string;
|
|
3004
|
+
/** Operator identity id. */
|
|
3005
|
+
identity_id: string;
|
|
3006
|
+
/**
|
|
3007
|
+
* Display template id. Resolved by the dashboard against a registered
|
|
3008
|
+
* template catalog; the catalog owns the actual render strings. Backends
|
|
3009
|
+
* MUST NOT emit raw display copy. Template id space is namespaced per
|
|
3010
|
+
* inbox kind, e.g., "approval_pending.tier1.export".
|
|
3011
|
+
*/
|
|
3012
|
+
display_template_id: string;
|
|
3013
|
+
/**
|
|
3014
|
+
* Typed args interpolated into the template. Every value MUST be a
|
|
3015
|
+
* `HubDisplayTemplateArg` instance — no free-form strings. Renderers
|
|
3016
|
+
* reject any arg outside this union, which structurally blocks secret
|
|
3017
|
+
* leakage via inbox copy.
|
|
3018
|
+
*/
|
|
3019
|
+
display_template_args: HubDisplayTemplateArg[];
|
|
3020
|
+
/** Whether the operator has resolved this inbox item. */
|
|
3021
|
+
resolved: boolean;
|
|
3022
|
+
/** ISO8601 timestamp of resolution, if resolved. */
|
|
3023
|
+
resolved_at?: string;
|
|
3024
|
+
}
|
|
3025
|
+
/**
|
|
3026
|
+
* A pending Tier 1 or Tier 2 approval surfaced to the operator inbox.
|
|
3027
|
+
*/
|
|
3028
|
+
interface HubApprovalPendingItem extends HubInboxItemHeader {
|
|
3029
|
+
kind: "approval_pending";
|
|
3030
|
+
/** Policy tier the underlying operation falls under. */
|
|
3031
|
+
tier: "tier1" | "tier2";
|
|
3032
|
+
/**
|
|
3033
|
+
* Coarse operation category. Stable enum so the UI can group consistently;
|
|
3034
|
+
* does not reveal underlying tool args. Names align with the canonical
|
|
3035
|
+
* Tier 1 / Tier 2 sets in `server/src/principal-policy/loader.ts`. Names
|
|
3036
|
+
* NOT in the canonical loader (e.g., `exit_bundle_export`, `policy_change`,
|
|
3037
|
+
* `lockdown`, `unwrap`) are v1.1-new and MUST be added to the loader's
|
|
3038
|
+
* Tier 1 set in the same PR that lands their behavior. Drift is a release
|
|
3039
|
+
* blocker.
|
|
3040
|
+
*/
|
|
3041
|
+
operation_category: "state_export" | "state_import" | "state_delete" | "identity_rotate" | "reputation_export" | "reputation_import" | "sanctuary_export_identity_bundle" | "exit_bundle_export" | "exit_bundle_import" | "exit_bundle_rekey" | "policy_change" | "lockdown" | "unwrap" | "other";
|
|
3042
|
+
/** ISO8601 deadline after which the request will be auto-denied if applicable. */
|
|
3043
|
+
deadline?: string;
|
|
3044
|
+
/**
|
|
3045
|
+
* Result fields surfaced after the Tier 1 handler runs. Empty until
|
|
3046
|
+
* resolution. Populated for fortress-scope `exit_bundle_export` so the
|
|
3047
|
+
* dashboard exit-drill page can advance the wizard from the inbox
|
|
3048
|
+
* resolution alone, without round-tripping through the activity feed.
|
|
3049
|
+
* Per-agent items leave it undefined. Producers MUST keep field values
|
|
3050
|
+
* to safe metadata only (paths and hex hashes); raw secrets MUST NOT
|
|
3051
|
+
* appear here.
|
|
3052
|
+
*/
|
|
3053
|
+
resolution_payload?: {
|
|
3054
|
+
bundle_dir?: string;
|
|
3055
|
+
manifest_hash?: string;
|
|
3056
|
+
artifact_count?: number;
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Outbound traffic was blocked by the egress policy or the privacy filter.
|
|
3061
|
+
*/
|
|
3062
|
+
interface HubBlockedEgressItem extends HubInboxItemHeader {
|
|
3063
|
+
kind: "blocked_egress";
|
|
3064
|
+
/**
|
|
3065
|
+
* Destination category. Same enum as the privacy filter so unified inbox,
|
|
3066
|
+
* privacy panel, and egress dashboards group consistently. Drift is a
|
|
3067
|
+
* release blocker.
|
|
3068
|
+
*/
|
|
3069
|
+
destination_category: PrivacyDestinationCategory;
|
|
3070
|
+
/**
|
|
3071
|
+
* Why the egress was blocked. Coarse enum, not free text. Specific policy
|
|
3072
|
+
* rule names are NOT revealed.
|
|
3073
|
+
*/
|
|
3074
|
+
block_reason_class: "egress_policy_deny" | "budget_exceeded" | "privacy_fail_closed" | "privacy_deny_rule" | "lockdown_active" | "other";
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* A privacy event surfaced to the inbox. References the underlying privacy
|
|
3078
|
+
* event id; the inbox card is a thin pointer, not a duplicate of the event.
|
|
3079
|
+
*/
|
|
3080
|
+
interface HubPrivacyEventItem extends HubInboxItemHeader {
|
|
3081
|
+
kind: "privacy_event";
|
|
3082
|
+
/** Foreign key into the privacy-event chain. */
|
|
3083
|
+
privacy_event_id: string;
|
|
3084
|
+
/** Privacy event kind. */
|
|
3085
|
+
privacy_event_kind: "filtered" | "allowed" | "denied" | "error" | "rehydrated";
|
|
3086
|
+
}
|
|
3087
|
+
/**
|
|
3088
|
+
* A budget threshold was crossed.
|
|
3089
|
+
*/
|
|
3090
|
+
interface HubBudgetWarningItem extends HubInboxItemHeader {
|
|
3091
|
+
kind: "budget_warning";
|
|
3092
|
+
/** Budget bucket identifier (daily / monthly / per-agent / custom). */
|
|
3093
|
+
bucket: "daily" | "monthly" | "per_agent" | "custom";
|
|
3094
|
+
/** Soft-warn or hard-cap. Hard-cap usually requires operator unblock. */
|
|
3095
|
+
severity: "soft_warn" | "hard_cap";
|
|
3096
|
+
/** Percentage of budget used at event time. 0..1. */
|
|
3097
|
+
used_fraction: number;
|
|
3098
|
+
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Recovery prompt — operator should run a recovery flow (passphrase reset,
|
|
3101
|
+
* keychain rebind, exit drill, etc.).
|
|
3102
|
+
*/
|
|
3103
|
+
interface HubRecoveryPromptItem extends HubInboxItemHeader {
|
|
3104
|
+
kind: "recovery_prompt";
|
|
3105
|
+
/** Coarse recovery class. */
|
|
3106
|
+
recovery_class: "passphrase_reset" | "keychain_rebind" | "config_backup_restore" | "exit_drill" | "other";
|
|
3107
|
+
}
|
|
3108
|
+
/**
|
|
3109
|
+
* Agent reported an internal error.
|
|
3110
|
+
*/
|
|
3111
|
+
interface HubAgentErrorItem extends HubInboxItemHeader {
|
|
3112
|
+
kind: "agent_error";
|
|
3113
|
+
/** Stable error code class. Implementation-specific catalog. */
|
|
3114
|
+
error_class: string;
|
|
3115
|
+
/** Whether the agent is still serving traffic after the error. */
|
|
3116
|
+
agent_still_active: boolean;
|
|
3117
|
+
}
|
|
3118
|
+
/**
|
|
3119
|
+
* Discriminated union of every v1.1 hub inbox item.
|
|
3120
|
+
*/
|
|
3121
|
+
type HubInboxItem = HubApprovalPendingItem | HubBlockedEgressItem | HubPrivacyEventItem | HubBudgetWarningItem | HubRecoveryPromptItem | HubAgentErrorItem;
|
|
3122
|
+
/**
|
|
3123
|
+
* Activity feed entry. The feed is a flat stream backed by the audit chain;
|
|
3124
|
+
* inbox items often reference a feed entry, but feed entries are not always
|
|
3125
|
+
* inbox items.
|
|
3126
|
+
*
|
|
3127
|
+
* Activity feed entries are read-from-storage projections of audit-chain
|
|
3128
|
+
* entries. They are NOT signed envelopes themselves; integrity derives from
|
|
3129
|
+
* the underlying audit entry. Consumers that need to verify the feed entry
|
|
3130
|
+
* MUST resolve it to the source audit entry by `entry_id` and verify there.
|
|
3131
|
+
*/
|
|
3132
|
+
interface HubActivityFeedEntry {
|
|
3133
|
+
version: "1.1";
|
|
3134
|
+
/** Audit-chain entry id. */
|
|
3135
|
+
entry_id: string;
|
|
3136
|
+
/** ISO8601 timestamp. */
|
|
3137
|
+
emitted_at: string;
|
|
3138
|
+
/** Wrapped agent id, if applicable. */
|
|
3139
|
+
agent_id?: string;
|
|
3140
|
+
/** Identity id. */
|
|
3141
|
+
identity_id: string;
|
|
3142
|
+
/** Stable category enum. */
|
|
3143
|
+
category: "policy_decision" | "approval" | "denial" | "egress" | "privacy" | "handoff" | "lifecycle" | "config" | "other";
|
|
3144
|
+
/**
|
|
3145
|
+
* Display template id. Resolved by the dashboard against the activity-feed
|
|
3146
|
+
* template catalog. Backends MUST NOT emit raw summary text — the template
|
|
3147
|
+
* id plus typed args is the only legitimate channel.
|
|
3148
|
+
*/
|
|
3149
|
+
display_template_id: string;
|
|
3150
|
+
/** Typed args. Same constraints as `HubInboxItemHeader.display_template_args`. */
|
|
3151
|
+
display_template_args: HubDisplayTemplateArg[];
|
|
3152
|
+
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Per-agent status snapshot returned by the hub API. Mirrors the agent
|
|
3155
|
+
* registry record but is computed-on-read; it does not flow through the
|
|
3156
|
+
* audit chain by itself.
|
|
3157
|
+
*/
|
|
3158
|
+
interface HubAgentStatusSnapshot {
|
|
3159
|
+
version: "1.1";
|
|
3160
|
+
agent_id: string;
|
|
3161
|
+
status: HubAgentStatus;
|
|
3162
|
+
/**
|
|
3163
|
+
* Reason class for the current status. Same enum as
|
|
3164
|
+
* `LocalAgentRecord.status_reason_class`. Stable, not free text. Present
|
|
3165
|
+
* only when status is `locked_down`, `error`, or `restarting`.
|
|
3166
|
+
*/
|
|
3167
|
+
status_reason_class?: "operator_lockdown" | "policy_breach" | "budget_hard_cap" | "harness_error" | "harness_unreachable" | "passphrase_required" | "config_drift" | "other";
|
|
3168
|
+
/** ISO8601 last-seen timestamp. */
|
|
3169
|
+
last_activity_at: string;
|
|
3170
|
+
/** Inbox-item ids currently unresolved against this agent. */
|
|
3171
|
+
open_inbox_item_ids: string[];
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
/**
|
|
3175
|
+
* Sanctuary v1.1 — Local Agent Registry Records
|
|
3176
|
+
*
|
|
3177
|
+
* Shared shape for the per-agent record returned by the operator hub registry
|
|
3178
|
+
* API. Implementations of the hub API workstream (Prompt 5) write these;
|
|
3179
|
+
* dashboard UI (Prompt 8), internal coordination (Prompt 6), and the exit
|
|
3180
|
+
* bundle workstream (Prompt 7) read these.
|
|
3181
|
+
*
|
|
3182
|
+
* Local-only invariant:
|
|
3183
|
+
* Records describe agents wrapped by a single fortress on a single operator's
|
|
3184
|
+
* machine. Cross-fortress agent discovery is deferred to v1.3.
|
|
3185
|
+
*
|
|
3186
|
+
* No-secret invariant:
|
|
3187
|
+
* Records MUST NOT carry private keys, passphrases, recovery seeds, or raw
|
|
3188
|
+
* provider credentials. Provider identifiers and policy ids are safe;
|
|
3189
|
+
* provider tokens are not.
|
|
3190
|
+
*/
|
|
3191
|
+
|
|
3192
|
+
/**
|
|
3193
|
+
* Coarse harness label. Mirrors the README-supported wrap targets at v1.1
|
|
3194
|
+
* ship. Adding a harness requires a new entry here plus harness-compatibility
|
|
3195
|
+
* coverage from Prompt 9.
|
|
3196
|
+
*
|
|
3197
|
+
* `mastra` has a first-class Tier B adapter at
|
|
3198
|
+
* `server/src/agent-contract/adapters/mastra.ts` and is therefore a
|
|
3199
|
+
* first-class kind here. `langgraph` does NOT have a dedicated adapter at
|
|
3200
|
+
* v1.1 ship; LangGraph wraps land via the generic `sanctuary wrap --wrap
|
|
3201
|
+
* <path>` path and surface as `generic_mcp`. When a dedicated LangGraph
|
|
3202
|
+
* adapter ships, add `langgraph` here in the same PR.
|
|
3203
|
+
*/
|
|
3204
|
+
type LocalHarnessKind = "openclaw" | "hermes" | "claude_code" | "cursor" | "cline" | "mastra" | "generic_mcp" | "other";
|
|
3205
|
+
/**
|
|
3206
|
+
* Provider category for the underlying model. Distinct from the privacy
|
|
3207
|
+
* destination category enum because providers and destinations are not 1:1
|
|
3208
|
+
* (one provider can serve multiple destination categories).
|
|
3209
|
+
*/
|
|
3210
|
+
interface LocalAgentModelProvider {
|
|
3211
|
+
/** Coarse provider label, e.g., "anthropic", "openai", "xai", "local", "other". */
|
|
3212
|
+
vendor: string;
|
|
3213
|
+
/** Concrete model identifier reported by the provider, e.g., "claude-opus-4". */
|
|
3214
|
+
model_id: string;
|
|
3215
|
+
/**
|
|
3216
|
+
* Whether the model runs locally (on-device or LAN) versus a remote provider.
|
|
3217
|
+
* Local models still flow through the privacy filter where applicable.
|
|
3218
|
+
*/
|
|
3219
|
+
runs_locally: boolean;
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Budget summary surfaced to the hub. Concrete budget enforcement lives in
|
|
3223
|
+
* the policy engine; this is a read-only snapshot.
|
|
3224
|
+
*/
|
|
3225
|
+
interface LocalAgentBudgetSummary {
|
|
3226
|
+
/** Daily bucket. */
|
|
3227
|
+
daily?: {
|
|
3228
|
+
/** Allotment unit, e.g., "tokens", "usd". */
|
|
3229
|
+
unit: string;
|
|
3230
|
+
/** Total allotment for the bucket. */
|
|
3231
|
+
cap: number;
|
|
3232
|
+
/** Amount used so far in the bucket window. */
|
|
3233
|
+
used: number;
|
|
3234
|
+
/** Soft-warn threshold fraction (0..1). */
|
|
3235
|
+
soft_warn?: number;
|
|
3236
|
+
};
|
|
3237
|
+
/** Monthly bucket. */
|
|
3238
|
+
monthly?: {
|
|
3239
|
+
unit: string;
|
|
3240
|
+
cap: number;
|
|
3241
|
+
used: number;
|
|
3242
|
+
soft_warn?: number;
|
|
3243
|
+
};
|
|
3244
|
+
/** ISO8601 timestamp of last budget refresh. */
|
|
3245
|
+
last_refreshed_at: string;
|
|
3246
|
+
}
|
|
3247
|
+
/**
|
|
3248
|
+
* The canonical local agent registry record for v1.1.
|
|
3249
|
+
*
|
|
3250
|
+
* Implementations SHOULD treat this as read-from-storage; mutating fields is
|
|
3251
|
+
* the responsibility of the hub API plus the underlying agent lifecycle owner
|
|
3252
|
+
* (wrap / unwrap / template assignment / lockdown).
|
|
3253
|
+
*/
|
|
3254
|
+
interface LocalAgentRecord {
|
|
3255
|
+
version: "1.1";
|
|
3256
|
+
/** Stable agent identifier, scoped to this fortress. */
|
|
3257
|
+
agent_id: string;
|
|
3258
|
+
/** Operator identity that owns the agent. */
|
|
3259
|
+
identity_id: string;
|
|
3260
|
+
/** Harness the agent runs under. */
|
|
3261
|
+
harness: LocalHarnessKind;
|
|
3262
|
+
/** Free-text harness version string from the harness, when available. */
|
|
3263
|
+
harness_version?: string;
|
|
3264
|
+
/** Model and provider details. */
|
|
3265
|
+
model_provider: LocalAgentModelProvider;
|
|
3266
|
+
/** Bound policy id (compiled policy artifact). */
|
|
3267
|
+
policy_id: string;
|
|
3268
|
+
/**
|
|
3269
|
+
* Bound channel-template id, when one applies. Template id space is owned
|
|
3270
|
+
* by the policy engine.
|
|
3271
|
+
*/
|
|
3272
|
+
channel_template_id?: string;
|
|
3273
|
+
/** Current lifecycle status as surfaced to the hub. */
|
|
3274
|
+
status: HubAgentStatus;
|
|
3275
|
+
/**
|
|
3276
|
+
* Reason class for the current status. Stable enum, not free text.
|
|
3277
|
+
* Present only when status is `locked_down`, `error`, or `restarting`.
|
|
3278
|
+
* The dashboard renders human-readable copy from a template catalog
|
|
3279
|
+
* keyed by this value; backends MUST NOT emit raw reason text.
|
|
3280
|
+
*/
|
|
3281
|
+
status_reason_class?: "operator_lockdown" | "policy_breach" | "budget_hard_cap" | "harness_error" | "harness_unreachable" | "passphrase_required" | "config_drift" | "other";
|
|
3282
|
+
/** Budget summary snapshot. */
|
|
3283
|
+
budget_summary: LocalAgentBudgetSummary;
|
|
3284
|
+
/** ISO8601 timestamp of last agent activity. */
|
|
3285
|
+
last_activity_at: string;
|
|
3286
|
+
/** ISO8601 timestamp of wrap. */
|
|
3287
|
+
wrapped_at: string;
|
|
3288
|
+
/**
|
|
3289
|
+
* Capabilities flag set surfaced by the harness. Stable string set;
|
|
3290
|
+
* dashboard renders supported controls based on this set.
|
|
3291
|
+
*/
|
|
3292
|
+
capabilities: {
|
|
3293
|
+
can_pause: boolean;
|
|
3294
|
+
can_resume: boolean;
|
|
3295
|
+
can_restart: boolean;
|
|
3296
|
+
can_unwrap: boolean;
|
|
3297
|
+
can_lockdown: boolean;
|
|
3298
|
+
can_chat: boolean;
|
|
3299
|
+
can_change_template: boolean;
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
/**
|
|
3303
|
+
* Note on signing:
|
|
3304
|
+
* `LocalAgentRecord` is a read-from-storage projection of agent registry
|
|
3305
|
+
* state. It is NOT a signed envelope. Signed audit entries that reference
|
|
3306
|
+
* this record (wrap, unwrap, policy change, lockdown, etc.) carry the
|
|
3307
|
+
* signature scheme on the enclosing audit-chain entry, not on the record
|
|
3308
|
+
* itself. Consumers that need to verify a registry change MUST resolve
|
|
3309
|
+
* through the audit chain.
|
|
3310
|
+
*/
|
|
3311
|
+
/**
|
|
3312
|
+
* Hub-side filter shape used by the registry list API. Workstreams may extend
|
|
3313
|
+
* with additional filters; the canonical fields below are stable.
|
|
3314
|
+
*/
|
|
3315
|
+
interface LocalAgentRegistryFilter {
|
|
3316
|
+
/** Restrict to one identity id. */
|
|
3317
|
+
identity_id?: string;
|
|
3318
|
+
/** Restrict to one or more harness kinds. */
|
|
3319
|
+
harnesses?: LocalHarnessKind[];
|
|
3320
|
+
/** Restrict to one or more lifecycle statuses. */
|
|
3321
|
+
statuses?: HubAgentStatus[];
|
|
3322
|
+
/**
|
|
3323
|
+
* Maximum records to return. Implementations SHOULD enforce a server-side
|
|
3324
|
+
* upper bound regardless of caller value.
|
|
3325
|
+
*/
|
|
3326
|
+
limit?: number;
|
|
3327
|
+
/** Pagination cursor; opaque to the caller. */
|
|
3328
|
+
cursor?: string;
|
|
3329
|
+
}
|
|
3330
|
+
|
|
3331
|
+
/**
|
|
3332
|
+
* Sanctuary v1.1 — Exit Bundle Manifest Contract
|
|
3333
|
+
*
|
|
3334
|
+
* `SANCTUARY_EXIT_BUNDLE_V1` is the canonical manifest produced by the v1.1
|
|
3335
|
+
* exit-bundle workstream (Prompt 7) and consumed by the standalone verifier
|
|
3336
|
+
* CLI plus the import command.
|
|
3337
|
+
*
|
|
3338
|
+
* Local-only invariant:
|
|
3339
|
+
* The bundle is produced by a single fortress on a single operator's machine
|
|
3340
|
+
* and consumed by another single-operator destination. v1.1 ships local-only,
|
|
3341
|
+
* single-operator scope. Cross-operator transfer is deferred to v1.3.
|
|
3342
|
+
*
|
|
3343
|
+
* Identity-binding invariant:
|
|
3344
|
+
* The manifest is signed by the operator's fortress-master identity. The
|
|
3345
|
+
* verifier MUST refuse to activate any artifact whose hash chain does not
|
|
3346
|
+
* match the manifest, and MUST refuse to activate any manifest whose
|
|
3347
|
+
* signature does not verify against the bound public identity.
|
|
3348
|
+
*
|
|
3349
|
+
* Public-only invariant:
|
|
3350
|
+
* The bundle MUST NOT contain private keys, raw passphrases, or recovery
|
|
3351
|
+
* seeds. Encrypted state may travel inside the bundle, but the master key
|
|
3352
|
+
* MUST NOT. Re-keying happens on import using new operator-supplied
|
|
3353
|
+
* material.
|
|
3354
|
+
*
|
|
3355
|
+
* Manifest-version invariant:
|
|
3356
|
+
* v1.1 ships only "SANCTUARY_EXIT_BUNDLE_V1". Future versions land through
|
|
3357
|
+
* coordinator-approved spec amendments. v1.1 verifiers MUST reject unknown
|
|
3358
|
+
* manifest versions rather than silently accept.
|
|
3359
|
+
*/
|
|
3360
|
+
|
|
3361
|
+
/**
|
|
3362
|
+
* Hashing algorithm identifier embedded in every artifact entry. v1.1 uses
|
|
3363
|
+
* SHA-256. Forward-compat: a future bundle version may add SHA-3 or BLAKE3.
|
|
3364
|
+
*/
|
|
3365
|
+
type ExitBundleHashAlg = "sha256";
|
|
3366
|
+
/**
|
|
3367
|
+
* One artifact entry inside the manifest. Each artifact lives at a relative
|
|
3368
|
+
* path inside the bundle archive. The verifier reads the file at that path
|
|
3369
|
+
* and confirms its hash. See `EXIT_BUNDLE_PATH_PATTERN` and the safe-path
|
|
3370
|
+
* rules block above for the full set of constraints.
|
|
3371
|
+
*/
|
|
3372
|
+
interface ExitBundleArtifactEntry {
|
|
3373
|
+
/** Coarse artifact kind. */
|
|
3374
|
+
kind: ExitBundleArtifactKind;
|
|
3375
|
+
/**
|
|
3376
|
+
* Relative path inside the bundle, POSIX-style. MUST satisfy
|
|
3377
|
+
* `EXIT_BUNDLE_PATH_PATTERN` and the safe-path rules block above.
|
|
3378
|
+
* The verifier rejects any entry whose path is absolute, contains "..",
|
|
3379
|
+
* contains backslashes, or duplicates another entry's path. The verifier
|
|
3380
|
+
* does NOT follow symlinks or hardlinks during extraction.
|
|
3381
|
+
*/
|
|
3382
|
+
path: string;
|
|
3383
|
+
/** Hash algorithm. v1.1 ships only "sha256". */
|
|
3384
|
+
hash_alg: ExitBundleHashAlg;
|
|
3385
|
+
/** Hex-encoded artifact hash. */
|
|
3386
|
+
hash: string;
|
|
3387
|
+
/** Size in bytes. Verifier MAY independently re-size and reject on mismatch. */
|
|
3388
|
+
size_bytes: number;
|
|
3389
|
+
/**
|
|
3390
|
+
* Optional discriminator inside the kind, e.g., "audit-receipt-2026-Q2".
|
|
3391
|
+
* Verifier does not interpret this; the import command may use it to order
|
|
3392
|
+
* artifacts. Same path-pattern constraints DO NOT apply to subkind, but
|
|
3393
|
+
* subkind MUST NOT contain control characters.
|
|
3394
|
+
*/
|
|
3395
|
+
subkind?: string;
|
|
3396
|
+
}
|
|
3397
|
+
/**
|
|
3398
|
+
* Identity binding embedded in the manifest. Carries only public material.
|
|
3399
|
+
*/
|
|
3400
|
+
interface ExitBundleIdentityBinding {
|
|
3401
|
+
/** Operator identity id. */
|
|
3402
|
+
identity_id: string;
|
|
3403
|
+
/** Fortress id. */
|
|
3404
|
+
fortress_id: string;
|
|
3405
|
+
/** Base64url-encoded Ed25519 public key of the fortress-master. */
|
|
3406
|
+
fortress_master_pubkey: string;
|
|
3407
|
+
/** Optional DID, when one is bound to this identity. */
|
|
3408
|
+
did?: string;
|
|
3409
|
+
}
|
|
3410
|
+
/**
|
|
3411
|
+
* v1 manifest body — what the operator's fortress-master signs.
|
|
3412
|
+
*
|
|
3413
|
+
* `signature_scheme` lives INSIDE the body deliberately so the scheme is
|
|
3414
|
+
* covered by the fortress-master signature. Without this, an attacker who
|
|
3415
|
+
* substituted both `signature` and `signature_scheme` on the wrapper could
|
|
3416
|
+
* present a valid-looking manifest with a different scheme. Pinning the
|
|
3417
|
+
* scheme inside the signed bytes makes the crypto-agility hinge non-
|
|
3418
|
+
* substitutable.
|
|
3419
|
+
*/
|
|
3420
|
+
interface ExitBundleManifestBody {
|
|
3421
|
+
/** Manifest version constant. */
|
|
3422
|
+
manifest_version: ExitBundleManifestVersion;
|
|
3423
|
+
/** ISO8601 timestamp at export time. */
|
|
3424
|
+
exported_at: string;
|
|
3425
|
+
/** Source fortress / operator identity binding. */
|
|
3426
|
+
identity_binding: ExitBundleIdentityBinding;
|
|
3427
|
+
/**
|
|
3428
|
+
* Sanctuary version string at export time. Verifier surfaces version skew
|
|
3429
|
+
* to the operator if the destination fortress is older.
|
|
3430
|
+
*/
|
|
3431
|
+
source_sanctuary_version: string;
|
|
3432
|
+
/** Every artifact carried in the bundle. */
|
|
3433
|
+
artifacts: ExitBundleArtifactEntry[];
|
|
3434
|
+
/**
|
|
3435
|
+
* Aggregate hash over canonicalize(artifacts[]). Lets the verifier perform
|
|
3436
|
+
* a fast sanity check before walking each entry.
|
|
3437
|
+
*/
|
|
3438
|
+
artifacts_aggregate_hash: string;
|
|
3439
|
+
/** Aggregate hash algorithm. v1.1 ships only "sha256". */
|
|
3440
|
+
artifacts_aggregate_hash_alg: ExitBundleHashAlg;
|
|
3441
|
+
/**
|
|
3442
|
+
* Tier 1 audit-event id that captured the export approval. Consumers MAY
|
|
3443
|
+
* cross-reference with the source fortress audit chain.
|
|
3444
|
+
*/
|
|
3445
|
+
export_approval_audit_id: string;
|
|
3446
|
+
/**
|
|
3447
|
+
* Signature scheme covering the wrapper's `signature` field. v1.1 ships
|
|
3448
|
+
* only "ed25519-v1". Embedded inside the signed body so the scheme cannot
|
|
3449
|
+
* be substituted independently of the signature.
|
|
3450
|
+
*/
|
|
3451
|
+
signature_scheme: SignatureScheme;
|
|
3452
|
+
}
|
|
3453
|
+
/**
|
|
3454
|
+
* Full signed manifest. Top-level shape that ships in the bundle archive.
|
|
3455
|
+
*
|
|
3456
|
+
* The wrapper carries only the `signature` and a pointer to the body. The
|
|
3457
|
+
* scheme that produced the signature lives inside `body.signature_scheme`,
|
|
3458
|
+
* so the signature itself attests to which scheme produced it.
|
|
3459
|
+
*/
|
|
3460
|
+
interface ExitBundleManifest {
|
|
3461
|
+
/** Body — what the signature covers. */
|
|
3462
|
+
body: ExitBundleManifestBody;
|
|
3463
|
+
/**
|
|
3464
|
+
* Base64url-encoded Ed25519 signature over canonicalize(body) by the
|
|
3465
|
+
* fortress-master private key. The bundle archive is otherwise unsigned;
|
|
3466
|
+
* artifact integrity comes from artifact hashes inside the body. The
|
|
3467
|
+
* signing scheme is `body.signature_scheme`.
|
|
3468
|
+
*/
|
|
3469
|
+
signature: string;
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Verifier output shape. The standalone verifier CLI emits this structure on
|
|
3473
|
+
* stdout (or as JSON for tool consumers) so import commands can branch
|
|
3474
|
+
* cleanly. v1.1 ships one VerifierResult shape; future versions extend.
|
|
3475
|
+
*/
|
|
3476
|
+
interface ExitBundleVerifierResult {
|
|
3477
|
+
version: "1.1";
|
|
3478
|
+
/** True iff manifest signature, every artifact hash, and the aggregate hash all verify. */
|
|
3479
|
+
passed: boolean;
|
|
3480
|
+
/** ISO8601 timestamp of verification. */
|
|
3481
|
+
verified_at: string;
|
|
3482
|
+
/** Reference to the verified manifest body. */
|
|
3483
|
+
manifest_summary: {
|
|
3484
|
+
manifest_version: ExitBundleManifestVersion;
|
|
3485
|
+
fortress_id: string;
|
|
3486
|
+
identity_id: string;
|
|
3487
|
+
exported_at: string;
|
|
3488
|
+
artifact_count: number;
|
|
3489
|
+
};
|
|
3490
|
+
/**
|
|
3491
|
+
* Per-artifact verification result. Order matches `manifest.body.artifacts`.
|
|
3492
|
+
*/
|
|
3493
|
+
artifact_results: Array<{
|
|
3494
|
+
path: string;
|
|
3495
|
+
kind: ExitBundleArtifactKind;
|
|
3496
|
+
hash_passed: boolean;
|
|
3497
|
+
size_passed: boolean;
|
|
3498
|
+
}>;
|
|
3499
|
+
/**
|
|
3500
|
+
* Coarse failure-class enum, when `passed` is false. Distinct from a free-text
|
|
3501
|
+
* error message so import commands can branch.
|
|
3502
|
+
*/
|
|
3503
|
+
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";
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3506
|
+
/**
|
|
3507
|
+
* Sanctuary v1.1 — local query privacy core.
|
|
3508
|
+
*
|
|
3509
|
+
* This module is intentionally independent of dashboard UI and transport
|
|
3510
|
+
* enforcement. Enforcement paths call it with a payload, destination category,
|
|
3511
|
+
* identity-bound policy, and encrypted placeholder vault; the module returns a
|
|
3512
|
+
* filtered payload or a fail-closed denial plus a shared privacy audit payload.
|
|
3513
|
+
*/
|
|
3514
|
+
|
|
3515
|
+
type PrivacyPolicyAction = "placeholder" | Extract<PrivacyAction, "allow" | "redact" | "hash" | "deny">;
|
|
3516
|
+
interface PrivacyPolicy {
|
|
3517
|
+
version: 1;
|
|
3518
|
+
policy_id: string;
|
|
3519
|
+
policy_name?: string;
|
|
3520
|
+
identity_id: string;
|
|
3521
|
+
detector_actions?: Partial<Record<PrivacyDetectorClass, PrivacyPolicyAction>>;
|
|
3522
|
+
destination_detector_actions?: Partial<Record<PrivacyDestinationCategory, Partial<Record<PrivacyDetectorClass, PrivacyPolicyAction>>>>;
|
|
3523
|
+
client_names?: string[];
|
|
3524
|
+
project_names?: string[];
|
|
3525
|
+
domain_terms?: string[];
|
|
3526
|
+
person_names?: string[];
|
|
3527
|
+
placeholder_scope?: "identity" | "policy";
|
|
3528
|
+
rehydration?: {
|
|
3529
|
+
default_action?: "allow" | "deny";
|
|
3530
|
+
allowed_destinations?: PrivacyDestinationCategory[];
|
|
3531
|
+
denied_destinations?: PrivacyDestinationCategory[];
|
|
3532
|
+
};
|
|
3533
|
+
max_depth?: number;
|
|
3534
|
+
max_payload_bytes?: number;
|
|
3535
|
+
max_string_bytes?: number;
|
|
3536
|
+
operator_override?: {
|
|
3537
|
+
allow_on_policy_error?: boolean;
|
|
3538
|
+
allow_on_filter_error?: boolean;
|
|
3539
|
+
allow_on_vault_error?: boolean;
|
|
3540
|
+
allow_on_detector_error?: boolean;
|
|
3541
|
+
};
|
|
3542
|
+
created_at: string;
|
|
3543
|
+
updated_at: string;
|
|
3544
|
+
}
|
|
3545
|
+
interface PrivacyCoreFinding {
|
|
3546
|
+
raw_path: string;
|
|
3547
|
+
detector_class: PrivacyDetectorClass;
|
|
3548
|
+
span_class: PrivacySpanClass;
|
|
3549
|
+
action: PrivacyAction;
|
|
3550
|
+
content_hash: string;
|
|
3551
|
+
placeholder_label?: string;
|
|
3552
|
+
}
|
|
3553
|
+
interface PrivacyFilterRequest {
|
|
3554
|
+
payload: unknown;
|
|
3555
|
+
policy: PrivacyPolicy | null;
|
|
3556
|
+
identity_id?: string;
|
|
3557
|
+
agent_id: string;
|
|
3558
|
+
destination_category: PrivacyDestinationCategory;
|
|
3559
|
+
audit_log?: AuditLog;
|
|
3560
|
+
event_id?: string;
|
|
3561
|
+
}
|
|
3562
|
+
type PrivacyFilterDecision = {
|
|
3563
|
+
status: "allowed";
|
|
3564
|
+
payload: unknown;
|
|
3565
|
+
findings: [];
|
|
3566
|
+
audit_payload: PrivacyAuditPayload;
|
|
3567
|
+
} | {
|
|
3568
|
+
status: "filtered";
|
|
3569
|
+
payload: unknown;
|
|
3570
|
+
findings: PrivacyCoreFinding[];
|
|
3571
|
+
audit_payload: PrivacyAuditPayload;
|
|
3572
|
+
} | {
|
|
3573
|
+
status: "denied";
|
|
3574
|
+
payload: undefined;
|
|
3575
|
+
findings: PrivacyCoreFinding[];
|
|
3576
|
+
audit_payload: PrivacyDeniedPayload;
|
|
3577
|
+
};
|
|
3578
|
+
interface PrivacyRehydrationRequest {
|
|
3579
|
+
response: unknown;
|
|
3580
|
+
policy: PrivacyPolicy | null;
|
|
3581
|
+
identity_id?: string;
|
|
3582
|
+
agent_id: string;
|
|
3583
|
+
destination_category: PrivacyDestinationCategory;
|
|
3584
|
+
audit_log?: AuditLog;
|
|
3585
|
+
event_id?: string;
|
|
3586
|
+
}
|
|
3587
|
+
type PrivacyRehydrationDecision = {
|
|
3588
|
+
status: "rehydrated";
|
|
3589
|
+
response: unknown;
|
|
3590
|
+
rehydrated_count: number;
|
|
3591
|
+
unresolvable_count: number;
|
|
3592
|
+
audit_payload: PrivacyAuditPayload;
|
|
3593
|
+
} | {
|
|
3594
|
+
status: "denied";
|
|
3595
|
+
response: unknown;
|
|
3596
|
+
rehydrated_count: 0;
|
|
3597
|
+
unresolvable_count: 0;
|
|
3598
|
+
audit_payload: PrivacyDeniedPayload;
|
|
3599
|
+
};
|
|
3600
|
+
declare class LocalPrivacyEngine {
|
|
3601
|
+
private vault;
|
|
3602
|
+
private hmacKey;
|
|
3603
|
+
constructor(vault: PrivacyPlaceholderVault, masterKey: Uint8Array);
|
|
3604
|
+
filterOutbound(request: PrivacyFilterRequest): Promise<PrivacyFilterDecision>;
|
|
3605
|
+
rehydrateResponse(request: PrivacyRehydrationRequest): Promise<PrivacyRehydrationDecision>;
|
|
3606
|
+
private filterNode;
|
|
3607
|
+
private filterString;
|
|
3608
|
+
private fieldDecisionsForFindings;
|
|
3609
|
+
private rehydrateNode;
|
|
3610
|
+
private rehydrateString;
|
|
3611
|
+
private assertPayloadWithinBounds;
|
|
3612
|
+
private deniedPayload;
|
|
3613
|
+
private keyedHash;
|
|
3614
|
+
}
|
|
3615
|
+
|
|
2584
3616
|
/**
|
|
2585
3617
|
* Sanctuary MCP Server — Proxy Router
|
|
2586
3618
|
*
|
|
@@ -2603,6 +3635,27 @@ interface ProxyRouterOptions {
|
|
|
2603
3635
|
contextGateFilter?: (toolName: string, args: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
2604
3636
|
/** Optional call governor for runtime governance */
|
|
2605
3637
|
governor?: CallGovernor;
|
|
3638
|
+
/**
|
|
3639
|
+
* Optional v1.1 remote-bound privacy enforcement.
|
|
3640
|
+
*
|
|
3641
|
+
* When set, every proxied tool call is routed through
|
|
3642
|
+
* `engine.filterOutbound` before the upstream forward. The bound
|
|
3643
|
+
* `PrivacyPolicy` is resolved per-server via `policyResolver`, and the
|
|
3644
|
+
* destination category comes from the server's `destination_category`
|
|
3645
|
+
* field (defaulting to `tool-api` when absent).
|
|
3646
|
+
*
|
|
3647
|
+
* Fail-closed semantics:
|
|
3648
|
+
* - `policyResolver` returns null when no policy is bound for the server;
|
|
3649
|
+
* the privacy engine treats that as `fail_closed_no_policy` and denies.
|
|
3650
|
+
* - `policyResolver` rejecting (vault unreachable, decrypt failure, etc.)
|
|
3651
|
+
* is treated as `fail_closed_filter_error` and denies.
|
|
3652
|
+
* - Operator overrides on the policy (`operator_override.allow_on_*`)
|
|
3653
|
+
* are honored by the engine itself.
|
|
3654
|
+
*/
|
|
3655
|
+
privacyEnforcement?: {
|
|
3656
|
+
engine: LocalPrivacyEngine;
|
|
3657
|
+
policyResolver: (server: string, identityId: string | undefined) => Promise<PrivacyPolicy | null>;
|
|
3658
|
+
};
|
|
2606
3659
|
/** Optional callback after each proxy call decision (for dashboard feed) */
|
|
2607
3660
|
onProxyCall?: (data: {
|
|
2608
3661
|
tool: string;
|
|
@@ -2720,6 +3773,246 @@ declare class FilesystemStorage implements StorageBackend {
|
|
|
2720
3773
|
totalSize(): Promise<number>;
|
|
2721
3774
|
}
|
|
2722
3775
|
|
|
3776
|
+
/**
|
|
3777
|
+
* Sanctuary MCP Server — Key Derivation
|
|
3778
|
+
*
|
|
3779
|
+
* Two-tier key derivation:
|
|
3780
|
+
* 1. Master key from passphrase via Argon2id (memory-hard, GPU-resistant)
|
|
3781
|
+
* 2. Namespace keys from master key via HKDF-SHA256
|
|
3782
|
+
*
|
|
3783
|
+
* This ensures:
|
|
3784
|
+
* - Passphrase brute-force is expensive (Argon2id)
|
|
3785
|
+
* - Compromise of one namespace key doesn't expose others (HKDF domain separation)
|
|
3786
|
+
*/
|
|
3787
|
+
/** Stored key derivation parameters (for re-deriving the master key) */
|
|
3788
|
+
interface KeyDerivationParams {
|
|
3789
|
+
/** Algorithm */
|
|
3790
|
+
alg: "argon2id";
|
|
3791
|
+
/** Salt (base64url) */
|
|
3792
|
+
salt: string;
|
|
3793
|
+
/** Memory cost in KiB */
|
|
3794
|
+
m: number;
|
|
3795
|
+
/** Time cost (iterations) */
|
|
3796
|
+
t: number;
|
|
3797
|
+
/** Parallelism */
|
|
3798
|
+
p: number;
|
|
3799
|
+
/** Output length in bytes */
|
|
3800
|
+
l: number;
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
/**
|
|
3804
|
+
* Sanctuary v1.1 exit-bundle export/import implementation.
|
|
3805
|
+
*
|
|
3806
|
+
* The public bundle is a directory containing `manifest.json` and hashed JSON
|
|
3807
|
+
* artifacts. Private keys and passphrases are never emitted. Encrypted user
|
|
3808
|
+
* state can be re-keyed on import when the operator supplies source key
|
|
3809
|
+
* material and the destination has a signing identity.
|
|
3810
|
+
*/
|
|
3811
|
+
|
|
3812
|
+
interface ExitEncryptedStateBundle {
|
|
3813
|
+
format: "SANCTUARY_EXIT_ENCRYPTED_STATE_V1";
|
|
3814
|
+
exported_at: string;
|
|
3815
|
+
key_source: "passphrase" | "recovery-key" | "unknown";
|
|
3816
|
+
source_key_derivation?: KeyDerivationParams;
|
|
3817
|
+
namespaces: string[];
|
|
3818
|
+
total_keys: number;
|
|
3819
|
+
contains_reserved_namespaces: false;
|
|
3820
|
+
entries: Array<{
|
|
3821
|
+
namespace: string;
|
|
3822
|
+
key: string;
|
|
3823
|
+
entry: StateEntry;
|
|
3824
|
+
}>;
|
|
3825
|
+
}
|
|
3826
|
+
interface ExitPublicIdentityArtifact {
|
|
3827
|
+
bundle: {
|
|
3828
|
+
format: "SANCTUARY_IDENTITY_BUNDLE_V1";
|
|
3829
|
+
publicKey: string;
|
|
3830
|
+
did: string;
|
|
3831
|
+
identity_id: string;
|
|
3832
|
+
label: string;
|
|
3833
|
+
key_type: "ed25519";
|
|
3834
|
+
key_protection: string;
|
|
3835
|
+
rotation_history: StoredIdentity["rotation_history"];
|
|
3836
|
+
exported_at: string;
|
|
3837
|
+
};
|
|
3838
|
+
signature: string;
|
|
3839
|
+
signed_by: string;
|
|
3840
|
+
}
|
|
3841
|
+
interface ExitPolicySetArtifact {
|
|
3842
|
+
format: "SANCTUARY_EXIT_POLICY_SET_V1";
|
|
3843
|
+
exported_at: string;
|
|
3844
|
+
principal_policy: PrincipalPolicy;
|
|
3845
|
+
config_summary: {
|
|
3846
|
+
version: string;
|
|
3847
|
+
state: SanctuaryConfig["state"];
|
|
3848
|
+
execution: SanctuaryConfig["execution"];
|
|
3849
|
+
disclosure: SanctuaryConfig["disclosure"];
|
|
3850
|
+
reputation: SanctuaryConfig["reputation"];
|
|
3851
|
+
privacy_filter: SanctuaryConfig["privacy_filter"];
|
|
3852
|
+
};
|
|
3853
|
+
}
|
|
3854
|
+
interface ExitAuditReceiptsArtifact {
|
|
3855
|
+
format: "SANCTUARY_AUDIT_RECEIPTS_V1";
|
|
3856
|
+
exported_at: string;
|
|
3857
|
+
total: number;
|
|
3858
|
+
individual_entry_signatures: false;
|
|
3859
|
+
entries: AuditEntry[];
|
|
3860
|
+
}
|
|
3861
|
+
interface ExitCommitmentsArtifact {
|
|
3862
|
+
format: "SANCTUARY_EXIT_COMMITMENTS_V1";
|
|
3863
|
+
exported_at: string;
|
|
3864
|
+
public_commitments: Array<{
|
|
3865
|
+
commitment_id: string;
|
|
3866
|
+
commitment: string;
|
|
3867
|
+
committed_at: string;
|
|
3868
|
+
revealed: boolean;
|
|
3869
|
+
revealed_at?: string;
|
|
3870
|
+
}>;
|
|
3871
|
+
unreadable_count: number;
|
|
3872
|
+
redacted_fields: ["value", "blinding_factor"];
|
|
3873
|
+
}
|
|
3874
|
+
interface ExitPlaceholderVaultMetadataArtifact {
|
|
3875
|
+
format: "SANCTUARY_PLACEHOLDER_VAULT_METADATA_V1";
|
|
3876
|
+
exported_at: string;
|
|
3877
|
+
entries: Array<Record<string, unknown>>;
|
|
3878
|
+
unreadable_count: number;
|
|
3879
|
+
redacted_fields: ["raw_value", "raw_path"];
|
|
3880
|
+
}
|
|
3881
|
+
interface ExportExitBundleOptions {
|
|
3882
|
+
bundleDir: string;
|
|
3883
|
+
storage: StorageBackend;
|
|
3884
|
+
masterKey: Uint8Array;
|
|
3885
|
+
identityManager: IdentityManager;
|
|
3886
|
+
auditLog: AuditLog;
|
|
3887
|
+
policy: PrincipalPolicy;
|
|
3888
|
+
config?: SanctuaryConfig;
|
|
3889
|
+
reputationStore?: ReputationStore;
|
|
3890
|
+
stateStoragePath?: string;
|
|
3891
|
+
stateNamespaces?: string[];
|
|
3892
|
+
keySource?: "passphrase" | "recovery-key" | "unknown";
|
|
3893
|
+
/**
|
|
3894
|
+
* When the export is gated by a Tier 1 approval flow (e.g. the hub's
|
|
3895
|
+
* fortress-scope export endpoint), the caller supplies the approval's
|
|
3896
|
+
* audit id here. The value is embedded in the manifest's
|
|
3897
|
+
* `export_approval_audit_id` field and as the `approval_id` of the L1
|
|
3898
|
+
* "exit_bundle_export" audit entry, tying the manifest to the operator's
|
|
3899
|
+
* actual approval rather than an internally-generated id (v1.0.2 (j)).
|
|
3900
|
+
* When omitted, the export self-generates an id.
|
|
3901
|
+
*/
|
|
3902
|
+
exportApprovalAuditId?: string;
|
|
3903
|
+
}
|
|
3904
|
+
interface ExportExitBundleResult {
|
|
3905
|
+
bundle_dir: string;
|
|
3906
|
+
manifest: ExitBundleManifest;
|
|
3907
|
+
manifest_hash: string;
|
|
3908
|
+
artifact_count: number;
|
|
3909
|
+
unsupported_artifacts: string[];
|
|
3910
|
+
}
|
|
3911
|
+
interface ImportExitBundleOptions {
|
|
3912
|
+
bundleDir: string;
|
|
3913
|
+
storage: StorageBackend;
|
|
3914
|
+
masterKey: Uint8Array;
|
|
3915
|
+
identityManager: IdentityManager;
|
|
3916
|
+
auditLog: AuditLog;
|
|
3917
|
+
reputationStore?: ReputationStore;
|
|
3918
|
+
activate?: boolean;
|
|
3919
|
+
conflictResolution?: "skip" | "overwrite" | "version";
|
|
3920
|
+
sourcePassphrase?: string;
|
|
3921
|
+
sourceRecoveryKey?: string;
|
|
3922
|
+
sourceMasterKey?: Uint8Array;
|
|
3923
|
+
destinationSignerIdentityId?: string;
|
|
3924
|
+
}
|
|
3925
|
+
interface ExitBundleConflictReport {
|
|
3926
|
+
public_identity_exists: boolean;
|
|
3927
|
+
state_conflicts: Array<{
|
|
3928
|
+
namespace: string;
|
|
3929
|
+
key: string;
|
|
3930
|
+
}>;
|
|
3931
|
+
reputation_conflicts: string[];
|
|
3932
|
+
policy_set_exists: boolean;
|
|
3933
|
+
audit_receipts_exist: boolean;
|
|
3934
|
+
}
|
|
3935
|
+
interface ImportExitBundleResult {
|
|
3936
|
+
verified: boolean;
|
|
3937
|
+
activated: boolean;
|
|
3938
|
+
conflicts: ExitBundleConflictReport;
|
|
3939
|
+
state: {
|
|
3940
|
+
status: "not_requested" | "rekeyed" | "staged_requires_source_key" | "skipped_no_destination_signer";
|
|
3941
|
+
imported_keys: number;
|
|
3942
|
+
skipped_keys: number;
|
|
3943
|
+
skipped_invalid_sig: number;
|
|
3944
|
+
skipped_unknown_kid: number;
|
|
3945
|
+
conflicts: number;
|
|
3946
|
+
};
|
|
3947
|
+
reputation: {
|
|
3948
|
+
imported_attestations: number;
|
|
3949
|
+
invalid_attestations: number;
|
|
3950
|
+
unverifiable_attestations: number;
|
|
3951
|
+
};
|
|
3952
|
+
staged_artifacts: string[];
|
|
3953
|
+
warnings: string[];
|
|
3954
|
+
unsupported_artifacts: string[];
|
|
3955
|
+
}
|
|
3956
|
+
declare function exportExitBundle(opts: ExportExitBundleOptions): Promise<ExportExitBundleResult>;
|
|
3957
|
+
declare function importExitBundle(opts: ImportExitBundleOptions): Promise<ImportExitBundleResult>;
|
|
3958
|
+
declare function exitBundleManifestShape(): Record<string, unknown>;
|
|
3959
|
+
|
|
3960
|
+
/**
|
|
3961
|
+
* Sanctuary v1.1 exit-bundle verifier.
|
|
3962
|
+
*
|
|
3963
|
+
* Verifies the signed SANCTUARY_EXIT_BUNDLE_V1 manifest, every artifact hash,
|
|
3964
|
+
* and the exported identity / reputation signatures that are independently
|
|
3965
|
+
* verifiable from public material in the bundle.
|
|
3966
|
+
*/
|
|
3967
|
+
|
|
3968
|
+
interface ExitBundleDetailedVerifierResult extends ExitBundleVerifierResult {
|
|
3969
|
+
manifest_path: string;
|
|
3970
|
+
manifest_hash: string | null;
|
|
3971
|
+
warnings: string[];
|
|
3972
|
+
unsupported_artifacts: string[];
|
|
3973
|
+
identity?: {
|
|
3974
|
+
signature_valid: boolean;
|
|
3975
|
+
identity_id?: string;
|
|
3976
|
+
did?: string;
|
|
3977
|
+
};
|
|
3978
|
+
audit?: {
|
|
3979
|
+
receipt_count: number;
|
|
3980
|
+
individual_signatures_verified: boolean;
|
|
3981
|
+
};
|
|
3982
|
+
reputation?: {
|
|
3983
|
+
bundle_signature_valid: boolean | "unverifiable";
|
|
3984
|
+
attestation_count: number;
|
|
3985
|
+
verified_attestations: number;
|
|
3986
|
+
invalid_attestations: number;
|
|
3987
|
+
unverifiable_attestations: number;
|
|
3988
|
+
};
|
|
3989
|
+
}
|
|
3990
|
+
interface LoadedExitArtifact<T = unknown> {
|
|
3991
|
+
entry: ExitBundleArtifactEntry;
|
|
3992
|
+
path: string;
|
|
3993
|
+
json: T;
|
|
3994
|
+
bytes: Uint8Array;
|
|
3995
|
+
}
|
|
3996
|
+
declare function readManifest(bundleDir: string): Promise<ExitBundleManifest>;
|
|
3997
|
+
declare function loadExitArtifact<T = unknown>(bundleDir: string, manifest: ExitBundleManifest, kind: ExitBundleArtifactKind): Promise<LoadedExitArtifact<T> | null>;
|
|
3998
|
+
declare function verifyExitBundle(bundleDir: string): Promise<ExitBundleDetailedVerifierResult>;
|
|
3999
|
+
|
|
4000
|
+
/**
|
|
4001
|
+
* `sanctuary exit` CLI.
|
|
4002
|
+
*
|
|
4003
|
+
* Operator-facing export/import/verifier path for SANCTUARY_EXIT_BUNDLE_V1.
|
|
4004
|
+
* Dashboard wizard work consumes the same module APIs later.
|
|
4005
|
+
*/
|
|
4006
|
+
|
|
4007
|
+
interface ExitCommandArgs {
|
|
4008
|
+
argv: string[];
|
|
4009
|
+
out?: Writable;
|
|
4010
|
+
err?: Writable;
|
|
4011
|
+
stdin?: NodeJS.ReadableStream;
|
|
4012
|
+
env?: NodeJS.ProcessEnv;
|
|
4013
|
+
}
|
|
4014
|
+
declare function runExitCommand(args: ExitCommandArgs): Promise<number>;
|
|
4015
|
+
|
|
2723
4016
|
/**
|
|
2724
4017
|
* Sanctuary MCP Server — Principal Policy Loader
|
|
2725
4018
|
*
|
|
@@ -2806,6 +4099,412 @@ interface SHRGeneratorOptions {
|
|
|
2806
4099
|
*/
|
|
2807
4100
|
declare function generateSHR(identityId: string | undefined, opts: SHRGeneratorOptions): SignedSHR | string;
|
|
2808
4101
|
|
|
4102
|
+
/**
|
|
4103
|
+
* Sanctuary v1.1 Operator Hub API Constants
|
|
4104
|
+
*
|
|
4105
|
+
* Routes, prefixes, and small enums shared across the hub modules.
|
|
4106
|
+
* The hub API surface is consumed by the v1.1 dashboard UI (Prompt 8).
|
|
4107
|
+
*
|
|
4108
|
+
* Local-only invariant:
|
|
4109
|
+
* Every route here describes activity inside a single fortress on a single
|
|
4110
|
+
* operator's machine. Cross-fortress, fleet, and public-federation routes
|
|
4111
|
+
* are out of scope.
|
|
4112
|
+
*/
|
|
4113
|
+
|
|
4114
|
+
/**
|
|
4115
|
+
* Inbox-resolve actions. The router rejects any other action token.
|
|
4116
|
+
*/
|
|
4117
|
+
declare const HUB_INBOX_ACTIONS: readonly ["approve", "deny", "dismiss"];
|
|
4118
|
+
type HubInboxAction = (typeof HUB_INBOX_ACTIONS)[number];
|
|
4119
|
+
/**
|
|
4120
|
+
* Agent-control actions surfaced by `POST /api/hub/agents/:id/:action`.
|
|
4121
|
+
*
|
|
4122
|
+
* `pause` / `resume` / `restart` are control-plane operations that the
|
|
4123
|
+
* underlying harness may execute immediately; they are not Tier 1.
|
|
4124
|
+
*
|
|
4125
|
+
* `unwrap` and `lockdown` are Tier 1 operations per the Principal Policy
|
|
4126
|
+
* loader. Hub endpoints for these MUST enqueue an `approval_pending` inbox
|
|
4127
|
+
* item rather than execute directly. Tier 1 approval gates remain in force
|
|
4128
|
+
* from the dashboard. The dashboard never auto-approves Tier 1 work.
|
|
4129
|
+
*/
|
|
4130
|
+
declare const HUB_AGENT_CONTROL_ACTIONS: readonly ["pause", "resume", "restart", "unwrap", "lockdown"];
|
|
4131
|
+
type HubAgentControlAction = (typeof HUB_AGENT_CONTROL_ACTIONS)[number];
|
|
4132
|
+
|
|
4133
|
+
/** Channel-template identifiers per Walkthrough Key 10 LOCKED starter set. */
|
|
4134
|
+
declare const CHANNEL_TEMPLATE_IDS: readonly ["read-outputs-only", "bidirectional-sync", "credential-share-scoped", "plan-inspect-read-only", "escrow-handoff"];
|
|
4135
|
+
type ChannelTemplateId = (typeof CHANNEL_TEMPLATE_IDS)[number];
|
|
4136
|
+
|
|
4137
|
+
/**
|
|
4138
|
+
* Sanctuary v1.1. Operator Hub API Types
|
|
4139
|
+
*
|
|
4140
|
+
* Service-deps shapes + small payload types not already defined in the
|
|
4141
|
+
* v1.1 contracts. The contract surface (HubInboxItem, LocalAgentRecord,
|
|
4142
|
+
* HubActivityFeedEntry, HubAgentStatusSnapshot) is the source of truth for
|
|
4143
|
+
* everything that crosses the API boundary; types in this file are
|
|
4144
|
+
* implementation glue.
|
|
4145
|
+
*/
|
|
4146
|
+
|
|
4147
|
+
/**
|
|
4148
|
+
* Result returned from a synchronous (non-Tier-1) agent control action.
|
|
4149
|
+
*/
|
|
4150
|
+
interface HubAgentControlResult {
|
|
4151
|
+
agent_id: string;
|
|
4152
|
+
prior_status: HubAgentStatus;
|
|
4153
|
+
new_status: HubAgentStatus;
|
|
4154
|
+
applied_at: string;
|
|
4155
|
+
}
|
|
4156
|
+
/**
|
|
4157
|
+
* Result returned from a Tier-1 agent control action that has been
|
|
4158
|
+
* deferred to operator approval. The hub returns the inbox item id so the
|
|
4159
|
+
* caller can poll or subscribe; nothing executes until the operator
|
|
4160
|
+
* resolves the inbox item.
|
|
4161
|
+
*/
|
|
4162
|
+
interface HubTier1ApprovalEnqueuedResult {
|
|
4163
|
+
agent_id: string;
|
|
4164
|
+
inbox_item_id: string;
|
|
4165
|
+
status: "approval_pending";
|
|
4166
|
+
/**
|
|
4167
|
+
* Same enum as
|
|
4168
|
+
* `HubApprovalPendingItem.operation_category`. Surfaced separately so
|
|
4169
|
+
* non-inbox callers (CLI scripts, test harnesses) can act on the
|
|
4170
|
+
* category without a second fetch.
|
|
4171
|
+
*/
|
|
4172
|
+
operation_category: HubApprovalPendingItem["operation_category"];
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Result returned from a fortress-scope Tier-1 action that has been
|
|
4176
|
+
* deferred to operator approval. Distinguished from the per-agent shape by
|
|
4177
|
+
* the absence of `agent_id` and the presence of `fortress_scope: true`.
|
|
4178
|
+
* The Tier 1 handler iterates fortress-wide on approval; nothing executes
|
|
4179
|
+
* until the operator resolves the inbox item.
|
|
4180
|
+
*/
|
|
4181
|
+
interface HubTier1FortressApprovalEnqueuedResult {
|
|
4182
|
+
inbox_item_id: string;
|
|
4183
|
+
status: "approval_pending";
|
|
4184
|
+
operation_category: HubApprovalPendingItem["operation_category"];
|
|
4185
|
+
/** Always true. Distinguishes from the per-agent shape. */
|
|
4186
|
+
fortress_scope: true;
|
|
4187
|
+
}
|
|
4188
|
+
/**
|
|
4189
|
+
* Result returned from `fortressExportBundle` after a fortress-scope
|
|
4190
|
+
* exit-bundle export approval lands. Surfaced both in the inbox item's
|
|
4191
|
+
* `resolution_payload` and (separately) in an activity feed entry.
|
|
4192
|
+
*/
|
|
4193
|
+
interface HubFortressExportResult {
|
|
4194
|
+
bundle_dir: string;
|
|
4195
|
+
manifest_hash: string;
|
|
4196
|
+
artifact_count: number;
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Generic capability check delegated to the underlying harness controller.
|
|
4200
|
+
* The hub never performs the harness-side action itself; it asks the
|
|
4201
|
+
* controller to apply a transition and reports the new status back.
|
|
4202
|
+
*
|
|
4203
|
+
* Each callback returns the agent's new status after the action lands.
|
|
4204
|
+
* The controller MUST throw if it cannot apply the action; the hub maps
|
|
4205
|
+
* those throws to HubCapabilityError or HubConflictError.
|
|
4206
|
+
*/
|
|
4207
|
+
interface HubAgentController {
|
|
4208
|
+
pause(agentId: string): Promise<HubAgentStatus>;
|
|
4209
|
+
resume(agentId: string): Promise<HubAgentStatus>;
|
|
4210
|
+
restart(agentId: string): Promise<HubAgentStatus>;
|
|
4211
|
+
/**
|
|
4212
|
+
* Apply an operator-approved unwrap. Called only after a Tier 1
|
|
4213
|
+
* approval lands through the inbox flow. Implementations SHOULD treat
|
|
4214
|
+
* unwrap as durable (cocoon teardown + registry deregister).
|
|
4215
|
+
*/
|
|
4216
|
+
unwrap(agentId: string): Promise<HubAgentStatus>;
|
|
4217
|
+
/**
|
|
4218
|
+
* Apply an operator-approved lockdown. Called only after a Tier 1
|
|
4219
|
+
* approval lands. Implementations SHOULD treat lockdown as a hard-stop
|
|
4220
|
+
* (deny all egress, freeze gates) until explicitly cleared.
|
|
4221
|
+
*/
|
|
4222
|
+
lockdown(agentId: string): Promise<HubAgentStatus>;
|
|
4223
|
+
/**
|
|
4224
|
+
* Apply an operator-approved policy bind. Called only after a Tier 1
|
|
4225
|
+
* approval lands.
|
|
4226
|
+
*/
|
|
4227
|
+
bindPolicy(agentId: string, policyId: string): Promise<void>;
|
|
4228
|
+
/**
|
|
4229
|
+
* Apply a non-Tier-1 channel-template binding. Channel templates are
|
|
4230
|
+
* compositions over the canonical four slots; binding does not require
|
|
4231
|
+
* Tier 1 approval at v1.1.
|
|
4232
|
+
*/
|
|
4233
|
+
bindChannelTemplate(agentId: string, templateId: ChannelTemplateId): Promise<void>;
|
|
4234
|
+
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Source-side input shapes the inbox aggregator pulls from. Each callback
|
|
4237
|
+
* returns recent occurrences pre-shaped as the underlying contract type;
|
|
4238
|
+
* the aggregator wraps them into HubInboxItem header form.
|
|
4239
|
+
*
|
|
4240
|
+
* Source callbacks are deliberately narrow; the hub does not know how to
|
|
4241
|
+
* compute privacy events or budget thresholds. Other workstreams own those
|
|
4242
|
+
* computations and feed them in through these callbacks.
|
|
4243
|
+
*/
|
|
4244
|
+
interface HubInboxSources {
|
|
4245
|
+
/**
|
|
4246
|
+
* Currently unresolved Tier 1 / Tier 2 approval requests. Items already
|
|
4247
|
+
* in the hub-side inbox store are deduplicated by `item_id` against these.
|
|
4248
|
+
*/
|
|
4249
|
+
listPendingApprovals: () => HubApprovalPendingItem[];
|
|
4250
|
+
/**
|
|
4251
|
+
* Recent egress denials. The hub surfaces each as a blocked-egress inbox
|
|
4252
|
+
* card. The caller is responsible for trimming to the recent window.
|
|
4253
|
+
*/
|
|
4254
|
+
listRecentBlockedEgress: () => HubBlockedEgressItem[];
|
|
4255
|
+
/**
|
|
4256
|
+
* Recent privacy events the operator should attend to. The hub does NOT
|
|
4257
|
+
* surface every privacy event; it surfaces the ones that the privacy
|
|
4258
|
+
* core has already promoted to operator attention (denied, error, plus
|
|
4259
|
+
* filtered events flagged by the bound policy).
|
|
4260
|
+
*/
|
|
4261
|
+
listRecentPrivacyEvents: () => HubPrivacyEventItem[];
|
|
4262
|
+
/**
|
|
4263
|
+
* Active budget warnings (soft-warn or hard-cap). Closed warnings are
|
|
4264
|
+
* not returned.
|
|
4265
|
+
*/
|
|
4266
|
+
listActiveBudgetWarnings: () => HubBudgetWarningItem[];
|
|
4267
|
+
/**
|
|
4268
|
+
* Active recovery prompts (passphrase reset due, exit drill recommended,
|
|
4269
|
+
* keychain rebind required, etc.).
|
|
4270
|
+
*/
|
|
4271
|
+
listActiveRecoveryPrompts: () => HubRecoveryPromptItem[];
|
|
4272
|
+
/**
|
|
4273
|
+
* Recent agent-error events.
|
|
4274
|
+
*/
|
|
4275
|
+
listRecentAgentErrors: () => HubAgentErrorItem[];
|
|
4276
|
+
}
|
|
4277
|
+
interface HubActivitySources {
|
|
4278
|
+
/**
|
|
4279
|
+
* Underlying audit log the activity feed projects from.
|
|
4280
|
+
*/
|
|
4281
|
+
auditLog: AuditLog;
|
|
4282
|
+
/**
|
|
4283
|
+
* Identity id the dashboard is currently scoped to. Activity entries are
|
|
4284
|
+
* filtered to this identity; v1.1 is single-operator; the parameter is
|
|
4285
|
+
* here so v1.2 can scope per-identity without breaking the API.
|
|
4286
|
+
*/
|
|
4287
|
+
identityId: string;
|
|
4288
|
+
}
|
|
4289
|
+
/**
|
|
4290
|
+
* Lightweight summary of a bound policy. Suitable for UI cards. Raw policy
|
|
4291
|
+
* bytes never appear here.
|
|
4292
|
+
*/
|
|
4293
|
+
interface HubPolicySummary {
|
|
4294
|
+
policy_id: string;
|
|
4295
|
+
display_label: string;
|
|
4296
|
+
/** ISO8601 timestamp the policy was bound. */
|
|
4297
|
+
bound_at: string;
|
|
4298
|
+
/** Number of agents currently bound to this policy. */
|
|
4299
|
+
agent_count: number;
|
|
4300
|
+
/** Channel template id the policy was compiled from, if applicable. */
|
|
4301
|
+
channel_template_id?: ChannelTemplateId;
|
|
4302
|
+
}
|
|
4303
|
+
/**
|
|
4304
|
+
* Lightweight summary of a budget bucket. Suitable for UI cards.
|
|
4305
|
+
*/
|
|
4306
|
+
interface HubBudgetSummary {
|
|
4307
|
+
bucket_id: string;
|
|
4308
|
+
/** Display label drawn from the policy compile step. */
|
|
4309
|
+
display_label: string;
|
|
4310
|
+
unit: string;
|
|
4311
|
+
cap: number;
|
|
4312
|
+
used: number;
|
|
4313
|
+
/** Soft-warn threshold fraction (0..1). */
|
|
4314
|
+
soft_warn?: number;
|
|
4315
|
+
/** ISO8601 timestamp of last refresh. */
|
|
4316
|
+
last_refreshed_at: string;
|
|
4317
|
+
}
|
|
4318
|
+
interface HubPolicyAndBudgetSources {
|
|
4319
|
+
listPolicySummaries: () => HubPolicySummary[];
|
|
4320
|
+
listBudgetSummaries: () => HubBudgetSummary[];
|
|
4321
|
+
}
|
|
4322
|
+
/**
|
|
4323
|
+
* Read interface for the local agent registry. The hub does not invent
|
|
4324
|
+
* agent records; it pulls them from this source. Backend implementations
|
|
4325
|
+
* may persist records to disk or recompute them per call.
|
|
4326
|
+
*/
|
|
4327
|
+
interface HubAgentRegistrySource {
|
|
4328
|
+
list(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4329
|
+
get(agentId: string): LocalAgentRecord | null;
|
|
4330
|
+
/**
|
|
4331
|
+
* Update a single field on a record. The hub uses this to flip status
|
|
4332
|
+
* after a synchronous control action lands. Returns the updated record;
|
|
4333
|
+
* throws if the agent does not exist.
|
|
4334
|
+
*/
|
|
4335
|
+
updateStatus(agentId: string, status: HubAgentStatus, statusReasonClass?: LocalAgentRecord["status_reason_class"]): LocalAgentRecord;
|
|
4336
|
+
/**
|
|
4337
|
+
* Bind a different policy on a record. Used after an approved Tier 1
|
|
4338
|
+
* policy_change action lands.
|
|
4339
|
+
*/
|
|
4340
|
+
updatePolicyBinding(agentId: string, policyId: string): LocalAgentRecord;
|
|
4341
|
+
/**
|
|
4342
|
+
* Bind a different channel template on a record. Non-Tier-1.
|
|
4343
|
+
*/
|
|
4344
|
+
updateChannelTemplateBinding(agentId: string, templateId: ChannelTemplateId): LocalAgentRecord;
|
|
4345
|
+
}
|
|
4346
|
+
interface HubServiceDeps {
|
|
4347
|
+
/** Operator identity id this hub is scoped to. */
|
|
4348
|
+
identityId: string;
|
|
4349
|
+
/** Stable fortress id. */
|
|
4350
|
+
fortressId: string;
|
|
4351
|
+
/** Local agent registry source. */
|
|
4352
|
+
agentRegistry: HubAgentRegistrySource;
|
|
4353
|
+
/** Inbox aggregation sources. */
|
|
4354
|
+
inboxSources: HubInboxSources;
|
|
4355
|
+
/** Activity feed sources. */
|
|
4356
|
+
activitySources: HubActivitySources;
|
|
4357
|
+
/** Policy + budget summary sources. */
|
|
4358
|
+
policyBudgetSources: HubPolicyAndBudgetSources;
|
|
4359
|
+
/** Underlying agent controller for control endpoints. */
|
|
4360
|
+
agentController: HubAgentController;
|
|
4361
|
+
/**
|
|
4362
|
+
* Optional fortress-scope exit-bundle export callback. Invoked only
|
|
4363
|
+
* after a fortress-scope Tier 1 approval lands. The callback owns its
|
|
4364
|
+
* own dependency wiring (storage, masterKey, identityManager, auditLog,
|
|
4365
|
+
* policy, reputationStore, state namespaces); the hub layer remains
|
|
4366
|
+
* crypto-agnostic. When omitted, the fortress export endpoint returns
|
|
4367
|
+
* `HubCapabilityError`.
|
|
4368
|
+
*
|
|
4369
|
+
* The hub passes the inbox item's id as `approvalAuditId` so the
|
|
4370
|
+
* callback can thread it into `exportExitBundle({ exportApprovalAuditId })`,
|
|
4371
|
+
* tying the manifest's `export_approval_audit_id` to the operator's
|
|
4372
|
+
* actual approval flow rather than an internally-generated value
|
|
4373
|
+
* (closes v1.0.2 backlog item (j)). The argument is optional for
|
|
4374
|
+
* backwards compatibility with existing callbacks.
|
|
4375
|
+
*/
|
|
4376
|
+
fortressExportBundle?: (approvalAuditId?: string) => Promise<HubFortressExportResult>;
|
|
4377
|
+
/**
|
|
4378
|
+
* Clock override for deterministic timestamp emission in tests.
|
|
4379
|
+
* Defaults to `() => new Date()` when omitted.
|
|
4380
|
+
*/
|
|
4381
|
+
now?: () => Date;
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
/**
|
|
4385
|
+
* Sanctuary v1.1. Operator Hub Service
|
|
4386
|
+
*
|
|
4387
|
+
* Public API the router calls. Owns no domain logic: it composes the
|
|
4388
|
+
* agent registry source, the inbox aggregator + store, the activity feed
|
|
4389
|
+
* projection, and the agent controller.
|
|
4390
|
+
*
|
|
4391
|
+
* Tier 1 enforcement contract:
|
|
4392
|
+
* Hub control endpoints for `unwrap`, `lockdown`, and `policy_change` MUST
|
|
4393
|
+
* NOT execute synchronously. The hub enqueues an `approval_pending` inbox
|
|
4394
|
+
* item carrying the operation_category and binds the controller call to
|
|
4395
|
+
* the inbox-store resolution handler. Only operator approval through the
|
|
4396
|
+
* inbox path causes the controller call to fire. The dashboard never
|
|
4397
|
+
* auto-approves Tier 1 work.
|
|
4398
|
+
*/
|
|
4399
|
+
|
|
4400
|
+
declare class HubService {
|
|
4401
|
+
private deps;
|
|
4402
|
+
private inboxStore;
|
|
4403
|
+
constructor(deps: HubServiceDeps);
|
|
4404
|
+
private now;
|
|
4405
|
+
private nowIso;
|
|
4406
|
+
listInbox(): HubInboxItem[];
|
|
4407
|
+
resolveInboxItem(itemId: string, action: HubInboxAction): Promise<HubInboxItem>;
|
|
4408
|
+
listAgents(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4409
|
+
getAgent(agentId: string): LocalAgentRecord;
|
|
4410
|
+
getAgentStatusSnapshot(agentId: string): HubAgentStatusSnapshot;
|
|
4411
|
+
controlAgent(agentId: string, action: HubAgentControlAction): Promise<HubAgentControlResult | HubTier1ApprovalEnqueuedResult>;
|
|
4412
|
+
/**
|
|
4413
|
+
* Capability gate. Returns silently when the action is supported by the
|
|
4414
|
+
* harness; throws HubCapabilityError when not.
|
|
4415
|
+
*/
|
|
4416
|
+
private assertCapability;
|
|
4417
|
+
/**
|
|
4418
|
+
* Build a Tier 1 inbox item for an unwrap/lockdown/policy_change action
|
|
4419
|
+
* and bind the controller call to its resolution.
|
|
4420
|
+
*/
|
|
4421
|
+
private enqueueTier1ControlAction;
|
|
4422
|
+
/**
|
|
4423
|
+
* Bind a different policy on an agent. Tier 1: enqueues an approval
|
|
4424
|
+
* pending inbox item rather than executing synchronously.
|
|
4425
|
+
*/
|
|
4426
|
+
bindAgentPolicy(agentId: string, policyId: string): HubTier1ApprovalEnqueuedResult;
|
|
4427
|
+
/**
|
|
4428
|
+
* Bind a different channel template. Not Tier 1; channel templates are
|
|
4429
|
+
* compositions over the four canonical slots and bind synchronously.
|
|
4430
|
+
*/
|
|
4431
|
+
bindAgentChannelTemplate(agentId: string, rawTemplateId: unknown): Promise<LocalAgentRecord>;
|
|
4432
|
+
/**
|
|
4433
|
+
* Enqueue a fortress-scope Tier 1 lockdown. One inbox item is created;
|
|
4434
|
+
* on operator approval the handler iterates `agentController.lockdown`
|
|
4435
|
+
* over every wrapped agent for the bound identity, captures partial
|
|
4436
|
+
* failures as per-agent `agent_error` inbox items, and emits a single
|
|
4437
|
+
* `lifecycle` activity entry. Stacked fortress lockdowns are rejected
|
|
4438
|
+
* with `HubConflictError` until the prior pending item resolves.
|
|
4439
|
+
*/
|
|
4440
|
+
enqueueFortressLockdown(): HubTier1FortressApprovalEnqueuedResult;
|
|
4441
|
+
/**
|
|
4442
|
+
* Enqueue a fortress-scope Tier 1 exit-bundle export. One inbox item is
|
|
4443
|
+
* created; on operator approval the handler invokes
|
|
4444
|
+
* `fortressExportBundle()` once at fortress scope, attaches
|
|
4445
|
+
* `bundle_dir` + `manifest_hash` + `artifact_count` to the inbox item's
|
|
4446
|
+
* `resolution_payload`, and emits a `lifecycle` activity entry.
|
|
4447
|
+
* Stacked exports are rejected with `HubConflictError`.
|
|
4448
|
+
*/
|
|
4449
|
+
enqueueFortressExportBundle(): HubTier1FortressApprovalEnqueuedResult;
|
|
4450
|
+
/**
|
|
4451
|
+
* Reject stacked fortress-scope Tier 1 items. The check scans the inbox
|
|
4452
|
+
* store for an unresolved `approval_pending` item with the same
|
|
4453
|
+
* `operation_category` and no `agent_id` (the fortress-scope marker).
|
|
4454
|
+
*/
|
|
4455
|
+
private assertNoPendingFortressTier1;
|
|
4456
|
+
listActivity(filter: {
|
|
4457
|
+
since?: string;
|
|
4458
|
+
limit?: number;
|
|
4459
|
+
agent_id?: string;
|
|
4460
|
+
category?: HubActivityFeedEntry["category"];
|
|
4461
|
+
}): Promise<HubActivityFeedEntry[]>;
|
|
4462
|
+
listPolicySummaries(): HubPolicySummary[];
|
|
4463
|
+
listBudgetSummaries(): HubBudgetSummary[];
|
|
4464
|
+
/**
|
|
4465
|
+
* Validate that a caller-supplied filter does not request cross-fortress
|
|
4466
|
+
* scope; v1.1 hub is single-fortress; the filter rejects fortress-bridging
|
|
4467
|
+
* fields outright; v1.3 federation will introduce an alternate surface.
|
|
4468
|
+
*/
|
|
4469
|
+
static assertLocalOnlyFilter(filter: Record<string, unknown> | null): void;
|
|
4470
|
+
/**
|
|
4471
|
+
* Test/inspection helper. Not part of the public service surface.
|
|
4472
|
+
*/
|
|
4473
|
+
inboxStoreSize(): number;
|
|
4474
|
+
}
|
|
4475
|
+
|
|
4476
|
+
/**
|
|
4477
|
+
* v1.1 Server Wiring (v1.1.1 hotfix)
|
|
4478
|
+
*
|
|
4479
|
+
* v1.1.0 shipped the v1.1 module suite (dashboard / hub API / exit bundle
|
|
4480
|
+
* endpoints / coordination) but no entry-point server imported any of it.
|
|
4481
|
+
* This module builds the canonical HubService construction the dashboard
|
|
4482
|
+
* entry points share so the routes light up at boot without forcing each
|
|
4483
|
+
* caller to know the deps shape.
|
|
4484
|
+
*
|
|
4485
|
+
* The wiring is deliberately minimal at v1.1.1:
|
|
4486
|
+
*
|
|
4487
|
+
* - Local agent registry starts empty. v1.2 will populate it from
|
|
4488
|
+
* `discoverTenants()` and the wrapped harness manifest. v1.1.1 ships
|
|
4489
|
+
* the API surface so existing operator scripts can hit it; the data
|
|
4490
|
+
* plane is the next conversation.
|
|
4491
|
+
* - Inbox sources return empty arrays. The privacy chokepoint already
|
|
4492
|
+
* emits audit events through PR #69 / PR #71; the inbox aggregator is
|
|
4493
|
+
* the v1.2 work to project those into operator cards.
|
|
4494
|
+
* - Activity feed reads from the real audit log. This is the one source
|
|
4495
|
+
* that's already complete in v1.1.0 and just needs to be plugged in.
|
|
4496
|
+
* - Agent controller errors on every action. v1.1.1 cannot honestly
|
|
4497
|
+
* pause / unwrap / lockdown anything because no agent registry yet
|
|
4498
|
+
* exists; the wiring returns `HubCapabilityError` rather than lying
|
|
4499
|
+
* about what shipped.
|
|
4500
|
+
*/
|
|
4501
|
+
|
|
4502
|
+
interface V11Bindings {
|
|
4503
|
+
hubService: HubService;
|
|
4504
|
+
identityId: string;
|
|
4505
|
+
fortressId: string;
|
|
4506
|
+
}
|
|
4507
|
+
|
|
2809
4508
|
/**
|
|
2810
4509
|
* Sanctuary MCP Server — Principal Dashboard
|
|
2811
4510
|
*
|
|
@@ -2889,6 +4588,12 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
2889
4588
|
* policy change.
|
|
2890
4589
|
*/
|
|
2891
4590
|
private _autoAuthLocalhost;
|
|
4591
|
+
/**
|
|
4592
|
+
* v1.1 routes (dashboard HTML at /v1.1, hub API at /api/hub/*) are
|
|
4593
|
+
* mounted additively when set. Legacy routes at / continue to serve
|
|
4594
|
+
* regardless. Default route flip is deferred to v1.2.
|
|
4595
|
+
*/
|
|
4596
|
+
private v11Bindings;
|
|
2892
4597
|
constructor(config: DashboardConfig);
|
|
2893
4598
|
/**
|
|
2894
4599
|
* Inject dependencies after construction.
|
|
@@ -2910,6 +4615,26 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
2910
4615
|
* Exposed via /api/status so the frontend can show an appropriate banner.
|
|
2911
4616
|
*/
|
|
2912
4617
|
setStandaloneMode(standalone: boolean): void;
|
|
4618
|
+
/**
|
|
4619
|
+
* v1.1.1 hotfix: bind the v1.1 dashboard + hub API to this dashboard
|
|
4620
|
+
* instance. After binding, requests to `/v1.1` serve the v1.1 HTML and
|
|
4621
|
+
* requests under `/api/hub/*` route through the hub API. Legacy routes
|
|
4622
|
+
* at `/` and `/api/*` keep their pre-v1.1 behavior (additive mount).
|
|
4623
|
+
*
|
|
4624
|
+
* Pass `null` to detach the bindings (used by tests and during shutdown).
|
|
4625
|
+
*/
|
|
4626
|
+
setV11Bindings(bindings: V11Bindings | null): void;
|
|
4627
|
+
/**
|
|
4628
|
+
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
4629
|
+
* legacy route table. Returns true when the request was served by v1.1
|
|
4630
|
+
* routes; false to fall through to legacy routing.
|
|
4631
|
+
*
|
|
4632
|
+
* Auth gating: the v1.1 dashboard HTML is served unconditionally (the
|
|
4633
|
+
* client script handles its own auth dance). Hub API routes run through
|
|
4634
|
+
* the same auth contract as legacy `/api/*` routes via the AuthConfig
|
|
4635
|
+
* passed to `handleHubRoute`.
|
|
4636
|
+
*/
|
|
4637
|
+
private dispatchV11;
|
|
2913
4638
|
/**
|
|
2914
4639
|
* v0.10.2: enable (or disable) the loopback auto-auth fast path. See
|
|
2915
4640
|
* {@link _autoAuthLocalhost} for the rationale and threat model. Callers
|
|
@@ -2985,6 +4710,7 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
2985
4710
|
*/
|
|
2986
4711
|
private pruneRateLimits;
|
|
2987
4712
|
private handleRequest;
|
|
4713
|
+
private handleLegacyRequest;
|
|
2988
4714
|
/**
|
|
2989
4715
|
* SEC-012: Exchange a long-lived auth token (in Authorization header)
|
|
2990
4716
|
* for a short-lived session ID. The session ID can be used in URL
|
|
@@ -3631,6 +5357,12 @@ interface UpstreamServerStatus {
|
|
|
3631
5357
|
tool_count: number;
|
|
3632
5358
|
error?: string;
|
|
3633
5359
|
}
|
|
5360
|
+
interface PrivacySummary {
|
|
5361
|
+
filtered_events: number;
|
|
5362
|
+
filtered_spans: number;
|
|
5363
|
+
classes: Record<string, number>;
|
|
5364
|
+
last_filtered_at: string | null;
|
|
5365
|
+
}
|
|
3634
5366
|
interface ProtectionSnapshot {
|
|
3635
5367
|
overall: {
|
|
3636
5368
|
status: OverallStatus;
|
|
@@ -3647,6 +5379,7 @@ interface ProtectionSnapshot {
|
|
|
3647
5379
|
activity: ActivityEntry[];
|
|
3648
5380
|
pending_approvals: PendingApproval[];
|
|
3649
5381
|
audit: AuditEntry[];
|
|
5382
|
+
privacy: PrivacySummary;
|
|
3650
5383
|
upstream_servers: UpstreamServerStatus[];
|
|
3651
5384
|
mode: "co-located" | "standalone";
|
|
3652
5385
|
server_version: string;
|
|
@@ -3700,8 +5433,19 @@ interface ApprovalHandlers {
|
|
|
3700
5433
|
allow: (id: string) => Promise<boolean>;
|
|
3701
5434
|
deny: (id: string) => Promise<boolean>;
|
|
3702
5435
|
}
|
|
5436
|
+
/**
|
|
5437
|
+
* SSE event taxonomy.
|
|
5438
|
+
*
|
|
5439
|
+
* v1.0 event names: `snapshot` (initial hydration), `activity` (audit feed
|
|
5440
|
+
* append), `approval` (pending approval surfaced).
|
|
5441
|
+
*
|
|
5442
|
+
* v1.1 added: `inbox` (HubInboxItem replace-or-prepend by item_id) and
|
|
5443
|
+
* `agent_status` (HubAgentStatusSnapshot replace by agent_id). The hub
|
|
5444
|
+
* service emits these via the existing `publish` interface; the producer
|
|
5445
|
+
* wires every name verbatim through `event: <type>` SSE frames.
|
|
5446
|
+
*/
|
|
3703
5447
|
interface StreamEvent {
|
|
3704
|
-
type: "snapshot" | "activity" | "approval";
|
|
5448
|
+
type: "snapshot" | "activity" | "approval" | "inbox" | "agent_status";
|
|
3705
5449
|
data: unknown;
|
|
3706
5450
|
}
|
|
3707
5451
|
|
|
@@ -3739,6 +5483,18 @@ interface DashboardHandle {
|
|
|
3739
5483
|
publishActivity: (entry: ActivityEntry) => void;
|
|
3740
5484
|
/** Push a new pending approval (already added by the approval channel). */
|
|
3741
5485
|
publishApproval: (approval: PendingApproval) => void;
|
|
5486
|
+
/**
|
|
5487
|
+
* Push a v1.1 hub inbox item update. Producers (HubService) call this
|
|
5488
|
+
* on inbox writes (Tier 1 enqueue, Tier 1 resolve, source-pulled item
|
|
5489
|
+
* surfaced). Consumers replace-or-prepend by `item_id`.
|
|
5490
|
+
*/
|
|
5491
|
+
publishInbox: (item: unknown) => void;
|
|
5492
|
+
/**
|
|
5493
|
+
* Push a v1.1 per-agent status update. Producers call this when the
|
|
5494
|
+
* agent registry's `updateStatus` transitions. Consumers replace by
|
|
5495
|
+
* `agent_id`.
|
|
5496
|
+
*/
|
|
5497
|
+
publishAgentStatus: (snapshot: unknown) => void;
|
|
3742
5498
|
}
|
|
3743
5499
|
declare function startDashboardServer(options: DashboardServerOptions): Promise<DashboardHandle>;
|
|
3744
5500
|
|
|
@@ -3835,4 +5591,4 @@ declare function createSanctuaryServer(options?: {
|
|
|
3835
5591
|
storage?: StorageBackend;
|
|
3836
5592
|
}): Promise<SanctuaryServer>;
|
|
3837
5593
|
|
|
3838
|
-
export { ATTESTATION_VERSION, type ActivityEntry, type AggregatorSources, ApprovalGate, type ApprovalHandlers, type AttestationBody, type AttestationVerificationResult, AuditLog, AutoApproveChannel, BaselineTracker, type BridgeAttestationRequest, type BridgeAttestationResult, type BridgeCommitment, type BridgeVerificationResult, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, ClientManager, CommitmentStore, type ConcordiaOutcome, type ConnectionState, type ContextAction, type ContextFilterResult, ContextGateEnforcer, type ContextGatePolicy, ContextGatePolicyStore, type ContextGateRule, type ContextGateTemplate, DashboardApprovalChannel, type DashboardConfig, type DashboardHandle, type DashboardServerOptions, type DetectionResult, type EnforcerConfig, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, HERO_COPY, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, type L1Status, type L2Status, type L3Status, type L4Status, MODEL_PRESETS, MemoryStorage, type ModelProvenance, type ModelProvenanceStore, type PedersenCommitment, type PeerTrustEvaluation, type PendingApproval, type PolicyRecommendation, PolicyStore, type PrincipalPolicy, type ProtectionSnapshot, type ProviderCategory, ProxyRouter, type ProxyRouterOptions, type ReputationLookup, ReputationStore, type SHRBody, type SHRGeneratorOptions, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedAttestation, type SignedSHR, type SovereigntyProfile, SovereigntyProfileStore, type SovereigntyProfileUpdate, type SovereigntyTier, type StartDashboardOptions, StateStore, StderrApprovalChannel, type StreamEvent, TIER_WEIGHTS, type TierMetadata, type TieredAttestation, type UpstreamConnection, type UpstreamServer, type UpstreamTool, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getProtectionSnapshot, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, renderDashboardHTML, resolveTier, respondToHandshake, signPayload, startDashboard, startDashboardServer, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|
|
5594
|
+
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, 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, 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 };
|