@sanctuary-framework/mcp-server 1.1.7 → 1.2.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/README.md +112 -52
- package/dist/cli.cjs +6552 -392
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +6551 -395
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +10215 -4615
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1175 -30
- package/dist/index.d.ts +1175 -30
- package/dist/index.js +7501 -1906
- package/dist/index.js.map +1 -1
- package/dist/templates/coding-assistant/commitments.json +14 -0
- package/dist/templates/coding-assistant/defaults.json +34 -0
- package/dist/templates/coding-assistant/onboarding.md +24 -0
- package/dist/templates/coding-assistant/policy.md +1 -0
- package/dist/templates/coding-assistant/template.json +23 -0
- package/dist/templates/handoff-coordinator/commitments.json +14 -0
- package/dist/templates/handoff-coordinator/defaults.json +10 -0
- package/dist/templates/handoff-coordinator/onboarding.md +23 -0
- package/dist/templates/handoff-coordinator/policy.md +1 -0
- package/dist/templates/handoff-coordinator/template.json +17 -0
- package/dist/templates/ops-runner/commitments.json +14 -0
- package/dist/templates/ops-runner/defaults.json +12 -0
- package/dist/templates/ops-runner/onboarding.md +25 -0
- package/dist/templates/ops-runner/policy.md +1 -0
- package/dist/templates/ops-runner/template.json +16 -0
- package/dist/templates/planner/commitments.json +9 -0
- package/dist/templates/planner/defaults.json +10 -0
- package/dist/templates/planner/onboarding.md +22 -0
- package/dist/templates/planner/policy.md +1 -0
- package/dist/templates/planner/template.json +8 -0
- package/dist/templates/research-assistant/commitments.json +9 -0
- package/dist/templates/research-assistant/defaults.json +25 -0
- package/dist/templates/research-assistant/onboarding.md +21 -0
- package/dist/templates/research-assistant/policy.md +1 -0
- package/dist/templates/research-assistant/template.json +8 -0
- package/package.json +9 -4
package/dist/index.d.ts
CHANGED
|
@@ -1248,6 +1248,18 @@ declare class PolicyStore {
|
|
|
1248
1248
|
private persist;
|
|
1249
1249
|
}
|
|
1250
1250
|
|
|
1251
|
+
/**
|
|
1252
|
+
* Signature scheme identifier embedded in every AuditEntry and crypto-agility-bearing surface.
|
|
1253
|
+
*
|
|
1254
|
+
* v1.0: only "ed25519-v1" is valid.
|
|
1255
|
+
* v1.x post-quantum migration: "ed25519+ml-dsa-v1" hybrid will be introduced.
|
|
1256
|
+
* v1.0 verifiers MUST reject unknown schemes; the field exists so v1.x can add
|
|
1257
|
+
* hybrid signing without breaking v1.0 readers. Do not optimize this field away.
|
|
1258
|
+
*
|
|
1259
|
+
* Spec: §5.3 (Crypto-agility per thesis §3 L1 PQ note).
|
|
1260
|
+
*/
|
|
1261
|
+
type SignatureScheme$1 = "ed25519-v1";
|
|
1262
|
+
|
|
1251
1263
|
/**
|
|
1252
1264
|
* Sanctuary MCP Server — Sovereignty Health Report (SHR) Types
|
|
1253
1265
|
*
|
|
@@ -1258,6 +1270,7 @@ declare class PolicyStore {
|
|
|
1258
1270
|
*
|
|
1259
1271
|
* SHR version: 1.0
|
|
1260
1272
|
*/
|
|
1273
|
+
|
|
1261
1274
|
type LayerStatus = "active" | "degraded" | "inactive";
|
|
1262
1275
|
type DegradationSeverity = "info" | "warning" | "critical";
|
|
1263
1276
|
type DegradationCode = "NO_TEE" | "PROCESS_ISOLATION_ONLY" | "COMMITMENT_ONLY" | "NO_ZK_PROOFS" | "SELF_REPORTED_ATTESTATION" | "NO_SELECTIVE_DISCLOSURE" | "BASIC_SYBIL_ONLY" | "NO_REPUTATION_HISTORY" | "LOW_TIER_DOMINANCE" | "STALE_REPUTATION" | "DISPUTE_ON_RECORD" | "NO_VERASCORE_LINK";
|
|
@@ -1337,6 +1350,7 @@ interface SHRBody {
|
|
|
1337
1350
|
interface SignedSHR {
|
|
1338
1351
|
body: SHRBody;
|
|
1339
1352
|
signed_by: string;
|
|
1353
|
+
signature_scheme: SignatureScheme$1;
|
|
1340
1354
|
signature: string;
|
|
1341
1355
|
}
|
|
1342
1356
|
interface SHRVerificationResult {
|
|
@@ -2925,13 +2939,13 @@ interface PrivacyRehydratedPayload extends PrivacyAuditPayloadHeader {
|
|
|
2925
2939
|
type PrivacyAuditPayload = PrivacyFilteredPayload | PrivacyAllowedPayload | PrivacyDeniedPayload | PrivacyErrorPayload | PrivacyRehydratedPayload;
|
|
2926
2940
|
|
|
2927
2941
|
/**
|
|
2928
|
-
* Sanctuary v1.1
|
|
2942
|
+
* Sanctuary v1.1 Operator Hub Event Contracts
|
|
2929
2943
|
*
|
|
2930
2944
|
* Shared shapes for the unified inbox, the activity feed, and the per-agent
|
|
2931
2945
|
* status panels. The operator hub API workstream (Prompt 5) emits these; the
|
|
2932
2946
|
* dashboard UI workstream (Prompt 8) consumes them. v1.2 mobile companion
|
|
2933
2947
|
* planning will evaluate these shapes when it scopes a phone surface, but
|
|
2934
|
-
* v1.1 does not commit to mobile compatibility
|
|
2948
|
+
* v1.1 does not commit to mobile compatibility. These contracts are
|
|
2935
2949
|
* tuned for the local dashboard surface only.
|
|
2936
2950
|
*
|
|
2937
2951
|
* Local-only invariant:
|
|
@@ -2952,7 +2966,7 @@ type PrivacyAuditPayload = PrivacyFilteredPayload | PrivacyAllowedPayload | Priv
|
|
|
2952
2966
|
* accepted; the dashboard rejects rendering on any value outside this union.
|
|
2953
2967
|
*
|
|
2954
2968
|
* The renderer treats every value as data to interpolate into a fixed
|
|
2955
|
-
* template registered under `template_id
|
|
2969
|
+
* template registered under `template_id`, never as raw content. This
|
|
2956
2970
|
* defends against secrets, query text, file paths, and client names leaking
|
|
2957
2971
|
* into inbox cards via stringly-typed display fields.
|
|
2958
2972
|
*/
|
|
@@ -2965,6 +2979,9 @@ type HubDisplayTemplateArg = {
|
|
|
2965
2979
|
} | {
|
|
2966
2980
|
kind: "policy_id";
|
|
2967
2981
|
value: string;
|
|
2982
|
+
} | {
|
|
2983
|
+
kind: "channel_template_id";
|
|
2984
|
+
value: string;
|
|
2968
2985
|
} | {
|
|
2969
2986
|
kind: "destination_category";
|
|
2970
2987
|
value: PrivacyDestinationCategory;
|
|
@@ -3012,7 +3029,7 @@ interface HubInboxItemHeader {
|
|
|
3012
3029
|
display_template_id: string;
|
|
3013
3030
|
/**
|
|
3014
3031
|
* Typed args interpolated into the template. Every value MUST be a
|
|
3015
|
-
* `HubDisplayTemplateArg` instance
|
|
3032
|
+
* `HubDisplayTemplateArg` instance, no free-form strings. Renderers
|
|
3016
3033
|
* reject any arg outside this union, which structurally blocks secret
|
|
3017
3034
|
* leakage via inbox copy.
|
|
3018
3035
|
*/
|
|
@@ -3097,7 +3114,7 @@ interface HubBudgetWarningItem extends HubInboxItemHeader {
|
|
|
3097
3114
|
used_fraction: number;
|
|
3098
3115
|
}
|
|
3099
3116
|
/**
|
|
3100
|
-
* Recovery prompt
|
|
3117
|
+
* Recovery prompt. Operator should run a recovery flow (passphrase reset,
|
|
3101
3118
|
* keychain rebind, exit drill, etc.).
|
|
3102
3119
|
*/
|
|
3103
3120
|
interface HubRecoveryPromptItem extends HubInboxItemHeader {
|
|
@@ -3143,12 +3160,32 @@ interface HubActivityFeedEntry {
|
|
|
3143
3160
|
category: "policy_decision" | "approval" | "denial" | "egress" | "privacy" | "handoff" | "lifecycle" | "config" | "other";
|
|
3144
3161
|
/**
|
|
3145
3162
|
* Display template id. Resolved by the dashboard against the activity-feed
|
|
3146
|
-
* template catalog. Backends MUST NOT emit raw summary text
|
|
3163
|
+
* template catalog. Backends MUST NOT emit raw summary text. The template
|
|
3147
3164
|
* id plus typed args is the only legitimate channel.
|
|
3148
3165
|
*/
|
|
3149
3166
|
display_template_id: string;
|
|
3150
3167
|
/** Typed args. Same constraints as `HubInboxItemHeader.display_template_args`. */
|
|
3151
3168
|
display_template_args: HubDisplayTemplateArg[];
|
|
3169
|
+
/**
|
|
3170
|
+
* Per-action attestation fragment for dashboard timeline rendering.
|
|
3171
|
+
*
|
|
3172
|
+
* Optional; absence means the row renders without a badge.
|
|
3173
|
+
*
|
|
3174
|
+
* `state` drives the `att-action` CSS class on the rendered badge.
|
|
3175
|
+
* `fragment` is a deterministic short hex string derived from the
|
|
3176
|
+
* audit-chain entry id; it gives operators a stable per-row visual hook
|
|
3177
|
+
* the same shape the Sprint Piece 2 attestation gallery shows.
|
|
3178
|
+
*
|
|
3179
|
+
* Important: the fragment is NOT a real per-event Ed25519 signature.
|
|
3180
|
+
* The audit chain itself is tamper-evident at the main-process boundary
|
|
3181
|
+
* (scope-lock §8); the fragment is the visible projection of the entry's
|
|
3182
|
+
* audit-chain identity. Real per-event signatures land post-v1.5+ in the
|
|
3183
|
+
* Crypto Agility Sprint.
|
|
3184
|
+
*/
|
|
3185
|
+
attestation?: {
|
|
3186
|
+
state: "verified" | "degraded" | "unverified" | "neutral";
|
|
3187
|
+
fragment: string;
|
|
3188
|
+
};
|
|
3152
3189
|
}
|
|
3153
3190
|
/**
|
|
3154
3191
|
* Per-agent status snapshot returned by the hub API. Mirrors the agent
|
|
@@ -3758,6 +3795,27 @@ declare class MemoryStorage implements StorageBackend {
|
|
|
3758
3795
|
* - Secure deletion overwrites file content with random bytes before unlinking
|
|
3759
3796
|
* - Directory creation uses restrictive permissions (0o700)
|
|
3760
3797
|
* - File creation uses restrictive permissions (0o600)
|
|
3798
|
+
*
|
|
3799
|
+
* Path encoding (bijective, full-sweep #41):
|
|
3800
|
+
* Distinct (namespace, key) inputs MUST produce distinct on-disk paths;
|
|
3801
|
+
* otherwise an agent that can choose namespace/key strings within a tenant
|
|
3802
|
+
* could overwrite or read another namespace by colliding on the sanitized
|
|
3803
|
+
* form (multi-tenant isolation invariant). The encoder retains the safe
|
|
3804
|
+
* set [A-Za-z0-9_.-] (so internal namespaces such as `_audit`, `_bridge`,
|
|
3805
|
+
* etc. preserve their on-disk paths verbatim) and `!`-escapes every other
|
|
3806
|
+
* character as `!XX` where XX is the upper-hex byte. The escape character
|
|
3807
|
+
* `!` itself is NOT in the safe set, so a literal `!` in input encodes as
|
|
3808
|
+
* `!21` and decoding remains unambiguous.
|
|
3809
|
+
*
|
|
3810
|
+
* Legacy fallback (forward compatibility):
|
|
3811
|
+
* Pre-fix code used `replace(/[^a-zA-Z0-9_-]/g, "_")` for namespaces and
|
|
3812
|
+
* `replace(/[^a-zA-Z0-9_.-]/g, "_")` for keys; non-bijective. read(),
|
|
3813
|
+
* exists(), and delete() try the new path first; on ENOENT they fall back
|
|
3814
|
+
* to the legacy path so existing fortresses with operator-supplied
|
|
3815
|
+
* namespaces containing non-safe characters keep working. write() always
|
|
3816
|
+
* uses the new bijective path. list() and totalSize() walk on-disk
|
|
3817
|
+
* directory names directly and cannot disambiguate legacy collision-class
|
|
3818
|
+
* pairs; they are forward-only by design.
|
|
3761
3819
|
*/
|
|
3762
3820
|
|
|
3763
3821
|
declare class FilesystemStorage implements StorageBackend {
|
|
@@ -3765,9 +3823,12 @@ declare class FilesystemStorage implements StorageBackend {
|
|
|
3765
3823
|
constructor(basePath: string);
|
|
3766
3824
|
private entryPath;
|
|
3767
3825
|
private namespacePath;
|
|
3826
|
+
private legacyEntryPath;
|
|
3768
3827
|
write(namespace: string, key: string, data: Uint8Array): Promise<void>;
|
|
3769
3828
|
read(namespace: string, key: string): Promise<Uint8Array | null>;
|
|
3829
|
+
private readAtPath;
|
|
3770
3830
|
delete(namespace: string, key: string, secureOverwrite?: boolean): Promise<boolean>;
|
|
3831
|
+
private deleteAtPath;
|
|
3771
3832
|
list(namespace: string, prefix?: string): Promise<StorageEntryMeta[]>;
|
|
3772
3833
|
exists(namespace: string, key: string): Promise<boolean>;
|
|
3773
3834
|
totalSize(): Promise<number>;
|
|
@@ -3921,6 +3982,31 @@ interface ImportExitBundleOptions {
|
|
|
3921
3982
|
sourceRecoveryKey?: string;
|
|
3922
3983
|
sourceMasterKey?: Uint8Array;
|
|
3923
3984
|
destinationSignerIdentityId?: string;
|
|
3985
|
+
/**
|
|
3986
|
+
* v1.0.2 (i) / full-sweep #54. When the destination fortress already has a
|
|
3987
|
+
* staged `public_identity` for the bundle's identity_id, activation is refused
|
|
3988
|
+
* unless the operator passes this flag. The CLI surfaces the flag as
|
|
3989
|
+
* `--force-rebind` and re-prompts Tier 1 confirmation. When `forceRebind` is
|
|
3990
|
+
* true and the rebind triggers, an `exit_bundle_force_rebind` L1 audit entry
|
|
3991
|
+
* records the explicit replacement.
|
|
3992
|
+
*/
|
|
3993
|
+
forceRebind?: boolean;
|
|
3994
|
+
/**
|
|
3995
|
+
* v1.0.2 / full-sweep #55. Reputation attestations whose signer DID is not
|
|
3996
|
+
* present in the bundle's published identity material are marked
|
|
3997
|
+
* `unverifiable` by the verifier. By default the verdict is now strict and
|
|
3998
|
+
* an unverifiable attestation fails the bundle. Setting this flag opts the
|
|
3999
|
+
* operator in to an explicit relaxed verdict (Tier 1 confirmation in CLI).
|
|
4000
|
+
*/
|
|
4001
|
+
acceptUnverifiableAttestations?: boolean;
|
|
4002
|
+
}
|
|
4003
|
+
/**
|
|
4004
|
+
* Structured error raised by `importExitBundle` for codes the CLI / hub want
|
|
4005
|
+
* to branch on without parsing free-text messages. v1.0.2 (i) / full-sweep #54.
|
|
4006
|
+
*/
|
|
4007
|
+
declare class ExitBundleImportError extends Error {
|
|
4008
|
+
readonly code: string;
|
|
4009
|
+
constructor(code: string, message: string);
|
|
3924
4010
|
}
|
|
3925
4011
|
interface ExitBundleConflictReport {
|
|
3926
4012
|
public_identity_exists: boolean;
|
|
@@ -3957,14 +4043,6 @@ declare function exportExitBundle(opts: ExportExitBundleOptions): Promise<Export
|
|
|
3957
4043
|
declare function importExitBundle(opts: ImportExitBundleOptions): Promise<ImportExitBundleResult>;
|
|
3958
4044
|
declare function exitBundleManifestShape(): Record<string, unknown>;
|
|
3959
4045
|
|
|
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
4046
|
interface ExitBundleDetailedVerifierResult extends ExitBundleVerifierResult {
|
|
3969
4047
|
manifest_path: string;
|
|
3970
4048
|
manifest_hash: string | null;
|
|
@@ -3995,7 +4073,19 @@ interface LoadedExitArtifact<T = unknown> {
|
|
|
3995
4073
|
}
|
|
3996
4074
|
declare function readManifest(bundleDir: string): Promise<ExitBundleManifest>;
|
|
3997
4075
|
declare function loadExitArtifact<T = unknown>(bundleDir: string, manifest: ExitBundleManifest, kind: ExitBundleArtifactKind): Promise<LoadedExitArtifact<T> | null>;
|
|
3998
|
-
|
|
4076
|
+
/**
|
|
4077
|
+
* Caller-supplied verifier knobs. v1.0.2 / full-sweep #55.
|
|
4078
|
+
*
|
|
4079
|
+
* `acceptUnverifiableAttestations` flips the bundle verdict from strict-by-default
|
|
4080
|
+
* (any unverifiable attestation fails the bundle) to a relaxed verdict that
|
|
4081
|
+
* tolerates attestations whose signer DID is not in the bundle's published
|
|
4082
|
+
* identity material. Operators opt in explicitly through the CLI
|
|
4083
|
+
* `--accept-unverifiable-attestations` flag (Tier 1 confirmation).
|
|
4084
|
+
*/
|
|
4085
|
+
interface VerifyExitBundleOptions {
|
|
4086
|
+
acceptUnverifiableAttestations?: boolean;
|
|
4087
|
+
}
|
|
4088
|
+
declare function verifyExitBundle(bundleDir: string, options?: VerifyExitBundleOptions): Promise<ExitBundleDetailedVerifierResult>;
|
|
3999
4089
|
|
|
4000
4090
|
/**
|
|
4001
4091
|
* `sanctuary exit` CLI.
|
|
@@ -4130,10 +4220,981 @@ type HubInboxAction = (typeof HUB_INBOX_ACTIONS)[number];
|
|
|
4130
4220
|
declare const HUB_AGENT_CONTROL_ACTIONS: readonly ["pause", "resume", "restart", "unwrap", "lockdown"];
|
|
4131
4221
|
type HubAgentControlAction = (typeof HUB_AGENT_CONTROL_ACTIONS)[number];
|
|
4132
4222
|
|
|
4133
|
-
/** Channel-template identifiers per
|
|
4134
|
-
declare const CHANNEL_TEMPLATE_IDS: readonly ["
|
|
4223
|
+
/** Channel-template identifiers per the five-template canonical starter set. */
|
|
4224
|
+
declare const CHANNEL_TEMPLATE_IDS: readonly ["request-approve-act", "read-then-report", "scheduled-digest", "plan-draft-only", "fortress-relay"];
|
|
4135
4225
|
type ChannelTemplateId = (typeof CHANNEL_TEMPLATE_IDS)[number];
|
|
4136
4226
|
|
|
4227
|
+
/**
|
|
4228
|
+
* Sanctuary MCP Server — Intelligence Substrate Selector Types
|
|
4229
|
+
*
|
|
4230
|
+
* The substrate selector lets operators pick (and re-pick) the LLM substrate
|
|
4231
|
+
* that powers Sanctuary's intelligence-layer surfaces: concierge, sentinel
|
|
4232
|
+
* scoring, gate explanation, privacy filter Tier 2, template suggestion,
|
|
4233
|
+
* direct-agent gate advisory.
|
|
4234
|
+
*
|
|
4235
|
+
* Per Erik directive 2026-04-29: the selector IS the architecture. Sanctuary's
|
|
4236
|
+
* job is to make the tradeoffs visible and let the operator choose. Multi-option
|
|
4237
|
+
* framing is preserved; no single substrate is surfaced as a winner.
|
|
4238
|
+
*
|
|
4239
|
+
* Per the position paper Intelligence_Layer_Drift_Audit_and_Substrate_Resolution_2026-04-29.md
|
|
4240
|
+
* (sections 4 + 5), four substrates ship as operator-pickable:
|
|
4241
|
+
*
|
|
4242
|
+
* - local: Ollama-hosted local model (Gemma 2 2B / Phi-4 Mini / Llama 3.1 8B)
|
|
4243
|
+
* - venice: Venice.ai privacy-respecting hosted relay
|
|
4244
|
+
* - frontier-with-filter: operator's frontier API account, Privacy Filter Tier 2 pre-egress
|
|
4245
|
+
* - hybrid: per-surface routing across the above
|
|
4246
|
+
* - disabled: surface refuses LLM calls; Tier 1 regex fallback for privacy filter
|
|
4247
|
+
*
|
|
4248
|
+
* Per-surface defaults (Erik ratification 2026-04-29):
|
|
4249
|
+
* - concierge: local (Gemma 2 2B)
|
|
4250
|
+
* - sentinel-scoring: local (rules + Phi-4 Mini on escalation)
|
|
4251
|
+
* - gate-explanation: templates v1.2; small LLM v1.3+ for custom policies
|
|
4252
|
+
* - privacy-filter-tier-2: local (NER + small LLM PII classifier)
|
|
4253
|
+
* - direct-agent-gate-advisor: same as concierge by default
|
|
4254
|
+
* - template-suggestion: same as concierge by default
|
|
4255
|
+
*/
|
|
4256
|
+
/**
|
|
4257
|
+
* The set of intelligence-layer surfaces the selector routes for.
|
|
4258
|
+
*
|
|
4259
|
+
* The enum is closed. Adding a surface requires updating the selector's
|
|
4260
|
+
* default-config builder, the audit emission shape registry, and the
|
|
4261
|
+
* transparency UI in the same PR.
|
|
4262
|
+
*/
|
|
4263
|
+
type Surface = "concierge" | "direct-agent-gate-advisor" | "sentinel-scoring" | "gate-explanation" | "privacy-filter-tier-2" | "template-suggestion";
|
|
4264
|
+
/**
|
|
4265
|
+
* The substrate choice an operator may bind to a surface.
|
|
4266
|
+
*/
|
|
4267
|
+
type SubstrateChoice = "local" | "venice" | "frontier-with-filter" | "hybrid" | "disabled";
|
|
4268
|
+
/**
|
|
4269
|
+
* Local-model picks for the Ollama-backed local substrate.
|
|
4270
|
+
*
|
|
4271
|
+
* Bundled tiers per position paper §5 hardware-tier table:
|
|
4272
|
+
* - gemma-2-2b (Baseline / 8GB RAM)
|
|
4273
|
+
* - phi-4-mini (Mid / 16GB RAM)
|
|
4274
|
+
* - llama-3.1-8b (Pro / 32GB+ RAM)
|
|
4275
|
+
*
|
|
4276
|
+
* Custom Ollama-installed models can be specified via `customModelTag` on the
|
|
4277
|
+
* substrate config; the selector probes Ollama for availability at runtime.
|
|
4278
|
+
*/
|
|
4279
|
+
type LocalModelPick = "gemma-2-2b" | "phi-4-mini" | "llama-3.1-8b";
|
|
4280
|
+
/**
|
|
4281
|
+
* Frontier providers operator may pick for the frontier-with-filter substrate.
|
|
4282
|
+
* v1.2 ships three; v1.3+ may add Mistral / xAI / Cohere.
|
|
4283
|
+
*/
|
|
4284
|
+
type FrontierProvider = "anthropic" | "openai" | "google";
|
|
4285
|
+
/**
|
|
4286
|
+
* What the selector does when its chosen substrate fails (e.g. Ollama not
|
|
4287
|
+
* running, Venice API unreachable, frontier API key revoked).
|
|
4288
|
+
*
|
|
4289
|
+
* Per surface, operator-configurable. Defaults per position paper §5:
|
|
4290
|
+
* - concierge: degrade-silent (next-tier substrate)
|
|
4291
|
+
* - sentinel-scoring: conservative-deny (refuse rather than route elsewhere)
|
|
4292
|
+
* - privacy-filter-tier-2: degrade-silent (Tier 1 regex always works)
|
|
4293
|
+
* - others: conservative-deny
|
|
4294
|
+
*/
|
|
4295
|
+
type FallbackBehavior = "conservative-deny" | "degrade-silent" | "disable-surface";
|
|
4296
|
+
/**
|
|
4297
|
+
* Per-surface routing rules for the hybrid substrate.
|
|
4298
|
+
*
|
|
4299
|
+
* v1.2 ships per-surface routing only — operator pre-binds each surface to a
|
|
4300
|
+
* concrete substrate. Per-query sensitivity classification routing is deferred
|
|
4301
|
+
* to v1.3+.
|
|
4302
|
+
*/
|
|
4303
|
+
interface HybridRoutingRules {
|
|
4304
|
+
perSurface: Record<Surface, Exclude<SubstrateChoice, "hybrid">>;
|
|
4305
|
+
}
|
|
4306
|
+
/**
|
|
4307
|
+
* Operator-readable status badge for the transparency UI and chat headers.
|
|
4308
|
+
*
|
|
4309
|
+
* Backends emit a stable shape (no free-form prose); the dashboard's template
|
|
4310
|
+
* registry renders it. This mirrors the v1.1 hub `HubDisplayTemplateArg`
|
|
4311
|
+
* discipline so secret-leakage into operator-facing copy stays structurally
|
|
4312
|
+
* impossible.
|
|
4313
|
+
*/
|
|
4314
|
+
interface SubstrateBadge {
|
|
4315
|
+
surface: Surface;
|
|
4316
|
+
substrate: SubstrateChoice;
|
|
4317
|
+
/** Stable badge label key resolved by dashboard template registry. */
|
|
4318
|
+
labelKey: string;
|
|
4319
|
+
/** Stable tradeoff body key resolved by dashboard template registry. */
|
|
4320
|
+
tradeoffKey: string;
|
|
4321
|
+
/** Stable status; green = working; yellow = degraded; red = disabled / failing. */
|
|
4322
|
+
status: "green" | "yellow" | "red";
|
|
4323
|
+
}
|
|
4324
|
+
/**
|
|
4325
|
+
* Frontier provider configs. Operator's API key per provider is stored
|
|
4326
|
+
* encrypted; never leaves the fortress except as outbound HTTPS to the
|
|
4327
|
+
* provider after Privacy Filter Tier 2 redaction.
|
|
4328
|
+
*/
|
|
4329
|
+
interface FrontierProviderConfig {
|
|
4330
|
+
/** Operator's per-provider API key (encrypted at rest). */
|
|
4331
|
+
anthropic?: string;
|
|
4332
|
+
openai?: string;
|
|
4333
|
+
google?: string;
|
|
4334
|
+
}
|
|
4335
|
+
/**
|
|
4336
|
+
* Operator-overridable substrate config. Persisted encrypted under the
|
|
4337
|
+
* fortress master key in storage namespace `_intelligence`.
|
|
4338
|
+
*
|
|
4339
|
+
* v1.0 of this shape (`version: 1`) is the only shape this PR ships. Future
|
|
4340
|
+
* v1.x extensions (per-query sensitivity classifier, MLX runtime pick,
|
|
4341
|
+
* per-patron substrate scoping) MUST bump this version and provide a
|
|
4342
|
+
* forward-compat migration in the selector.
|
|
4343
|
+
*/
|
|
4344
|
+
interface SubstrateConfig {
|
|
4345
|
+
version: 1;
|
|
4346
|
+
/** Operator's per-surface choice. Defaults from position paper §5. */
|
|
4347
|
+
perSurface: Record<Surface, SubstrateChoice>;
|
|
4348
|
+
/** Operator's local-model picks per surface, when 'local' is chosen. */
|
|
4349
|
+
localModelPicks: Partial<Record<Surface, LocalModelPick>>;
|
|
4350
|
+
/** Custom Ollama model tag override per surface (overrides localModelPicks if set). */
|
|
4351
|
+
customLocalModelTags?: Partial<Record<Surface, string>>;
|
|
4352
|
+
/** Ollama HTTP endpoint; defaults to http://localhost:11434. */
|
|
4353
|
+
ollamaEndpoint?: string;
|
|
4354
|
+
/** Venice API key, if 'venice' chosen for any surface. Encrypted at rest. */
|
|
4355
|
+
veniceApiKey?: string;
|
|
4356
|
+
/** Venice model selection; defaults to llama-3.1-70b. */
|
|
4357
|
+
veniceModel?: string;
|
|
4358
|
+
/** Frontier provider configs, if 'frontier-with-filter' chosen. */
|
|
4359
|
+
frontierConfig: FrontierProviderConfig;
|
|
4360
|
+
/** Hybrid routing rules, if 'hybrid' chosen for any surface. */
|
|
4361
|
+
hybridRules?: HybridRoutingRules;
|
|
4362
|
+
/** Fallback behavior per surface. */
|
|
4363
|
+
fallback: Record<Surface, FallbackBehavior>;
|
|
4364
|
+
/**
|
|
4365
|
+
* Operator preference for the picker modal: when true, picking a
|
|
4366
|
+
* substrate + key for any one surface fans out to every surface in one
|
|
4367
|
+
* save (Finding SS, v1.2.0-rc.1). Defaults to true; operators wanting
|
|
4368
|
+
* per-surface granularity flip the picker toggle off and the next
|
|
4369
|
+
* single-surface choice persists this back to false.
|
|
4370
|
+
*/
|
|
4371
|
+
applyToAllSurfaces?: boolean;
|
|
4372
|
+
/** ISO8601 timestamp of last operator change. */
|
|
4373
|
+
updatedAt: string;
|
|
4374
|
+
}
|
|
4375
|
+
interface SummarizeRequest {
|
|
4376
|
+
kind: "summarize";
|
|
4377
|
+
context: string;
|
|
4378
|
+
query: string;
|
|
4379
|
+
maxTokens?: number;
|
|
4380
|
+
}
|
|
4381
|
+
interface ClassifyRequest {
|
|
4382
|
+
kind: "classify";
|
|
4383
|
+
items: string[];
|
|
4384
|
+
categories: string[];
|
|
4385
|
+
maxTokens?: number;
|
|
4386
|
+
}
|
|
4387
|
+
interface RedactRequest {
|
|
4388
|
+
kind: "redact";
|
|
4389
|
+
text: string;
|
|
4390
|
+
}
|
|
4391
|
+
/**
|
|
4392
|
+
* Per-substrate response envelope. Substrate clients return content + telemetry;
|
|
4393
|
+
* audit-emission and badge-rendering happen at the selector layer.
|
|
4394
|
+
*/
|
|
4395
|
+
interface SubstrateResponse {
|
|
4396
|
+
/** The substrate that actually served this invocation (may differ from chosen if fallback fired). */
|
|
4397
|
+
servedBy: SubstrateChoice;
|
|
4398
|
+
/** Stable failure-class enum on failure; null on success. */
|
|
4399
|
+
failureClass: SubstrateFailureClass | null;
|
|
4400
|
+
/** Body shape varies by request kind. */
|
|
4401
|
+
body: {
|
|
4402
|
+
kind: "summarize";
|
|
4403
|
+
text: string;
|
|
4404
|
+
} | {
|
|
4405
|
+
kind: "classify";
|
|
4406
|
+
results: {
|
|
4407
|
+
category: string;
|
|
4408
|
+
confidence: number;
|
|
4409
|
+
}[];
|
|
4410
|
+
} | {
|
|
4411
|
+
kind: "redact";
|
|
4412
|
+
redacted: string;
|
|
4413
|
+
placeholders: Record<string, string>;
|
|
4414
|
+
} | {
|
|
4415
|
+
kind: "failure";
|
|
4416
|
+
message: string;
|
|
4417
|
+
};
|
|
4418
|
+
/** ISO8601 of when invocation completed. */
|
|
4419
|
+
completedAt: string;
|
|
4420
|
+
/** Total wall-clock latency in ms. */
|
|
4421
|
+
latencyMs: number;
|
|
4422
|
+
}
|
|
4423
|
+
/**
|
|
4424
|
+
* Stable failure-class enum. Backends return one of these when a substrate
|
|
4425
|
+
* invocation fails; the selector's audit emission carries this verbatim.
|
|
4426
|
+
*
|
|
4427
|
+
* Adding a new failure class requires updating the audit-event consumer and
|
|
4428
|
+
* the dashboard status-mapping in the same PR.
|
|
4429
|
+
*/
|
|
4430
|
+
type SubstrateFailureClass = "substrate_unavailable" | "substrate_misconfigured" | "substrate_rate_limited" | "substrate_auth_failed" | "substrate_timeout" | "substrate_capability_unsupported" | "substrate_disabled" | "internal_error";
|
|
4431
|
+
/**
|
|
4432
|
+
* Capability profile for each substrate. Surfaces consult this before
|
|
4433
|
+
* invoking; if the substrate cannot serve the request kind, the selector
|
|
4434
|
+
* applies the fallback policy.
|
|
4435
|
+
*/
|
|
4436
|
+
interface SubstrateCapability {
|
|
4437
|
+
summarize: boolean;
|
|
4438
|
+
classify: boolean;
|
|
4439
|
+
redact: boolean;
|
|
4440
|
+
}
|
|
4441
|
+
/**
|
|
4442
|
+
* The handle a surface holds after `selector.getSubstrate(surface)`. The
|
|
4443
|
+
* surface invokes via the typed methods; the substrate client implements them.
|
|
4444
|
+
*
|
|
4445
|
+
* Surfaces MUST treat any thrown error as a `substrate_unavailable` failure;
|
|
4446
|
+
* the selector's invoke wrapper catches and emits the audit event.
|
|
4447
|
+
*/
|
|
4448
|
+
interface SubstrateHandle {
|
|
4449
|
+
surface: Surface;
|
|
4450
|
+
substrate: SubstrateChoice;
|
|
4451
|
+
badge: SubstrateBadge;
|
|
4452
|
+
capability: SubstrateCapability;
|
|
4453
|
+
/**
|
|
4454
|
+
* Optional operator-readable display string for the chat / dashboard headers.
|
|
4455
|
+
* Resolved from the badge labelKey; produced by the selector at handle issue,
|
|
4456
|
+
* not by the substrate client.
|
|
4457
|
+
*/
|
|
4458
|
+
displayLabel: string;
|
|
4459
|
+
summarize?: (req: SummarizeRequest) => Promise<SubstrateResponse>;
|
|
4460
|
+
classify?: (req: ClassifyRequest) => Promise<SubstrateResponse>;
|
|
4461
|
+
redact?: (req: RedactRequest) => Promise<SubstrateResponse>;
|
|
4462
|
+
}
|
|
4463
|
+
/**
|
|
4464
|
+
* Operator-visible per-surface status report rendered by the transparency UI.
|
|
4465
|
+
*
|
|
4466
|
+
* The dashboard SPA consumes this via the `/api/hub/intelligence/status`
|
|
4467
|
+
* route; the picker modal consumes it before substrate selection to surface
|
|
4468
|
+
* hardware-capability hints.
|
|
4469
|
+
*/
|
|
4470
|
+
interface SubstrateStatusReport {
|
|
4471
|
+
version: "1.2";
|
|
4472
|
+
generatedAt: string;
|
|
4473
|
+
surfaces: SurfaceStatus[];
|
|
4474
|
+
hardware: HardwareCapabilityReport;
|
|
4475
|
+
}
|
|
4476
|
+
interface SurfaceStatus {
|
|
4477
|
+
surface: Surface;
|
|
4478
|
+
chosen: SubstrateChoice;
|
|
4479
|
+
badge: SubstrateBadge;
|
|
4480
|
+
/** Substrate-side health probe result. */
|
|
4481
|
+
health: "ok" | "degraded" | "unavailable";
|
|
4482
|
+
/** Stable failure class when health != "ok"; null when "ok". */
|
|
4483
|
+
failureClass: SubstrateFailureClass | null;
|
|
4484
|
+
/**
|
|
4485
|
+
* Recent runtime + validation failures for this surface, capped at 5
|
|
4486
|
+
* entries and time-windowed to 24 hours. Sourced from real chat-call
|
|
4487
|
+
* outcomes (and validateKey results for substrates that expose it),
|
|
4488
|
+
* NOT from the static probe-time misconfig check.
|
|
4489
|
+
*
|
|
4490
|
+
* Per Finding VV (v1.2.0-rc.1): the operator-visible badge degrades to
|
|
4491
|
+
* "yellow" / "degraded" whenever this array is non-empty even if the
|
|
4492
|
+
* static probe still says ok. This closes the truth-telling gap where
|
|
4493
|
+
* the dashboard reported all surfaces healthy after the runtime chat
|
|
4494
|
+
* had already failed against the same substrate.
|
|
4495
|
+
*/
|
|
4496
|
+
recentFailures: RecentFailureEntry[];
|
|
4497
|
+
}
|
|
4498
|
+
/**
|
|
4499
|
+
* One observed substrate failure surfaced via `/api/hub/intelligence/status`.
|
|
4500
|
+
* Carries enough metadata for the operator to triage (when, what failure
|
|
4501
|
+
* class, brief operator-safe snippet) without leaking request bodies,
|
|
4502
|
+
* response bodies, or operator credentials.
|
|
4503
|
+
*
|
|
4504
|
+
* Snippets are bounded human-readable strings (e.g. "venice configured
|
|
4505
|
+
* model not found") drawn from the substrate failure-message field; the
|
|
4506
|
+
* selector strips anything resembling an API key or PII before retention.
|
|
4507
|
+
* Operators wanting full forensic detail consult the L2 audit log; this
|
|
4508
|
+
* surface is the at-a-glance triage path.
|
|
4509
|
+
*/
|
|
4510
|
+
interface RecentFailureEntry {
|
|
4511
|
+
/** ISO8601 timestamp of when the failure was observed. */
|
|
4512
|
+
ts: string;
|
|
4513
|
+
/** Stable failure-class enum carried verbatim from the substrate response. */
|
|
4514
|
+
failureClass: SubstrateFailureClass;
|
|
4515
|
+
/** Bounded operator-safe snippet describing the failure. */
|
|
4516
|
+
snippet: string;
|
|
4517
|
+
}
|
|
4518
|
+
interface HardwareCapabilityReport {
|
|
4519
|
+
/** Detected total RAM in GB. Self-reported via os.totalmem(). */
|
|
4520
|
+
totalRamGb: number;
|
|
4521
|
+
/** Apple Silicon family if detectable, or "other". */
|
|
4522
|
+
cpuArch: "apple-silicon-m1" | "apple-silicon-m2" | "apple-silicon-m3" | "apple-silicon-m4" | "apple-silicon-other" | "x86_64" | "other";
|
|
4523
|
+
/** Computed tier per position paper §5 (baseline / mid / pro / below-baseline). */
|
|
4524
|
+
tier: "below-baseline" | "baseline" | "mid" | "pro";
|
|
4525
|
+
/** Recommended local model tier per detected hardware. */
|
|
4526
|
+
recommendedLocalModel: LocalModelPick | null;
|
|
4527
|
+
/** Whether Ollama is reachable at the configured endpoint. */
|
|
4528
|
+
ollamaReachable: boolean;
|
|
4529
|
+
/** Models present in Ollama at the time of the report. Empty if not reachable. */
|
|
4530
|
+
ollamaModels: string[];
|
|
4531
|
+
}
|
|
4532
|
+
|
|
4533
|
+
/**
|
|
4534
|
+
* Sanctuary MCP Server — Frontier-with-Filter Substrate
|
|
4535
|
+
*
|
|
4536
|
+
* Operator's frontier API account (Anthropic / OpenAI / Google) wrapped with
|
|
4537
|
+
* mandatory pre-egress Privacy Filter Tier 2 redaction.
|
|
4538
|
+
*
|
|
4539
|
+
* Per position paper §5: every query routes through Privacy Filter Tier 2
|
|
4540
|
+
* BEFORE the frontier API call. The Privacy Filter event log captures the
|
|
4541
|
+
* pre-redaction match count so the operator can audit what was sent.
|
|
4542
|
+
*
|
|
4543
|
+
* Honesty discipline (CLAUDE.md):
|
|
4544
|
+
* - Tradeoff badge text explicitly names the leakage
|
|
4545
|
+
* - Required caveat about subtle PII (paraphrased addresses, contextual
|
|
4546
|
+
* identifiers) appears in tradeoff text
|
|
4547
|
+
* - Operator MUST acknowledge before configuration completes (enforced
|
|
4548
|
+
* by the picker modal in the dashboard SPA, deferred to the v1.2 UI
|
|
4549
|
+
* follow-up commit)
|
|
4550
|
+
*
|
|
4551
|
+
* Provider clients are kept minimal: one Chat Completions / Messages call
|
|
4552
|
+
* per surface request, no streaming in v1.2 (streaming is a v1.3 chat
|
|
4553
|
+
* surface enhancement).
|
|
4554
|
+
*/
|
|
4555
|
+
|
|
4556
|
+
/**
|
|
4557
|
+
* Pre-egress redaction hook. The substrate adapter calls this on every
|
|
4558
|
+
* outbound text; returns the redacted text + placeholder map. The Privacy
|
|
4559
|
+
* Filter Tier 2 implementation lives in `l2-operational/privacy-filter.ts`
|
|
4560
|
+
* (extended in this PR to wire the substrate-aware Tier 2 path).
|
|
4561
|
+
*
|
|
4562
|
+
* For v1.2, the redactor passed in is responsible for emitting the audit
|
|
4563
|
+
* event `intelligence_pii_redaction_event` via the selector's auditLog
|
|
4564
|
+
* binding. The frontier substrate is provider-agnostic about how redaction
|
|
4565
|
+
* happens; it just refuses to call the frontier API on `failureClass !== null`.
|
|
4566
|
+
*/
|
|
4567
|
+
type FrontierRedactor = (text: string) => Promise<{
|
|
4568
|
+
redacted: string;
|
|
4569
|
+
matchCount: number;
|
|
4570
|
+
}>;
|
|
4571
|
+
|
|
4572
|
+
/**
|
|
4573
|
+
* Sanctuary MCP Server — Intelligence Substrate Selector
|
|
4574
|
+
*
|
|
4575
|
+
* The selector IS the architecture (Erik directive 2026-04-29). Operators
|
|
4576
|
+
* pick (and re-pick) the LLM substrate that powers each intelligence-layer
|
|
4577
|
+
* surface; the selector binds choices to surfaces, provides a typed
|
|
4578
|
+
* `SubstrateHandle` to consumers, applies operator-configured fallback
|
|
4579
|
+
* behavior on substrate failure, and emits audit events for every change
|
|
4580
|
+
* and every invocation.
|
|
4581
|
+
*
|
|
4582
|
+
* Architecture per position paper section 5:
|
|
4583
|
+
* ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
4584
|
+
* │ concierge│ │ sentinel │ │ gate-expl│ │ priv-f-2 │ ... surfaces
|
|
4585
|
+
* └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
4586
|
+
* ▼ ▼ ▼ ▼
|
|
4587
|
+
* ┌──────────────────────────────────────────────────┐
|
|
4588
|
+
* │ SubstrateSelector (per-surface routing) │
|
|
4589
|
+
* └────┬──────────┬──────────┬──────────┬────────────┘
|
|
4590
|
+
* ▼ ▼ ▼ ▼
|
|
4591
|
+
* ┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
4592
|
+
* │ Local │ │ Venice │ │ Frontier │ │ Disabled │
|
|
4593
|
+
* │(Ollama)│ │ (relay) │ │ + filter │ │ (refuse) │
|
|
4594
|
+
* └────────┘ └──────────┘ └──────────┘ └──────────┘
|
|
4595
|
+
*
|
|
4596
|
+
* The hybrid substrate is per-surface routing only at v1.2 — operator
|
|
4597
|
+
* pre-binds each surface to a concrete substrate; per-query sensitivity
|
|
4598
|
+
* classification routing is deferred to v1.3+.
|
|
4599
|
+
*
|
|
4600
|
+
* Audit emission discipline:
|
|
4601
|
+
* Every public method that changes config or invokes a substrate appends
|
|
4602
|
+
* an `IntelligenceAuditPayload` to the L2 audit log. The selector never
|
|
4603
|
+
* stores raw request bodies, response bodies, or operator credentials in
|
|
4604
|
+
* audit details; only safe metadata (surface, substrate, hashes, latency,
|
|
4605
|
+
* failure-class enum). The event payload contracts live in
|
|
4606
|
+
* `contracts/v1.2/intelligence-events.ts`.
|
|
4607
|
+
*
|
|
4608
|
+
* Sovereignty invariants preserved:
|
|
4609
|
+
* - Operator API keys live in the encrypted SubstrateConfig persisted
|
|
4610
|
+
* under the fortress master key.
|
|
4611
|
+
* - Frontier-with-filter substrate ALWAYS routes through a redactor
|
|
4612
|
+
* before any frontier API call; the redactor argument is required in
|
|
4613
|
+
* the constructor; passing a null redactor disables the substrate.
|
|
4614
|
+
* - Sentinel-scoring surface defaults to `conservative-deny` fallback so
|
|
4615
|
+
* substrate failure cannot silently allow an unverified tool call.
|
|
4616
|
+
*/
|
|
4617
|
+
|
|
4618
|
+
/**
|
|
4619
|
+
* Configuration the selector needs at construction. The audit-log binding
|
|
4620
|
+
* is required: a selector without an audit log violates the audit-emission
|
|
4621
|
+
* invariant and is structurally rejected.
|
|
4622
|
+
*/
|
|
4623
|
+
interface SelectorConfig {
|
|
4624
|
+
storage: StorageBackend;
|
|
4625
|
+
masterKey: Uint8Array;
|
|
4626
|
+
auditLog: AuditLog;
|
|
4627
|
+
/** Identity that owns the substrate config. Stamped on every audit event. */
|
|
4628
|
+
identityId: string;
|
|
4629
|
+
/**
|
|
4630
|
+
* Pre-egress redactor for the frontier-with-filter substrate. Defaults
|
|
4631
|
+
* to `IDENTITY_REDACTOR` until Privacy Filter Tier 2 wires through.
|
|
4632
|
+
* Passing a custom redactor at construction allows tests + the Tier 2
|
|
4633
|
+
* commit to install a real implementation without modifying the
|
|
4634
|
+
* selector.
|
|
4635
|
+
*/
|
|
4636
|
+
redactor?: FrontierRedactor;
|
|
4637
|
+
/**
|
|
4638
|
+
* Optional fetch override for substrate clients. Forwarded to Ollama,
|
|
4639
|
+
* Venice, and frontier client constructors so tests can stub out
|
|
4640
|
+
* network calls.
|
|
4641
|
+
*/
|
|
4642
|
+
fetchImpl?: typeof fetch;
|
|
4643
|
+
}
|
|
4644
|
+
declare class SubstrateSelector {
|
|
4645
|
+
private store;
|
|
4646
|
+
private auditLog;
|
|
4647
|
+
private identityId;
|
|
4648
|
+
private redactor;
|
|
4649
|
+
private fetchImpl;
|
|
4650
|
+
private config;
|
|
4651
|
+
private loaded;
|
|
4652
|
+
/**
|
|
4653
|
+
* Per-surface ring buffer of recent runtime + validation failures. See
|
|
4654
|
+
* `RECENT_FAILURES_CAP` and `RECENT_FAILURES_WINDOW_MS`. Populated by
|
|
4655
|
+
* `recordRecentFailure()` from the `invoke()` failure path and from the
|
|
4656
|
+
* post-config validation hook on substrates that expose validateKey.
|
|
4657
|
+
* Drives the operator-visible degrade in `getOperatorVisibleStatus()`.
|
|
4658
|
+
*/
|
|
4659
|
+
private recentFailures;
|
|
4660
|
+
constructor(cfg: SelectorConfig);
|
|
4661
|
+
/**
|
|
4662
|
+
* Load (or initialize) the operator's substrate config. Emits the
|
|
4663
|
+
* `intelligence_config_loaded` audit event regardless of branch so the
|
|
4664
|
+
* audit chain shows config-load activity on boot.
|
|
4665
|
+
*/
|
|
4666
|
+
load(): Promise<void>;
|
|
4667
|
+
/**
|
|
4668
|
+
* Operator picked (or re-picked) a substrate for a surface. Persists the
|
|
4669
|
+
* change and emits `intelligence_substrate_chosen`. The picker modal
|
|
4670
|
+
* surfaces the tradeoff text BEFORE invoking this method; the audit
|
|
4671
|
+
* payload captures the hash of that text for auditor verification.
|
|
4672
|
+
*/
|
|
4673
|
+
setPerSurfaceChoice(surface: Surface, substrate: SubstrateChoice): Promise<void>;
|
|
4674
|
+
/**
|
|
4675
|
+
* Apply a substrate choice to every surface in one save. Used by the
|
|
4676
|
+
* picker modal's "Apply to all surfaces" affordance (Finding SS,
|
|
4677
|
+
* v1.2.0-rc.1). Persists the per-surface map mutation in a single
|
|
4678
|
+
* write and emits ONE `intelligence_bulk_substrate_chosen` audit
|
|
4679
|
+
* event rather than six per-surface events.
|
|
4680
|
+
*
|
|
4681
|
+
* If `localModelPick` is provided AND substrate === "local", the same
|
|
4682
|
+
* pick is applied to every surface; ignored for other substrates.
|
|
4683
|
+
*
|
|
4684
|
+
* Per-surface bindings the operator had previously customized are
|
|
4685
|
+
* captured in the audit payload's `prior_substrates` map so the
|
|
4686
|
+
* forensic record makes the configuration discontinuity visible.
|
|
4687
|
+
*/
|
|
4688
|
+
applyChoiceToAllSurfaces(substrate: SubstrateChoice, opts?: {
|
|
4689
|
+
localModelPick?: LocalModelPick | null;
|
|
4690
|
+
}): Promise<void>;
|
|
4691
|
+
/**
|
|
4692
|
+
* Persist the operator's "Apply to all surfaces" preference. The
|
|
4693
|
+
* picker modal calls this when the operator flips the toggle so the
|
|
4694
|
+
* preference survives a dashboard reload. Does not emit a discrete
|
|
4695
|
+
* audit event; the next bulk or per-surface choice carries the
|
|
4696
|
+
* operator-visible signal.
|
|
4697
|
+
*/
|
|
4698
|
+
setApplyToAllPreference(value: boolean): Promise<void>;
|
|
4699
|
+
/**
|
|
4700
|
+
* Operator picked a local model for a surface bound to the local
|
|
4701
|
+
* substrate. Mirrors `setPerSurfaceChoice` for the model-picker case.
|
|
4702
|
+
* Does not emit a separate audit event class; the next
|
|
4703
|
+
* `intelligence_substrate_chosen` event captures the change and the
|
|
4704
|
+
* dashboard transparency UI calls this method only as part of a binding
|
|
4705
|
+
* flow that already audited the substrate choice.
|
|
4706
|
+
*/
|
|
4707
|
+
setLocalModelPick(surface: Surface, pick: LocalModelPick | null): Promise<void>;
|
|
4708
|
+
/**
|
|
4709
|
+
* Set the Venice API key. Stored as part of the encrypted
|
|
4710
|
+
* SubstrateConfig record. Does not emit a substrate_chosen event by
|
|
4711
|
+
* itself; the dashboard flow always pairs key entry with a substrate
|
|
4712
|
+
* choice and the choice carries the audit semantics.
|
|
4713
|
+
*
|
|
4714
|
+
* Post-set validation (Finding VV, v1.2.0-rc.1): if a non-null key is
|
|
4715
|
+
* provided, the selector probes Venice with `validateKey()` and records
|
|
4716
|
+
* a failure entry on every Venice-bound surface when the result is not
|
|
4717
|
+
* `"ok"`. This lets the operator-visible status degrade from validation
|
|
4718
|
+
* outcomes alone, not just from runtime chat-call failures, so a broken
|
|
4719
|
+
* key or drifted model is visible before the operator's first chat
|
|
4720
|
+
* attempt. Probe failures (timeout, transport) are not recorded; the
|
|
4721
|
+
* runtime path will surface those when the operator actually invokes.
|
|
4722
|
+
*/
|
|
4723
|
+
setVeniceApiKey(apiKey: string | null): Promise<void>;
|
|
4724
|
+
/**
|
|
4725
|
+
* Probe Venice with the given API key and record a failure entry on
|
|
4726
|
+
* every surface bound to Venice when the probe returns anything other
|
|
4727
|
+
* than `"ok"`. Failures map to stable substrate failure-class enum
|
|
4728
|
+
* values: `invalid-key` -> `substrate_auth_failed`, `invalid-model` ->
|
|
4729
|
+
* `substrate_misconfigured`, `unreachable` -> swallow (runtime path
|
|
4730
|
+
* will surface).
|
|
4731
|
+
*/
|
|
4732
|
+
private validateVeniceAndRecord;
|
|
4733
|
+
/**
|
|
4734
|
+
* Set a frontier provider's API key. See `setVeniceApiKey` for the
|
|
4735
|
+
* audit-semantics rationale.
|
|
4736
|
+
*/
|
|
4737
|
+
setFrontierApiKey(provider: FrontierProvider, apiKey: string | null): Promise<void>;
|
|
4738
|
+
/**
|
|
4739
|
+
* Set the hybrid routing rules. The picker modal calls this when the
|
|
4740
|
+
* operator saves the hybrid configuration tab. Validates the rules
|
|
4741
|
+
* (every surface bound, no `hybrid` recursion) before persist; throws
|
|
4742
|
+
* on invalid input so the operator-facing form can surface the failure.
|
|
4743
|
+
*
|
|
4744
|
+
* Setting rules does NOT change any surface's per-surface choice; the
|
|
4745
|
+
* operator must also pick `hybrid` for the surfaces they want routed
|
|
4746
|
+
* through these rules. This separation keeps the flow obvious in the
|
|
4747
|
+
* UI (set rules + then choose hybrid for each surface that should use
|
|
4748
|
+
* them) and lets the operator test rule changes without mass-flipping
|
|
4749
|
+
* surfaces to hybrid.
|
|
4750
|
+
*/
|
|
4751
|
+
setHybridRules(rules: HybridRoutingRules): Promise<void>;
|
|
4752
|
+
/**
|
|
4753
|
+
* Override the per-surface fallback behavior. Defaults are set per
|
|
4754
|
+
* position paper section 5; the picker modal surfaces the tradeoff and
|
|
4755
|
+
* the operator can override.
|
|
4756
|
+
*/
|
|
4757
|
+
setFallbackBehavior(surface: Surface, fallback: FallbackBehavior): Promise<void>;
|
|
4758
|
+
/**
|
|
4759
|
+
* Reset every binding to the per-surface defaults. Emits
|
|
4760
|
+
* `intelligence_config_reset` so post-reset audit trails make the
|
|
4761
|
+
* configuration discontinuity visible.
|
|
4762
|
+
*/
|
|
4763
|
+
resetToDefaults(): Promise<void>;
|
|
4764
|
+
/**
|
|
4765
|
+
* Snapshot the current config (read-only). Tests + the dashboard
|
|
4766
|
+
* transparency UI consume this; mutations always go through the
|
|
4767
|
+
* setter methods so audit-emission stays consistent.
|
|
4768
|
+
*/
|
|
4769
|
+
getConfig(): SubstrateConfig;
|
|
4770
|
+
/**
|
|
4771
|
+
* Install (or replace) the redactor used by the frontier-with-filter
|
|
4772
|
+
* substrate. Bootstrap code calls this after constructing the selector
|
|
4773
|
+
* with the default IDENTITY_REDACTOR; the Privacy Filter Tier 2
|
|
4774
|
+
* commit's `buildPrivacyTier2Redactor` produces the redactor that
|
|
4775
|
+
* closes over the selector for audit emission. Late-binding via this
|
|
4776
|
+
* method avoids the circular construction dependency
|
|
4777
|
+
* (selector needs redactor; redactor needs selector for emit).
|
|
4778
|
+
*
|
|
4779
|
+
* Subsequent calls to getSubstrate("...frontier-with-filter") will use
|
|
4780
|
+
* the installed redactor; already-issued handles continue to use the
|
|
4781
|
+
* redactor that was installed at handle-issue time. Consumers that
|
|
4782
|
+
* cache handles SHOULD re-issue after installRedactor.
|
|
4783
|
+
*/
|
|
4784
|
+
installRedactor(redactor: FrontierRedactor): void;
|
|
4785
|
+
/**
|
|
4786
|
+
* Build a typed SubstrateHandle for the given surface. Lazily
|
|
4787
|
+
* instantiates the substrate client based on the operator's binding;
|
|
4788
|
+
* the handle carries the substrate label, tradeoff badge, capability
|
|
4789
|
+
* surface, and bound `summarize` / `classify` / `redact` methods that
|
|
4790
|
+
* delegate to the substrate client.
|
|
4791
|
+
*
|
|
4792
|
+
* For the `disabled` substrate, the returned handle has the capability
|
|
4793
|
+
* surface zeroed and no methods bound; consumers checking
|
|
4794
|
+
* `handle.capability.summarize === false` short-circuit to the
|
|
4795
|
+
* surface's static fallback (templates for gate-explanation, Tier 1
|
|
4796
|
+
* regex for privacy-filter-tier-2, etc.).
|
|
4797
|
+
*
|
|
4798
|
+
* For the `hybrid` substrate, this method delegates to the per-surface
|
|
4799
|
+
* routing rules (set via `setPerSurfaceChoice` on a substrate other
|
|
4800
|
+
* than `hybrid`); v1.2 ships per-surface routing only.
|
|
4801
|
+
*/
|
|
4802
|
+
getSubstrate(surface: Surface): Promise<SubstrateHandle>;
|
|
4803
|
+
/**
|
|
4804
|
+
* Operator-visible per-surface status report. Consumers: the dashboard
|
|
4805
|
+
* transparency UI and the `/api/hub/intelligence/status` route.
|
|
4806
|
+
*
|
|
4807
|
+
* Probes hardware + Ollama at call time. The dashboard re-fetches every
|
|
4808
|
+
* 5 minutes to refresh status badges (degraded -> ok flip when Ollama
|
|
4809
|
+
* comes back up, and so on).
|
|
4810
|
+
*/
|
|
4811
|
+
getOperatorVisibleStatus(): Promise<SubstrateStatusReport>;
|
|
4812
|
+
/**
|
|
4813
|
+
* Probe the host machine's hardware capability. v1.2 reports total RAM
|
|
4814
|
+
* + CPU arch (Apple Silicon family if detectable) and computes the tier
|
|
4815
|
+
* per position paper section 5. Used by the picker modal to surface
|
|
4816
|
+
* "below-baseline -> recommend Venice" guidance.
|
|
4817
|
+
*/
|
|
4818
|
+
probeHardware(): Promise<HardwareCapabilityReport>;
|
|
4819
|
+
/**
|
|
4820
|
+
* Invoke a substrate with audit emission. Wraps the underlying
|
|
4821
|
+
* SubstrateHandle method, applies fallback behavior on failure per the
|
|
4822
|
+
* operator's per-surface config, and emits `intelligence_substrate_invoked`
|
|
4823
|
+
* + (on failure) `intelligence_substrate_failure`.
|
|
4824
|
+
*
|
|
4825
|
+
* Consumers SHOULD call this method rather than calling `handle.summarize`
|
|
4826
|
+
* etc. directly; the handle is exposed for cases where audit emission
|
|
4827
|
+
* needs to be explicitly skipped (probe paths, tests).
|
|
4828
|
+
*/
|
|
4829
|
+
invokeSummarize(surface: Surface, req: SummarizeRequest): Promise<SubstrateResponse>;
|
|
4830
|
+
invokeClassify(surface: Surface, req: ClassifyRequest): Promise<SubstrateResponse>;
|
|
4831
|
+
invokeRedact(surface: Surface, req: RedactRequest): Promise<SubstrateResponse>;
|
|
4832
|
+
private ensureLoaded;
|
|
4833
|
+
private invoke;
|
|
4834
|
+
/**
|
|
4835
|
+
* Append a failure entry to the per-surface ring buffer. The selector
|
|
4836
|
+
* uses this in the `invoke()` failure path and in the post-config
|
|
4837
|
+
* `setVeniceApiKey` validation hook so the operator-visible badge
|
|
4838
|
+
* degrades from runtime AND from validation outcomes.
|
|
4839
|
+
*
|
|
4840
|
+
* Operator-safe by construction: snippets are bounded by
|
|
4841
|
+
* `FAILURE_SNIPPET_MAX_LEN` and pulled from substrate `failure.message`
|
|
4842
|
+
* fields (which substrates produce for operator-readable output and
|
|
4843
|
+
* never include API keys or PII). The cap + window prune happen on
|
|
4844
|
+
* every read in `recentFailuresFor()` so the ring buffer never grows.
|
|
4845
|
+
*/
|
|
4846
|
+
private recordRecentFailure;
|
|
4847
|
+
/**
|
|
4848
|
+
* Read recent failures for a surface, pruning entries older than the
|
|
4849
|
+
* 24-hour window. Pruning happens lazily on read so a long-quiet surface
|
|
4850
|
+
* does not retain stale entries from yesterday's debugging.
|
|
4851
|
+
*/
|
|
4852
|
+
private recentFailuresFor;
|
|
4853
|
+
/**
|
|
4854
|
+
* Test-only seam: lets selector tests assert on recorded failures
|
|
4855
|
+
* without poking the private ring buffer. Returns a defensive copy.
|
|
4856
|
+
*/
|
|
4857
|
+
getRecentFailuresForTest(surface: Surface): RecentFailureEntry[];
|
|
4858
|
+
/**
|
|
4859
|
+
* Test-only seam: lets selector tests seed a recent-failure entry on a
|
|
4860
|
+
* surface so the buffer-clear behavior added for Finding ZZ (v1.2.0-rc.2)
|
|
4861
|
+
* can be exercised without spinning up a real failing substrate. Mirrors
|
|
4862
|
+
* `getRecentFailuresForTest`; never call from production paths.
|
|
4863
|
+
*/
|
|
4864
|
+
recordRecentFailureForTest(surface: Surface, failureClass: SubstrateFailureClass, snippet: string): void;
|
|
4865
|
+
/**
|
|
4866
|
+
* Build a substrate handle for a surface bound to a concrete choice.
|
|
4867
|
+
* The substrate-client constructor is paid lazily so the selector
|
|
4868
|
+
* doesn't pre-spawn HTTP clients for substrates the operator never
|
|
4869
|
+
* touches.
|
|
4870
|
+
*/
|
|
4871
|
+
private buildHandle;
|
|
4872
|
+
private disabledHandle;
|
|
4873
|
+
private localHandle;
|
|
4874
|
+
private veniceHandle;
|
|
4875
|
+
private frontierHandle;
|
|
4876
|
+
private probeSurfaceHealth;
|
|
4877
|
+
private makeBadge;
|
|
4878
|
+
private fallbackAction;
|
|
4879
|
+
/**
|
|
4880
|
+
* Internal hook for the Privacy Filter Tier 2 commit. Lets a redactor
|
|
4881
|
+
* audit-emit a `pii_redaction_event` payload through the selector
|
|
4882
|
+
* without exposing the AuditLog binding directly to redactor
|
|
4883
|
+
* implementations.
|
|
4884
|
+
*/
|
|
4885
|
+
emitRedactionEvent(args: {
|
|
4886
|
+
surface: Surface;
|
|
4887
|
+
substrate: SubstrateChoice;
|
|
4888
|
+
matchCount: number;
|
|
4889
|
+
filterTier: 1 | 2;
|
|
4890
|
+
}): void;
|
|
4891
|
+
private emit;
|
|
4892
|
+
}
|
|
4893
|
+
|
|
4894
|
+
/**
|
|
4895
|
+
* Sanctuary MCP Server — Operator Chat Types
|
|
4896
|
+
*
|
|
4897
|
+
* Distinct from the existing agent-to-agent mesh chat (`chat-service.ts`).
|
|
4898
|
+
* Operator chat is the operator-fortress concierge surface: an operator
|
|
4899
|
+
* types into the v1.1 dashboard, Sanctuary persists the conversation,
|
|
4900
|
+
* audits every message, and routes responses through the substrate
|
|
4901
|
+
* selector.
|
|
4902
|
+
*
|
|
4903
|
+
* The direct-agent surface (operator-to-wrapped-agent conversation) was
|
|
4904
|
+
* removed in the v1.2 reshape. The concierge surface (operator-to-
|
|
4905
|
+
* Sanctuary) is the only operator chat surface that ships in v1.2.
|
|
4906
|
+
*
|
|
4907
|
+
* Sovereignty invariants:
|
|
4908
|
+
* - Conversation history is encrypted at rest under the fortress master
|
|
4909
|
+
* key via an HKDF-derived purpose key.
|
|
4910
|
+
* - Audit emission is non-optional: every operator submit and every
|
|
4911
|
+
* concierge reply lands in the L2 audit log.
|
|
4912
|
+
* - No raw message bodies are stored in audit `details`; only message
|
|
4913
|
+
* hashes and safe metadata. Bodies live in the encrypted chat store
|
|
4914
|
+
* that the operator can export, delete, or rotate.
|
|
4915
|
+
*/
|
|
4916
|
+
|
|
4917
|
+
/**
|
|
4918
|
+
* The chat surface a message belongs to. Concierge is the only operator
|
|
4919
|
+
* chat surface in v1.2; the type stays a single-member union for
|
|
4920
|
+
* forward-compatibility if additional Sanctuary-side surfaces land later.
|
|
4921
|
+
*/
|
|
4922
|
+
type OperatorChatSurface = "concierge";
|
|
4923
|
+
/**
|
|
4924
|
+
* Message-role enum. Concierge has two roles: `operator` (the human) and
|
|
4925
|
+
* `concierge` (Sanctuary's response).
|
|
4926
|
+
*/
|
|
4927
|
+
type OperatorChatRole = "operator" | "concierge";
|
|
4928
|
+
/**
|
|
4929
|
+
* One message in a concierge thread. The body is stored encrypted at
|
|
4930
|
+
* rest; the in-memory shape carries the cleartext for service consumers,
|
|
4931
|
+
* and the audit emission carries only `message_hash` + safe metadata.
|
|
4932
|
+
*/
|
|
4933
|
+
interface OperatorChatMessage {
|
|
4934
|
+
/** Stable message id (uuid) assigned at create time. */
|
|
4935
|
+
message_id: string;
|
|
4936
|
+
/** Surface this message belongs to. */
|
|
4937
|
+
surface: OperatorChatSurface;
|
|
4938
|
+
/** Sender role. */
|
|
4939
|
+
role: OperatorChatRole;
|
|
4940
|
+
/** Cleartext body. NEVER appears in audit `details`. */
|
|
4941
|
+
body: string;
|
|
4942
|
+
/** ISO8601 timestamp the message was created. */
|
|
4943
|
+
created_at: string;
|
|
4944
|
+
/**
|
|
4945
|
+
* For concierge response messages: which substrate served the response.
|
|
4946
|
+
* Null on operator-sent messages. Surfaces in the chat header badge.
|
|
4947
|
+
*/
|
|
4948
|
+
served_by?: SubstrateChoice;
|
|
4949
|
+
/**
|
|
4950
|
+
* For concierge response messages: latency of the substrate call in ms.
|
|
4951
|
+
* Operator-side surfaces this in the message tooltip / activity feed.
|
|
4952
|
+
*/
|
|
4953
|
+
substrate_latency_ms?: number;
|
|
4954
|
+
}
|
|
4955
|
+
/**
|
|
4956
|
+
* The shape persisted to disk under `_chat/<surface>/<thread-key>`.
|
|
4957
|
+
*
|
|
4958
|
+
* Threads are append-only; the persisted record is read-rewritten on
|
|
4959
|
+
* every message append. v1.2 caps thread length at
|
|
4960
|
+
* `OPERATOR_CHAT_MAX_THREAD_LENGTH`; older messages drop off when the
|
|
4961
|
+
* cap is exceeded.
|
|
4962
|
+
*/
|
|
4963
|
+
interface OperatorChatThread {
|
|
4964
|
+
/** Forward-compat field. v1.2 uses 1; bump on schema change. */
|
|
4965
|
+
version: 1;
|
|
4966
|
+
/** Surface (concierge in v1.2). */
|
|
4967
|
+
surface: OperatorChatSurface;
|
|
4968
|
+
/** Thread key; concierge is fortress-scoped under `CONCIERGE_THREAD_KEY`. */
|
|
4969
|
+
thread_key: string;
|
|
4970
|
+
/** Append-only message log; oldest first. */
|
|
4971
|
+
messages: OperatorChatMessage[];
|
|
4972
|
+
/** ISO8601 timestamp the thread was last updated. */
|
|
4973
|
+
updated_at: string;
|
|
4974
|
+
}
|
|
4975
|
+
/**
|
|
4976
|
+
* Concierge response envelope. Carries the substrate response (or
|
|
4977
|
+
* fallback message) plus the operator-visible substrate badge.
|
|
4978
|
+
*/
|
|
4979
|
+
interface ConciergeResponse {
|
|
4980
|
+
/** The response message persisted into the concierge thread. */
|
|
4981
|
+
message: OperatorChatMessage;
|
|
4982
|
+
/** The substrate that served this query. */
|
|
4983
|
+
served_by: SubstrateChoice;
|
|
4984
|
+
/** Operator-visible label rendered next to the response. */
|
|
4985
|
+
display_label: string;
|
|
4986
|
+
/** Outcome class for activity-feed projection. */
|
|
4987
|
+
outcome: "ok" | "substrate_failure" | "substrate_disabled";
|
|
4988
|
+
}
|
|
4989
|
+
|
|
4990
|
+
/**
|
|
4991
|
+
* Sanctuary MCP Server — Operator Chat Persistence
|
|
4992
|
+
*
|
|
4993
|
+
* Encrypted at-rest store for the operator-chat concierge thread.
|
|
4994
|
+
* Mirrors the `IntelligenceConfigStore` shape but addresses records by
|
|
4995
|
+
* `(surface, thread-key)` for forward-compatibility.
|
|
4996
|
+
*
|
|
4997
|
+
* Storage layout:
|
|
4998
|
+
* namespace: `_chat` (underscore-prefixed = reserved L1 namespace)
|
|
4999
|
+
* key: `concierge.{thread_key}`
|
|
5000
|
+
* payload: AES-256-GCM-encrypted `OperatorChatThread` JSON, key
|
|
5001
|
+
* derived via HKDF from the fortress master key with info
|
|
5002
|
+
* string `operator-chat-store-v1`.
|
|
5003
|
+
*
|
|
5004
|
+
* The direct-agent surface (per-agent threads + session records) was
|
|
5005
|
+
* removed in the v1.2 reshape. The concierge surface stores under a
|
|
5006
|
+
* single record with sentinel thread-key `_fortress`
|
|
5007
|
+
* (CONCIERGE_THREAD_KEY).
|
|
5008
|
+
*
|
|
5009
|
+
* Append-only semantics:
|
|
5010
|
+
* Threads are append-only at the message level. Persist is full-record
|
|
5011
|
+
* read-modify-write; the cap on thread length is enforced at append time
|
|
5012
|
+
* (oldest messages fall off when `OPERATOR_CHAT_MAX_THREAD_LENGTH` is
|
|
5013
|
+
* exceeded). The audit log retains every message regardless.
|
|
5014
|
+
*/
|
|
5015
|
+
|
|
5016
|
+
/**
|
|
5017
|
+
* Encrypted operator chat persistence.
|
|
5018
|
+
*/
|
|
5019
|
+
declare class OperatorChatStore {
|
|
5020
|
+
private storage;
|
|
5021
|
+
private encryptionKey;
|
|
5022
|
+
constructor(storage: StorageBackend, masterKey: Uint8Array);
|
|
5023
|
+
/**
|
|
5024
|
+
* Load a thread. Returns null if no record exists or if the on-disk
|
|
5025
|
+
* record is corrupt; callers treat both as "empty thread, start
|
|
5026
|
+
* fresh" and emit no audit event for the absence.
|
|
5027
|
+
*/
|
|
5028
|
+
loadThread(surface: OperatorChatSurface, threadKey: string): Promise<OperatorChatThread | null>;
|
|
5029
|
+
/**
|
|
5030
|
+
* Persist a thread. Caller is responsible for cap enforcement; the
|
|
5031
|
+
* `appendMessage` helper below drops oldest messages before persist
|
|
5032
|
+
* when the cap is exceeded.
|
|
5033
|
+
*/
|
|
5034
|
+
saveThread(thread: OperatorChatThread): Promise<void>;
|
|
5035
|
+
/**
|
|
5036
|
+
* Append a message to a thread, creating the thread if it doesn't
|
|
5037
|
+
* exist, and persist. Enforces the per-thread length cap by dropping
|
|
5038
|
+
* oldest messages first. Returns the persisted thread.
|
|
5039
|
+
*/
|
|
5040
|
+
appendMessage(surface: OperatorChatSurface, threadKey: string, message: OperatorChatMessage): Promise<OperatorChatThread>;
|
|
5041
|
+
/**
|
|
5042
|
+
* Delete a thread. Used by operator-driven thread reset. The audit
|
|
5043
|
+
* log retains the per-message history regardless.
|
|
5044
|
+
*/
|
|
5045
|
+
deleteThread(surface: OperatorChatSurface, threadKey: string): Promise<void>;
|
|
5046
|
+
}
|
|
5047
|
+
|
|
5048
|
+
/**
|
|
5049
|
+
* Sanctuary MCP Server — Operator Chat Service
|
|
5050
|
+
*
|
|
5051
|
+
* The operator-fortress concierge surface. Distinct from the
|
|
5052
|
+
* agent-to-agent mesh chat (`chat-service.ts`) which handles libp2p +
|
|
5053
|
+
* OpenMLS group sessions among wrapped agents.
|
|
5054
|
+
*
|
|
5055
|
+
* The direct-agent surface (operator-to-wrapped-agent conversation) was
|
|
5056
|
+
* removed in the v1.2 reshape; the concierge surface is the only
|
|
5057
|
+
* operator-chat surface in v1.2.
|
|
5058
|
+
*
|
|
5059
|
+
* Concierge surface (path: `sendConcierge`):
|
|
5060
|
+
* 1. PII-filter the operator query (Tier 1 regex).
|
|
5061
|
+
* 2. Build fortress context from audit log + activity feed +
|
|
5062
|
+
* agent registry (`assembleConciergeContext`).
|
|
5063
|
+
* 3. Invoke the substrate selector at `surface: "concierge"`.
|
|
5064
|
+
* 4. Persist operator query + concierge response in the concierge
|
|
5065
|
+
* thread under `_chat/concierge.<sentinel>`.
|
|
5066
|
+
* 5. Emit `operator_concierge_chat` audit event with safe metadata.
|
|
5067
|
+
*
|
|
5068
|
+
* Sovereignty invariants:
|
|
5069
|
+
* - Audit emission is non-optional on every public method that mutates
|
|
5070
|
+
* the chat state. Construction with no audit log is structurally
|
|
5071
|
+
* rejected.
|
|
5072
|
+
* - The substrate selector is OPTIONAL: a service constructed without
|
|
5073
|
+
* one degrades to "Concierge unavailable; substrate not configured".
|
|
5074
|
+
* The wiring layer can instantiate the service before the substrate
|
|
5075
|
+
* selector when bootstrap order requires it.
|
|
5076
|
+
* - The PII filter is the Tier 1 regex shipped in
|
|
5077
|
+
* `l2-operational/privacy-filter.ts`; Tier 2 NER+LLM redaction lives
|
|
5078
|
+
* in the substrate-selector layer (substrate-routed), not here.
|
|
5079
|
+
*/
|
|
5080
|
+
|
|
5081
|
+
/**
|
|
5082
|
+
* Snapshot of fortress state surfaces the concierge consults to
|
|
5083
|
+
* answer operator queries. Caller (the hub-service wiring) supplies
|
|
5084
|
+
* the providers; the service wires them into the substrate prompt.
|
|
5085
|
+
*
|
|
5086
|
+
* Each provider returns plain strings the substrate selector folds
|
|
5087
|
+
* into a single context blob; the service does not attempt to
|
|
5088
|
+
* structure the prompt beyond stitching with newlines. Keeping the
|
|
5089
|
+
* prompt-shape decisions in the service-construction layer (rather
|
|
5090
|
+
* than in the wiring) lets the dashboard team iterate concierge
|
|
5091
|
+
* prompts without touching server code.
|
|
5092
|
+
*/
|
|
5093
|
+
interface ConciergeContextProviders {
|
|
5094
|
+
/** Recent activity-feed entries as a free-form string, oldest first. */
|
|
5095
|
+
recentActivity: () => Promise<string>;
|
|
5096
|
+
/** Wrapped-agent inventory as a free-form string. */
|
|
5097
|
+
agentInventory: () => Promise<string>;
|
|
5098
|
+
/** Open inbox items as a free-form string. */
|
|
5099
|
+
openInbox: () => Promise<string>;
|
|
5100
|
+
}
|
|
5101
|
+
/**
|
|
5102
|
+
* PII filter the concierge applies to operator queries before passing
|
|
5103
|
+
* them to the substrate. v1.2 wires the Tier 1 regex; the substrate
|
|
5104
|
+
* selector handles Tier 2 NER+LLM redaction internally on egress paths.
|
|
5105
|
+
*
|
|
5106
|
+
* Returns the filtered query plus the count of redactions performed
|
|
5107
|
+
* (surfaced in the audit event for operator visibility).
|
|
5108
|
+
*/
|
|
5109
|
+
interface ConciergePiiFilter {
|
|
5110
|
+
filter(input: string): {
|
|
5111
|
+
filtered: string;
|
|
5112
|
+
redactions: number;
|
|
5113
|
+
};
|
|
5114
|
+
}
|
|
5115
|
+
/**
|
|
5116
|
+
* Construction inputs for the operator chat service.
|
|
5117
|
+
*/
|
|
5118
|
+
interface OperatorChatServiceDeps {
|
|
5119
|
+
/** Encrypted at-rest store; built from fortress master key. */
|
|
5120
|
+
store: OperatorChatStore;
|
|
5121
|
+
/** Audit log for `operator_concierge_chat` events. */
|
|
5122
|
+
auditLog: AuditLog;
|
|
5123
|
+
/** Operator identity that owns the chat session. */
|
|
5124
|
+
identityId: string;
|
|
5125
|
+
/**
|
|
5126
|
+
* Substrate selector for concierge LLM calls. Optional: when omitted
|
|
5127
|
+
* the concierge surface degrades to a "substrate not configured"
|
|
5128
|
+
* response.
|
|
5129
|
+
*/
|
|
5130
|
+
substrateSelector?: SubstrateSelector;
|
|
5131
|
+
/**
|
|
5132
|
+
* Concierge context providers. Required when a substrate selector
|
|
5133
|
+
* is wired; otherwise unused. Wiring layer assembles these from the
|
|
5134
|
+
* activity feed, agent registry, and inbox aggregator.
|
|
5135
|
+
*/
|
|
5136
|
+
conciergeContextProviders?: ConciergeContextProviders;
|
|
5137
|
+
/**
|
|
5138
|
+
* PII filter applied to concierge queries pre-substrate. Optional;
|
|
5139
|
+
* when omitted the service still works (no redactions performed).
|
|
5140
|
+
* v1.2 wiring passes the Tier 1 regex.
|
|
5141
|
+
*/
|
|
5142
|
+
conciergePiiFilter?: ConciergePiiFilter;
|
|
5143
|
+
/**
|
|
5144
|
+
* Stable max tokens for concierge responses. Defaults to 512 (small
|
|
5145
|
+
* enough for snappy local-model latency, large enough for a useful
|
|
5146
|
+
* summary). Operator-tunable via dashboard config.
|
|
5147
|
+
*/
|
|
5148
|
+
conciergeMaxTokens?: number;
|
|
5149
|
+
}
|
|
5150
|
+
declare class OperatorChatService {
|
|
5151
|
+
private store;
|
|
5152
|
+
private auditLog;
|
|
5153
|
+
private identityId;
|
|
5154
|
+
private substrateSelector?;
|
|
5155
|
+
private contextProviders?;
|
|
5156
|
+
private piiFilter?;
|
|
5157
|
+
private conciergeMaxTokens;
|
|
5158
|
+
constructor(deps: OperatorChatServiceDeps);
|
|
5159
|
+
/**
|
|
5160
|
+
* Operator submit on the concierge surface. Persists the operator's
|
|
5161
|
+
* query, fans out to the substrate selector, persists the response,
|
|
5162
|
+
* and emits the audit event.
|
|
5163
|
+
*
|
|
5164
|
+
* On substrate failure or absence: persists an honest "concierge
|
|
5165
|
+
* unavailable" response and audit-emits with `outcome` = the
|
|
5166
|
+
* appropriate failure class. The chat history reflects what the
|
|
5167
|
+
* operator sees on the page (no silent dropping).
|
|
5168
|
+
*/
|
|
5169
|
+
sendConcierge(query: string): Promise<ConciergeResponse>;
|
|
5170
|
+
/**
|
|
5171
|
+
* Read the persisted concierge thread, oldest message first. Returns
|
|
5172
|
+
* an empty array when no thread exists yet.
|
|
5173
|
+
*/
|
|
5174
|
+
getConciergeHistory(): Promise<OperatorChatMessage[]>;
|
|
5175
|
+
/**
|
|
5176
|
+
* Stitch fortress state into a single context blob the substrate
|
|
5177
|
+
* folds into its summarization prompt.
|
|
5178
|
+
*
|
|
5179
|
+
* The blob is intentionally plain text (not structured JSON) because
|
|
5180
|
+
* small local models (Gemma 2 2B) handle plain text more reliably
|
|
5181
|
+
* than nested structures. Format:
|
|
5182
|
+
*
|
|
5183
|
+
* ```
|
|
5184
|
+
* ## Recent activity
|
|
5185
|
+
* <recentActivity output>
|
|
5186
|
+
*
|
|
5187
|
+
* ## Wrapped agents
|
|
5188
|
+
* <agentInventory output>
|
|
5189
|
+
*
|
|
5190
|
+
* ## Open inbox
|
|
5191
|
+
* <openInbox output>
|
|
5192
|
+
* ```
|
|
5193
|
+
*/
|
|
5194
|
+
private assembleConciergeContext;
|
|
5195
|
+
private emit;
|
|
5196
|
+
}
|
|
5197
|
+
|
|
4137
5198
|
/**
|
|
4138
5199
|
* Sanctuary v1.1. Operator Hub API Types
|
|
4139
5200
|
*
|
|
@@ -4171,6 +5232,11 @@ interface HubTier1ApprovalEnqueuedResult {
|
|
|
4171
5232
|
*/
|
|
4172
5233
|
operation_category: HubApprovalPendingItem["operation_category"];
|
|
4173
5234
|
}
|
|
5235
|
+
interface HubTemplateBindingApprovalEnqueuedResult extends HubTier1ApprovalEnqueuedResult {
|
|
5236
|
+
current_template_id?: ChannelTemplateId;
|
|
5237
|
+
proposed_template_id: ChannelTemplateId;
|
|
5238
|
+
compiled_policy_id: string;
|
|
5239
|
+
}
|
|
4174
5240
|
/**
|
|
4175
5241
|
* Result returned from a fortress-scope Tier-1 action that has been
|
|
4176
5242
|
* deferred to operator approval. Distinguished from the per-agent shape by
|
|
@@ -4225,11 +5291,7 @@ interface HubAgentController {
|
|
|
4225
5291
|
* approval lands.
|
|
4226
5292
|
*/
|
|
4227
5293
|
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
|
-
*/
|
|
5294
|
+
/** Apply an operator-approved channel-template binding. */
|
|
4233
5295
|
bindChannelTemplate(agentId: string, templateId: ChannelTemplateId): Promise<void>;
|
|
4234
5296
|
}
|
|
4235
5297
|
/**
|
|
@@ -4362,6 +5424,11 @@ interface HubServiceDeps {
|
|
|
4362
5424
|
* returning the in-memory projection.
|
|
4363
5425
|
*/
|
|
4364
5426
|
readPersistedLocalAgents?: () => LocalAgentRecord[];
|
|
5427
|
+
/**
|
|
5428
|
+
* Optional persisted agent writer. Used when approved hub actions mutate
|
|
5429
|
+
* registry-local fields that should survive refresh and restart.
|
|
5430
|
+
*/
|
|
5431
|
+
writePersistedLocalAgents?: (records: LocalAgentRecord[]) => void;
|
|
4365
5432
|
/** Inbox aggregation sources. */
|
|
4366
5433
|
inboxSources: HubInboxSources;
|
|
4367
5434
|
/** Activity feed sources. */
|
|
@@ -4391,6 +5458,44 @@ interface HubServiceDeps {
|
|
|
4391
5458
|
* Defaults to `() => new Date()` when omitted.
|
|
4392
5459
|
*/
|
|
4393
5460
|
now?: () => Date;
|
|
5461
|
+
/**
|
|
5462
|
+
* Optional operator-chat service. When supplied, the hub exposes the
|
|
5463
|
+
* concierge chat endpoints; when omitted, those routes return
|
|
5464
|
+
* HubCapabilityError. Construction-time injection lets the dashboard
|
|
5465
|
+
* wiring layer build the chat service against the same audit log +
|
|
5466
|
+
* master key + storage backend as the rest of the v1.1 hub without
|
|
5467
|
+
* forcing the chat-service constructor through a circular import.
|
|
5468
|
+
* The direct-agent chat surface was removed in the v1.2 reshape
|
|
5469
|
+
* (2026-04-30); the field name is retained for source compatibility.
|
|
5470
|
+
*/
|
|
5471
|
+
operatorChat?: OperatorChatService;
|
|
5472
|
+
}
|
|
5473
|
+
/**
|
|
5474
|
+
* Click-to-inspect panel returned by `openAgentInspectPanel`. The panel
|
|
5475
|
+
* surfaces the agent's recent activity, pending approvals routed through
|
|
5476
|
+
* this agent, and policy summary at a glance, repurposing the click-
|
|
5477
|
+
* to-chat wire-up shipped in PR #98 + PR #100. The direct-agent chat
|
|
5478
|
+
* surface was removed in the v1.2 reshape; this panel is the operational
|
|
5479
|
+
* destination for the click.
|
|
5480
|
+
*/
|
|
5481
|
+
interface HubAgentInspectPanel {
|
|
5482
|
+
/** The agent the panel was opened on. */
|
|
5483
|
+
agent_id: string;
|
|
5484
|
+
/** ISO8601 timestamp the panel was opened. */
|
|
5485
|
+
opened_at: string;
|
|
5486
|
+
/** Recent activity-feed entries for this agent, oldest first. */
|
|
5487
|
+
recent_activity: HubActivityFeedEntry[];
|
|
5488
|
+
/**
|
|
5489
|
+
* Open Tier 1 inbox items routed through this agent. Empty when the
|
|
5490
|
+
* agent has no pending approvals.
|
|
5491
|
+
*/
|
|
5492
|
+
pending_approvals: HubInboxItem[];
|
|
5493
|
+
/**
|
|
5494
|
+
* Bound policy summary for this agent. Null when the agent has no
|
|
5495
|
+
* channel-template binding (e.g. immediately after wrap, before the
|
|
5496
|
+
* operator picks a template).
|
|
5497
|
+
*/
|
|
5498
|
+
policy_summary: HubPolicySummary | null;
|
|
4394
5499
|
}
|
|
4395
5500
|
|
|
4396
5501
|
/**
|
|
@@ -4438,10 +5543,10 @@ declare class HubService {
|
|
|
4438
5543
|
*/
|
|
4439
5544
|
bindAgentPolicy(agentId: string, policyId: string): HubTier1ApprovalEnqueuedResult;
|
|
4440
5545
|
/**
|
|
4441
|
-
* Bind a different channel template.
|
|
4442
|
-
*
|
|
5546
|
+
* Bind a different channel template. Tier 1: enqueues a policy_change
|
|
5547
|
+
* approval item and only applies the binding after operator approval.
|
|
4443
5548
|
*/
|
|
4444
|
-
bindAgentChannelTemplate(agentId: string, rawTemplateId: unknown):
|
|
5549
|
+
bindAgentChannelTemplate(agentId: string, rawTemplateId: unknown): HubTemplateBindingApprovalEnqueuedResult;
|
|
4445
5550
|
/**
|
|
4446
5551
|
* Enqueue a fortress-scope Tier 1 lockdown. One inbox item is created;
|
|
4447
5552
|
* on operator approval the handler iterates `agentController.lockdown`
|
|
@@ -4484,6 +5589,33 @@ declare class HubService {
|
|
|
4484
5589
|
* Test/inspection helper. Not part of the public service surface.
|
|
4485
5590
|
*/
|
|
4486
5591
|
inboxStoreSize(): number;
|
|
5592
|
+
private requireOperatorChat;
|
|
5593
|
+
/**
|
|
5594
|
+
* Operator submit on the concierge chat surface. Pass-through to the
|
|
5595
|
+
* operator-chat-service which owns substrate-selector routing, PII
|
|
5596
|
+
* filtering, persistence, and audit emission.
|
|
5597
|
+
*/
|
|
5598
|
+
sendConcierge(query: string): Promise<ConciergeResponse>;
|
|
5599
|
+
/**
|
|
5600
|
+
* Read the persisted concierge thread.
|
|
5601
|
+
*/
|
|
5602
|
+
getConciergeHistory(): Promise<OperatorChatMessage[]>;
|
|
5603
|
+
/**
|
|
5604
|
+
* Open the click-to-inspect/approve panel for a wrapped agent. The
|
|
5605
|
+
* panel surfaces recent activity routed through this agent, pending
|
|
5606
|
+
* Tier 1 approvals on this agent, and the bound policy summary,
|
|
5607
|
+
* repurposing the click-to-chat wire-up from PR #98 + PR #100 to a
|
|
5608
|
+
* substrate-aligned inspect destination after the v1.2 reshape removed
|
|
5609
|
+
* direct-agent chat.
|
|
5610
|
+
*
|
|
5611
|
+
* Synchronous open shape preserved (caller's `await` semantics
|
|
5612
|
+
* unchanged from the prior `openDirectAgentSession` surface). The
|
|
5613
|
+
* panel is read-only; no side effects beyond the audit-event emission
|
|
5614
|
+
* for the panel-open itself.
|
|
5615
|
+
*/
|
|
5616
|
+
openAgentInspectPanel(agentId: string, options?: {
|
|
5617
|
+
activityLimit?: number;
|
|
5618
|
+
}): Promise<HubAgentInspectPanel>;
|
|
4487
5619
|
}
|
|
4488
5620
|
|
|
4489
5621
|
/**
|
|
@@ -4509,16 +5641,29 @@ declare class HubService {
|
|
|
4509
5641
|
* the v1.2 work to project those into operator cards.
|
|
4510
5642
|
* - Activity feed reads from the real audit log. This is the one source
|
|
4511
5643
|
* that's already complete in v1.1.0 and just needs to be plugged in.
|
|
4512
|
-
* - Agent controller errors on
|
|
4513
|
-
*
|
|
4514
|
-
*
|
|
4515
|
-
*
|
|
5644
|
+
* - Agent controller errors on runtime harness actions that v1.1 cannot
|
|
5645
|
+
* honestly execute. Channel-template binding is registry-local in v1.2,
|
|
5646
|
+
* so its controller hook is a no-op and HubService persists the binding
|
|
5647
|
+
* after Tier 1 approval.
|
|
4516
5648
|
*/
|
|
4517
5649
|
|
|
4518
5650
|
interface V11Bindings {
|
|
4519
5651
|
hubService: HubService;
|
|
4520
5652
|
identityId: string;
|
|
4521
5653
|
fortressId: string;
|
|
5654
|
+
/**
|
|
5655
|
+
* Optional Intelligence Substrate Selector. Dispatch layer routes
|
|
5656
|
+
* `/api/hub/intelligence/*` here when set; absent means the routes
|
|
5657
|
+
* 503 with a "selector not configured" body.
|
|
5658
|
+
*/
|
|
5659
|
+
intelligenceSelector?: SubstrateSelector;
|
|
5660
|
+
/**
|
|
5661
|
+
* Optional Operator Chat Service. Constructed when storage + masterKey
|
|
5662
|
+
* are passed to `buildV11Bindings`. The HubService accepts this
|
|
5663
|
+
* directly via its `operatorChat` dep; callers that want the harness-
|
|
5664
|
+
* side `recordAgentReply` integration also need the service handle.
|
|
5665
|
+
*/
|
|
5666
|
+
operatorChatService?: OperatorChatService;
|
|
4522
5667
|
}
|
|
4523
5668
|
|
|
4524
5669
|
/**
|
|
@@ -5624,4 +6769,4 @@ declare function createSanctuaryServer(options?: {
|
|
|
5624
6769
|
storage?: StorageBackend;
|
|
5625
6770
|
}): Promise<SanctuaryServer>;
|
|
5626
6771
|
|
|
5627
|
-
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 };
|
|
6772
|
+
export { ATTESTATION_VERSION, type ActivityEntry, type AggregatorSources, ApprovalGate, type ApprovalHandlers, type AttestationBody, type AttestationVerificationResult, AuditLog, AutoApproveChannel, BaselineTracker, type BridgeAttestationRequest, type BridgeAttestationResult, type BridgeCommitment, type BridgeVerificationResult, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, ClientManager, CommitmentStore, type ConcordiaOutcome, type ConnectionState, type ContextAction, type ContextFilterResult, ContextGateEnforcer, type ContextGatePolicy, ContextGatePolicyStore, type ContextGateRule, type ContextGateTemplate, DashboardApprovalChannel, type DashboardConfig, type DashboardHandle, type DashboardServerOptions, type DetectionResult, type EnforcerConfig, type ExitAuditReceiptsArtifact, type ExitBundleDetailedVerifierResult, ExitBundleImportError, type ExitCommandArgs, type ExitCommitmentsArtifact, type ExitEncryptedStateBundle, type ExitPlaceholderVaultMetadataArtifact, type ExitPolicySetArtifact, type ExitPublicIdentityArtifact, type ExportExitBundleOptions, type ExportExitBundleResult, type FederationCapabilities, type FederationPeer, FederationRegistry, type FieldClassification, type FieldFilterResult, FilesystemStorage, type GateResult, HERO_COPY, type HandshakeChallenge, type HandshakeCompletion, type HandshakeResponse, type HandshakeResult, type ImportExitBundleOptions, type ImportExitBundleResult, InMemoryModelProvenanceStore, InjectionDetector, type InjectionDetectorConfig, type InjectionSignal, type L1Status, type L2Status, type L3Status, type L4Status, type LoadedExitArtifact, MODEL_PRESETS, MemoryStorage, type ModelProvenance, type ModelProvenanceStore, type PedersenCommitment, type PeerTrustEvaluation, type PendingApproval, type PolicyRecommendation, PolicyStore, type PrincipalPolicy, type ProtectionSnapshot, type ProviderCategory, ProxyRouter, type ProxyRouterOptions, type ReputationLookup, ReputationStore, type SHRBody, type SHRGeneratorOptions, type SHRVerificationResult, type SanctuaryConfig, type SanctuaryServer, type SignedAttestation, type SignedSHR, type SovereigntyProfile, SovereigntyProfileStore, type SovereigntyProfileUpdate, type SovereigntyTier, type StartDashboardOptions, StateStore, StderrApprovalChannel, type StreamEvent, TIER_WEIGHTS, type TierMetadata, type TieredAttestation, type UpstreamConnection, type UpstreamServer, type UpstreamTool, type VerifyExitBundleOptions, WebhookApprovalChannel, type WebhookCallbackPayload, type WebhookConfig, type WebhookPayload, type ZKProofOfKnowledge, type ZKRangeProof, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createDefaultProfile, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, exitBundleManifestShape, exportExitBundle, filterContext, generateAttestation, generateSHR, generateSystemPrompt, getProtectionSnapshot, getTemplate, importExitBundle, initiateHandshake, listTemplateIds, loadConfig, loadExitArtifact, loadPrincipalPolicy, readManifest, recommendPolicy, renderDashboardHTML, resolveTier, respondToHandshake, runExitCommand, signPayload, startDashboard, startDashboardServer, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyExitBundle, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|