@sanctuary-framework/mcp-server 1.2.10 → 1.2.12
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 +1359 -45
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1359 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +940 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +161 -15
- package/dist/index.d.ts +161 -15
- package/dist/index.js +940 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -16565,6 +16565,598 @@ async function handleSentinelRoute(deps, req, res) {
|
|
|
16565
16565
|
return true;
|
|
16566
16566
|
}
|
|
16567
16567
|
}
|
|
16568
|
+
var HANDOFF_LOG_OBSERVED_OPS = {
|
|
16569
|
+
/** Tau-3 in-process coordination handoff. */
|
|
16570
|
+
LOCAL_HANDOFF: "v1.1_local_handoff",
|
|
16571
|
+
/** Upsilon-1 cross-harness approval (wrapped-agent -> operator). */
|
|
16572
|
+
CROSS_HARNESS_APPROVAL: "cross_harness_approval_aggregated"
|
|
16573
|
+
};
|
|
16574
|
+
var OBSERVED_OP_LIST = [
|
|
16575
|
+
HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF,
|
|
16576
|
+
HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL
|
|
16577
|
+
];
|
|
16578
|
+
var OPERATOR_PSEUDO_AGENT = "operator";
|
|
16579
|
+
function makeEntryId(auditEventId) {
|
|
16580
|
+
return crypto.createHash("sha256").update(auditEventId).digest("hex").slice(0, 32);
|
|
16581
|
+
}
|
|
16582
|
+
var DEFAULT_LIMIT = 50;
|
|
16583
|
+
var MAX_LIMIT = 500;
|
|
16584
|
+
var AUDIT_QUERY_LIMIT = 1e4;
|
|
16585
|
+
var HandoffLog = class {
|
|
16586
|
+
auditLog;
|
|
16587
|
+
fortressId;
|
|
16588
|
+
constructor(opts) {
|
|
16589
|
+
this.auditLog = opts.auditLog;
|
|
16590
|
+
this.fortressId = opts.fortressId;
|
|
16591
|
+
}
|
|
16592
|
+
/** Stable fortress id this HandoffLog reads. */
|
|
16593
|
+
getFortressId() {
|
|
16594
|
+
return this.fortressId;
|
|
16595
|
+
}
|
|
16596
|
+
/**
|
|
16597
|
+
* Query handoffs in chronological-newest-first order. Filters
|
|
16598
|
+
* applied after normalization so the per-event-class shape
|
|
16599
|
+
* differences (sender field name, recipient inference) are handled
|
|
16600
|
+
* once.
|
|
16601
|
+
*/
|
|
16602
|
+
async query(opts) {
|
|
16603
|
+
const limit = Math.min(opts.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
|
|
16604
|
+
const queryResult = await this.auditLog.query({
|
|
16605
|
+
...opts.since !== void 0 ? { since: opts.since } : {},
|
|
16606
|
+
layer: "l2",
|
|
16607
|
+
limit: AUDIT_QUERY_LIMIT
|
|
16608
|
+
});
|
|
16609
|
+
const normalized = [];
|
|
16610
|
+
for (const entry of queryResult.entries) {
|
|
16611
|
+
if (!OBSERVED_OP_LIST.includes(entry.operation)) continue;
|
|
16612
|
+
const handoff = this.normalize(entry);
|
|
16613
|
+
if (!handoff) continue;
|
|
16614
|
+
if (opts.until && handoff.observed_at > opts.until) continue;
|
|
16615
|
+
if (opts.since && handoff.observed_at < opts.since) continue;
|
|
16616
|
+
if (opts.agent_id) {
|
|
16617
|
+
if (handoff.source_agent_id !== opts.agent_id && handoff.target_agent_id !== opts.agent_id) {
|
|
16618
|
+
continue;
|
|
16619
|
+
}
|
|
16620
|
+
}
|
|
16621
|
+
normalized.push(handoff);
|
|
16622
|
+
}
|
|
16623
|
+
normalized.sort((a, b) => a.observed_at < b.observed_at ? 1 : -1);
|
|
16624
|
+
return normalized.slice(0, limit);
|
|
16625
|
+
}
|
|
16626
|
+
/**
|
|
16627
|
+
* Look up a single entry by id. Returns the normalized entry +
|
|
16628
|
+
* the source audit payload for operator-facing detail rendering.
|
|
16629
|
+
* Returns null when no audit entry maps to the given id.
|
|
16630
|
+
*/
|
|
16631
|
+
async getEntry(entryId) {
|
|
16632
|
+
const queryResult = await this.auditLog.query({
|
|
16633
|
+
layer: "l2",
|
|
16634
|
+
limit: AUDIT_QUERY_LIMIT
|
|
16635
|
+
});
|
|
16636
|
+
for (const audit of queryResult.entries) {
|
|
16637
|
+
if (!OBSERVED_OP_LIST.includes(audit.operation)) continue;
|
|
16638
|
+
const handoff = this.normalize(audit);
|
|
16639
|
+
if (!handoff) continue;
|
|
16640
|
+
if (handoff.entry_id === entryId) {
|
|
16641
|
+
return { entry: handoff, source_audit_entry: audit };
|
|
16642
|
+
}
|
|
16643
|
+
}
|
|
16644
|
+
return null;
|
|
16645
|
+
}
|
|
16646
|
+
normalize(audit) {
|
|
16647
|
+
const details = audit.details;
|
|
16648
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF) {
|
|
16649
|
+
const sender = optString(details, "sender_agent_id");
|
|
16650
|
+
const recipient = optString(details, "recipient_agent_id");
|
|
16651
|
+
if (!sender || !recipient || sender === recipient) return null;
|
|
16652
|
+
const auditEventId = optString(details, "event_id") ?? auditEventIdFallback(audit);
|
|
16653
|
+
return {
|
|
16654
|
+
entry_id: makeEntryId(auditEventId),
|
|
16655
|
+
audit_event_id: auditEventId,
|
|
16656
|
+
source_agent_id: sender,
|
|
16657
|
+
target_agent_id: recipient,
|
|
16658
|
+
observed_at: audit.timestamp,
|
|
16659
|
+
event_class: audit.operation,
|
|
16660
|
+
context_transfer_summary: localHandoffSummary(details, sender, recipient),
|
|
16661
|
+
workflow_link: null
|
|
16662
|
+
};
|
|
16663
|
+
}
|
|
16664
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL) {
|
|
16665
|
+
const sender = optString(details, "source_harness") ?? optString(details, "source_agent_id");
|
|
16666
|
+
if (!sender) return null;
|
|
16667
|
+
const auditEventId = optString(details, "aggregator_id") ?? auditEventIdFallback(audit);
|
|
16668
|
+
return {
|
|
16669
|
+
entry_id: makeEntryId(auditEventId),
|
|
16670
|
+
audit_event_id: auditEventId,
|
|
16671
|
+
source_agent_id: sender,
|
|
16672
|
+
target_agent_id: OPERATOR_PSEUDO_AGENT,
|
|
16673
|
+
observed_at: audit.timestamp,
|
|
16674
|
+
event_class: audit.operation,
|
|
16675
|
+
context_transfer_summary: crossHarnessSummary(details, sender),
|
|
16676
|
+
workflow_link: null
|
|
16677
|
+
};
|
|
16678
|
+
}
|
|
16679
|
+
return null;
|
|
16680
|
+
}
|
|
16681
|
+
};
|
|
16682
|
+
function optString(details, key) {
|
|
16683
|
+
if (!details) return null;
|
|
16684
|
+
const value = details[key];
|
|
16685
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
16686
|
+
return value;
|
|
16687
|
+
}
|
|
16688
|
+
function auditEventIdFallback(audit) {
|
|
16689
|
+
return `${audit.timestamp}:${audit.operation}`;
|
|
16690
|
+
}
|
|
16691
|
+
function localHandoffSummary(details, sender, recipient) {
|
|
16692
|
+
const taskScope = optString(details, "task_scope");
|
|
16693
|
+
const reasonClass = optString(details, "reason_class");
|
|
16694
|
+
if (taskScope) {
|
|
16695
|
+
return `${sender} -> ${recipient} handoff: ${taskScope}`;
|
|
16696
|
+
}
|
|
16697
|
+
if (reasonClass) {
|
|
16698
|
+
return `${sender} -> ${recipient} handoff (${reasonClass})`;
|
|
16699
|
+
}
|
|
16700
|
+
return `${sender} -> ${recipient} handoff`;
|
|
16701
|
+
}
|
|
16702
|
+
function crossHarnessSummary(details, sender) {
|
|
16703
|
+
const policyRule = optString(details, "policy_rule_id");
|
|
16704
|
+
if (policyRule) {
|
|
16705
|
+
return `${sender} -> operator approval (${policyRule})`;
|
|
16706
|
+
}
|
|
16707
|
+
return `${sender} -> operator approval`;
|
|
16708
|
+
}
|
|
16709
|
+
var COORDINATION_VIEW_AUDIT_OPS = {
|
|
16710
|
+
VIEW_OPENED: "operator_coordination_view_opened",
|
|
16711
|
+
ENTRY_DRILLED: "operator_handoff_entry_drilled"
|
|
16712
|
+
};
|
|
16713
|
+
|
|
16714
|
+
// src/coordination/context-transfer-extractor.ts
|
|
16715
|
+
var SUMMARY_MAX_CHARS = 240;
|
|
16716
|
+
var CATEGORY_VALUES = [
|
|
16717
|
+
"memory",
|
|
16718
|
+
"credentials",
|
|
16719
|
+
"plans",
|
|
16720
|
+
"outputs",
|
|
16721
|
+
"audit-refs",
|
|
16722
|
+
"other"
|
|
16723
|
+
];
|
|
16724
|
+
async function extractContextTransferBreakdown(detail, deps = {}) {
|
|
16725
|
+
const pathA = tryStructuredPath(detail);
|
|
16726
|
+
if (pathA) return pathA;
|
|
16727
|
+
const pathB = tryCompositionPath(detail);
|
|
16728
|
+
if (pathB) return pathB;
|
|
16729
|
+
const pathC = tryHeuristicPath(detail);
|
|
16730
|
+
if (pathC.confidence >= 0.5 || !deps.substrateSelector) {
|
|
16731
|
+
return pathC;
|
|
16732
|
+
}
|
|
16733
|
+
const assist = await tryLlmAssistPath(detail, deps.substrateSelector);
|
|
16734
|
+
return assist ?? pathC;
|
|
16735
|
+
}
|
|
16736
|
+
function tryStructuredPath(detail) {
|
|
16737
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
16738
|
+
if (!details) return null;
|
|
16739
|
+
const transferredRaw = details["transferred"];
|
|
16740
|
+
const withheldRaw = details["withheld"];
|
|
16741
|
+
if (transferredRaw === void 0 && withheldRaw === void 0) return null;
|
|
16742
|
+
const transferred = parseExplicitContextItems(transferredRaw);
|
|
16743
|
+
const withheld = parseExplicitContextItems(withheldRaw);
|
|
16744
|
+
return {
|
|
16745
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
16746
|
+
transferred,
|
|
16747
|
+
withheld,
|
|
16748
|
+
source: "structured",
|
|
16749
|
+
confidence: 1
|
|
16750
|
+
};
|
|
16751
|
+
}
|
|
16752
|
+
function tryCompositionPath(detail) {
|
|
16753
|
+
const op = detail.source_audit_entry.operation;
|
|
16754
|
+
if (!op.startsWith("composition_completed")) return null;
|
|
16755
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
16756
|
+
if (!details) return null;
|
|
16757
|
+
const receiptRaw = details["receipt"];
|
|
16758
|
+
const sourceStateRaw = details["source_state_snapshot"];
|
|
16759
|
+
if (receiptRaw === void 0) return null;
|
|
16760
|
+
const transferred = parseExplicitContextItems(receiptRaw);
|
|
16761
|
+
const withheld = [];
|
|
16762
|
+
if (Array.isArray(sourceStateRaw)) {
|
|
16763
|
+
const transferredKeys = new Set(
|
|
16764
|
+
transferred.map((t) => `${t.category}:${t.summary}`)
|
|
16765
|
+
);
|
|
16766
|
+
for (const item of parseExplicitContextItems(sourceStateRaw)) {
|
|
16767
|
+
const key = `${item.category}:${item.summary}`;
|
|
16768
|
+
if (!transferredKeys.has(key)) withheld.push(item);
|
|
16769
|
+
}
|
|
16770
|
+
}
|
|
16771
|
+
return {
|
|
16772
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
16773
|
+
transferred,
|
|
16774
|
+
withheld,
|
|
16775
|
+
source: "composition",
|
|
16776
|
+
confidence: 0.9
|
|
16777
|
+
};
|
|
16778
|
+
}
|
|
16779
|
+
function tryHeuristicPath(detail) {
|
|
16780
|
+
const entry = detail.entry;
|
|
16781
|
+
const audit = detail.source_audit_entry;
|
|
16782
|
+
const details = sourceDetails(audit);
|
|
16783
|
+
if (audit.operation === "cross_harness_approval_aggregated") {
|
|
16784
|
+
const ruleId = optString2(details, "policy_rule_id");
|
|
16785
|
+
if (ruleId) {
|
|
16786
|
+
const category = categoryFromPolicyRuleId(ruleId);
|
|
16787
|
+
const summary = `${ruleId} (${entry.source_agent_id} -> operator)`;
|
|
16788
|
+
return {
|
|
16789
|
+
handoff_entry_id: entry.entry_id,
|
|
16790
|
+
transferred: [
|
|
16791
|
+
{
|
|
16792
|
+
category,
|
|
16793
|
+
summary: truncate(summary, SUMMARY_MAX_CHARS),
|
|
16794
|
+
size_hint: "minimal"
|
|
16795
|
+
}
|
|
16796
|
+
],
|
|
16797
|
+
withheld: [],
|
|
16798
|
+
source: "heuristic",
|
|
16799
|
+
confidence: 0.5
|
|
16800
|
+
};
|
|
16801
|
+
}
|
|
16802
|
+
}
|
|
16803
|
+
if (audit.operation === "v1.1_local_handoff") {
|
|
16804
|
+
const reasonClass = optString2(details, "reason_class");
|
|
16805
|
+
const newStatus = optString2(details, "new_status");
|
|
16806
|
+
const previousStatus = optString2(details, "previous_status");
|
|
16807
|
+
const transferred = [];
|
|
16808
|
+
const withheld = [];
|
|
16809
|
+
if (newStatus === "denied" || newStatus === "failed") {
|
|
16810
|
+
withheld.push({
|
|
16811
|
+
category: "other",
|
|
16812
|
+
summary: truncate(
|
|
16813
|
+
`handoff ${newStatus}${reasonClass ? ` (${reasonClass})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
16814
|
+
SUMMARY_MAX_CHARS
|
|
16815
|
+
),
|
|
16816
|
+
size_hint: "minimal"
|
|
16817
|
+
});
|
|
16818
|
+
} else if (newStatus === "accepted" || newStatus === "completed") {
|
|
16819
|
+
transferred.push({
|
|
16820
|
+
category: "other",
|
|
16821
|
+
summary: truncate(
|
|
16822
|
+
`handoff ${newStatus}${previousStatus ? ` (from ${previousStatus})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
16823
|
+
SUMMARY_MAX_CHARS
|
|
16824
|
+
),
|
|
16825
|
+
size_hint: "small"
|
|
16826
|
+
});
|
|
16827
|
+
} else {
|
|
16828
|
+
transferred.push({
|
|
16829
|
+
category: "other",
|
|
16830
|
+
summary: truncate(
|
|
16831
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}${newStatus ? ` (${newStatus})` : ""}`,
|
|
16832
|
+
SUMMARY_MAX_CHARS
|
|
16833
|
+
),
|
|
16834
|
+
size_hint: "minimal"
|
|
16835
|
+
});
|
|
16836
|
+
}
|
|
16837
|
+
return {
|
|
16838
|
+
handoff_entry_id: entry.entry_id,
|
|
16839
|
+
transferred,
|
|
16840
|
+
withheld,
|
|
16841
|
+
source: "heuristic",
|
|
16842
|
+
confidence: reasonClass || newStatus ? 0.5 : 0.3
|
|
16843
|
+
};
|
|
16844
|
+
}
|
|
16845
|
+
return {
|
|
16846
|
+
handoff_entry_id: entry.entry_id,
|
|
16847
|
+
transferred: [
|
|
16848
|
+
{
|
|
16849
|
+
category: "other",
|
|
16850
|
+
summary: truncate(
|
|
16851
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
16852
|
+
SUMMARY_MAX_CHARS
|
|
16853
|
+
),
|
|
16854
|
+
size_hint: "minimal"
|
|
16855
|
+
}
|
|
16856
|
+
],
|
|
16857
|
+
withheld: [],
|
|
16858
|
+
source: "heuristic",
|
|
16859
|
+
confidence: 0.3
|
|
16860
|
+
};
|
|
16861
|
+
}
|
|
16862
|
+
async function tryLlmAssistPath(detail, selector) {
|
|
16863
|
+
const entry = detail.entry;
|
|
16864
|
+
const audit = detail.source_audit_entry;
|
|
16865
|
+
const probe = `event=${audit.operation} sender=${entry.source_agent_id} target=${entry.target_agent_id} summary=${entry.context_transfer_summary}`;
|
|
16866
|
+
try {
|
|
16867
|
+
const response = await selector.invokeClassify("sentinel-scoring", {
|
|
16868
|
+
kind: "classify",
|
|
16869
|
+
items: [probe],
|
|
16870
|
+
categories: [...CATEGORY_VALUES]
|
|
16871
|
+
});
|
|
16872
|
+
if (response.body.kind !== "classify") return null;
|
|
16873
|
+
const top = response.body.results[0];
|
|
16874
|
+
if (!top || !isCategory(top.category) || top.confidence < 0.4) {
|
|
16875
|
+
return null;
|
|
16876
|
+
}
|
|
16877
|
+
return {
|
|
16878
|
+
handoff_entry_id: entry.entry_id,
|
|
16879
|
+
transferred: [
|
|
16880
|
+
{
|
|
16881
|
+
category: top.category,
|
|
16882
|
+
summary: truncate(
|
|
16883
|
+
`LLM-classified handoff ${entry.source_agent_id} -> ${entry.target_agent_id}: ${top.category} (confidence ${top.confidence.toFixed(2)})`,
|
|
16884
|
+
SUMMARY_MAX_CHARS
|
|
16885
|
+
),
|
|
16886
|
+
size_hint: "minimal"
|
|
16887
|
+
}
|
|
16888
|
+
],
|
|
16889
|
+
withheld: [],
|
|
16890
|
+
source: "llm-assist",
|
|
16891
|
+
confidence: 0.6
|
|
16892
|
+
};
|
|
16893
|
+
} catch {
|
|
16894
|
+
return null;
|
|
16895
|
+
}
|
|
16896
|
+
}
|
|
16897
|
+
function sourceDetails(audit) {
|
|
16898
|
+
return audit.details;
|
|
16899
|
+
}
|
|
16900
|
+
function optString2(details, key) {
|
|
16901
|
+
if (!details) return null;
|
|
16902
|
+
const value = details[key];
|
|
16903
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
16904
|
+
return value;
|
|
16905
|
+
}
|
|
16906
|
+
function isCategory(value) {
|
|
16907
|
+
return CATEGORY_VALUES.includes(value);
|
|
16908
|
+
}
|
|
16909
|
+
function truncate(s, cap) {
|
|
16910
|
+
return s.length <= cap ? s : `${s.slice(0, cap - 3)}...`;
|
|
16911
|
+
}
|
|
16912
|
+
function parseExplicitContextItems(raw) {
|
|
16913
|
+
if (raw === null || raw === void 0) return [];
|
|
16914
|
+
if (Array.isArray(raw)) {
|
|
16915
|
+
const out = [];
|
|
16916
|
+
for (const entry of raw) {
|
|
16917
|
+
if (typeof entry === "string") {
|
|
16918
|
+
out.push({
|
|
16919
|
+
category: "other",
|
|
16920
|
+
summary: truncate(entry, SUMMARY_MAX_CHARS),
|
|
16921
|
+
size_hint: "minimal"
|
|
16922
|
+
});
|
|
16923
|
+
continue;
|
|
16924
|
+
}
|
|
16925
|
+
if (entry && typeof entry === "object") {
|
|
16926
|
+
const obj = entry;
|
|
16927
|
+
const category = isCategoryValue(obj["category"]) ? obj["category"] : "other";
|
|
16928
|
+
const summary = typeof obj["summary"] === "string" ? truncate(obj["summary"], SUMMARY_MAX_CHARS) : "(unspecified)";
|
|
16929
|
+
const sizeHint = isSizeHintValue(obj["size_hint"]) ? obj["size_hint"] : "minimal";
|
|
16930
|
+
out.push({ category, summary, size_hint: sizeHint });
|
|
16931
|
+
}
|
|
16932
|
+
}
|
|
16933
|
+
return out;
|
|
16934
|
+
}
|
|
16935
|
+
if (typeof raw === "object" && raw !== null) {
|
|
16936
|
+
const out = [];
|
|
16937
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
16938
|
+
const category = isCategoryValue(k) ? k : "other";
|
|
16939
|
+
if (Array.isArray(v)) {
|
|
16940
|
+
for (const item of v) {
|
|
16941
|
+
if (typeof item === "string") {
|
|
16942
|
+
out.push({
|
|
16943
|
+
category,
|
|
16944
|
+
summary: truncate(item, SUMMARY_MAX_CHARS),
|
|
16945
|
+
size_hint: "minimal"
|
|
16946
|
+
});
|
|
16947
|
+
}
|
|
16948
|
+
}
|
|
16949
|
+
}
|
|
16950
|
+
}
|
|
16951
|
+
return out;
|
|
16952
|
+
}
|
|
16953
|
+
return [];
|
|
16954
|
+
}
|
|
16955
|
+
function isCategoryValue(v) {
|
|
16956
|
+
return typeof v === "string" && CATEGORY_VALUES.includes(v);
|
|
16957
|
+
}
|
|
16958
|
+
function isSizeHintValue(v) {
|
|
16959
|
+
return typeof v === "string" && (v === "minimal" || v === "small" || v === "medium" || v === "large");
|
|
16960
|
+
}
|
|
16961
|
+
function categoryFromPolicyRuleId(ruleId) {
|
|
16962
|
+
const lower = ruleId.toLowerCase();
|
|
16963
|
+
if (lower.includes("credential") || lower.includes("broker_secret")) {
|
|
16964
|
+
return "credentials";
|
|
16965
|
+
}
|
|
16966
|
+
if (lower.includes("memory") || lower.includes("state_read")) {
|
|
16967
|
+
return "memory";
|
|
16968
|
+
}
|
|
16969
|
+
if (lower.includes("plan")) {
|
|
16970
|
+
return "plans";
|
|
16971
|
+
}
|
|
16972
|
+
if (lower.includes("export") || lower.includes("output")) {
|
|
16973
|
+
return "outputs";
|
|
16974
|
+
}
|
|
16975
|
+
if (lower.includes("audit")) {
|
|
16976
|
+
return "audit-refs";
|
|
16977
|
+
}
|
|
16978
|
+
return "other";
|
|
16979
|
+
}
|
|
16980
|
+
var CONTEXT_TRANSFER_AUDIT_OPS = {
|
|
16981
|
+
DECODED: "operator_handoff_context_transfer_decoded"
|
|
16982
|
+
};
|
|
16983
|
+
|
|
16984
|
+
// src/coordination/handoff-routes.ts
|
|
16985
|
+
var COORDINATION_API_PREFIX = "/api/coordination";
|
|
16986
|
+
var COORDINATION_HANDOFFS_PREFIX = "/api/coordination/handoffs";
|
|
16987
|
+
var COORDINATION_LIST_DEFAULT_LIMIT = 50;
|
|
16988
|
+
var COORDINATION_LIST_MAX_LIMIT = 500;
|
|
16989
|
+
var HandoffEventBridge = class {
|
|
16990
|
+
listeners = /* @__PURE__ */ new Set();
|
|
16991
|
+
subscribe(listener) {
|
|
16992
|
+
this.listeners.add(listener);
|
|
16993
|
+
return () => this.listeners.delete(listener);
|
|
16994
|
+
}
|
|
16995
|
+
emit(entry) {
|
|
16996
|
+
for (const listener of this.listeners) {
|
|
16997
|
+
try {
|
|
16998
|
+
listener(entry);
|
|
16999
|
+
} catch {
|
|
17000
|
+
}
|
|
17001
|
+
}
|
|
17002
|
+
}
|
|
17003
|
+
};
|
|
17004
|
+
function writeJSON6(res, status, payload) {
|
|
17005
|
+
res.writeHead(status, {
|
|
17006
|
+
"Content-Type": "application/json",
|
|
17007
|
+
"Cache-Control": "no-store"
|
|
17008
|
+
});
|
|
17009
|
+
res.end(JSON.stringify(payload));
|
|
17010
|
+
}
|
|
17011
|
+
function parseLimit4(raw, defaultValue, max) {
|
|
17012
|
+
if (raw === null || raw === "") return defaultValue;
|
|
17013
|
+
const parsed = Number.parseInt(raw, 10);
|
|
17014
|
+
if (Number.isNaN(parsed) || parsed < 0) return defaultValue;
|
|
17015
|
+
return Math.min(parsed, max);
|
|
17016
|
+
}
|
|
17017
|
+
function matchEntryRoute2(path) {
|
|
17018
|
+
const prefix = `${COORDINATION_HANDOFFS_PREFIX}/`;
|
|
17019
|
+
if (!path.startsWith(prefix)) return null;
|
|
17020
|
+
const rest = path.slice(prefix.length);
|
|
17021
|
+
if (rest.length === 0 || rest === "stream") return null;
|
|
17022
|
+
if (rest.includes("/")) return null;
|
|
17023
|
+
return { entryId: decodeURIComponent(rest) };
|
|
17024
|
+
}
|
|
17025
|
+
async function handleStream3(deps, res) {
|
|
17026
|
+
res.writeHead(200, {
|
|
17027
|
+
"Content-Type": "text/event-stream",
|
|
17028
|
+
"Cache-Control": "no-cache, no-transform",
|
|
17029
|
+
Connection: "keep-alive",
|
|
17030
|
+
"X-Accel-Buffering": "no"
|
|
17031
|
+
});
|
|
17032
|
+
const snapshot = await deps.handoffLog.query({ limit: 50 });
|
|
17033
|
+
res.write(
|
|
17034
|
+
`event: handoff_snapshot
|
|
17035
|
+
data: ${JSON.stringify({ entries: snapshot })}
|
|
17036
|
+
|
|
17037
|
+
`
|
|
17038
|
+
);
|
|
17039
|
+
const unsubscribe = deps.events.subscribe((entry) => {
|
|
17040
|
+
try {
|
|
17041
|
+
res.write(
|
|
17042
|
+
`event: handoff_added
|
|
17043
|
+
data: ${JSON.stringify(entry)}
|
|
17044
|
+
|
|
17045
|
+
`
|
|
17046
|
+
);
|
|
17047
|
+
} catch {
|
|
17048
|
+
}
|
|
17049
|
+
});
|
|
17050
|
+
const keepAlive = setInterval(() => {
|
|
17051
|
+
try {
|
|
17052
|
+
res.write(": keepalive\n\n");
|
|
17053
|
+
} catch {
|
|
17054
|
+
}
|
|
17055
|
+
}, 25e3);
|
|
17056
|
+
const cleanup = () => {
|
|
17057
|
+
clearInterval(keepAlive);
|
|
17058
|
+
unsubscribe();
|
|
17059
|
+
};
|
|
17060
|
+
res.on("close", cleanup);
|
|
17061
|
+
res.on("error", cleanup);
|
|
17062
|
+
}
|
|
17063
|
+
async function handleCoordinationRoute(deps, req, res) {
|
|
17064
|
+
const host = req.headers.host || "localhost";
|
|
17065
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
17066
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
17067
|
+
const path = url.pathname;
|
|
17068
|
+
if (path !== COORDINATION_API_PREFIX && !path.startsWith(`${COORDINATION_API_PREFIX}/`)) {
|
|
17069
|
+
return false;
|
|
17070
|
+
}
|
|
17071
|
+
const checkAuth = authMiddleware(deps.authConfig);
|
|
17072
|
+
if (!checkAuth(req, res, url)) return true;
|
|
17073
|
+
try {
|
|
17074
|
+
if (method === "GET" && path === `${COORDINATION_HANDOFFS_PREFIX}/stream`) {
|
|
17075
|
+
await handleStream3(deps, res);
|
|
17076
|
+
return true;
|
|
17077
|
+
}
|
|
17078
|
+
if (method === "GET" && path === COORDINATION_HANDOFFS_PREFIX) {
|
|
17079
|
+
const limit = parseLimit4(
|
|
17080
|
+
url.searchParams.get("limit"),
|
|
17081
|
+
COORDINATION_LIST_DEFAULT_LIMIT,
|
|
17082
|
+
COORDINATION_LIST_MAX_LIMIT
|
|
17083
|
+
);
|
|
17084
|
+
const since = url.searchParams.get("since") ?? void 0;
|
|
17085
|
+
const until = url.searchParams.get("until") ?? void 0;
|
|
17086
|
+
const agentId = url.searchParams.get("agent_id") ?? void 0;
|
|
17087
|
+
const entries = await deps.handoffLog.query({
|
|
17088
|
+
limit,
|
|
17089
|
+
...since !== void 0 ? { since } : {},
|
|
17090
|
+
...until !== void 0 ? { until } : {},
|
|
17091
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
17092
|
+
});
|
|
17093
|
+
deps.auditLog.append(
|
|
17094
|
+
"l2",
|
|
17095
|
+
COORDINATION_VIEW_AUDIT_OPS.VIEW_OPENED,
|
|
17096
|
+
deps.operatorId,
|
|
17097
|
+
{
|
|
17098
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
17099
|
+
result_count: entries.length,
|
|
17100
|
+
...since !== void 0 ? { since } : {},
|
|
17101
|
+
...until !== void 0 ? { until } : {},
|
|
17102
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
17103
|
+
}
|
|
17104
|
+
);
|
|
17105
|
+
writeJSON6(res, 200, { ok: true, data: { entries } });
|
|
17106
|
+
return true;
|
|
17107
|
+
}
|
|
17108
|
+
const entryMatch = matchEntryRoute2(path);
|
|
17109
|
+
if (method === "GET" && entryMatch) {
|
|
17110
|
+
const detail = await deps.handoffLog.getEntry(entryMatch.entryId);
|
|
17111
|
+
if (!detail) {
|
|
17112
|
+
writeJSON6(res, 404, { ok: false, error: "not_found" });
|
|
17113
|
+
return true;
|
|
17114
|
+
}
|
|
17115
|
+
deps.auditLog.append(
|
|
17116
|
+
"l2",
|
|
17117
|
+
COORDINATION_VIEW_AUDIT_OPS.ENTRY_DRILLED,
|
|
17118
|
+
deps.operatorId,
|
|
17119
|
+
{
|
|
17120
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
17121
|
+
entry_id: detail.entry.entry_id,
|
|
17122
|
+
event_class: detail.entry.event_class,
|
|
17123
|
+
source_agent_id: detail.entry.source_agent_id,
|
|
17124
|
+
target_agent_id: detail.entry.target_agent_id
|
|
17125
|
+
}
|
|
17126
|
+
);
|
|
17127
|
+
let breakdown = null;
|
|
17128
|
+
try {
|
|
17129
|
+
breakdown = await extractContextTransferBreakdown(
|
|
17130
|
+
detail,
|
|
17131
|
+
deps.contextTransfer ?? {}
|
|
17132
|
+
);
|
|
17133
|
+
deps.auditLog.append(
|
|
17134
|
+
"l2",
|
|
17135
|
+
CONTEXT_TRANSFER_AUDIT_OPS.DECODED,
|
|
17136
|
+
deps.operatorId,
|
|
17137
|
+
{
|
|
17138
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
17139
|
+
entry_id: detail.entry.entry_id,
|
|
17140
|
+
extractor_path: breakdown.source,
|
|
17141
|
+
confidence: breakdown.confidence,
|
|
17142
|
+
transferred_count: breakdown.transferred.length,
|
|
17143
|
+
withheld_count: breakdown.withheld.length
|
|
17144
|
+
}
|
|
17145
|
+
);
|
|
17146
|
+
} catch {
|
|
17147
|
+
}
|
|
17148
|
+
const responseData = breakdown !== null ? { ...detail, context_transfer_breakdown: breakdown } : detail;
|
|
17149
|
+
writeJSON6(res, 200, { ok: true, data: responseData });
|
|
17150
|
+
return true;
|
|
17151
|
+
}
|
|
17152
|
+
writeJSON6(res, 404, { ok: false, error: "not_found", path });
|
|
17153
|
+
return true;
|
|
17154
|
+
} catch (err) {
|
|
17155
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
17156
|
+
writeJSON6(res, 500, { ok: false, error: "internal", detail: msg });
|
|
17157
|
+
return true;
|
|
17158
|
+
}
|
|
17159
|
+
}
|
|
16568
17160
|
|
|
16569
17161
|
// src/principal-policy/dashboard.ts
|
|
16570
17162
|
var SESSION_TTL_REMOTE_MS = 5 * 60 * 1e3;
|
|
@@ -16645,6 +17237,17 @@ var DashboardApprovalChannel = class {
|
|
|
16645
17237
|
* dispatcher's audited paths.
|
|
16646
17238
|
*/
|
|
16647
17239
|
sentinelDispatcher = null;
|
|
17240
|
+
/**
|
|
17241
|
+
* v1.3 WP-V1.3-3 Omega-1 Coordination Handoff Visualization.
|
|
17242
|
+
* Mounted additively at `/api/coordination/*` when set. Read-only
|
|
17243
|
+
* against the audit log; the only writes are operator-action audit
|
|
17244
|
+
* events (operator_coordination_view_opened,
|
|
17245
|
+
* operator_handoff_entry_drilled).
|
|
17246
|
+
*/
|
|
17247
|
+
handoffLog = null;
|
|
17248
|
+
handoffEventBridge = null;
|
|
17249
|
+
handoffAuditLog = null;
|
|
17250
|
+
handoffOperatorId = null;
|
|
16648
17251
|
constructor(config) {
|
|
16649
17252
|
this.config = config;
|
|
16650
17253
|
this.authToken = config.auth_token;
|
|
@@ -16712,6 +17315,18 @@ var DashboardApprovalChannel = class {
|
|
|
16712
17315
|
setSentinelDispatcher(dispatcher) {
|
|
16713
17316
|
this.sentinelDispatcher = dispatcher;
|
|
16714
17317
|
}
|
|
17318
|
+
/**
|
|
17319
|
+
* v1.3 WP-V1.3-3 Omega-1: bind the Coordination handoff log +
|
|
17320
|
+
* event bridge + audit log + operator id. Once set, requests to
|
|
17321
|
+
* `/api/coordination/*` route through `handleCoordinationRoute`.
|
|
17322
|
+
* Pass `null` for any field to detach.
|
|
17323
|
+
*/
|
|
17324
|
+
setHandoffLog(opts) {
|
|
17325
|
+
this.handoffLog = opts.handoffLog;
|
|
17326
|
+
this.handoffEventBridge = opts.eventBridge ?? null;
|
|
17327
|
+
this.handoffAuditLog = opts.auditLog ?? null;
|
|
17328
|
+
this.handoffOperatorId = opts.operatorId ?? null;
|
|
17329
|
+
}
|
|
16715
17330
|
/**
|
|
16716
17331
|
* v1.3 WP-V1.3-10 dispatch entry point. Called from `handleRequest`
|
|
16717
17332
|
* before the legacy approval route table. Returns true when served.
|
|
@@ -16750,6 +17365,30 @@ var DashboardApprovalChannel = class {
|
|
|
16750
17365
|
res
|
|
16751
17366
|
);
|
|
16752
17367
|
}
|
|
17368
|
+
/**
|
|
17369
|
+
* v1.3 WP-V1.3-3 Omega-1 dispatch entry point. Routes
|
|
17370
|
+
* `/api/coordination/*` requests through the coordination router
|
|
17371
|
+
* when a HandoffLog has been bound. Returns true when served.
|
|
17372
|
+
*/
|
|
17373
|
+
async dispatchCoordination(req, res) {
|
|
17374
|
+
if (!this.handoffLog || !this.handoffEventBridge || !this.handoffAuditLog) {
|
|
17375
|
+
return false;
|
|
17376
|
+
}
|
|
17377
|
+
return handleCoordinationRoute(
|
|
17378
|
+
{
|
|
17379
|
+
authConfig: {
|
|
17380
|
+
loopbackAutoAuth: this._autoAuthLocalhost,
|
|
17381
|
+
...this.authToken !== void 0 ? { authToken: this.authToken } : {}
|
|
17382
|
+
},
|
|
17383
|
+
handoffLog: this.handoffLog,
|
|
17384
|
+
auditLog: this.handoffAuditLog,
|
|
17385
|
+
operatorId: this.handoffOperatorId ?? this.identityManager?.getPrimaryIdentityId() ?? "operator_dashboard",
|
|
17386
|
+
events: this.handoffEventBridge
|
|
17387
|
+
},
|
|
17388
|
+
req,
|
|
17389
|
+
res
|
|
17390
|
+
);
|
|
17391
|
+
}
|
|
16753
17392
|
/**
|
|
16754
17393
|
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
16755
17394
|
* legacy route table. Returns true when the request was served by v1.1
|
|
@@ -17149,6 +17788,18 @@ var DashboardApprovalChannel = class {
|
|
|
17149
17788
|
});
|
|
17150
17789
|
return;
|
|
17151
17790
|
}
|
|
17791
|
+
if (this.handoffLog && url.pathname.startsWith(COORDINATION_API_PREFIX)) {
|
|
17792
|
+
this.dispatchCoordination(req, res).then((handled) => {
|
|
17793
|
+
if (handled) return;
|
|
17794
|
+
this.handleLegacyRequest(req, res, url, method);
|
|
17795
|
+
}).catch(() => {
|
|
17796
|
+
if (!res.headersSent) {
|
|
17797
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
17798
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
17799
|
+
}
|
|
17800
|
+
});
|
|
17801
|
+
return;
|
|
17802
|
+
}
|
|
17152
17803
|
if (this.v11Bindings) {
|
|
17153
17804
|
this.dispatchV11(req, res, url, method).then((handled) => {
|
|
17154
17805
|
if (handled) return;
|
|
@@ -20952,13 +21603,33 @@ var SentinelDispatcher = class {
|
|
|
20952
21603
|
}
|
|
20953
21604
|
}
|
|
20954
21605
|
};
|
|
21606
|
+
|
|
21607
|
+
// src/anomaly-detection/classifier-state-store.ts
|
|
21608
|
+
init_encryption();
|
|
21609
|
+
init_encoding();
|
|
21610
|
+
|
|
21611
|
+
// src/anomaly-detection/classifiers/cusum.ts
|
|
21612
|
+
var CUSUM_CLASSIFIER_ID = "cusum";
|
|
21613
|
+
|
|
21614
|
+
// src/anomaly-detection/classifiers/psi.ts
|
|
21615
|
+
var PSI_CLASSIFIER_ID = "psi";
|
|
21616
|
+
|
|
21617
|
+
// src/anomaly-detection/anomaly-pipeline.ts
|
|
20955
21618
|
var ANOMALY_AUDIT_OPS = {
|
|
20956
21619
|
DETECTOR_REGISTERED: "anomaly_detector_registered",
|
|
20957
21620
|
DETECTOR_UNREGISTERED: "anomaly_detector_unregistered",
|
|
20958
21621
|
FINDING_EMITTED: "anomaly_finding_emitted",
|
|
20959
21622
|
EVALUATION_FAILED: "anomaly_evaluation_failed",
|
|
20960
21623
|
TRAINING_COMPLETED: "anomaly_training_completed",
|
|
20961
|
-
TRAINING_FAILED: "anomaly_training_failed"
|
|
21624
|
+
TRAINING_FAILED: "anomaly_training_failed",
|
|
21625
|
+
/** Chi-2: a classifier was attached to an existing detector. */
|
|
21626
|
+
CLASSIFIER_SUBSCRIBED: "anomaly_classifier_subscribed",
|
|
21627
|
+
/** Chi-2: a classifier was detached from an existing detector. */
|
|
21628
|
+
CLASSIFIER_UNSUBSCRIBED: "anomaly_classifier_unsubscribed",
|
|
21629
|
+
/** Chi-2: CUSUM-flagged mean-shift drift on a per-agent feature. */
|
|
21630
|
+
CUSUM_DRIFT_DETECTED: "anomaly_cusum_drift_detected",
|
|
21631
|
+
/** Chi-2: PSI-flagged distribution shift on a per-agent feature. */
|
|
21632
|
+
PSI_DISTRIBUTION_SHIFT_DETECTED: "anomaly_psi_distribution_shift_detected"
|
|
20962
21633
|
};
|
|
20963
21634
|
var DEFAULT_TICK_INTERVAL_MS2 = 6e4;
|
|
20964
21635
|
var AnomalyPipelineDispatcher = class {
|
|
@@ -21049,34 +21720,37 @@ var AnomalyPipelineDispatcher = class {
|
|
|
21049
21720
|
const stamped = await this.routeFinding(detectorId, raw);
|
|
21050
21721
|
findings.push(stamped);
|
|
21051
21722
|
}
|
|
21052
|
-
|
|
21053
|
-
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
|
|
21060
|
-
|
|
21061
|
-
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
|
|
21073
|
-
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21723
|
+
for (const classifier of detector.getAllClassifiers()) {
|
|
21724
|
+
try {
|
|
21725
|
+
const trainingResult = await classifier.train();
|
|
21726
|
+
this.auditLog.append(
|
|
21727
|
+
"l2",
|
|
21728
|
+
ANOMALY_AUDIT_OPS.TRAINING_COMPLETED,
|
|
21729
|
+
this.identityId,
|
|
21730
|
+
{
|
|
21731
|
+
detector_id: detectorId,
|
|
21732
|
+
classifier_id: classifier.classifierId,
|
|
21733
|
+
trained_at: trainingResult.trained_at,
|
|
21734
|
+
sample_count: trainingResult.sample_count,
|
|
21735
|
+
agent_count: trainingResult.agent_count,
|
|
21736
|
+
fortress_id: this.fortressId
|
|
21737
|
+
}
|
|
21738
|
+
);
|
|
21739
|
+
} catch (trainErr) {
|
|
21740
|
+
const message = trainErr instanceof Error ? trainErr.message : String(trainErr);
|
|
21741
|
+
this.auditLog.append(
|
|
21742
|
+
"l2",
|
|
21743
|
+
ANOMALY_AUDIT_OPS.TRAINING_FAILED,
|
|
21744
|
+
this.identityId,
|
|
21745
|
+
{
|
|
21746
|
+
detector_id: detectorId,
|
|
21747
|
+
classifier_id: classifier.classifierId,
|
|
21748
|
+
error_message: message,
|
|
21749
|
+
fortress_id: this.fortressId
|
|
21750
|
+
},
|
|
21751
|
+
"failure"
|
|
21752
|
+
);
|
|
21753
|
+
}
|
|
21080
21754
|
}
|
|
21081
21755
|
} catch (err) {
|
|
21082
21756
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -21139,6 +21813,7 @@ var AnomalyPipelineDispatcher = class {
|
|
|
21139
21813
|
observed_at: raw.observed_at || this.now().toISOString()
|
|
21140
21814
|
};
|
|
21141
21815
|
await this.findingStore.saveFinding(stamped);
|
|
21816
|
+
const classifierId = stamped.details["classifier_id"] ?? null;
|
|
21142
21817
|
this.auditLog.append(
|
|
21143
21818
|
"l2",
|
|
21144
21819
|
ANOMALY_AUDIT_OPS.FINDING_EMITTED,
|
|
@@ -21148,13 +21823,79 @@ var AnomalyPipelineDispatcher = class {
|
|
|
21148
21823
|
finding_id: stamped.finding_id,
|
|
21149
21824
|
severity: stamped.severity,
|
|
21150
21825
|
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
21826
|
+
...classifierId !== null ? { classifier_id: classifierId } : {},
|
|
21151
21827
|
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
21152
21828
|
fortress_id: this.fortressId
|
|
21153
21829
|
}
|
|
21154
21830
|
);
|
|
21831
|
+
const specificOp = classifierSpecificAuditOp(classifierId);
|
|
21832
|
+
if (specificOp !== null) {
|
|
21833
|
+
this.auditLog.append("l2", specificOp, this.identityId, {
|
|
21834
|
+
detector_id: detectorId,
|
|
21835
|
+
finding_id: stamped.finding_id,
|
|
21836
|
+
severity: stamped.severity,
|
|
21837
|
+
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
21838
|
+
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
21839
|
+
fortress_id: this.fortressId
|
|
21840
|
+
});
|
|
21841
|
+
}
|
|
21155
21842
|
this.emit({ type: "finding", finding: stamped });
|
|
21156
21843
|
return stamped;
|
|
21157
21844
|
}
|
|
21845
|
+
/**
|
|
21846
|
+
* Chi-2: attach an additional classifier to an already-registered
|
|
21847
|
+
* detector. Emits ANOMALY_CLASSIFIER_SUBSCRIBED on success. The
|
|
21848
|
+
* factory is called with the fortress AnomalyContext so the
|
|
21849
|
+
* classifier can build its own state-store binding. Idempotent: a
|
|
21850
|
+
* second call with the same classifierId returns false.
|
|
21851
|
+
*/
|
|
21852
|
+
async addClassifierToDetector(detectorId, factory) {
|
|
21853
|
+
const detector = this.detectors.get(detectorId);
|
|
21854
|
+
if (!detector) return false;
|
|
21855
|
+
const context = {
|
|
21856
|
+
fortressId: this.fortressId,
|
|
21857
|
+
auditLog: this.auditLog,
|
|
21858
|
+
storage: this.storage,
|
|
21859
|
+
masterKey: this.masterKey,
|
|
21860
|
+
now: this.now
|
|
21861
|
+
};
|
|
21862
|
+
const classifier = factory(context);
|
|
21863
|
+
const added = detector.addClassifier(classifier);
|
|
21864
|
+
if (!added) return false;
|
|
21865
|
+
this.auditLog.append(
|
|
21866
|
+
"l2",
|
|
21867
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_SUBSCRIBED,
|
|
21868
|
+
this.identityId,
|
|
21869
|
+
{
|
|
21870
|
+
detector_id: detectorId,
|
|
21871
|
+
classifier_id: classifier.classifierId,
|
|
21872
|
+
fortress_id: this.fortressId
|
|
21873
|
+
}
|
|
21874
|
+
);
|
|
21875
|
+
return true;
|
|
21876
|
+
}
|
|
21877
|
+
/**
|
|
21878
|
+
* Chi-2: detach an additional classifier from an already-registered
|
|
21879
|
+
* detector. Emits ANOMALY_CLASSIFIER_UNSUBSCRIBED on success. The
|
|
21880
|
+
* primary classifier cannot be detached (returns false).
|
|
21881
|
+
*/
|
|
21882
|
+
async removeClassifierFromDetector(detectorId, classifierId) {
|
|
21883
|
+
const detector = this.detectors.get(detectorId);
|
|
21884
|
+
if (!detector) return false;
|
|
21885
|
+
const removed = detector.removeClassifier(classifierId);
|
|
21886
|
+
if (!removed) return false;
|
|
21887
|
+
this.auditLog.append(
|
|
21888
|
+
"l2",
|
|
21889
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_UNSUBSCRIBED,
|
|
21890
|
+
this.identityId,
|
|
21891
|
+
{
|
|
21892
|
+
detector_id: detectorId,
|
|
21893
|
+
classifier_id: classifierId,
|
|
21894
|
+
fortress_id: this.fortressId
|
|
21895
|
+
}
|
|
21896
|
+
);
|
|
21897
|
+
return true;
|
|
21898
|
+
}
|
|
21158
21899
|
emit(event) {
|
|
21159
21900
|
for (const listener of this.listeners) {
|
|
21160
21901
|
try {
|
|
@@ -21164,6 +21905,16 @@ var AnomalyPipelineDispatcher = class {
|
|
|
21164
21905
|
}
|
|
21165
21906
|
}
|
|
21166
21907
|
};
|
|
21908
|
+
function classifierSpecificAuditOp(classifierId) {
|
|
21909
|
+
if (classifierId === null) return null;
|
|
21910
|
+
if (classifierId === CUSUM_CLASSIFIER_ID) {
|
|
21911
|
+
return ANOMALY_AUDIT_OPS.CUSUM_DRIFT_DETECTED;
|
|
21912
|
+
}
|
|
21913
|
+
if (classifierId === PSI_CLASSIFIER_ID) {
|
|
21914
|
+
return ANOMALY_AUDIT_OPS.PSI_DISTRIBUTION_SHIFT_DETECTED;
|
|
21915
|
+
}
|
|
21916
|
+
return null;
|
|
21917
|
+
}
|
|
21167
21918
|
|
|
21168
21919
|
// src/sentinel/sentinel.ts
|
|
21169
21920
|
var Sentinel = class {
|
|
@@ -21344,7 +22095,7 @@ var ALERT_SIGMA2 = 6;
|
|
|
21344
22095
|
var BASELINE_WINDOWS2 = 7;
|
|
21345
22096
|
var QUERY_LIMIT2 = 1e4;
|
|
21346
22097
|
var MULTI_NEW_PARTNER_ALERT_THRESHOLD = 3;
|
|
21347
|
-
var
|
|
22098
|
+
var OPERATOR_PSEUDO_AGENT2 = "operator";
|
|
21348
22099
|
var HANDOFF_OP = "v1.1_local_handoff";
|
|
21349
22100
|
var CROSS_HARNESS_OPS = /* @__PURE__ */ new Set([
|
|
21350
22101
|
"cross_harness_approval_aggregated",
|
|
@@ -21577,7 +22328,7 @@ function extractInterAgentEvents(entries) {
|
|
|
21577
22328
|
if (!sender) continue;
|
|
21578
22329
|
out.push({
|
|
21579
22330
|
sender,
|
|
21580
|
-
recipient:
|
|
22331
|
+
recipient: OPERATOR_PSEUDO_AGENT2,
|
|
21581
22332
|
timestampMs: Date.parse(entry.timestamp),
|
|
21582
22333
|
auditId: `${entry.timestamp}:${entry.operation}`
|
|
21583
22334
|
});
|
|
@@ -37843,6 +38594,136 @@ function tryParseClassification3(text) {
|
|
|
37843
38594
|
}
|
|
37844
38595
|
}
|
|
37845
38596
|
|
|
38597
|
+
// src/query-anonymity/header-strip.ts
|
|
38598
|
+
var QUERY_ANONYMITY_AUDIT_OPS = {
|
|
38599
|
+
HEADERS_STRIPPED: "query_anonymity_headers_stripped"
|
|
38600
|
+
};
|
|
38601
|
+
var CANONICAL_STRIP_LIST = [
|
|
38602
|
+
// Browser / runtime fingerprinting.
|
|
38603
|
+
{ name: "user-agent", reason: "user-agent" },
|
|
38604
|
+
{ name: "sec-ch-ua", reason: "fingerprintable-extension" },
|
|
38605
|
+
{ name: "sec-ch-ua-mobile", reason: "fingerprintable-extension" },
|
|
38606
|
+
{ name: "sec-ch-ua-platform", reason: "fingerprintable-extension" },
|
|
38607
|
+
{ name: "sec-ch-ua-platform-version", reason: "fingerprintable-extension" },
|
|
38608
|
+
{ name: "sec-ch-ua-arch", reason: "fingerprintable-extension" },
|
|
38609
|
+
{ name: "sec-ch-ua-bitness", reason: "fingerprintable-extension" },
|
|
38610
|
+
{ name: "sec-ch-ua-model", reason: "fingerprintable-extension" },
|
|
38611
|
+
{ name: "sec-ch-ua-full-version-list", reason: "fingerprintable-extension" },
|
|
38612
|
+
// Locale fingerprint.
|
|
38613
|
+
{ name: "accept-language", reason: "locale-fingerprint" },
|
|
38614
|
+
// Request-origin leak.
|
|
38615
|
+
{ name: "referer", reason: "leaking-network-info" },
|
|
38616
|
+
{ name: "referrer-policy", reason: "leaking-network-info" },
|
|
38617
|
+
{ name: "origin", reason: "leaking-network-info" },
|
|
38618
|
+
// Forwarded-by / IP-derived network info.
|
|
38619
|
+
{ name: "via", reason: "leaking-network-info" },
|
|
38620
|
+
{ name: "forwarded", reason: "leaking-network-info" },
|
|
38621
|
+
{ name: "x-forwarded-for", reason: "leaking-network-info" },
|
|
38622
|
+
{ name: "x-real-ip", reason: "leaking-network-info" },
|
|
38623
|
+
{ name: "x-client-ip", reason: "leaking-network-info" },
|
|
38624
|
+
// DNT / GPC are technically anti-tracking signals but they
|
|
38625
|
+
// themselves form a fingerprint (operators who set DNT=1 are a
|
|
38626
|
+
// smaller subset). Strip to keep the substrate ignorant of
|
|
38627
|
+
// operator preferences.
|
|
38628
|
+
{ name: "dnt", reason: "unnecessary-metadata" },
|
|
38629
|
+
{ name: "sec-gpc", reason: "unnecessary-metadata" }
|
|
38630
|
+
];
|
|
38631
|
+
var REQUIRED_HEADERS = [
|
|
38632
|
+
"authorization",
|
|
38633
|
+
"content-type",
|
|
38634
|
+
"content-length",
|
|
38635
|
+
"host",
|
|
38636
|
+
"accept",
|
|
38637
|
+
"x-api-key",
|
|
38638
|
+
// Anthropic API auth
|
|
38639
|
+
"anthropic-version",
|
|
38640
|
+
// Anthropic API contract version
|
|
38641
|
+
"anthropic-beta",
|
|
38642
|
+
// optional Anthropic beta opt-in
|
|
38643
|
+
"openai-organization",
|
|
38644
|
+
// optional OpenAI org id
|
|
38645
|
+
"x-stainless-package-version",
|
|
38646
|
+
// allowed for Anthropic + OpenAI SDK contract compat
|
|
38647
|
+
"x-goog-api-key",
|
|
38648
|
+
// Google AI Studio
|
|
38649
|
+
"x-goog-user-project"
|
|
38650
|
+
// Google AI Studio
|
|
38651
|
+
];
|
|
38652
|
+
var REQUIRED_HEADER_SET = new Set(
|
|
38653
|
+
REQUIRED_HEADERS.map((h) => h.toLowerCase())
|
|
38654
|
+
);
|
|
38655
|
+
var STRIP_REASON_BY_NAME = new Map(
|
|
38656
|
+
CANONICAL_STRIP_LIST.map((h) => [h.name.toLowerCase(), h.reason])
|
|
38657
|
+
);
|
|
38658
|
+
function stripHeaders(headers) {
|
|
38659
|
+
const stripped = {};
|
|
38660
|
+
const removed = [];
|
|
38661
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
38662
|
+
const lower = name.toLowerCase();
|
|
38663
|
+
if (REQUIRED_HEADER_SET.has(lower)) {
|
|
38664
|
+
stripped[name] = value;
|
|
38665
|
+
continue;
|
|
38666
|
+
}
|
|
38667
|
+
const reason = STRIP_REASON_BY_NAME.get(lower);
|
|
38668
|
+
if (reason !== void 0) {
|
|
38669
|
+
removed.push({ name, reason });
|
|
38670
|
+
continue;
|
|
38671
|
+
}
|
|
38672
|
+
stripped[name] = value;
|
|
38673
|
+
}
|
|
38674
|
+
return { stripped, removed };
|
|
38675
|
+
}
|
|
38676
|
+
function defeatUndiciDefaultsInto(headers) {
|
|
38677
|
+
if (headers["user-agent"] === void 0 && headers["User-Agent"] === void 0) {
|
|
38678
|
+
headers["User-Agent"] = "";
|
|
38679
|
+
}
|
|
38680
|
+
if (headers["accept-language"] === void 0 && headers["Accept-Language"] === void 0) {
|
|
38681
|
+
headers["Accept-Language"] = "";
|
|
38682
|
+
}
|
|
38683
|
+
return headers;
|
|
38684
|
+
}
|
|
38685
|
+
function createAnonymizedFetch(baseFetch, onAudit) {
|
|
38686
|
+
const wrapped = async (input, init) => {
|
|
38687
|
+
const headers = normalizeHeadersInit(init?.headers);
|
|
38688
|
+
const result = stripHeaders(headers);
|
|
38689
|
+
defeatUndiciDefaultsInto(result.stripped);
|
|
38690
|
+
const preservedRequired = Object.keys(result.stripped).filter(
|
|
38691
|
+
(k) => REQUIRED_HEADER_SET.has(k.toLowerCase())
|
|
38692
|
+
);
|
|
38693
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
38694
|
+
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
38695
|
+
if (onAudit) {
|
|
38696
|
+
onAudit({
|
|
38697
|
+
url,
|
|
38698
|
+
method,
|
|
38699
|
+
stripped_count: result.removed.length,
|
|
38700
|
+
removed: result.removed,
|
|
38701
|
+
required_preserved: preservedRequired
|
|
38702
|
+
});
|
|
38703
|
+
}
|
|
38704
|
+
return baseFetch(input, { ...init, headers: result.stripped });
|
|
38705
|
+
};
|
|
38706
|
+
return wrapped;
|
|
38707
|
+
}
|
|
38708
|
+
function normalizeHeadersInit(raw) {
|
|
38709
|
+
if (raw === void 0) return {};
|
|
38710
|
+
if (typeof Headers !== "undefined" && raw instanceof Headers) {
|
|
38711
|
+
const out = {};
|
|
38712
|
+
raw.forEach((value, key) => {
|
|
38713
|
+
out[key] = value;
|
|
38714
|
+
});
|
|
38715
|
+
return out;
|
|
38716
|
+
}
|
|
38717
|
+
if (Array.isArray(raw)) {
|
|
38718
|
+
const out = {};
|
|
38719
|
+
for (const [k, v] of raw) {
|
|
38720
|
+
if (k !== void 0 && v !== void 0) out[k] = v;
|
|
38721
|
+
}
|
|
38722
|
+
return out;
|
|
38723
|
+
}
|
|
38724
|
+
return { ...raw };
|
|
38725
|
+
}
|
|
38726
|
+
|
|
37846
38727
|
// src/intelligence/substrates/hybrid/per-surface-router.ts
|
|
37847
38728
|
function resolveHybridChoice(rules, surface) {
|
|
37848
38729
|
if (!rules) return null;
|
|
@@ -37903,7 +38784,21 @@ var SubstrateSelector = class {
|
|
|
37903
38784
|
this.auditLog = cfg.auditLog;
|
|
37904
38785
|
this.identityId = cfg.identityId;
|
|
37905
38786
|
this.redactor = cfg.redactor ?? IDENTITY_REDACTOR;
|
|
37906
|
-
|
|
38787
|
+
const baseFetch = cfg.fetchImpl ?? globalThis.fetch;
|
|
38788
|
+
this.fetchImpl = createAnonymizedFetch(baseFetch, (event) => {
|
|
38789
|
+
this.auditLog.append(
|
|
38790
|
+
"l2",
|
|
38791
|
+
QUERY_ANONYMITY_AUDIT_OPS.HEADERS_STRIPPED,
|
|
38792
|
+
this.identityId,
|
|
38793
|
+
{
|
|
38794
|
+
url: event.url,
|
|
38795
|
+
method: event.method,
|
|
38796
|
+
stripped_count: event.stripped_count,
|
|
38797
|
+
removed: event.removed,
|
|
38798
|
+
required_preserved: event.required_preserved
|
|
38799
|
+
}
|
|
38800
|
+
);
|
|
38801
|
+
});
|
|
37907
38802
|
this.config = buildDefaultConfig();
|
|
37908
38803
|
}
|
|
37909
38804
|
/**
|
|
@@ -41088,6 +41983,19 @@ ${err.message}
|
|
|
41088
41983
|
identityId: aggregatorIdentityId
|
|
41089
41984
|
});
|
|
41090
41985
|
anomalyDispatcher.start();
|
|
41986
|
+
const handoffLog = new HandoffLog({
|
|
41987
|
+
auditLog,
|
|
41988
|
+
fortressId: fortressIdForAggregator
|
|
41989
|
+
});
|
|
41990
|
+
const handoffEventBridge = new HandoffEventBridge();
|
|
41991
|
+
if (dashboard) {
|
|
41992
|
+
dashboard.setHandoffLog({
|
|
41993
|
+
handoffLog,
|
|
41994
|
+
eventBridge: handoffEventBridge,
|
|
41995
|
+
auditLog,
|
|
41996
|
+
operatorId: aggregatorIdentityId
|
|
41997
|
+
});
|
|
41998
|
+
}
|
|
41091
41999
|
const policyTools = createPrincipalPolicyTools(policy, baseline, auditLog);
|
|
41092
42000
|
const { tools: sanctuaryMetaTools } = createSanctuaryTools({
|
|
41093
42001
|
config,
|