@sanctuary-framework/mcp-server 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +20801 -17906
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +20804 -17909
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +19373 -16889
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +852 -0
- package/dist/index.d.ts +852 -0
- package/dist/index.js +19374 -16890
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2204,6 +2204,21 @@ type PrivacyAction = (typeof PRIVACY_ACTIONS)[number];
|
|
|
2204
2204
|
*/
|
|
2205
2205
|
declare const PRIVACY_HASH_ALGS: readonly ["hmac-sha256-fortress-keyed-v1"];
|
|
2206
2206
|
type PrivacyHashAlg = (typeof PRIVACY_HASH_ALGS)[number];
|
|
2207
|
+
/**
|
|
2208
|
+
* Hub inbox item kinds. Hub API and dashboard consume the same enum so the
|
|
2209
|
+
* unified inbox renders without inventing new categories per surface.
|
|
2210
|
+
*/
|
|
2211
|
+
declare const HUB_INBOX_KINDS: readonly ["approval_pending", "blocked_egress", "privacy_event", "budget_warning", "recovery_prompt", "agent_error"];
|
|
2212
|
+
type HubInboxKind = (typeof HUB_INBOX_KINDS)[number];
|
|
2213
|
+
/**
|
|
2214
|
+
* Agent lifecycle states surfaced to the operator hub.
|
|
2215
|
+
*
|
|
2216
|
+
* Underlying harness capability dictates which transitions are reachable; the
|
|
2217
|
+
* hub API surfaces unsupported transitions as "not_supported" rather than
|
|
2218
|
+
* faking them.
|
|
2219
|
+
*/
|
|
2220
|
+
declare const HUB_AGENT_STATUSES: readonly ["active", "paused", "restarting", "locked_down", "unwrapping", "error", "unknown"];
|
|
2221
|
+
type HubAgentStatus = (typeof HUB_AGENT_STATUSES)[number];
|
|
2207
2222
|
/**
|
|
2208
2223
|
* Exit-bundle manifest version. v1 is the only valid value at v1.1 ship.
|
|
2209
2224
|
* v1.x bumps require coordinator-approved manifest amendment.
|
|
@@ -2909,6 +2924,410 @@ interface PrivacyRehydratedPayload extends PrivacyAuditPayloadHeader {
|
|
|
2909
2924
|
*/
|
|
2910
2925
|
type PrivacyAuditPayload = PrivacyFilteredPayload | PrivacyAllowedPayload | PrivacyDeniedPayload | PrivacyErrorPayload | PrivacyRehydratedPayload;
|
|
2911
2926
|
|
|
2927
|
+
/**
|
|
2928
|
+
* Sanctuary v1.1 — Operator Hub Event Contracts
|
|
2929
|
+
*
|
|
2930
|
+
* Shared shapes for the unified inbox, the activity feed, and the per-agent
|
|
2931
|
+
* status panels. The operator hub API workstream (Prompt 5) emits these; the
|
|
2932
|
+
* dashboard UI workstream (Prompt 8) consumes them. v1.2 mobile companion
|
|
2933
|
+
* planning will evaluate these shapes when it scopes a phone surface, but
|
|
2934
|
+
* v1.1 does not commit to mobile compatibility — these contracts are
|
|
2935
|
+
* tuned for the local dashboard surface only.
|
|
2936
|
+
*
|
|
2937
|
+
* Local-only invariant:
|
|
2938
|
+
* Every event in this file describes activity inside a single fortress on a
|
|
2939
|
+
* single operator's machine. Cross-fortress, fleet, and public-federation
|
|
2940
|
+
* events are out of scope.
|
|
2941
|
+
*
|
|
2942
|
+
* Safe-metadata invariant:
|
|
2943
|
+
* No raw sensitive content in any field. Inbox cards may carry display titles
|
|
2944
|
+
* and subtitles, but those titles MUST be derived from policy templates and
|
|
2945
|
+
* MUST NOT contain raw query text, tool args, filenames, client names,
|
|
2946
|
+
* passphrases, or secrets.
|
|
2947
|
+
*/
|
|
2948
|
+
|
|
2949
|
+
/**
|
|
2950
|
+
* Allowed value space for `display_template_args`. Only safe primitives plus
|
|
2951
|
+
* a small enumerated value set are permitted. Free-form strings ARE NOT
|
|
2952
|
+
* accepted; the dashboard rejects rendering on any value outside this union.
|
|
2953
|
+
*
|
|
2954
|
+
* The renderer treats every value as data to interpolate into a fixed
|
|
2955
|
+
* template registered under `template_id` — never as raw content. This
|
|
2956
|
+
* defends against secrets, query text, file paths, and client names leaking
|
|
2957
|
+
* into inbox cards via stringly-typed display fields.
|
|
2958
|
+
*/
|
|
2959
|
+
type HubDisplayTemplateArg = {
|
|
2960
|
+
kind: "agent_id";
|
|
2961
|
+
value: string;
|
|
2962
|
+
} | {
|
|
2963
|
+
kind: "identity_id";
|
|
2964
|
+
value: string;
|
|
2965
|
+
} | {
|
|
2966
|
+
kind: "policy_id";
|
|
2967
|
+
value: string;
|
|
2968
|
+
} | {
|
|
2969
|
+
kind: "destination_category";
|
|
2970
|
+
value: PrivacyDestinationCategory;
|
|
2971
|
+
} | {
|
|
2972
|
+
kind: "tier";
|
|
2973
|
+
value: "tier1" | "tier2" | "tier3";
|
|
2974
|
+
} | {
|
|
2975
|
+
kind: "count";
|
|
2976
|
+
value: number;
|
|
2977
|
+
} | {
|
|
2978
|
+
kind: "iso8601";
|
|
2979
|
+
value: string;
|
|
2980
|
+
} | {
|
|
2981
|
+
kind: "duration_ms";
|
|
2982
|
+
value: number;
|
|
2983
|
+
};
|
|
2984
|
+
/**
|
|
2985
|
+
* Common header on every v1.1 hub inbox item.
|
|
2986
|
+
*
|
|
2987
|
+
* Display rendering uses a `template_id` plus typed args, NOT free-form
|
|
2988
|
+
* strings. The dashboard owns the template registry; backends only emit the
|
|
2989
|
+
* id and the args. This makes secret-leakage into inbox copy structurally
|
|
2990
|
+
* impossible: a backend cannot smuggle raw query content into a card by
|
|
2991
|
+
* accident, because there is no free-text channel.
|
|
2992
|
+
*/
|
|
2993
|
+
interface HubInboxItemHeader {
|
|
2994
|
+
/** v1.1 event-shape version. */
|
|
2995
|
+
version: "1.1";
|
|
2996
|
+
/** Stable inbox-item id. SHOULD reference an audit-chain id where applicable. */
|
|
2997
|
+
item_id: string;
|
|
2998
|
+
/** Inbox kind discriminator. */
|
|
2999
|
+
kind: HubInboxKind;
|
|
3000
|
+
/** ISO8601 timestamp the item was created. */
|
|
3001
|
+
created_at: string;
|
|
3002
|
+
/** Wrapped agent id this item refers to, if applicable. */
|
|
3003
|
+
agent_id?: string;
|
|
3004
|
+
/** Operator identity id. */
|
|
3005
|
+
identity_id: string;
|
|
3006
|
+
/**
|
|
3007
|
+
* Display template id. Resolved by the dashboard against a registered
|
|
3008
|
+
* template catalog; the catalog owns the actual render strings. Backends
|
|
3009
|
+
* MUST NOT emit raw display copy. Template id space is namespaced per
|
|
3010
|
+
* inbox kind, e.g., "approval_pending.tier1.export".
|
|
3011
|
+
*/
|
|
3012
|
+
display_template_id: string;
|
|
3013
|
+
/**
|
|
3014
|
+
* Typed args interpolated into the template. Every value MUST be a
|
|
3015
|
+
* `HubDisplayTemplateArg` instance — no free-form strings. Renderers
|
|
3016
|
+
* reject any arg outside this union, which structurally blocks secret
|
|
3017
|
+
* leakage via inbox copy.
|
|
3018
|
+
*/
|
|
3019
|
+
display_template_args: HubDisplayTemplateArg[];
|
|
3020
|
+
/** Whether the operator has resolved this inbox item. */
|
|
3021
|
+
resolved: boolean;
|
|
3022
|
+
/** ISO8601 timestamp of resolution, if resolved. */
|
|
3023
|
+
resolved_at?: string;
|
|
3024
|
+
}
|
|
3025
|
+
/**
|
|
3026
|
+
* A pending Tier 1 or Tier 2 approval surfaced to the operator inbox.
|
|
3027
|
+
*/
|
|
3028
|
+
interface HubApprovalPendingItem extends HubInboxItemHeader {
|
|
3029
|
+
kind: "approval_pending";
|
|
3030
|
+
/** Policy tier the underlying operation falls under. */
|
|
3031
|
+
tier: "tier1" | "tier2";
|
|
3032
|
+
/**
|
|
3033
|
+
* Coarse operation category. Stable enum so the UI can group consistently;
|
|
3034
|
+
* does not reveal underlying tool args. Names align with the canonical
|
|
3035
|
+
* Tier 1 / Tier 2 sets in `server/src/principal-policy/loader.ts`. Names
|
|
3036
|
+
* NOT in the canonical loader (e.g., `exit_bundle_export`, `policy_change`,
|
|
3037
|
+
* `lockdown`, `unwrap`) are v1.1-new and MUST be added to the loader's
|
|
3038
|
+
* Tier 1 set in the same PR that lands their behavior. Drift is a release
|
|
3039
|
+
* blocker.
|
|
3040
|
+
*/
|
|
3041
|
+
operation_category: "state_export" | "state_import" | "state_delete" | "identity_rotate" | "reputation_export" | "reputation_import" | "sanctuary_export_identity_bundle" | "exit_bundle_export" | "exit_bundle_import" | "exit_bundle_rekey" | "policy_change" | "lockdown" | "unwrap" | "other";
|
|
3042
|
+
/** ISO8601 deadline after which the request will be auto-denied if applicable. */
|
|
3043
|
+
deadline?: string;
|
|
3044
|
+
/**
|
|
3045
|
+
* Result fields surfaced after the Tier 1 handler runs. Empty until
|
|
3046
|
+
* resolution. Populated for fortress-scope `exit_bundle_export` so the
|
|
3047
|
+
* dashboard exit-drill page can advance the wizard from the inbox
|
|
3048
|
+
* resolution alone, without round-tripping through the activity feed.
|
|
3049
|
+
* Per-agent items leave it undefined. Producers MUST keep field values
|
|
3050
|
+
* to safe metadata only (paths and hex hashes); raw secrets MUST NOT
|
|
3051
|
+
* appear here.
|
|
3052
|
+
*/
|
|
3053
|
+
resolution_payload?: {
|
|
3054
|
+
bundle_dir?: string;
|
|
3055
|
+
manifest_hash?: string;
|
|
3056
|
+
artifact_count?: number;
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Outbound traffic was blocked by the egress policy or the privacy filter.
|
|
3061
|
+
*/
|
|
3062
|
+
interface HubBlockedEgressItem extends HubInboxItemHeader {
|
|
3063
|
+
kind: "blocked_egress";
|
|
3064
|
+
/**
|
|
3065
|
+
* Destination category. Same enum as the privacy filter so unified inbox,
|
|
3066
|
+
* privacy panel, and egress dashboards group consistently. Drift is a
|
|
3067
|
+
* release blocker.
|
|
3068
|
+
*/
|
|
3069
|
+
destination_category: PrivacyDestinationCategory;
|
|
3070
|
+
/**
|
|
3071
|
+
* Why the egress was blocked. Coarse enum, not free text. Specific policy
|
|
3072
|
+
* rule names are NOT revealed.
|
|
3073
|
+
*/
|
|
3074
|
+
block_reason_class: "egress_policy_deny" | "budget_exceeded" | "privacy_fail_closed" | "privacy_deny_rule" | "lockdown_active" | "other";
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* A privacy event surfaced to the inbox. References the underlying privacy
|
|
3078
|
+
* event id; the inbox card is a thin pointer, not a duplicate of the event.
|
|
3079
|
+
*/
|
|
3080
|
+
interface HubPrivacyEventItem extends HubInboxItemHeader {
|
|
3081
|
+
kind: "privacy_event";
|
|
3082
|
+
/** Foreign key into the privacy-event chain. */
|
|
3083
|
+
privacy_event_id: string;
|
|
3084
|
+
/** Privacy event kind. */
|
|
3085
|
+
privacy_event_kind: "filtered" | "allowed" | "denied" | "error" | "rehydrated";
|
|
3086
|
+
}
|
|
3087
|
+
/**
|
|
3088
|
+
* A budget threshold was crossed.
|
|
3089
|
+
*/
|
|
3090
|
+
interface HubBudgetWarningItem extends HubInboxItemHeader {
|
|
3091
|
+
kind: "budget_warning";
|
|
3092
|
+
/** Budget bucket identifier (daily / monthly / per-agent / custom). */
|
|
3093
|
+
bucket: "daily" | "monthly" | "per_agent" | "custom";
|
|
3094
|
+
/** Soft-warn or hard-cap. Hard-cap usually requires operator unblock. */
|
|
3095
|
+
severity: "soft_warn" | "hard_cap";
|
|
3096
|
+
/** Percentage of budget used at event time. 0..1. */
|
|
3097
|
+
used_fraction: number;
|
|
3098
|
+
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Recovery prompt — operator should run a recovery flow (passphrase reset,
|
|
3101
|
+
* keychain rebind, exit drill, etc.).
|
|
3102
|
+
*/
|
|
3103
|
+
interface HubRecoveryPromptItem extends HubInboxItemHeader {
|
|
3104
|
+
kind: "recovery_prompt";
|
|
3105
|
+
/** Coarse recovery class. */
|
|
3106
|
+
recovery_class: "passphrase_reset" | "keychain_rebind" | "config_backup_restore" | "exit_drill" | "other";
|
|
3107
|
+
}
|
|
3108
|
+
/**
|
|
3109
|
+
* Agent reported an internal error.
|
|
3110
|
+
*/
|
|
3111
|
+
interface HubAgentErrorItem extends HubInboxItemHeader {
|
|
3112
|
+
kind: "agent_error";
|
|
3113
|
+
/** Stable error code class. Implementation-specific catalog. */
|
|
3114
|
+
error_class: string;
|
|
3115
|
+
/** Whether the agent is still serving traffic after the error. */
|
|
3116
|
+
agent_still_active: boolean;
|
|
3117
|
+
}
|
|
3118
|
+
/**
|
|
3119
|
+
* Discriminated union of every v1.1 hub inbox item.
|
|
3120
|
+
*/
|
|
3121
|
+
type HubInboxItem = HubApprovalPendingItem | HubBlockedEgressItem | HubPrivacyEventItem | HubBudgetWarningItem | HubRecoveryPromptItem | HubAgentErrorItem;
|
|
3122
|
+
/**
|
|
3123
|
+
* Activity feed entry. The feed is a flat stream backed by the audit chain;
|
|
3124
|
+
* inbox items often reference a feed entry, but feed entries are not always
|
|
3125
|
+
* inbox items.
|
|
3126
|
+
*
|
|
3127
|
+
* Activity feed entries are read-from-storage projections of audit-chain
|
|
3128
|
+
* entries. They are NOT signed envelopes themselves; integrity derives from
|
|
3129
|
+
* the underlying audit entry. Consumers that need to verify the feed entry
|
|
3130
|
+
* MUST resolve it to the source audit entry by `entry_id` and verify there.
|
|
3131
|
+
*/
|
|
3132
|
+
interface HubActivityFeedEntry {
|
|
3133
|
+
version: "1.1";
|
|
3134
|
+
/** Audit-chain entry id. */
|
|
3135
|
+
entry_id: string;
|
|
3136
|
+
/** ISO8601 timestamp. */
|
|
3137
|
+
emitted_at: string;
|
|
3138
|
+
/** Wrapped agent id, if applicable. */
|
|
3139
|
+
agent_id?: string;
|
|
3140
|
+
/** Identity id. */
|
|
3141
|
+
identity_id: string;
|
|
3142
|
+
/** Stable category enum. */
|
|
3143
|
+
category: "policy_decision" | "approval" | "denial" | "egress" | "privacy" | "handoff" | "lifecycle" | "config" | "other";
|
|
3144
|
+
/**
|
|
3145
|
+
* Display template id. Resolved by the dashboard against the activity-feed
|
|
3146
|
+
* template catalog. Backends MUST NOT emit raw summary text — the template
|
|
3147
|
+
* id plus typed args is the only legitimate channel.
|
|
3148
|
+
*/
|
|
3149
|
+
display_template_id: string;
|
|
3150
|
+
/** Typed args. Same constraints as `HubInboxItemHeader.display_template_args`. */
|
|
3151
|
+
display_template_args: HubDisplayTemplateArg[];
|
|
3152
|
+
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Per-agent status snapshot returned by the hub API. Mirrors the agent
|
|
3155
|
+
* registry record but is computed-on-read; it does not flow through the
|
|
3156
|
+
* audit chain by itself.
|
|
3157
|
+
*/
|
|
3158
|
+
interface HubAgentStatusSnapshot {
|
|
3159
|
+
version: "1.1";
|
|
3160
|
+
agent_id: string;
|
|
3161
|
+
status: HubAgentStatus;
|
|
3162
|
+
/**
|
|
3163
|
+
* Reason class for the current status. Same enum as
|
|
3164
|
+
* `LocalAgentRecord.status_reason_class`. Stable, not free text. Present
|
|
3165
|
+
* only when status is `locked_down`, `error`, or `restarting`.
|
|
3166
|
+
*/
|
|
3167
|
+
status_reason_class?: "operator_lockdown" | "policy_breach" | "budget_hard_cap" | "harness_error" | "harness_unreachable" | "passphrase_required" | "config_drift" | "other";
|
|
3168
|
+
/** ISO8601 last-seen timestamp. */
|
|
3169
|
+
last_activity_at: string;
|
|
3170
|
+
/** Inbox-item ids currently unresolved against this agent. */
|
|
3171
|
+
open_inbox_item_ids: string[];
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
/**
|
|
3175
|
+
* Sanctuary v1.1 — Local Agent Registry Records
|
|
3176
|
+
*
|
|
3177
|
+
* Shared shape for the per-agent record returned by the operator hub registry
|
|
3178
|
+
* API. Implementations of the hub API workstream (Prompt 5) write these;
|
|
3179
|
+
* dashboard UI (Prompt 8), internal coordination (Prompt 6), and the exit
|
|
3180
|
+
* bundle workstream (Prompt 7) read these.
|
|
3181
|
+
*
|
|
3182
|
+
* Local-only invariant:
|
|
3183
|
+
* Records describe agents wrapped by a single fortress on a single operator's
|
|
3184
|
+
* machine. Cross-fortress agent discovery is deferred to v1.3.
|
|
3185
|
+
*
|
|
3186
|
+
* No-secret invariant:
|
|
3187
|
+
* Records MUST NOT carry private keys, passphrases, recovery seeds, or raw
|
|
3188
|
+
* provider credentials. Provider identifiers and policy ids are safe;
|
|
3189
|
+
* provider tokens are not.
|
|
3190
|
+
*/
|
|
3191
|
+
|
|
3192
|
+
/**
|
|
3193
|
+
* Coarse harness label. Mirrors the README-supported wrap targets at v1.1
|
|
3194
|
+
* ship. Adding a harness requires a new entry here plus harness-compatibility
|
|
3195
|
+
* coverage from Prompt 9.
|
|
3196
|
+
*
|
|
3197
|
+
* `mastra` has a first-class Tier B adapter at
|
|
3198
|
+
* `server/src/agent-contract/adapters/mastra.ts` and is therefore a
|
|
3199
|
+
* first-class kind here. `langgraph` does NOT have a dedicated adapter at
|
|
3200
|
+
* v1.1 ship; LangGraph wraps land via the generic `sanctuary wrap --wrap
|
|
3201
|
+
* <path>` path and surface as `generic_mcp`. When a dedicated LangGraph
|
|
3202
|
+
* adapter ships, add `langgraph` here in the same PR.
|
|
3203
|
+
*/
|
|
3204
|
+
type LocalHarnessKind = "openclaw" | "hermes" | "claude_code" | "cursor" | "cline" | "mastra" | "generic_mcp" | "other";
|
|
3205
|
+
/**
|
|
3206
|
+
* Provider category for the underlying model. Distinct from the privacy
|
|
3207
|
+
* destination category enum because providers and destinations are not 1:1
|
|
3208
|
+
* (one provider can serve multiple destination categories).
|
|
3209
|
+
*/
|
|
3210
|
+
interface LocalAgentModelProvider {
|
|
3211
|
+
/** Coarse provider label, e.g., "anthropic", "openai", "xai", "local", "other". */
|
|
3212
|
+
vendor: string;
|
|
3213
|
+
/** Concrete model identifier reported by the provider, e.g., "claude-opus-4". */
|
|
3214
|
+
model_id: string;
|
|
3215
|
+
/**
|
|
3216
|
+
* Whether the model runs locally (on-device or LAN) versus a remote provider.
|
|
3217
|
+
* Local models still flow through the privacy filter where applicable.
|
|
3218
|
+
*/
|
|
3219
|
+
runs_locally: boolean;
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Budget summary surfaced to the hub. Concrete budget enforcement lives in
|
|
3223
|
+
* the policy engine; this is a read-only snapshot.
|
|
3224
|
+
*/
|
|
3225
|
+
interface LocalAgentBudgetSummary {
|
|
3226
|
+
/** Daily bucket. */
|
|
3227
|
+
daily?: {
|
|
3228
|
+
/** Allotment unit, e.g., "tokens", "usd". */
|
|
3229
|
+
unit: string;
|
|
3230
|
+
/** Total allotment for the bucket. */
|
|
3231
|
+
cap: number;
|
|
3232
|
+
/** Amount used so far in the bucket window. */
|
|
3233
|
+
used: number;
|
|
3234
|
+
/** Soft-warn threshold fraction (0..1). */
|
|
3235
|
+
soft_warn?: number;
|
|
3236
|
+
};
|
|
3237
|
+
/** Monthly bucket. */
|
|
3238
|
+
monthly?: {
|
|
3239
|
+
unit: string;
|
|
3240
|
+
cap: number;
|
|
3241
|
+
used: number;
|
|
3242
|
+
soft_warn?: number;
|
|
3243
|
+
};
|
|
3244
|
+
/** ISO8601 timestamp of last budget refresh. */
|
|
3245
|
+
last_refreshed_at: string;
|
|
3246
|
+
}
|
|
3247
|
+
/**
|
|
3248
|
+
* The canonical local agent registry record for v1.1.
|
|
3249
|
+
*
|
|
3250
|
+
* Implementations SHOULD treat this as read-from-storage; mutating fields is
|
|
3251
|
+
* the responsibility of the hub API plus the underlying agent lifecycle owner
|
|
3252
|
+
* (wrap / unwrap / template assignment / lockdown).
|
|
3253
|
+
*/
|
|
3254
|
+
interface LocalAgentRecord {
|
|
3255
|
+
version: "1.1";
|
|
3256
|
+
/** Stable agent identifier, scoped to this fortress. */
|
|
3257
|
+
agent_id: string;
|
|
3258
|
+
/** Operator identity that owns the agent. */
|
|
3259
|
+
identity_id: string;
|
|
3260
|
+
/** Harness the agent runs under. */
|
|
3261
|
+
harness: LocalHarnessKind;
|
|
3262
|
+
/** Free-text harness version string from the harness, when available. */
|
|
3263
|
+
harness_version?: string;
|
|
3264
|
+
/** Model and provider details. */
|
|
3265
|
+
model_provider: LocalAgentModelProvider;
|
|
3266
|
+
/** Bound policy id (compiled policy artifact). */
|
|
3267
|
+
policy_id: string;
|
|
3268
|
+
/**
|
|
3269
|
+
* Bound channel-template id, when one applies. Template id space is owned
|
|
3270
|
+
* by the policy engine.
|
|
3271
|
+
*/
|
|
3272
|
+
channel_template_id?: string;
|
|
3273
|
+
/** Current lifecycle status as surfaced to the hub. */
|
|
3274
|
+
status: HubAgentStatus;
|
|
3275
|
+
/**
|
|
3276
|
+
* Reason class for the current status. Stable enum, not free text.
|
|
3277
|
+
* Present only when status is `locked_down`, `error`, or `restarting`.
|
|
3278
|
+
* The dashboard renders human-readable copy from a template catalog
|
|
3279
|
+
* keyed by this value; backends MUST NOT emit raw reason text.
|
|
3280
|
+
*/
|
|
3281
|
+
status_reason_class?: "operator_lockdown" | "policy_breach" | "budget_hard_cap" | "harness_error" | "harness_unreachable" | "passphrase_required" | "config_drift" | "other";
|
|
3282
|
+
/** Budget summary snapshot. */
|
|
3283
|
+
budget_summary: LocalAgentBudgetSummary;
|
|
3284
|
+
/** ISO8601 timestamp of last agent activity. */
|
|
3285
|
+
last_activity_at: string;
|
|
3286
|
+
/** ISO8601 timestamp of wrap. */
|
|
3287
|
+
wrapped_at: string;
|
|
3288
|
+
/**
|
|
3289
|
+
* Capabilities flag set surfaced by the harness. Stable string set;
|
|
3290
|
+
* dashboard renders supported controls based on this set.
|
|
3291
|
+
*/
|
|
3292
|
+
capabilities: {
|
|
3293
|
+
can_pause: boolean;
|
|
3294
|
+
can_resume: boolean;
|
|
3295
|
+
can_restart: boolean;
|
|
3296
|
+
can_unwrap: boolean;
|
|
3297
|
+
can_lockdown: boolean;
|
|
3298
|
+
can_chat: boolean;
|
|
3299
|
+
can_change_template: boolean;
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
/**
|
|
3303
|
+
* Note on signing:
|
|
3304
|
+
* `LocalAgentRecord` is a read-from-storage projection of agent registry
|
|
3305
|
+
* state. It is NOT a signed envelope. Signed audit entries that reference
|
|
3306
|
+
* this record (wrap, unwrap, policy change, lockdown, etc.) carry the
|
|
3307
|
+
* signature scheme on the enclosing audit-chain entry, not on the record
|
|
3308
|
+
* itself. Consumers that need to verify a registry change MUST resolve
|
|
3309
|
+
* through the audit chain.
|
|
3310
|
+
*/
|
|
3311
|
+
/**
|
|
3312
|
+
* Hub-side filter shape used by the registry list API. Workstreams may extend
|
|
3313
|
+
* with additional filters; the canonical fields below are stable.
|
|
3314
|
+
*/
|
|
3315
|
+
interface LocalAgentRegistryFilter {
|
|
3316
|
+
/** Restrict to one identity id. */
|
|
3317
|
+
identity_id?: string;
|
|
3318
|
+
/** Restrict to one or more harness kinds. */
|
|
3319
|
+
harnesses?: LocalHarnessKind[];
|
|
3320
|
+
/** Restrict to one or more lifecycle statuses. */
|
|
3321
|
+
statuses?: HubAgentStatus[];
|
|
3322
|
+
/**
|
|
3323
|
+
* Maximum records to return. Implementations SHOULD enforce a server-side
|
|
3324
|
+
* upper bound regardless of caller value.
|
|
3325
|
+
*/
|
|
3326
|
+
limit?: number;
|
|
3327
|
+
/** Pagination cursor; opaque to the caller. */
|
|
3328
|
+
cursor?: string;
|
|
3329
|
+
}
|
|
3330
|
+
|
|
2912
3331
|
/**
|
|
2913
3332
|
* Sanctuary v1.1 — Exit Bundle Manifest Contract
|
|
2914
3333
|
*
|
|
@@ -3680,6 +4099,412 @@ interface SHRGeneratorOptions {
|
|
|
3680
4099
|
*/
|
|
3681
4100
|
declare function generateSHR(identityId: string | undefined, opts: SHRGeneratorOptions): SignedSHR | string;
|
|
3682
4101
|
|
|
4102
|
+
/**
|
|
4103
|
+
* Sanctuary v1.1 Operator Hub API Constants
|
|
4104
|
+
*
|
|
4105
|
+
* Routes, prefixes, and small enums shared across the hub modules.
|
|
4106
|
+
* The hub API surface is consumed by the v1.1 dashboard UI (Prompt 8).
|
|
4107
|
+
*
|
|
4108
|
+
* Local-only invariant:
|
|
4109
|
+
* Every route here describes activity inside a single fortress on a single
|
|
4110
|
+
* operator's machine. Cross-fortress, fleet, and public-federation routes
|
|
4111
|
+
* are out of scope.
|
|
4112
|
+
*/
|
|
4113
|
+
|
|
4114
|
+
/**
|
|
4115
|
+
* Inbox-resolve actions. The router rejects any other action token.
|
|
4116
|
+
*/
|
|
4117
|
+
declare const HUB_INBOX_ACTIONS: readonly ["approve", "deny", "dismiss"];
|
|
4118
|
+
type HubInboxAction = (typeof HUB_INBOX_ACTIONS)[number];
|
|
4119
|
+
/**
|
|
4120
|
+
* Agent-control actions surfaced by `POST /api/hub/agents/:id/:action`.
|
|
4121
|
+
*
|
|
4122
|
+
* `pause` / `resume` / `restart` are control-plane operations that the
|
|
4123
|
+
* underlying harness may execute immediately; they are not Tier 1.
|
|
4124
|
+
*
|
|
4125
|
+
* `unwrap` and `lockdown` are Tier 1 operations per the Principal Policy
|
|
4126
|
+
* loader. Hub endpoints for these MUST enqueue an `approval_pending` inbox
|
|
4127
|
+
* item rather than execute directly. Tier 1 approval gates remain in force
|
|
4128
|
+
* from the dashboard. The dashboard never auto-approves Tier 1 work.
|
|
4129
|
+
*/
|
|
4130
|
+
declare const HUB_AGENT_CONTROL_ACTIONS: readonly ["pause", "resume", "restart", "unwrap", "lockdown"];
|
|
4131
|
+
type HubAgentControlAction = (typeof HUB_AGENT_CONTROL_ACTIONS)[number];
|
|
4132
|
+
|
|
4133
|
+
/** Channel-template identifiers per Walkthrough Key 10 LOCKED starter set. */
|
|
4134
|
+
declare const CHANNEL_TEMPLATE_IDS: readonly ["read-outputs-only", "bidirectional-sync", "credential-share-scoped", "plan-inspect-read-only", "escrow-handoff"];
|
|
4135
|
+
type ChannelTemplateId = (typeof CHANNEL_TEMPLATE_IDS)[number];
|
|
4136
|
+
|
|
4137
|
+
/**
|
|
4138
|
+
* Sanctuary v1.1. Operator Hub API Types
|
|
4139
|
+
*
|
|
4140
|
+
* Service-deps shapes + small payload types not already defined in the
|
|
4141
|
+
* v1.1 contracts. The contract surface (HubInboxItem, LocalAgentRecord,
|
|
4142
|
+
* HubActivityFeedEntry, HubAgentStatusSnapshot) is the source of truth for
|
|
4143
|
+
* everything that crosses the API boundary; types in this file are
|
|
4144
|
+
* implementation glue.
|
|
4145
|
+
*/
|
|
4146
|
+
|
|
4147
|
+
/**
|
|
4148
|
+
* Result returned from a synchronous (non-Tier-1) agent control action.
|
|
4149
|
+
*/
|
|
4150
|
+
interface HubAgentControlResult {
|
|
4151
|
+
agent_id: string;
|
|
4152
|
+
prior_status: HubAgentStatus;
|
|
4153
|
+
new_status: HubAgentStatus;
|
|
4154
|
+
applied_at: string;
|
|
4155
|
+
}
|
|
4156
|
+
/**
|
|
4157
|
+
* Result returned from a Tier-1 agent control action that has been
|
|
4158
|
+
* deferred to operator approval. The hub returns the inbox item id so the
|
|
4159
|
+
* caller can poll or subscribe; nothing executes until the operator
|
|
4160
|
+
* resolves the inbox item.
|
|
4161
|
+
*/
|
|
4162
|
+
interface HubTier1ApprovalEnqueuedResult {
|
|
4163
|
+
agent_id: string;
|
|
4164
|
+
inbox_item_id: string;
|
|
4165
|
+
status: "approval_pending";
|
|
4166
|
+
/**
|
|
4167
|
+
* Same enum as
|
|
4168
|
+
* `HubApprovalPendingItem.operation_category`. Surfaced separately so
|
|
4169
|
+
* non-inbox callers (CLI scripts, test harnesses) can act on the
|
|
4170
|
+
* category without a second fetch.
|
|
4171
|
+
*/
|
|
4172
|
+
operation_category: HubApprovalPendingItem["operation_category"];
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Result returned from a fortress-scope Tier-1 action that has been
|
|
4176
|
+
* deferred to operator approval. Distinguished from the per-agent shape by
|
|
4177
|
+
* the absence of `agent_id` and the presence of `fortress_scope: true`.
|
|
4178
|
+
* The Tier 1 handler iterates fortress-wide on approval; nothing executes
|
|
4179
|
+
* until the operator resolves the inbox item.
|
|
4180
|
+
*/
|
|
4181
|
+
interface HubTier1FortressApprovalEnqueuedResult {
|
|
4182
|
+
inbox_item_id: string;
|
|
4183
|
+
status: "approval_pending";
|
|
4184
|
+
operation_category: HubApprovalPendingItem["operation_category"];
|
|
4185
|
+
/** Always true. Distinguishes from the per-agent shape. */
|
|
4186
|
+
fortress_scope: true;
|
|
4187
|
+
}
|
|
4188
|
+
/**
|
|
4189
|
+
* Result returned from `fortressExportBundle` after a fortress-scope
|
|
4190
|
+
* exit-bundle export approval lands. Surfaced both in the inbox item's
|
|
4191
|
+
* `resolution_payload` and (separately) in an activity feed entry.
|
|
4192
|
+
*/
|
|
4193
|
+
interface HubFortressExportResult {
|
|
4194
|
+
bundle_dir: string;
|
|
4195
|
+
manifest_hash: string;
|
|
4196
|
+
artifact_count: number;
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Generic capability check delegated to the underlying harness controller.
|
|
4200
|
+
* The hub never performs the harness-side action itself; it asks the
|
|
4201
|
+
* controller to apply a transition and reports the new status back.
|
|
4202
|
+
*
|
|
4203
|
+
* Each callback returns the agent's new status after the action lands.
|
|
4204
|
+
* The controller MUST throw if it cannot apply the action; the hub maps
|
|
4205
|
+
* those throws to HubCapabilityError or HubConflictError.
|
|
4206
|
+
*/
|
|
4207
|
+
interface HubAgentController {
|
|
4208
|
+
pause(agentId: string): Promise<HubAgentStatus>;
|
|
4209
|
+
resume(agentId: string): Promise<HubAgentStatus>;
|
|
4210
|
+
restart(agentId: string): Promise<HubAgentStatus>;
|
|
4211
|
+
/**
|
|
4212
|
+
* Apply an operator-approved unwrap. Called only after a Tier 1
|
|
4213
|
+
* approval lands through the inbox flow. Implementations SHOULD treat
|
|
4214
|
+
* unwrap as durable (cocoon teardown + registry deregister).
|
|
4215
|
+
*/
|
|
4216
|
+
unwrap(agentId: string): Promise<HubAgentStatus>;
|
|
4217
|
+
/**
|
|
4218
|
+
* Apply an operator-approved lockdown. Called only after a Tier 1
|
|
4219
|
+
* approval lands. Implementations SHOULD treat lockdown as a hard-stop
|
|
4220
|
+
* (deny all egress, freeze gates) until explicitly cleared.
|
|
4221
|
+
*/
|
|
4222
|
+
lockdown(agentId: string): Promise<HubAgentStatus>;
|
|
4223
|
+
/**
|
|
4224
|
+
* Apply an operator-approved policy bind. Called only after a Tier 1
|
|
4225
|
+
* approval lands.
|
|
4226
|
+
*/
|
|
4227
|
+
bindPolicy(agentId: string, policyId: string): Promise<void>;
|
|
4228
|
+
/**
|
|
4229
|
+
* Apply a non-Tier-1 channel-template binding. Channel templates are
|
|
4230
|
+
* compositions over the canonical four slots; binding does not require
|
|
4231
|
+
* Tier 1 approval at v1.1.
|
|
4232
|
+
*/
|
|
4233
|
+
bindChannelTemplate(agentId: string, templateId: ChannelTemplateId): Promise<void>;
|
|
4234
|
+
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Source-side input shapes the inbox aggregator pulls from. Each callback
|
|
4237
|
+
* returns recent occurrences pre-shaped as the underlying contract type;
|
|
4238
|
+
* the aggregator wraps them into HubInboxItem header form.
|
|
4239
|
+
*
|
|
4240
|
+
* Source callbacks are deliberately narrow; the hub does not know how to
|
|
4241
|
+
* compute privacy events or budget thresholds. Other workstreams own those
|
|
4242
|
+
* computations and feed them in through these callbacks.
|
|
4243
|
+
*/
|
|
4244
|
+
interface HubInboxSources {
|
|
4245
|
+
/**
|
|
4246
|
+
* Currently unresolved Tier 1 / Tier 2 approval requests. Items already
|
|
4247
|
+
* in the hub-side inbox store are deduplicated by `item_id` against these.
|
|
4248
|
+
*/
|
|
4249
|
+
listPendingApprovals: () => HubApprovalPendingItem[];
|
|
4250
|
+
/**
|
|
4251
|
+
* Recent egress denials. The hub surfaces each as a blocked-egress inbox
|
|
4252
|
+
* card. The caller is responsible for trimming to the recent window.
|
|
4253
|
+
*/
|
|
4254
|
+
listRecentBlockedEgress: () => HubBlockedEgressItem[];
|
|
4255
|
+
/**
|
|
4256
|
+
* Recent privacy events the operator should attend to. The hub does NOT
|
|
4257
|
+
* surface every privacy event; it surfaces the ones that the privacy
|
|
4258
|
+
* core has already promoted to operator attention (denied, error, plus
|
|
4259
|
+
* filtered events flagged by the bound policy).
|
|
4260
|
+
*/
|
|
4261
|
+
listRecentPrivacyEvents: () => HubPrivacyEventItem[];
|
|
4262
|
+
/**
|
|
4263
|
+
* Active budget warnings (soft-warn or hard-cap). Closed warnings are
|
|
4264
|
+
* not returned.
|
|
4265
|
+
*/
|
|
4266
|
+
listActiveBudgetWarnings: () => HubBudgetWarningItem[];
|
|
4267
|
+
/**
|
|
4268
|
+
* Active recovery prompts (passphrase reset due, exit drill recommended,
|
|
4269
|
+
* keychain rebind required, etc.).
|
|
4270
|
+
*/
|
|
4271
|
+
listActiveRecoveryPrompts: () => HubRecoveryPromptItem[];
|
|
4272
|
+
/**
|
|
4273
|
+
* Recent agent-error events.
|
|
4274
|
+
*/
|
|
4275
|
+
listRecentAgentErrors: () => HubAgentErrorItem[];
|
|
4276
|
+
}
|
|
4277
|
+
interface HubActivitySources {
|
|
4278
|
+
/**
|
|
4279
|
+
* Underlying audit log the activity feed projects from.
|
|
4280
|
+
*/
|
|
4281
|
+
auditLog: AuditLog;
|
|
4282
|
+
/**
|
|
4283
|
+
* Identity id the dashboard is currently scoped to. Activity entries are
|
|
4284
|
+
* filtered to this identity; v1.1 is single-operator; the parameter is
|
|
4285
|
+
* here so v1.2 can scope per-identity without breaking the API.
|
|
4286
|
+
*/
|
|
4287
|
+
identityId: string;
|
|
4288
|
+
}
|
|
4289
|
+
/**
|
|
4290
|
+
* Lightweight summary of a bound policy. Suitable for UI cards. Raw policy
|
|
4291
|
+
* bytes never appear here.
|
|
4292
|
+
*/
|
|
4293
|
+
interface HubPolicySummary {
|
|
4294
|
+
policy_id: string;
|
|
4295
|
+
display_label: string;
|
|
4296
|
+
/** ISO8601 timestamp the policy was bound. */
|
|
4297
|
+
bound_at: string;
|
|
4298
|
+
/** Number of agents currently bound to this policy. */
|
|
4299
|
+
agent_count: number;
|
|
4300
|
+
/** Channel template id the policy was compiled from, if applicable. */
|
|
4301
|
+
channel_template_id?: ChannelTemplateId;
|
|
4302
|
+
}
|
|
4303
|
+
/**
|
|
4304
|
+
* Lightweight summary of a budget bucket. Suitable for UI cards.
|
|
4305
|
+
*/
|
|
4306
|
+
interface HubBudgetSummary {
|
|
4307
|
+
bucket_id: string;
|
|
4308
|
+
/** Display label drawn from the policy compile step. */
|
|
4309
|
+
display_label: string;
|
|
4310
|
+
unit: string;
|
|
4311
|
+
cap: number;
|
|
4312
|
+
used: number;
|
|
4313
|
+
/** Soft-warn threshold fraction (0..1). */
|
|
4314
|
+
soft_warn?: number;
|
|
4315
|
+
/** ISO8601 timestamp of last refresh. */
|
|
4316
|
+
last_refreshed_at: string;
|
|
4317
|
+
}
|
|
4318
|
+
interface HubPolicyAndBudgetSources {
|
|
4319
|
+
listPolicySummaries: () => HubPolicySummary[];
|
|
4320
|
+
listBudgetSummaries: () => HubBudgetSummary[];
|
|
4321
|
+
}
|
|
4322
|
+
/**
|
|
4323
|
+
* Read interface for the local agent registry. The hub does not invent
|
|
4324
|
+
* agent records; it pulls them from this source. Backend implementations
|
|
4325
|
+
* may persist records to disk or recompute them per call.
|
|
4326
|
+
*/
|
|
4327
|
+
interface HubAgentRegistrySource {
|
|
4328
|
+
list(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4329
|
+
get(agentId: string): LocalAgentRecord | null;
|
|
4330
|
+
/**
|
|
4331
|
+
* Update a single field on a record. The hub uses this to flip status
|
|
4332
|
+
* after a synchronous control action lands. Returns the updated record;
|
|
4333
|
+
* throws if the agent does not exist.
|
|
4334
|
+
*/
|
|
4335
|
+
updateStatus(agentId: string, status: HubAgentStatus, statusReasonClass?: LocalAgentRecord["status_reason_class"]): LocalAgentRecord;
|
|
4336
|
+
/**
|
|
4337
|
+
* Bind a different policy on a record. Used after an approved Tier 1
|
|
4338
|
+
* policy_change action lands.
|
|
4339
|
+
*/
|
|
4340
|
+
updatePolicyBinding(agentId: string, policyId: string): LocalAgentRecord;
|
|
4341
|
+
/**
|
|
4342
|
+
* Bind a different channel template on a record. Non-Tier-1.
|
|
4343
|
+
*/
|
|
4344
|
+
updateChannelTemplateBinding(agentId: string, templateId: ChannelTemplateId): LocalAgentRecord;
|
|
4345
|
+
}
|
|
4346
|
+
interface HubServiceDeps {
|
|
4347
|
+
/** Operator identity id this hub is scoped to. */
|
|
4348
|
+
identityId: string;
|
|
4349
|
+
/** Stable fortress id. */
|
|
4350
|
+
fortressId: string;
|
|
4351
|
+
/** Local agent registry source. */
|
|
4352
|
+
agentRegistry: HubAgentRegistrySource;
|
|
4353
|
+
/** Inbox aggregation sources. */
|
|
4354
|
+
inboxSources: HubInboxSources;
|
|
4355
|
+
/** Activity feed sources. */
|
|
4356
|
+
activitySources: HubActivitySources;
|
|
4357
|
+
/** Policy + budget summary sources. */
|
|
4358
|
+
policyBudgetSources: HubPolicyAndBudgetSources;
|
|
4359
|
+
/** Underlying agent controller for control endpoints. */
|
|
4360
|
+
agentController: HubAgentController;
|
|
4361
|
+
/**
|
|
4362
|
+
* Optional fortress-scope exit-bundle export callback. Invoked only
|
|
4363
|
+
* after a fortress-scope Tier 1 approval lands. The callback owns its
|
|
4364
|
+
* own dependency wiring (storage, masterKey, identityManager, auditLog,
|
|
4365
|
+
* policy, reputationStore, state namespaces); the hub layer remains
|
|
4366
|
+
* crypto-agnostic. When omitted, the fortress export endpoint returns
|
|
4367
|
+
* `HubCapabilityError`.
|
|
4368
|
+
*
|
|
4369
|
+
* The hub passes the inbox item's id as `approvalAuditId` so the
|
|
4370
|
+
* callback can thread it into `exportExitBundle({ exportApprovalAuditId })`,
|
|
4371
|
+
* tying the manifest's `export_approval_audit_id` to the operator's
|
|
4372
|
+
* actual approval flow rather than an internally-generated value
|
|
4373
|
+
* (closes v1.0.2 backlog item (j)). The argument is optional for
|
|
4374
|
+
* backwards compatibility with existing callbacks.
|
|
4375
|
+
*/
|
|
4376
|
+
fortressExportBundle?: (approvalAuditId?: string) => Promise<HubFortressExportResult>;
|
|
4377
|
+
/**
|
|
4378
|
+
* Clock override for deterministic timestamp emission in tests.
|
|
4379
|
+
* Defaults to `() => new Date()` when omitted.
|
|
4380
|
+
*/
|
|
4381
|
+
now?: () => Date;
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
/**
|
|
4385
|
+
* Sanctuary v1.1. Operator Hub Service
|
|
4386
|
+
*
|
|
4387
|
+
* Public API the router calls. Owns no domain logic: it composes the
|
|
4388
|
+
* agent registry source, the inbox aggregator + store, the activity feed
|
|
4389
|
+
* projection, and the agent controller.
|
|
4390
|
+
*
|
|
4391
|
+
* Tier 1 enforcement contract:
|
|
4392
|
+
* Hub control endpoints for `unwrap`, `lockdown`, and `policy_change` MUST
|
|
4393
|
+
* NOT execute synchronously. The hub enqueues an `approval_pending` inbox
|
|
4394
|
+
* item carrying the operation_category and binds the controller call to
|
|
4395
|
+
* the inbox-store resolution handler. Only operator approval through the
|
|
4396
|
+
* inbox path causes the controller call to fire. The dashboard never
|
|
4397
|
+
* auto-approves Tier 1 work.
|
|
4398
|
+
*/
|
|
4399
|
+
|
|
4400
|
+
declare class HubService {
|
|
4401
|
+
private deps;
|
|
4402
|
+
private inboxStore;
|
|
4403
|
+
constructor(deps: HubServiceDeps);
|
|
4404
|
+
private now;
|
|
4405
|
+
private nowIso;
|
|
4406
|
+
listInbox(): HubInboxItem[];
|
|
4407
|
+
resolveInboxItem(itemId: string, action: HubInboxAction): Promise<HubInboxItem>;
|
|
4408
|
+
listAgents(filter?: LocalAgentRegistryFilter): LocalAgentRecord[];
|
|
4409
|
+
getAgent(agentId: string): LocalAgentRecord;
|
|
4410
|
+
getAgentStatusSnapshot(agentId: string): HubAgentStatusSnapshot;
|
|
4411
|
+
controlAgent(agentId: string, action: HubAgentControlAction): Promise<HubAgentControlResult | HubTier1ApprovalEnqueuedResult>;
|
|
4412
|
+
/**
|
|
4413
|
+
* Capability gate. Returns silently when the action is supported by the
|
|
4414
|
+
* harness; throws HubCapabilityError when not.
|
|
4415
|
+
*/
|
|
4416
|
+
private assertCapability;
|
|
4417
|
+
/**
|
|
4418
|
+
* Build a Tier 1 inbox item for an unwrap/lockdown/policy_change action
|
|
4419
|
+
* and bind the controller call to its resolution.
|
|
4420
|
+
*/
|
|
4421
|
+
private enqueueTier1ControlAction;
|
|
4422
|
+
/**
|
|
4423
|
+
* Bind a different policy on an agent. Tier 1: enqueues an approval
|
|
4424
|
+
* pending inbox item rather than executing synchronously.
|
|
4425
|
+
*/
|
|
4426
|
+
bindAgentPolicy(agentId: string, policyId: string): HubTier1ApprovalEnqueuedResult;
|
|
4427
|
+
/**
|
|
4428
|
+
* Bind a different channel template. Not Tier 1; channel templates are
|
|
4429
|
+
* compositions over the four canonical slots and bind synchronously.
|
|
4430
|
+
*/
|
|
4431
|
+
bindAgentChannelTemplate(agentId: string, rawTemplateId: unknown): Promise<LocalAgentRecord>;
|
|
4432
|
+
/**
|
|
4433
|
+
* Enqueue a fortress-scope Tier 1 lockdown. One inbox item is created;
|
|
4434
|
+
* on operator approval the handler iterates `agentController.lockdown`
|
|
4435
|
+
* over every wrapped agent for the bound identity, captures partial
|
|
4436
|
+
* failures as per-agent `agent_error` inbox items, and emits a single
|
|
4437
|
+
* `lifecycle` activity entry. Stacked fortress lockdowns are rejected
|
|
4438
|
+
* with `HubConflictError` until the prior pending item resolves.
|
|
4439
|
+
*/
|
|
4440
|
+
enqueueFortressLockdown(): HubTier1FortressApprovalEnqueuedResult;
|
|
4441
|
+
/**
|
|
4442
|
+
* Enqueue a fortress-scope Tier 1 exit-bundle export. One inbox item is
|
|
4443
|
+
* created; on operator approval the handler invokes
|
|
4444
|
+
* `fortressExportBundle()` once at fortress scope, attaches
|
|
4445
|
+
* `bundle_dir` + `manifest_hash` + `artifact_count` to the inbox item's
|
|
4446
|
+
* `resolution_payload`, and emits a `lifecycle` activity entry.
|
|
4447
|
+
* Stacked exports are rejected with `HubConflictError`.
|
|
4448
|
+
*/
|
|
4449
|
+
enqueueFortressExportBundle(): HubTier1FortressApprovalEnqueuedResult;
|
|
4450
|
+
/**
|
|
4451
|
+
* Reject stacked fortress-scope Tier 1 items. The check scans the inbox
|
|
4452
|
+
* store for an unresolved `approval_pending` item with the same
|
|
4453
|
+
* `operation_category` and no `agent_id` (the fortress-scope marker).
|
|
4454
|
+
*/
|
|
4455
|
+
private assertNoPendingFortressTier1;
|
|
4456
|
+
listActivity(filter: {
|
|
4457
|
+
since?: string;
|
|
4458
|
+
limit?: number;
|
|
4459
|
+
agent_id?: string;
|
|
4460
|
+
category?: HubActivityFeedEntry["category"];
|
|
4461
|
+
}): Promise<HubActivityFeedEntry[]>;
|
|
4462
|
+
listPolicySummaries(): HubPolicySummary[];
|
|
4463
|
+
listBudgetSummaries(): HubBudgetSummary[];
|
|
4464
|
+
/**
|
|
4465
|
+
* Validate that a caller-supplied filter does not request cross-fortress
|
|
4466
|
+
* scope; v1.1 hub is single-fortress; the filter rejects fortress-bridging
|
|
4467
|
+
* fields outright; v1.3 federation will introduce an alternate surface.
|
|
4468
|
+
*/
|
|
4469
|
+
static assertLocalOnlyFilter(filter: Record<string, unknown> | null): void;
|
|
4470
|
+
/**
|
|
4471
|
+
* Test/inspection helper. Not part of the public service surface.
|
|
4472
|
+
*/
|
|
4473
|
+
inboxStoreSize(): number;
|
|
4474
|
+
}
|
|
4475
|
+
|
|
4476
|
+
/**
|
|
4477
|
+
* v1.1 Server Wiring (v1.1.1 hotfix)
|
|
4478
|
+
*
|
|
4479
|
+
* v1.1.0 shipped the v1.1 module suite (dashboard / hub API / exit bundle
|
|
4480
|
+
* endpoints / coordination) but no entry-point server imported any of it.
|
|
4481
|
+
* This module builds the canonical HubService construction the dashboard
|
|
4482
|
+
* entry points share so the routes light up at boot without forcing each
|
|
4483
|
+
* caller to know the deps shape.
|
|
4484
|
+
*
|
|
4485
|
+
* The wiring is deliberately minimal at v1.1.1:
|
|
4486
|
+
*
|
|
4487
|
+
* - Local agent registry starts empty. v1.2 will populate it from
|
|
4488
|
+
* `discoverTenants()` and the wrapped harness manifest. v1.1.1 ships
|
|
4489
|
+
* the API surface so existing operator scripts can hit it; the data
|
|
4490
|
+
* plane is the next conversation.
|
|
4491
|
+
* - Inbox sources return empty arrays. The privacy chokepoint already
|
|
4492
|
+
* emits audit events through PR #69 / PR #71; the inbox aggregator is
|
|
4493
|
+
* the v1.2 work to project those into operator cards.
|
|
4494
|
+
* - Activity feed reads from the real audit log. This is the one source
|
|
4495
|
+
* that's already complete in v1.1.0 and just needs to be plugged in.
|
|
4496
|
+
* - Agent controller errors on every action. v1.1.1 cannot honestly
|
|
4497
|
+
* pause / unwrap / lockdown anything because no agent registry yet
|
|
4498
|
+
* exists; the wiring returns `HubCapabilityError` rather than lying
|
|
4499
|
+
* about what shipped.
|
|
4500
|
+
*/
|
|
4501
|
+
|
|
4502
|
+
interface V11Bindings {
|
|
4503
|
+
hubService: HubService;
|
|
4504
|
+
identityId: string;
|
|
4505
|
+
fortressId: string;
|
|
4506
|
+
}
|
|
4507
|
+
|
|
3683
4508
|
/**
|
|
3684
4509
|
* Sanctuary MCP Server — Principal Dashboard
|
|
3685
4510
|
*
|
|
@@ -3763,6 +4588,12 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
3763
4588
|
* policy change.
|
|
3764
4589
|
*/
|
|
3765
4590
|
private _autoAuthLocalhost;
|
|
4591
|
+
/**
|
|
4592
|
+
* v1.1 routes (dashboard HTML at /v1.1, hub API at /api/hub/*) are
|
|
4593
|
+
* mounted additively when set. Legacy routes at / continue to serve
|
|
4594
|
+
* regardless. Default route flip is deferred to v1.2.
|
|
4595
|
+
*/
|
|
4596
|
+
private v11Bindings;
|
|
3766
4597
|
constructor(config: DashboardConfig);
|
|
3767
4598
|
/**
|
|
3768
4599
|
* Inject dependencies after construction.
|
|
@@ -3784,6 +4615,26 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
3784
4615
|
* Exposed via /api/status so the frontend can show an appropriate banner.
|
|
3785
4616
|
*/
|
|
3786
4617
|
setStandaloneMode(standalone: boolean): void;
|
|
4618
|
+
/**
|
|
4619
|
+
* v1.1.1 hotfix: bind the v1.1 dashboard + hub API to this dashboard
|
|
4620
|
+
* instance. After binding, requests to `/v1.1` serve the v1.1 HTML and
|
|
4621
|
+
* requests under `/api/hub/*` route through the hub API. Legacy routes
|
|
4622
|
+
* at `/` and `/api/*` keep their pre-v1.1 behavior (additive mount).
|
|
4623
|
+
*
|
|
4624
|
+
* Pass `null` to detach the bindings (used by tests and during shutdown).
|
|
4625
|
+
*/
|
|
4626
|
+
setV11Bindings(bindings: V11Bindings | null): void;
|
|
4627
|
+
/**
|
|
4628
|
+
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
4629
|
+
* legacy route table. Returns true when the request was served by v1.1
|
|
4630
|
+
* routes; false to fall through to legacy routing.
|
|
4631
|
+
*
|
|
4632
|
+
* Auth gating: the v1.1 dashboard HTML is served unconditionally (the
|
|
4633
|
+
* client script handles its own auth dance). Hub API routes run through
|
|
4634
|
+
* the same auth contract as legacy `/api/*` routes via the AuthConfig
|
|
4635
|
+
* passed to `handleHubRoute`.
|
|
4636
|
+
*/
|
|
4637
|
+
private dispatchV11;
|
|
3787
4638
|
/**
|
|
3788
4639
|
* v0.10.2: enable (or disable) the loopback auto-auth fast path. See
|
|
3789
4640
|
* {@link _autoAuthLocalhost} for the rationale and threat model. Callers
|
|
@@ -3859,6 +4710,7 @@ declare class DashboardApprovalChannel implements ApprovalChannel {
|
|
|
3859
4710
|
*/
|
|
3860
4711
|
private pruneRateLimits;
|
|
3861
4712
|
private handleRequest;
|
|
4713
|
+
private handleLegacyRequest;
|
|
3862
4714
|
/**
|
|
3863
4715
|
* SEC-012: Exchange a long-lived auth token (in Authorization header)
|
|
3864
4716
|
* for a short-lived session ID. The session ID can be used in URL
|