@sanctuary-framework/mcp-server 1.2.13 → 1.2.15
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 +2194 -30
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2194 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1004 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +561 -276
- package/dist/index.d.ts +561 -276
- package/dist/index.js +1005 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -4356,108 +4356,6 @@ declare class MalformedPrincipalPolicyError extends Error {
|
|
|
4356
4356
|
*/
|
|
4357
4357
|
declare function loadPrincipalPolicy(storagePath: string): Promise<PrincipalPolicy>;
|
|
4358
4358
|
|
|
4359
|
-
/**
|
|
4360
|
-
* Sanctuary MCP Server — SHR Generator
|
|
4361
|
-
*
|
|
4362
|
-
* Generates a Sovereignty Health Report from current server state,
|
|
4363
|
-
* signs it with a specified identity, and returns the complete signed SHR.
|
|
4364
|
-
*/
|
|
4365
|
-
|
|
4366
|
-
/**
|
|
4367
|
-
* Observed L4 reputation state used by the emitter. Callers gather these
|
|
4368
|
-
* facts from the reputation store + audit log; the emitter derives
|
|
4369
|
-
* degradations from them. Keeping evidence as plain data keeps the
|
|
4370
|
-
* generator synchronous and easy to test.
|
|
4371
|
-
*/
|
|
4372
|
-
interface L4Evidence {
|
|
4373
|
-
/** Total attestations attributed to the signing identity */
|
|
4374
|
-
attestation_count: number;
|
|
4375
|
-
/** Count of attestations at each sovereignty tier */
|
|
4376
|
-
tier_distribution: Record<SovereigntyTier, number>;
|
|
4377
|
-
/** ISO timestamp of most recent attestation, or null when none exist */
|
|
4378
|
-
most_recent_attestation_at: string | null;
|
|
4379
|
-
/** Count of attestations with outcome_result === "disputed" */
|
|
4380
|
-
dispute_count: number;
|
|
4381
|
-
/** Attestation count per context label (optional; used by dashboard) */
|
|
4382
|
-
context_breakdown?: Record<string, number>;
|
|
4383
|
-
/**
|
|
4384
|
-
* True iff the `reputation_publish` tool has been successfully invoked
|
|
4385
|
-
* for this identity (i.e., there is at least one success audit entry).
|
|
4386
|
-
*/
|
|
4387
|
-
verascore_linked: boolean;
|
|
4388
|
-
/**
|
|
4389
|
-
* Optional overrides for the emitter thresholds. Defaults apply when
|
|
4390
|
-
* omitted or when a field is missing.
|
|
4391
|
-
*/
|
|
4392
|
-
thresholds?: {
|
|
4393
|
-
freshness_window_days?: number;
|
|
4394
|
-
low_tier_dominance_threshold?: number;
|
|
4395
|
-
};
|
|
4396
|
-
}
|
|
4397
|
-
interface SHRGeneratorOptions {
|
|
4398
|
-
config: SanctuaryConfig;
|
|
4399
|
-
identityManager: IdentityManager;
|
|
4400
|
-
masterKey: Uint8Array;
|
|
4401
|
-
/** Override validity window (milliseconds). Default: 1 hour. */
|
|
4402
|
-
validityMs?: number;
|
|
4403
|
-
/**
|
|
4404
|
-
* Optional L4 reputation evidence. When provided, the generator emits
|
|
4405
|
-
* L4 degradations (NO_REPUTATION_HISTORY, LOW_TIER_DOMINANCE,
|
|
4406
|
-
* STALE_REPUTATION, DISPUTE_ON_RECORD, NO_VERASCORE_LINK) accordingly
|
|
4407
|
-
* and downgrades `layers.l4.status` to `degraded` when any fire.
|
|
4408
|
-
* When omitted, L4 is left at "active" (backward-compatible).
|
|
4409
|
-
*/
|
|
4410
|
-
l4Evidence?: L4Evidence;
|
|
4411
|
-
/**
|
|
4412
|
-
* Clock override for deterministic testing of staleness behavior.
|
|
4413
|
-
* Defaults to the current wall clock.
|
|
4414
|
-
*/
|
|
4415
|
-
now?: Date;
|
|
4416
|
-
}
|
|
4417
|
-
/**
|
|
4418
|
-
* Generate and sign a Sovereignty Health Report.
|
|
4419
|
-
*
|
|
4420
|
-
* @param identityId - Which identity to sign with (defaults to primary)
|
|
4421
|
-
* @param opts - Generator dependencies
|
|
4422
|
-
* @returns The signed SHR, or an error string
|
|
4423
|
-
*/
|
|
4424
|
-
declare function generateSHR(identityId: string | undefined, opts: SHRGeneratorOptions): SignedSHR | string;
|
|
4425
|
-
|
|
4426
|
-
/**
|
|
4427
|
-
* Sanctuary v1.1 Operator Hub API Constants
|
|
4428
|
-
*
|
|
4429
|
-
* Routes, prefixes, and small enums shared across the hub modules.
|
|
4430
|
-
* The hub API surface is consumed by the v1.1 dashboard UI (Prompt 8).
|
|
4431
|
-
*
|
|
4432
|
-
* Local-only invariant:
|
|
4433
|
-
* Every route here describes activity inside a single fortress on a single
|
|
4434
|
-
* operator's machine. Cross-fortress, fleet, and public-federation routes
|
|
4435
|
-
* are out of scope.
|
|
4436
|
-
*/
|
|
4437
|
-
|
|
4438
|
-
/**
|
|
4439
|
-
* Inbox-resolve actions. The router rejects any other action token.
|
|
4440
|
-
*/
|
|
4441
|
-
declare const HUB_INBOX_ACTIONS: readonly ["approve", "deny", "dismiss"];
|
|
4442
|
-
type HubInboxAction = (typeof HUB_INBOX_ACTIONS)[number];
|
|
4443
|
-
/**
|
|
4444
|
-
* Agent-control actions surfaced by `POST /api/hub/agents/:id/:action`.
|
|
4445
|
-
*
|
|
4446
|
-
* `pause` / `resume` / `restart` are control-plane operations that the
|
|
4447
|
-
* underlying harness may execute immediately; they are not Tier 1.
|
|
4448
|
-
*
|
|
4449
|
-
* `unwrap` and `lockdown` are Tier 1 operations per the Principal Policy
|
|
4450
|
-
* loader. Hub endpoints for these MUST enqueue an `approval_pending` inbox
|
|
4451
|
-
* item rather than execute directly. Tier 1 approval gates remain in force
|
|
4452
|
-
* from the dashboard. The dashboard never auto-approves Tier 1 work.
|
|
4453
|
-
*/
|
|
4454
|
-
declare const HUB_AGENT_CONTROL_ACTIONS: readonly ["pause", "resume", "restart", "unwrap", "lockdown"];
|
|
4455
|
-
type HubAgentControlAction = (typeof HUB_AGENT_CONTROL_ACTIONS)[number];
|
|
4456
|
-
|
|
4457
|
-
/** Channel-template identifiers per the five-template canonical starter set. */
|
|
4458
|
-
declare const CHANNEL_TEMPLATE_IDS: readonly ["request-approve-act", "read-then-report", "scheduled-digest", "plan-draft-only", "fortress-relay"];
|
|
4459
|
-
type ChannelTemplateId = (typeof CHANNEL_TEMPLATE_IDS)[number];
|
|
4460
|
-
|
|
4461
4359
|
/**
|
|
4462
4360
|
* Sanctuary MCP Server — Intelligence Substrate Selector Types
|
|
4463
4361
|
*
|
|
@@ -5102,28 +5000,445 @@ declare class SubstrateSelector {
|
|
|
5102
5000
|
* doesn't pre-spawn HTTP clients for substrates the operator never
|
|
5103
5001
|
* touches.
|
|
5104
5002
|
*/
|
|
5105
|
-
private buildHandle;
|
|
5106
|
-
private disabledHandle;
|
|
5107
|
-
private localHandle;
|
|
5108
|
-
private veniceHandle;
|
|
5109
|
-
private frontierHandle;
|
|
5110
|
-
private probeSurfaceHealth;
|
|
5111
|
-
private makeBadge;
|
|
5112
|
-
private fallbackAction;
|
|
5003
|
+
private buildHandle;
|
|
5004
|
+
private disabledHandle;
|
|
5005
|
+
private localHandle;
|
|
5006
|
+
private veniceHandle;
|
|
5007
|
+
private frontierHandle;
|
|
5008
|
+
private probeSurfaceHealth;
|
|
5009
|
+
private makeBadge;
|
|
5010
|
+
private fallbackAction;
|
|
5011
|
+
/**
|
|
5012
|
+
* Internal hook for the Privacy Filter Tier 2 commit. Lets a redactor
|
|
5013
|
+
* audit-emit a `pii_redaction_event` payload through the selector
|
|
5014
|
+
* without exposing the AuditLog binding directly to redactor
|
|
5015
|
+
* implementations.
|
|
5016
|
+
*/
|
|
5017
|
+
emitRedactionEvent(args: {
|
|
5018
|
+
surface: Surface;
|
|
5019
|
+
substrate: SubstrateChoice;
|
|
5020
|
+
matchCount: number;
|
|
5021
|
+
filterTier: 1 | 2;
|
|
5022
|
+
}): void;
|
|
5023
|
+
private emit;
|
|
5024
|
+
}
|
|
5025
|
+
|
|
5026
|
+
/**
|
|
5027
|
+
* Sanctuary v1.3 WP-V1.3-1 Sentinel Finding Store.
|
|
5028
|
+
*
|
|
5029
|
+
* Encrypted at-rest persistence for sentinel findings. Sibling to the
|
|
5030
|
+
* Upsilon-3 aggregator-store: same fortress-master-key-derived HKDF
|
|
5031
|
+
* subkey shape, AAD-bound to the finding_id, retention-aware.
|
|
5032
|
+
*
|
|
5033
|
+
* Storage layout:
|
|
5034
|
+
* namespace: `_sentinel_findings`
|
|
5035
|
+
* key: `finding.{finding_id}` (one record per finding)
|
|
5036
|
+
* payload: AES-256-GCM ciphertext of the JSON-serialized record.
|
|
5037
|
+
* key: `l2-sentinel-finding-v1` HKDF subkey of fortress master.
|
|
5038
|
+
* AAD: UTF-8 bytes of `finding_id`.
|
|
5039
|
+
*
|
|
5040
|
+
* Multi-fortress isolation: HKDF subkey derives from the fortress
|
|
5041
|
+
* master key. Two fortresses never produce identical encryption keys
|
|
5042
|
+
* for identical finding_ids.
|
|
5043
|
+
*
|
|
5044
|
+
* Retention: 30 days default, mirroring the audit-log envelope and the
|
|
5045
|
+
* aggregator payload store.
|
|
5046
|
+
*/
|
|
5047
|
+
|
|
5048
|
+
interface SentinelFindingStoreOptions {
|
|
5049
|
+
storage: StorageBackend;
|
|
5050
|
+
masterKey: Uint8Array;
|
|
5051
|
+
fortressId: string;
|
|
5052
|
+
/** Operator-tunable retention window. Default 30 days. */
|
|
5053
|
+
retentionDays?: number;
|
|
5054
|
+
/** Wall-clock provider for deterministic tests. */
|
|
5055
|
+
now?: () => Date;
|
|
5056
|
+
}
|
|
5057
|
+
declare class SentinelFindingStore {
|
|
5058
|
+
private readonly storage;
|
|
5059
|
+
private readonly encryptionKey;
|
|
5060
|
+
private readonly fortressId;
|
|
5061
|
+
private readonly retentionDays;
|
|
5062
|
+
private readonly now;
|
|
5063
|
+
constructor(opts: SentinelFindingStoreOptions);
|
|
5064
|
+
/**
|
|
5065
|
+
* Persist a finding. Truncates the operator-visible summary to
|
|
5066
|
+
* SENTINEL_SUMMARY_MAX_CHARS so the dashboard render stays bounded.
|
|
5067
|
+
* Returns the retention deadline so callers can audit it.
|
|
5068
|
+
*/
|
|
5069
|
+
saveFinding(finding: SentinelFinding): Promise<string>;
|
|
5070
|
+
/** Load a single finding by id, or null when absent / corrupted. */
|
|
5071
|
+
loadFinding(findingId: string): Promise<SentinelFinding | null>;
|
|
5072
|
+
/**
|
|
5073
|
+
* List findings, newest first. Optional filters: since (ISO 8601),
|
|
5074
|
+
* severity, sentinel_id, agent_id, limit. Default limit 100.
|
|
5075
|
+
*/
|
|
5076
|
+
listFindings(opts?: {
|
|
5077
|
+
since?: string;
|
|
5078
|
+
severity?: SentinelSeverity;
|
|
5079
|
+
sentinelId?: string;
|
|
5080
|
+
agentId?: string;
|
|
5081
|
+
limit?: number;
|
|
5082
|
+
}): Promise<SentinelFinding[]>;
|
|
5083
|
+
/**
|
|
5084
|
+
* Drop expired findings. Returns the count removed.
|
|
5085
|
+
*/
|
|
5086
|
+
pruneExpired(now?: Date): Promise<{
|
|
5087
|
+
pruned: number;
|
|
5088
|
+
}>;
|
|
5089
|
+
private decode;
|
|
5090
|
+
}
|
|
5091
|
+
|
|
5092
|
+
/**
|
|
5093
|
+
* Sanctuary v1.3 WP-V1.3-1 Sentinel Baseline Pack (Castle Layer 2 anchor)
|
|
5094
|
+
*
|
|
5095
|
+
* Shared types for the Sentinel observation surface.
|
|
5096
|
+
*
|
|
5097
|
+
* Castle-walking discipline:
|
|
5098
|
+
* - Castle Layer 1 (Castle Wall) blocks unauthorized egress at the kernel
|
|
5099
|
+
* boundary. That is the enforcement layer.
|
|
5100
|
+
* - Castle Layer 2 (Sentinels) observes server-local data only and surfaces
|
|
5101
|
+
* anomalies. NO outbound network. NO blocking. Findings flow into the
|
|
5102
|
+
* operator surface they already check.
|
|
5103
|
+
* - Castle Layer 3 (Cooperative MCP) is the agent contract. Sentinels do
|
|
5104
|
+
* not wrap agent tools and do not negotiate with agents.
|
|
5105
|
+
*
|
|
5106
|
+
* Phi-1 ships the framework + the egress-volume watcher. Phi-2 through
|
|
5107
|
+
* Phi-5 add credential-usage, cross-agent-chatter, suspicious-tool-call,
|
|
5108
|
+
* and anomaly-trigger sentinels against this same shape.
|
|
5109
|
+
*/
|
|
5110
|
+
|
|
5111
|
+
/** Severity tier returned by `Sentinel.evaluate()`. */
|
|
5112
|
+
type SentinelSeverity = "info" | "warn" | "alert";
|
|
5113
|
+
/**
|
|
5114
|
+
* Read-only context handed to every sentinel on subscribe + evaluate.
|
|
5115
|
+
* Sentinels do NOT receive a writable storage handle and do NOT receive
|
|
5116
|
+
* an outbound HTTP client. The substrate selector is the single
|
|
5117
|
+
* outbound-capable surface; Phi-1 sentinels do not exercise it but
|
|
5118
|
+
* Phi-2/3/4/5 may want to invoke a local LLM for reasoning.
|
|
5119
|
+
*/
|
|
5120
|
+
interface SentinelContext {
|
|
5121
|
+
/** Stable per-fortress identifier; multi-fortress isolation pivot. */
|
|
5122
|
+
fortressId: string;
|
|
5123
|
+
/** Audit log read API. Sentinels MUST NOT call append() through this. */
|
|
5124
|
+
auditLog: AuditLog;
|
|
5125
|
+
/** Optional substrate selector for LLM-backed reasoning. v1.3 Phi-1 unused. */
|
|
5126
|
+
substrateSelector?: SubstrateSelector;
|
|
5127
|
+
/** Wall-clock provider. Tests inject a deterministic clock. */
|
|
5128
|
+
now: () => Date;
|
|
5129
|
+
/**
|
|
5130
|
+
* Optional read view of the per-fortress sentinel finding store
|
|
5131
|
+
* (Phi-1 surface). First-order sentinels (Phi-1/2/3/4) do not need
|
|
5132
|
+
* this; the Phi-5 meta-sentinel reads it to detect patterns ACROSS
|
|
5133
|
+
* other sentinels' findings (compound finding, fortress-wide count
|
|
5134
|
+
* spikes, novel sentinel-ID combinations). The dispatcher attaches
|
|
5135
|
+
* the store automatically on `subscribeSentinel`; tests can omit it
|
|
5136
|
+
* when constructing a context literal for a first-order watcher.
|
|
5137
|
+
*
|
|
5138
|
+
* Multi-fortress isolation rides on the store's existing key shape:
|
|
5139
|
+
* the store is constructed per-fortress from the fortress master
|
|
5140
|
+
* key, so two fortresses' stores produce distinct ciphertext for
|
|
5141
|
+
* identical finding-ids and one fortress's read cannot decode
|
|
5142
|
+
* another fortress's findings.
|
|
5143
|
+
*/
|
|
5144
|
+
findingStore?: SentinelFindingStore;
|
|
5145
|
+
}
|
|
5146
|
+
/**
|
|
5147
|
+
* One observation a sentinel produced. Persisted under the sentinel
|
|
5148
|
+
* findings store + emitted as an audit event +
|
|
5149
|
+
* surfaced to the operator dashboard.
|
|
5150
|
+
*/
|
|
5151
|
+
interface SentinelFinding {
|
|
5152
|
+
/** Stable per-fortress finding id (UUID v4). */
|
|
5153
|
+
finding_id: string;
|
|
5154
|
+
/** Identifier of the sentinel that produced this finding. */
|
|
5155
|
+
sentinel_id: string;
|
|
5156
|
+
severity: SentinelSeverity;
|
|
5157
|
+
/**
|
|
5158
|
+
* Optional agent-id this finding pertains to. Absent when the finding
|
|
5159
|
+
* is fortress-wide (e.g. cross-agent chatter spike).
|
|
5160
|
+
*/
|
|
5161
|
+
agent_id?: string;
|
|
5162
|
+
/** Operator-friendly one-liner. Truncated to 240 chars on persist. */
|
|
5163
|
+
summary: string;
|
|
5164
|
+
/**
|
|
5165
|
+
* Structured payload. Schema varies per sentinel but every payload is
|
|
5166
|
+
* a flat record of JSON-serializable values.
|
|
5167
|
+
*/
|
|
5168
|
+
details: Record<string, unknown>;
|
|
5169
|
+
/** ISO 8601 timestamp at evaluation time. */
|
|
5170
|
+
observed_at: string;
|
|
5171
|
+
/**
|
|
5172
|
+
* Audit-log entries that triggered this finding. Sentinels populate
|
|
5173
|
+
* with `${entry.timestamp}:${entry.operation}` tuples (mirrors the
|
|
5174
|
+
* aggregator's audit_log_entry_id shape from Upsilon-1).
|
|
5175
|
+
*/
|
|
5176
|
+
evidence_audit_ids: string[];
|
|
5177
|
+
/** Stable fortress id stamped at emit. Multi-fortress isolation pivot. */
|
|
5178
|
+
fortress_id: string;
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
/**
|
|
5182
|
+
* Sanctuary v1.3 WP-V1.3-5 Pi-1 Honeypot Authoring types + audit ops.
|
|
5183
|
+
*
|
|
5184
|
+
* OPENS WP-V1.3-5 Honeypot Authoring. Operator writes a honeypot in
|
|
5185
|
+
* plain English; the compiler maps the English to a structured
|
|
5186
|
+
* TrapSpec; the runtime registers trap-handlers in the dashboard
|
|
5187
|
+
* route table; trap activations emit `honeypot_triggered` audit
|
|
5188
|
+
* events AND sentinel findings (Pi-1 reuses Phi-1's finding store so
|
|
5189
|
+
* traps surface in the existing sentinel UX).
|
|
5190
|
+
*
|
|
5191
|
+
* Pi-1 ships the http_endpoint trap class only; Pi-2 adds filesystem,
|
|
5192
|
+
* Pi-3 adds tool_call, Pi-4 adds credential. Architectural shape:
|
|
5193
|
+
* TrapSpec is a discriminated union keyed by `trap_class` so new
|
|
5194
|
+
* trap classes extend by adding a union arm + a runtime handler.
|
|
5195
|
+
*
|
|
5196
|
+
* Castle-walking discipline:
|
|
5197
|
+
* - Trap responses are server-local (404 or 500 returned to the
|
|
5198
|
+
* caller). No outbound surface from the trap path itself.
|
|
5199
|
+
* - The compile call routes through the substrate selector at the
|
|
5200
|
+
* `template-suggestion` surface (canonical outbound LLM channel
|
|
5201
|
+
* for template-shape generation; Rho-1 header strip applies).
|
|
5202
|
+
* - Trap findings route through the Phi-1 finding store, the
|
|
5203
|
+
* existing canonical pipeline for Castle Layer 2 observability.
|
|
5204
|
+
*/
|
|
5205
|
+
|
|
5206
|
+
/** Operator-friendly trap class enum. */
|
|
5207
|
+
type TrapClass = "http_endpoint" | "filesystem" | "tool_call" | "credential";
|
|
5208
|
+
/**
|
|
5209
|
+
* HTTP-endpoint trap trigger. The runtime matches incoming requests
|
|
5210
|
+
* against `path_pattern` (glob-style with `*` and `**`); `method`
|
|
5211
|
+
* narrows to a specific HTTP method when set, otherwise any method
|
|
5212
|
+
* fires. `expected_caller_types` is operator-recorded metadata that
|
|
5213
|
+
* surfaces in the finding's evidence; the runtime does not gate on
|
|
5214
|
+
* it (caller identity is observed, not constrained, at the trap
|
|
5215
|
+
* boundary).
|
|
5216
|
+
*/
|
|
5217
|
+
interface HttpEndpointTrigger {
|
|
5218
|
+
kind: "http_endpoint";
|
|
5219
|
+
path_pattern: string;
|
|
5220
|
+
method?: string;
|
|
5221
|
+
expected_caller_types: string[];
|
|
5222
|
+
}
|
|
5223
|
+
/**
|
|
5224
|
+
* Filesystem trap trigger (Pi-2). The runtime monitor observes
|
|
5225
|
+
* filesystem-shaped operations the operator declared sensitive and
|
|
5226
|
+
* fires when a matching operation is reported through
|
|
5227
|
+
* `FilesystemTrapMonitor.observe(...)`. Pi-2 ships the monitor as a
|
|
5228
|
+
* pure observation primitive; specific wiring (proxy-call accesses,
|
|
5229
|
+
* state-store reads, future tool-call instrumentation) attaches in
|
|
5230
|
+
* follow-up PRs by calling the monitor's observe API.
|
|
5231
|
+
*
|
|
5232
|
+
* `ops` declares which operations the operator cares about; an
|
|
5233
|
+
* `observe()` call whose `operation` is not in this set will not
|
|
5234
|
+
* fire the trap.
|
|
5235
|
+
*/
|
|
5236
|
+
interface FilesystemTrigger {
|
|
5237
|
+
kind: "filesystem";
|
|
5238
|
+
/**
|
|
5239
|
+
* Filesystem-path glob with `*` (one segment) / `**` (multiple
|
|
5240
|
+
* segments). Anchored at both ends per the Pi-1 glob contract.
|
|
5241
|
+
*/
|
|
5242
|
+
path_pattern: string;
|
|
5243
|
+
/** Operations the trap fires on. */
|
|
5244
|
+
ops: FilesystemOp[];
|
|
5245
|
+
/** Operator-recorded metadata; not gated on. */
|
|
5246
|
+
expected_caller_types: string[];
|
|
5247
|
+
}
|
|
5248
|
+
/** Filesystem operations recognized by the monitor. */
|
|
5249
|
+
type FilesystemOp = "read" | "write" | "delete" | "list";
|
|
5250
|
+
/**
|
|
5251
|
+
* Discriminated-union trigger keyed by `kind`. The outer `trap_class`
|
|
5252
|
+
* field on TrapSpec keeps the operator-facing taxonomy; the inner
|
|
5253
|
+
* `kind` discriminator on the trigger is what TypeScript narrows on
|
|
5254
|
+
* inside runtime handlers + the registry's matching code.
|
|
5255
|
+
*/
|
|
5256
|
+
type TrapTrigger = HttpEndpointTrigger | FilesystemTrigger;
|
|
5257
|
+
/**
|
|
5258
|
+
* One compiled trap. Persisted by the registry, deployed to the
|
|
5259
|
+
* runtime route table, and used by the finding emitter when a trap
|
|
5260
|
+
* triggers. Pi-1 shipped http_endpoint only; Pi-2 adds filesystem
|
|
5261
|
+
* via the `kind`-discriminated trigger union.
|
|
5262
|
+
*/
|
|
5263
|
+
interface TrapSpec {
|
|
5264
|
+
trap_id: string;
|
|
5265
|
+
trap_class: TrapClass;
|
|
5266
|
+
trigger: TrapTrigger;
|
|
5267
|
+
finding_severity: SentinelSeverity;
|
|
5268
|
+
english_text: string;
|
|
5269
|
+
explanation_paragraph: string;
|
|
5270
|
+
compiled_at: string;
|
|
5271
|
+
}
|
|
5272
|
+
|
|
5273
|
+
/**
|
|
5274
|
+
* Sanctuary v1.3 WP-V1.3-5 Pi-2 Trap Store.
|
|
5275
|
+
*
|
|
5276
|
+
* Encrypted at-rest persistence for deployed honeypot TrapSpecs.
|
|
5277
|
+
* Sibling to Phi-1's SentinelFindingStore: same fortress-master-key-
|
|
5278
|
+
* derived HKDF subkey shape, AAD-bound to the trap_id, per-fortress
|
|
5279
|
+
* scoped.
|
|
5280
|
+
*
|
|
5281
|
+
* Storage layout:
|
|
5282
|
+
* namespace: `_honeypot_traps`
|
|
5283
|
+
* key: `trap.{trap_id}` (one record per deployed trap)
|
|
5284
|
+
* payload: AES-256-GCM ciphertext of the JSON-serialized spec.
|
|
5285
|
+
* key: `l2-honeypot-trap-v1` HKDF subkey of fortress master.
|
|
5286
|
+
* AAD: UTF-8 bytes of `trap_id`.
|
|
5287
|
+
*
|
|
5288
|
+
* Multi-fortress isolation: HKDF subkey derives from the fortress
|
|
5289
|
+
* master key. Two fortresses never produce identical encryption keys
|
|
5290
|
+
* for identical trap_ids; a fortress that reads another fortress's
|
|
5291
|
+
* encrypted record cannot decrypt it.
|
|
5292
|
+
*
|
|
5293
|
+
* Persistence contract:
|
|
5294
|
+
* - save(spec): write the spec under its trap_id. Idempotent;
|
|
5295
|
+
* re-saves overwrite.
|
|
5296
|
+
* - delete(trapId): remove the record. Idempotent.
|
|
5297
|
+
* - loadAll(): rehydrate every persisted spec. Used at boot to
|
|
5298
|
+
* populate the in-memory TrapRegistry. Corrupted records are
|
|
5299
|
+
* dropped (best-effort recovery: a malformed entry should not
|
|
5300
|
+
* block the rest of the fortress).
|
|
5301
|
+
*
|
|
5302
|
+
* Pi-2 ships traps with no retention window (traps stay deployed
|
|
5303
|
+
* until explicitly undeployed). The store mirrors SentinelFindingStore's
|
|
5304
|
+
* AES-256-GCM envelope shape but omits retention deadlines.
|
|
5305
|
+
*/
|
|
5306
|
+
|
|
5307
|
+
interface TrapStoreOptions {
|
|
5308
|
+
storage: StorageBackend;
|
|
5309
|
+
masterKey: Uint8Array;
|
|
5310
|
+
fortressId: string;
|
|
5311
|
+
}
|
|
5312
|
+
declare class TrapStore {
|
|
5313
|
+
private readonly storage;
|
|
5314
|
+
private readonly encryptionKey;
|
|
5315
|
+
private readonly fortressId;
|
|
5316
|
+
constructor(opts: TrapStoreOptions);
|
|
5317
|
+
/** Persist (or overwrite) one trap. Returns the trap_id on success. */
|
|
5318
|
+
save(spec: TrapSpec): Promise<string>;
|
|
5319
|
+
/**
|
|
5320
|
+
* Remove one trap by id. Returns true when a record was removed,
|
|
5321
|
+
* false when no record existed (idempotent).
|
|
5322
|
+
*/
|
|
5323
|
+
delete(trapId: string): Promise<boolean>;
|
|
5324
|
+
/**
|
|
5325
|
+
* Load every persisted trap. Used at boot to repopulate the
|
|
5326
|
+
* in-memory TrapRegistry. Corrupted records are silently skipped
|
|
5327
|
+
* so one malformed entry never blocks the rest of the fortress's
|
|
5328
|
+
* traps from rehydrating.
|
|
5329
|
+
*
|
|
5330
|
+
* Returns the specs sorted by `compiled_at` ascending so the
|
|
5331
|
+
* in-memory registry's insertion order matches the original
|
|
5332
|
+
* deploy order (relevant for Pi-1's "first-deployed wins on
|
|
5333
|
+
* overlapping match" contract).
|
|
5334
|
+
*/
|
|
5335
|
+
loadAll(): Promise<TrapSpec[]>;
|
|
5336
|
+
/** Read-only fortress-id getter. */
|
|
5337
|
+
getFortressId(): string;
|
|
5338
|
+
private decode;
|
|
5339
|
+
}
|
|
5340
|
+
|
|
5341
|
+
/**
|
|
5342
|
+
* Sanctuary MCP Server — SHR Generator
|
|
5343
|
+
*
|
|
5344
|
+
* Generates a Sovereignty Health Report from current server state,
|
|
5345
|
+
* signs it with a specified identity, and returns the complete signed SHR.
|
|
5346
|
+
*/
|
|
5347
|
+
|
|
5348
|
+
/**
|
|
5349
|
+
* Observed L4 reputation state used by the emitter. Callers gather these
|
|
5350
|
+
* facts from the reputation store + audit log; the emitter derives
|
|
5351
|
+
* degradations from them. Keeping evidence as plain data keeps the
|
|
5352
|
+
* generator synchronous and easy to test.
|
|
5353
|
+
*/
|
|
5354
|
+
interface L4Evidence {
|
|
5355
|
+
/** Total attestations attributed to the signing identity */
|
|
5356
|
+
attestation_count: number;
|
|
5357
|
+
/** Count of attestations at each sovereignty tier */
|
|
5358
|
+
tier_distribution: Record<SovereigntyTier, number>;
|
|
5359
|
+
/** ISO timestamp of most recent attestation, or null when none exist */
|
|
5360
|
+
most_recent_attestation_at: string | null;
|
|
5361
|
+
/** Count of attestations with outcome_result === "disputed" */
|
|
5362
|
+
dispute_count: number;
|
|
5363
|
+
/** Attestation count per context label (optional; used by dashboard) */
|
|
5364
|
+
context_breakdown?: Record<string, number>;
|
|
5365
|
+
/**
|
|
5366
|
+
* True iff the `reputation_publish` tool has been successfully invoked
|
|
5367
|
+
* for this identity (i.e., there is at least one success audit entry).
|
|
5368
|
+
*/
|
|
5369
|
+
verascore_linked: boolean;
|
|
5370
|
+
/**
|
|
5371
|
+
* Optional overrides for the emitter thresholds. Defaults apply when
|
|
5372
|
+
* omitted or when a field is missing.
|
|
5373
|
+
*/
|
|
5374
|
+
thresholds?: {
|
|
5375
|
+
freshness_window_days?: number;
|
|
5376
|
+
low_tier_dominance_threshold?: number;
|
|
5377
|
+
};
|
|
5378
|
+
}
|
|
5379
|
+
interface SHRGeneratorOptions {
|
|
5380
|
+
config: SanctuaryConfig;
|
|
5381
|
+
identityManager: IdentityManager;
|
|
5382
|
+
masterKey: Uint8Array;
|
|
5383
|
+
/** Override validity window (milliseconds). Default: 1 hour. */
|
|
5384
|
+
validityMs?: number;
|
|
5385
|
+
/**
|
|
5386
|
+
* Optional L4 reputation evidence. When provided, the generator emits
|
|
5387
|
+
* L4 degradations (NO_REPUTATION_HISTORY, LOW_TIER_DOMINANCE,
|
|
5388
|
+
* STALE_REPUTATION, DISPUTE_ON_RECORD, NO_VERASCORE_LINK) accordingly
|
|
5389
|
+
* and downgrades `layers.l4.status` to `degraded` when any fire.
|
|
5390
|
+
* When omitted, L4 is left at "active" (backward-compatible).
|
|
5391
|
+
*/
|
|
5392
|
+
l4Evidence?: L4Evidence;
|
|
5113
5393
|
/**
|
|
5114
|
-
*
|
|
5115
|
-
*
|
|
5116
|
-
* without exposing the AuditLog binding directly to redactor
|
|
5117
|
-
* implementations.
|
|
5394
|
+
* Clock override for deterministic testing of staleness behavior.
|
|
5395
|
+
* Defaults to the current wall clock.
|
|
5118
5396
|
*/
|
|
5119
|
-
|
|
5120
|
-
surface: Surface;
|
|
5121
|
-
substrate: SubstrateChoice;
|
|
5122
|
-
matchCount: number;
|
|
5123
|
-
filterTier: 1 | 2;
|
|
5124
|
-
}): void;
|
|
5125
|
-
private emit;
|
|
5397
|
+
now?: Date;
|
|
5126
5398
|
}
|
|
5399
|
+
/**
|
|
5400
|
+
* Generate and sign a Sovereignty Health Report.
|
|
5401
|
+
*
|
|
5402
|
+
* @param identityId - Which identity to sign with (defaults to primary)
|
|
5403
|
+
* @param opts - Generator dependencies
|
|
5404
|
+
* @returns The signed SHR, or an error string
|
|
5405
|
+
*/
|
|
5406
|
+
declare function generateSHR(identityId: string | undefined, opts: SHRGeneratorOptions): SignedSHR | string;
|
|
5407
|
+
|
|
5408
|
+
/**
|
|
5409
|
+
* Sanctuary v1.1 Operator Hub API Constants
|
|
5410
|
+
*
|
|
5411
|
+
* Routes, prefixes, and small enums shared across the hub modules.
|
|
5412
|
+
* The hub API surface is consumed by the v1.1 dashboard UI (Prompt 8).
|
|
5413
|
+
*
|
|
5414
|
+
* Local-only invariant:
|
|
5415
|
+
* Every route here describes activity inside a single fortress on a single
|
|
5416
|
+
* operator's machine. Cross-fortress, fleet, and public-federation routes
|
|
5417
|
+
* are out of scope.
|
|
5418
|
+
*/
|
|
5419
|
+
|
|
5420
|
+
/**
|
|
5421
|
+
* Inbox-resolve actions. The router rejects any other action token.
|
|
5422
|
+
*/
|
|
5423
|
+
declare const HUB_INBOX_ACTIONS: readonly ["approve", "deny", "dismiss"];
|
|
5424
|
+
type HubInboxAction = (typeof HUB_INBOX_ACTIONS)[number];
|
|
5425
|
+
/**
|
|
5426
|
+
* Agent-control actions surfaced by `POST /api/hub/agents/:id/:action`.
|
|
5427
|
+
*
|
|
5428
|
+
* `pause` / `resume` / `restart` are control-plane operations that the
|
|
5429
|
+
* underlying harness may execute immediately; they are not Tier 1.
|
|
5430
|
+
*
|
|
5431
|
+
* `unwrap` and `lockdown` are Tier 1 operations per the Principal Policy
|
|
5432
|
+
* loader. Hub endpoints for these MUST enqueue an `approval_pending` inbox
|
|
5433
|
+
* item rather than execute directly. Tier 1 approval gates remain in force
|
|
5434
|
+
* from the dashboard. The dashboard never auto-approves Tier 1 work.
|
|
5435
|
+
*/
|
|
5436
|
+
declare const HUB_AGENT_CONTROL_ACTIONS: readonly ["pause", "resume", "restart", "unwrap", "lockdown"];
|
|
5437
|
+
type HubAgentControlAction = (typeof HUB_AGENT_CONTROL_ACTIONS)[number];
|
|
5438
|
+
|
|
5439
|
+
/** Channel-template identifiers per the five-template canonical starter set. */
|
|
5440
|
+
declare const CHANNEL_TEMPLATE_IDS: readonly ["request-approve-act", "read-then-report", "scheduled-digest", "plan-draft-only", "fortress-relay"];
|
|
5441
|
+
type ChannelTemplateId = (typeof CHANNEL_TEMPLATE_IDS)[number];
|
|
5127
5442
|
|
|
5128
5443
|
/**
|
|
5129
5444
|
* Sanctuary MCP Server — Operator Chat Types
|
|
@@ -7258,161 +7573,6 @@ declare class ApprovalAggregator {
|
|
|
7258
7573
|
private hydrate;
|
|
7259
7574
|
}
|
|
7260
7575
|
|
|
7261
|
-
/**
|
|
7262
|
-
* Sanctuary v1.3 WP-V1.3-1 Sentinel Finding Store.
|
|
7263
|
-
*
|
|
7264
|
-
* Encrypted at-rest persistence for sentinel findings. Sibling to the
|
|
7265
|
-
* Upsilon-3 aggregator-store: same fortress-master-key-derived HKDF
|
|
7266
|
-
* subkey shape, AAD-bound to the finding_id, retention-aware.
|
|
7267
|
-
*
|
|
7268
|
-
* Storage layout:
|
|
7269
|
-
* namespace: `_sentinel_findings`
|
|
7270
|
-
* key: `finding.{finding_id}` (one record per finding)
|
|
7271
|
-
* payload: AES-256-GCM ciphertext of the JSON-serialized record.
|
|
7272
|
-
* key: `l2-sentinel-finding-v1` HKDF subkey of fortress master.
|
|
7273
|
-
* AAD: UTF-8 bytes of `finding_id`.
|
|
7274
|
-
*
|
|
7275
|
-
* Multi-fortress isolation: HKDF subkey derives from the fortress
|
|
7276
|
-
* master key. Two fortresses never produce identical encryption keys
|
|
7277
|
-
* for identical finding_ids.
|
|
7278
|
-
*
|
|
7279
|
-
* Retention: 30 days default, mirroring the audit-log envelope and the
|
|
7280
|
-
* aggregator payload store.
|
|
7281
|
-
*/
|
|
7282
|
-
|
|
7283
|
-
interface SentinelFindingStoreOptions {
|
|
7284
|
-
storage: StorageBackend;
|
|
7285
|
-
masterKey: Uint8Array;
|
|
7286
|
-
fortressId: string;
|
|
7287
|
-
/** Operator-tunable retention window. Default 30 days. */
|
|
7288
|
-
retentionDays?: number;
|
|
7289
|
-
/** Wall-clock provider for deterministic tests. */
|
|
7290
|
-
now?: () => Date;
|
|
7291
|
-
}
|
|
7292
|
-
declare class SentinelFindingStore {
|
|
7293
|
-
private readonly storage;
|
|
7294
|
-
private readonly encryptionKey;
|
|
7295
|
-
private readonly fortressId;
|
|
7296
|
-
private readonly retentionDays;
|
|
7297
|
-
private readonly now;
|
|
7298
|
-
constructor(opts: SentinelFindingStoreOptions);
|
|
7299
|
-
/**
|
|
7300
|
-
* Persist a finding. Truncates the operator-visible summary to
|
|
7301
|
-
* SENTINEL_SUMMARY_MAX_CHARS so the dashboard render stays bounded.
|
|
7302
|
-
* Returns the retention deadline so callers can audit it.
|
|
7303
|
-
*/
|
|
7304
|
-
saveFinding(finding: SentinelFinding): Promise<string>;
|
|
7305
|
-
/** Load a single finding by id, or null when absent / corrupted. */
|
|
7306
|
-
loadFinding(findingId: string): Promise<SentinelFinding | null>;
|
|
7307
|
-
/**
|
|
7308
|
-
* List findings, newest first. Optional filters: since (ISO 8601),
|
|
7309
|
-
* severity, sentinel_id, agent_id, limit. Default limit 100.
|
|
7310
|
-
*/
|
|
7311
|
-
listFindings(opts?: {
|
|
7312
|
-
since?: string;
|
|
7313
|
-
severity?: SentinelSeverity;
|
|
7314
|
-
sentinelId?: string;
|
|
7315
|
-
agentId?: string;
|
|
7316
|
-
limit?: number;
|
|
7317
|
-
}): Promise<SentinelFinding[]>;
|
|
7318
|
-
/**
|
|
7319
|
-
* Drop expired findings. Returns the count removed.
|
|
7320
|
-
*/
|
|
7321
|
-
pruneExpired(now?: Date): Promise<{
|
|
7322
|
-
pruned: number;
|
|
7323
|
-
}>;
|
|
7324
|
-
private decode;
|
|
7325
|
-
}
|
|
7326
|
-
|
|
7327
|
-
/**
|
|
7328
|
-
* Sanctuary v1.3 WP-V1.3-1 Sentinel Baseline Pack (Castle Layer 2 anchor)
|
|
7329
|
-
*
|
|
7330
|
-
* Shared types for the Sentinel observation surface.
|
|
7331
|
-
*
|
|
7332
|
-
* Castle-walking discipline:
|
|
7333
|
-
* - Castle Layer 1 (Castle Wall) blocks unauthorized egress at the kernel
|
|
7334
|
-
* boundary. That is the enforcement layer.
|
|
7335
|
-
* - Castle Layer 2 (Sentinels) observes server-local data only and surfaces
|
|
7336
|
-
* anomalies. NO outbound network. NO blocking. Findings flow into the
|
|
7337
|
-
* operator surface they already check.
|
|
7338
|
-
* - Castle Layer 3 (Cooperative MCP) is the agent contract. Sentinels do
|
|
7339
|
-
* not wrap agent tools and do not negotiate with agents.
|
|
7340
|
-
*
|
|
7341
|
-
* Phi-1 ships the framework + the egress-volume watcher. Phi-2 through
|
|
7342
|
-
* Phi-5 add credential-usage, cross-agent-chatter, suspicious-tool-call,
|
|
7343
|
-
* and anomaly-trigger sentinels against this same shape.
|
|
7344
|
-
*/
|
|
7345
|
-
|
|
7346
|
-
/** Severity tier returned by `Sentinel.evaluate()`. */
|
|
7347
|
-
type SentinelSeverity = "info" | "warn" | "alert";
|
|
7348
|
-
/**
|
|
7349
|
-
* Read-only context handed to every sentinel on subscribe + evaluate.
|
|
7350
|
-
* Sentinels do NOT receive a writable storage handle and do NOT receive
|
|
7351
|
-
* an outbound HTTP client. The substrate selector is the single
|
|
7352
|
-
* outbound-capable surface; Phi-1 sentinels do not exercise it but
|
|
7353
|
-
* Phi-2/3/4/5 may want to invoke a local LLM for reasoning.
|
|
7354
|
-
*/
|
|
7355
|
-
interface SentinelContext {
|
|
7356
|
-
/** Stable per-fortress identifier; multi-fortress isolation pivot. */
|
|
7357
|
-
fortressId: string;
|
|
7358
|
-
/** Audit log read API. Sentinels MUST NOT call append() through this. */
|
|
7359
|
-
auditLog: AuditLog;
|
|
7360
|
-
/** Optional substrate selector for LLM-backed reasoning. v1.3 Phi-1 unused. */
|
|
7361
|
-
substrateSelector?: SubstrateSelector;
|
|
7362
|
-
/** Wall-clock provider. Tests inject a deterministic clock. */
|
|
7363
|
-
now: () => Date;
|
|
7364
|
-
/**
|
|
7365
|
-
* Optional read view of the per-fortress sentinel finding store
|
|
7366
|
-
* (Phi-1 surface). First-order sentinels (Phi-1/2/3/4) do not need
|
|
7367
|
-
* this; the Phi-5 meta-sentinel reads it to detect patterns ACROSS
|
|
7368
|
-
* other sentinels' findings (compound finding, fortress-wide count
|
|
7369
|
-
* spikes, novel sentinel-ID combinations). The dispatcher attaches
|
|
7370
|
-
* the store automatically on `subscribeSentinel`; tests can omit it
|
|
7371
|
-
* when constructing a context literal for a first-order watcher.
|
|
7372
|
-
*
|
|
7373
|
-
* Multi-fortress isolation rides on the store's existing key shape:
|
|
7374
|
-
* the store is constructed per-fortress from the fortress master
|
|
7375
|
-
* key, so two fortresses' stores produce distinct ciphertext for
|
|
7376
|
-
* identical finding-ids and one fortress's read cannot decode
|
|
7377
|
-
* another fortress's findings.
|
|
7378
|
-
*/
|
|
7379
|
-
findingStore?: SentinelFindingStore;
|
|
7380
|
-
}
|
|
7381
|
-
/**
|
|
7382
|
-
* One observation a sentinel produced. Persisted under the sentinel
|
|
7383
|
-
* findings store + emitted as an audit event +
|
|
7384
|
-
* surfaced to the operator dashboard.
|
|
7385
|
-
*/
|
|
7386
|
-
interface SentinelFinding {
|
|
7387
|
-
/** Stable per-fortress finding id (UUID v4). */
|
|
7388
|
-
finding_id: string;
|
|
7389
|
-
/** Identifier of the sentinel that produced this finding. */
|
|
7390
|
-
sentinel_id: string;
|
|
7391
|
-
severity: SentinelSeverity;
|
|
7392
|
-
/**
|
|
7393
|
-
* Optional agent-id this finding pertains to. Absent when the finding
|
|
7394
|
-
* is fortress-wide (e.g. cross-agent chatter spike).
|
|
7395
|
-
*/
|
|
7396
|
-
agent_id?: string;
|
|
7397
|
-
/** Operator-friendly one-liner. Truncated to 240 chars on persist. */
|
|
7398
|
-
summary: string;
|
|
7399
|
-
/**
|
|
7400
|
-
* Structured payload. Schema varies per sentinel but every payload is
|
|
7401
|
-
* a flat record of JSON-serializable values.
|
|
7402
|
-
*/
|
|
7403
|
-
details: Record<string, unknown>;
|
|
7404
|
-
/** ISO 8601 timestamp at evaluation time. */
|
|
7405
|
-
observed_at: string;
|
|
7406
|
-
/**
|
|
7407
|
-
* Audit-log entries that triggered this finding. Sentinels populate
|
|
7408
|
-
* with `${entry.timestamp}:${entry.operation}` tuples (mirrors the
|
|
7409
|
-
* aggregator's audit_log_entry_id shape from Upsilon-1).
|
|
7410
|
-
*/
|
|
7411
|
-
evidence_audit_ids: string[];
|
|
7412
|
-
/** Stable fortress id stamped at emit. Multi-fortress isolation pivot. */
|
|
7413
|
-
fortress_id: string;
|
|
7414
|
-
}
|
|
7415
|
-
|
|
7416
7576
|
/**
|
|
7417
7577
|
* Sanctuary v1.3 WP-V1.3-1 Sentinel base class.
|
|
7418
7578
|
*
|
|
@@ -8035,6 +8195,69 @@ declare class HandoffEventBridge {
|
|
|
8035
8195
|
emit(entry: HandoffEntry): void;
|
|
8036
8196
|
}
|
|
8037
8197
|
|
|
8198
|
+
/**
|
|
8199
|
+
* Sanctuary v1.3 WP-V1.3-5 Pi-1 Trap Registry.
|
|
8200
|
+
*
|
|
8201
|
+
* Per-fortress in-memory registry of deployed honeypot traps. Holds
|
|
8202
|
+
* the live TrapSpec set + provides path-matching for the runtime
|
|
8203
|
+
* dispatcher.
|
|
8204
|
+
*
|
|
8205
|
+
* Lifecycle:
|
|
8206
|
+
* deploy(spec): activates the trap; idempotent on trap_id.
|
|
8207
|
+
* undeploy(trapId): removes the trap; returns whether anything
|
|
8208
|
+
* was actually removed (idempotent).
|
|
8209
|
+
* list(): returns the live trap set as a fresh array.
|
|
8210
|
+
* findMatching(path,m): returns the first trap matching the request.
|
|
8211
|
+
*
|
|
8212
|
+
* Castle-walking discipline:
|
|
8213
|
+
* - Read-only path against deployed traps; mutating calls land here
|
|
8214
|
+
* deliberately from the management routes.
|
|
8215
|
+
* - No outbound surface; the registry is purely server-local state.
|
|
8216
|
+
* - Per-fortress isolation: one registry instance per fortress. The
|
|
8217
|
+
* dispatcher wires one registry per dashboard instance.
|
|
8218
|
+
*
|
|
8219
|
+
* Path-matching glob:
|
|
8220
|
+
* * matches one path segment (no slashes)
|
|
8221
|
+
* ** matches multiple path segments (zero or more, including
|
|
8222
|
+
* slashes)
|
|
8223
|
+
* anything else is a literal character. The pattern is anchored at
|
|
8224
|
+
* both ends so `/admin` does NOT match `/admin/foo`; the operator
|
|
8225
|
+
* must use `/admin/**` to match prefix-style.
|
|
8226
|
+
*/
|
|
8227
|
+
|
|
8228
|
+
interface TrapMatchInput {
|
|
8229
|
+
/** Request URL path. */
|
|
8230
|
+
path: string;
|
|
8231
|
+
/** Uppercased HTTP method. */
|
|
8232
|
+
method: string;
|
|
8233
|
+
}
|
|
8234
|
+
declare class TrapRegistry {
|
|
8235
|
+
private readonly traps;
|
|
8236
|
+
/**
|
|
8237
|
+
* Deploy a trap. Idempotent on `trap_id`: re-deploying replaces the
|
|
8238
|
+
* previous spec for that id. Returns true on first deploy, false on
|
|
8239
|
+
* re-deploy (so callers can branch audit emission).
|
|
8240
|
+
*/
|
|
8241
|
+
deploy(spec: TrapSpec): boolean;
|
|
8242
|
+
/**
|
|
8243
|
+
* Undeploy by trap_id. Returns true when a trap was removed, false
|
|
8244
|
+
* when no trap had that id (idempotent).
|
|
8245
|
+
*/
|
|
8246
|
+
undeploy(trapId: string): boolean;
|
|
8247
|
+
/** List deployed traps. Returns a fresh array; mutation is safe. */
|
|
8248
|
+
list(): TrapSpec[];
|
|
8249
|
+
/** Look up a single trap by id. */
|
|
8250
|
+
get(trapId: string): TrapSpec | undefined;
|
|
8251
|
+
/**
|
|
8252
|
+
* Find the first trap matching the request. Iteration order is
|
|
8253
|
+
* insertion order; operators who deploy multiple overlapping traps
|
|
8254
|
+
* see the earliest-deployed one fire. Tests cover this contract.
|
|
8255
|
+
*/
|
|
8256
|
+
findMatching(input: TrapMatchInput): TrapSpec | undefined;
|
|
8257
|
+
/** Drop every trap. Tests use this between runs; not surfaced via API. */
|
|
8258
|
+
clear(): void;
|
|
8259
|
+
}
|
|
8260
|
+
|
|
8038
8261
|
interface DashboardConfig {
|
|
8039
8262
|
port: number;
|
|
8040
8263
|
host: string;
|
|
@@ -8131,6 +8354,13 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
8131
8354
|
private workflowStateTracker;
|
|
8132
8355
|
private handoffAuditLog;
|
|
8133
8356
|
private handoffOperatorId;
|
|
8357
|
+
private honeypotRegistry;
|
|
8358
|
+
private honeypotFindingStore;
|
|
8359
|
+
private honeypotAuditLog;
|
|
8360
|
+
private honeypotOperatorId;
|
|
8361
|
+
private honeypotFortressId;
|
|
8362
|
+
private honeypotSelector;
|
|
8363
|
+
private honeypotStore;
|
|
8134
8364
|
constructor(config: DashboardConfig);
|
|
8135
8365
|
/**
|
|
8136
8366
|
* Inject dependencies after construction.
|
|
@@ -8199,6 +8429,38 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
8199
8429
|
*/
|
|
8200
8430
|
workflowStateTracker?: WorkflowStateTracker | null;
|
|
8201
8431
|
}): void;
|
|
8432
|
+
/**
|
|
8433
|
+
* v1.3 WP-V1.3-5 Pi-1 Honeypot Authoring: bind the per-fortress
|
|
8434
|
+
* trap registry + finding store + audit log + operator id. Once
|
|
8435
|
+
* set, two surfaces activate:
|
|
8436
|
+
* 1. Front-of-dispatch trap-trigger hook: every request runs
|
|
8437
|
+
* through `handleHoneypotTriggerIfMatch` BEFORE legacy/v1.1/
|
|
8438
|
+
* sentinel/coordination routing. Matching traps return 404
|
|
8439
|
+
* and the request never reaches the regular dispatcher.
|
|
8440
|
+
* 2. Management API at /api/honeypot/* routes through
|
|
8441
|
+
* `handleHoneypotRoute`.
|
|
8442
|
+
*
|
|
8443
|
+
* The optional `selector` opt wires the LLM compile path; absent
|
|
8444
|
+
* selector forces the heuristic compile path (which still produces
|
|
8445
|
+
* a usable TrapSpec with warnings).
|
|
8446
|
+
*/
|
|
8447
|
+
setHoneypotRegistry(opts: {
|
|
8448
|
+
registry: TrapRegistry | null;
|
|
8449
|
+
findingStore?: SentinelFindingStore | null;
|
|
8450
|
+
auditLog?: AuditLog | null;
|
|
8451
|
+
operatorId?: string | null;
|
|
8452
|
+
fortressId?: string | null;
|
|
8453
|
+
selector?: SubstrateSelector | null;
|
|
8454
|
+
/**
|
|
8455
|
+
* Pi-2: encrypted at-rest persistence for the deployed traps. When
|
|
8456
|
+
* non-null, the management API's deploy + undeploy handlers write
|
|
8457
|
+
* through to the store so the fortress keeps its trap deployment
|
|
8458
|
+
* across restart. Boot rehydration is the host's responsibility:
|
|
8459
|
+
* call `store.loadAll()` and `registry.deploy(spec)` for each
|
|
8460
|
+
* persisted spec BEFORE calling this method.
|
|
8461
|
+
*/
|
|
8462
|
+
store?: TrapStore | null;
|
|
8463
|
+
}): void;
|
|
8202
8464
|
/**
|
|
8203
8465
|
* v1.3 WP-V1.3-10 dispatch entry point. Called from `handleRequest`
|
|
8204
8466
|
* before the legacy approval route table. Returns true when served.
|
|
@@ -8216,6 +8478,21 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
8216
8478
|
* when a HandoffLog has been bound. Returns true when served.
|
|
8217
8479
|
*/
|
|
8218
8480
|
private dispatchCoordination;
|
|
8481
|
+
/**
|
|
8482
|
+
* v1.3 WP-V1.3-5 Pi-1 dispatch entry point. Routes
|
|
8483
|
+
* `/api/honeypot/*` requests through the honeypot management
|
|
8484
|
+
* router when a registry has been bound. Returns true when served.
|
|
8485
|
+
*/
|
|
8486
|
+
private dispatchHoneypot;
|
|
8487
|
+
/**
|
|
8488
|
+
* v1.3 WP-V1.3-5 Pi-1 front-of-dispatch trap-trigger hook. Examines
|
|
8489
|
+
* every request BEFORE legacy/v1.1/sentinel/coordination routing.
|
|
8490
|
+
* Returns true when a deployed trap matched the request and the
|
|
8491
|
+
* handler emitted the audit event + sentinel finding + plausible
|
|
8492
|
+
* 404 response. Returns false when no trap matched; caller
|
|
8493
|
+
* continues with normal routing.
|
|
8494
|
+
*/
|
|
8495
|
+
private dispatchHoneypotTrap;
|
|
8219
8496
|
/**
|
|
8220
8497
|
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
8221
8498
|
* legacy route table. Returns true when the request was served by v1.1
|
|
@@ -8302,6 +8579,14 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
8302
8579
|
*/
|
|
8303
8580
|
private pruneRateLimits;
|
|
8304
8581
|
private handleRequest;
|
|
8582
|
+
/**
|
|
8583
|
+
* v1.3 WP-V1.3-5 Pi-1: post-honeypot-trap request continuation. The
|
|
8584
|
+
* front-of-dispatch trap-trigger hook may short-circuit a request;
|
|
8585
|
+
* when it does not, this method runs the original dispatch ladder.
|
|
8586
|
+
* Pulled out as a helper so the trap-hook + non-trap paths share
|
|
8587
|
+
* one code path through every downstream dispatcher.
|
|
8588
|
+
*/
|
|
8589
|
+
private continueHandleRequest;
|
|
8305
8590
|
private handleLegacyRequest;
|
|
8306
8591
|
/**
|
|
8307
8592
|
* SEC-012: Exchange a long-lived auth token (in Authorization header)
|