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