@sanctuary-framework/mcp-server 1.2.11 → 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 +594 -31
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +594 -31
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +567 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +567 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -17624,6 +17624,281 @@ var init_handoff_log = __esm({
|
|
|
17624
17624
|
}
|
|
17625
17625
|
});
|
|
17626
17626
|
|
|
17627
|
+
// src/coordination/context-transfer-extractor.ts
|
|
17628
|
+
async function extractContextTransferBreakdown(detail, deps = {}) {
|
|
17629
|
+
const pathA = tryStructuredPath(detail);
|
|
17630
|
+
if (pathA) return pathA;
|
|
17631
|
+
const pathB = tryCompositionPath(detail);
|
|
17632
|
+
if (pathB) return pathB;
|
|
17633
|
+
const pathC = tryHeuristicPath(detail);
|
|
17634
|
+
if (pathC.confidence >= 0.5 || !deps.substrateSelector) {
|
|
17635
|
+
return pathC;
|
|
17636
|
+
}
|
|
17637
|
+
const assist = await tryLlmAssistPath(detail, deps.substrateSelector);
|
|
17638
|
+
return assist ?? pathC;
|
|
17639
|
+
}
|
|
17640
|
+
function tryStructuredPath(detail) {
|
|
17641
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
17642
|
+
if (!details) return null;
|
|
17643
|
+
const transferredRaw = details["transferred"];
|
|
17644
|
+
const withheldRaw = details["withheld"];
|
|
17645
|
+
if (transferredRaw === void 0 && withheldRaw === void 0) return null;
|
|
17646
|
+
const transferred = parseExplicitContextItems(transferredRaw);
|
|
17647
|
+
const withheld = parseExplicitContextItems(withheldRaw);
|
|
17648
|
+
return {
|
|
17649
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
17650
|
+
transferred,
|
|
17651
|
+
withheld,
|
|
17652
|
+
source: "structured",
|
|
17653
|
+
confidence: 1
|
|
17654
|
+
};
|
|
17655
|
+
}
|
|
17656
|
+
function tryCompositionPath(detail) {
|
|
17657
|
+
const op = detail.source_audit_entry.operation;
|
|
17658
|
+
if (!op.startsWith("composition_completed")) return null;
|
|
17659
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
17660
|
+
if (!details) return null;
|
|
17661
|
+
const receiptRaw = details["receipt"];
|
|
17662
|
+
const sourceStateRaw = details["source_state_snapshot"];
|
|
17663
|
+
if (receiptRaw === void 0) return null;
|
|
17664
|
+
const transferred = parseExplicitContextItems(receiptRaw);
|
|
17665
|
+
const withheld = [];
|
|
17666
|
+
if (Array.isArray(sourceStateRaw)) {
|
|
17667
|
+
const transferredKeys = new Set(
|
|
17668
|
+
transferred.map((t) => `${t.category}:${t.summary}`)
|
|
17669
|
+
);
|
|
17670
|
+
for (const item of parseExplicitContextItems(sourceStateRaw)) {
|
|
17671
|
+
const key = `${item.category}:${item.summary}`;
|
|
17672
|
+
if (!transferredKeys.has(key)) withheld.push(item);
|
|
17673
|
+
}
|
|
17674
|
+
}
|
|
17675
|
+
return {
|
|
17676
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
17677
|
+
transferred,
|
|
17678
|
+
withheld,
|
|
17679
|
+
source: "composition",
|
|
17680
|
+
confidence: 0.9
|
|
17681
|
+
};
|
|
17682
|
+
}
|
|
17683
|
+
function tryHeuristicPath(detail) {
|
|
17684
|
+
const entry = detail.entry;
|
|
17685
|
+
const audit = detail.source_audit_entry;
|
|
17686
|
+
const details = sourceDetails(audit);
|
|
17687
|
+
if (audit.operation === "cross_harness_approval_aggregated") {
|
|
17688
|
+
const ruleId = optString2(details, "policy_rule_id");
|
|
17689
|
+
if (ruleId) {
|
|
17690
|
+
const category = categoryFromPolicyRuleId(ruleId);
|
|
17691
|
+
const summary = `${ruleId} (${entry.source_agent_id} -> operator)`;
|
|
17692
|
+
return {
|
|
17693
|
+
handoff_entry_id: entry.entry_id,
|
|
17694
|
+
transferred: [
|
|
17695
|
+
{
|
|
17696
|
+
category,
|
|
17697
|
+
summary: truncate(summary, SUMMARY_MAX_CHARS),
|
|
17698
|
+
size_hint: "minimal"
|
|
17699
|
+
}
|
|
17700
|
+
],
|
|
17701
|
+
withheld: [],
|
|
17702
|
+
source: "heuristic",
|
|
17703
|
+
confidence: 0.5
|
|
17704
|
+
};
|
|
17705
|
+
}
|
|
17706
|
+
}
|
|
17707
|
+
if (audit.operation === "v1.1_local_handoff") {
|
|
17708
|
+
const reasonClass = optString2(details, "reason_class");
|
|
17709
|
+
const newStatus = optString2(details, "new_status");
|
|
17710
|
+
const previousStatus = optString2(details, "previous_status");
|
|
17711
|
+
const transferred = [];
|
|
17712
|
+
const withheld = [];
|
|
17713
|
+
if (newStatus === "denied" || newStatus === "failed") {
|
|
17714
|
+
withheld.push({
|
|
17715
|
+
category: "other",
|
|
17716
|
+
summary: truncate(
|
|
17717
|
+
`handoff ${newStatus}${reasonClass ? ` (${reasonClass})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17718
|
+
SUMMARY_MAX_CHARS
|
|
17719
|
+
),
|
|
17720
|
+
size_hint: "minimal"
|
|
17721
|
+
});
|
|
17722
|
+
} else if (newStatus === "accepted" || newStatus === "completed") {
|
|
17723
|
+
transferred.push({
|
|
17724
|
+
category: "other",
|
|
17725
|
+
summary: truncate(
|
|
17726
|
+
`handoff ${newStatus}${previousStatus ? ` (from ${previousStatus})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17727
|
+
SUMMARY_MAX_CHARS
|
|
17728
|
+
),
|
|
17729
|
+
size_hint: "small"
|
|
17730
|
+
});
|
|
17731
|
+
} else {
|
|
17732
|
+
transferred.push({
|
|
17733
|
+
category: "other",
|
|
17734
|
+
summary: truncate(
|
|
17735
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}${newStatus ? ` (${newStatus})` : ""}`,
|
|
17736
|
+
SUMMARY_MAX_CHARS
|
|
17737
|
+
),
|
|
17738
|
+
size_hint: "minimal"
|
|
17739
|
+
});
|
|
17740
|
+
}
|
|
17741
|
+
return {
|
|
17742
|
+
handoff_entry_id: entry.entry_id,
|
|
17743
|
+
transferred,
|
|
17744
|
+
withheld,
|
|
17745
|
+
source: "heuristic",
|
|
17746
|
+
confidence: reasonClass || newStatus ? 0.5 : 0.3
|
|
17747
|
+
};
|
|
17748
|
+
}
|
|
17749
|
+
return {
|
|
17750
|
+
handoff_entry_id: entry.entry_id,
|
|
17751
|
+
transferred: [
|
|
17752
|
+
{
|
|
17753
|
+
category: "other",
|
|
17754
|
+
summary: truncate(
|
|
17755
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17756
|
+
SUMMARY_MAX_CHARS
|
|
17757
|
+
),
|
|
17758
|
+
size_hint: "minimal"
|
|
17759
|
+
}
|
|
17760
|
+
],
|
|
17761
|
+
withheld: [],
|
|
17762
|
+
source: "heuristic",
|
|
17763
|
+
confidence: 0.3
|
|
17764
|
+
};
|
|
17765
|
+
}
|
|
17766
|
+
async function tryLlmAssistPath(detail, selector) {
|
|
17767
|
+
const entry = detail.entry;
|
|
17768
|
+
const audit = detail.source_audit_entry;
|
|
17769
|
+
const probe = `event=${audit.operation} sender=${entry.source_agent_id} target=${entry.target_agent_id} summary=${entry.context_transfer_summary}`;
|
|
17770
|
+
try {
|
|
17771
|
+
const response = await selector.invokeClassify("sentinel-scoring", {
|
|
17772
|
+
kind: "classify",
|
|
17773
|
+
items: [probe],
|
|
17774
|
+
categories: [...CATEGORY_VALUES]
|
|
17775
|
+
});
|
|
17776
|
+
if (response.body.kind !== "classify") return null;
|
|
17777
|
+
const top = response.body.results[0];
|
|
17778
|
+
if (!top || !isCategory(top.category) || top.confidence < 0.4) {
|
|
17779
|
+
return null;
|
|
17780
|
+
}
|
|
17781
|
+
return {
|
|
17782
|
+
handoff_entry_id: entry.entry_id,
|
|
17783
|
+
transferred: [
|
|
17784
|
+
{
|
|
17785
|
+
category: top.category,
|
|
17786
|
+
summary: truncate(
|
|
17787
|
+
`LLM-classified handoff ${entry.source_agent_id} -> ${entry.target_agent_id}: ${top.category} (confidence ${top.confidence.toFixed(2)})`,
|
|
17788
|
+
SUMMARY_MAX_CHARS
|
|
17789
|
+
),
|
|
17790
|
+
size_hint: "minimal"
|
|
17791
|
+
}
|
|
17792
|
+
],
|
|
17793
|
+
withheld: [],
|
|
17794
|
+
source: "llm-assist",
|
|
17795
|
+
confidence: 0.6
|
|
17796
|
+
};
|
|
17797
|
+
} catch {
|
|
17798
|
+
return null;
|
|
17799
|
+
}
|
|
17800
|
+
}
|
|
17801
|
+
function sourceDetails(audit) {
|
|
17802
|
+
return audit.details;
|
|
17803
|
+
}
|
|
17804
|
+
function optString2(details, key) {
|
|
17805
|
+
if (!details) return null;
|
|
17806
|
+
const value = details[key];
|
|
17807
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
17808
|
+
return value;
|
|
17809
|
+
}
|
|
17810
|
+
function isCategory(value) {
|
|
17811
|
+
return CATEGORY_VALUES.includes(value);
|
|
17812
|
+
}
|
|
17813
|
+
function truncate(s, cap) {
|
|
17814
|
+
return s.length <= cap ? s : `${s.slice(0, cap - 3)}...`;
|
|
17815
|
+
}
|
|
17816
|
+
function parseExplicitContextItems(raw) {
|
|
17817
|
+
if (raw === null || raw === void 0) return [];
|
|
17818
|
+
if (Array.isArray(raw)) {
|
|
17819
|
+
const out = [];
|
|
17820
|
+
for (const entry of raw) {
|
|
17821
|
+
if (typeof entry === "string") {
|
|
17822
|
+
out.push({
|
|
17823
|
+
category: "other",
|
|
17824
|
+
summary: truncate(entry, SUMMARY_MAX_CHARS),
|
|
17825
|
+
size_hint: "minimal"
|
|
17826
|
+
});
|
|
17827
|
+
continue;
|
|
17828
|
+
}
|
|
17829
|
+
if (entry && typeof entry === "object") {
|
|
17830
|
+
const obj = entry;
|
|
17831
|
+
const category = isCategoryValue(obj["category"]) ? obj["category"] : "other";
|
|
17832
|
+
const summary = typeof obj["summary"] === "string" ? truncate(obj["summary"], SUMMARY_MAX_CHARS) : "(unspecified)";
|
|
17833
|
+
const sizeHint = isSizeHintValue(obj["size_hint"]) ? obj["size_hint"] : "minimal";
|
|
17834
|
+
out.push({ category, summary, size_hint: sizeHint });
|
|
17835
|
+
}
|
|
17836
|
+
}
|
|
17837
|
+
return out;
|
|
17838
|
+
}
|
|
17839
|
+
if (typeof raw === "object" && raw !== null) {
|
|
17840
|
+
const out = [];
|
|
17841
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
17842
|
+
const category = isCategoryValue(k) ? k : "other";
|
|
17843
|
+
if (Array.isArray(v)) {
|
|
17844
|
+
for (const item of v) {
|
|
17845
|
+
if (typeof item === "string") {
|
|
17846
|
+
out.push({
|
|
17847
|
+
category,
|
|
17848
|
+
summary: truncate(item, SUMMARY_MAX_CHARS),
|
|
17849
|
+
size_hint: "minimal"
|
|
17850
|
+
});
|
|
17851
|
+
}
|
|
17852
|
+
}
|
|
17853
|
+
}
|
|
17854
|
+
}
|
|
17855
|
+
return out;
|
|
17856
|
+
}
|
|
17857
|
+
return [];
|
|
17858
|
+
}
|
|
17859
|
+
function isCategoryValue(v) {
|
|
17860
|
+
return typeof v === "string" && CATEGORY_VALUES.includes(v);
|
|
17861
|
+
}
|
|
17862
|
+
function isSizeHintValue(v) {
|
|
17863
|
+
return typeof v === "string" && (v === "minimal" || v === "small" || v === "medium" || v === "large");
|
|
17864
|
+
}
|
|
17865
|
+
function categoryFromPolicyRuleId(ruleId) {
|
|
17866
|
+
const lower = ruleId.toLowerCase();
|
|
17867
|
+
if (lower.includes("credential") || lower.includes("broker_secret")) {
|
|
17868
|
+
return "credentials";
|
|
17869
|
+
}
|
|
17870
|
+
if (lower.includes("memory") || lower.includes("state_read")) {
|
|
17871
|
+
return "memory";
|
|
17872
|
+
}
|
|
17873
|
+
if (lower.includes("plan")) {
|
|
17874
|
+
return "plans";
|
|
17875
|
+
}
|
|
17876
|
+
if (lower.includes("export") || lower.includes("output")) {
|
|
17877
|
+
return "outputs";
|
|
17878
|
+
}
|
|
17879
|
+
if (lower.includes("audit")) {
|
|
17880
|
+
return "audit-refs";
|
|
17881
|
+
}
|
|
17882
|
+
return "other";
|
|
17883
|
+
}
|
|
17884
|
+
var SUMMARY_MAX_CHARS, CATEGORY_VALUES, CONTEXT_TRANSFER_AUDIT_OPS;
|
|
17885
|
+
var init_context_transfer_extractor = __esm({
|
|
17886
|
+
"src/coordination/context-transfer-extractor.ts"() {
|
|
17887
|
+
SUMMARY_MAX_CHARS = 240;
|
|
17888
|
+
CATEGORY_VALUES = [
|
|
17889
|
+
"memory",
|
|
17890
|
+
"credentials",
|
|
17891
|
+
"plans",
|
|
17892
|
+
"outputs",
|
|
17893
|
+
"audit-refs",
|
|
17894
|
+
"other"
|
|
17895
|
+
];
|
|
17896
|
+
CONTEXT_TRANSFER_AUDIT_OPS = {
|
|
17897
|
+
DECODED: "operator_handoff_context_transfer_decoded"
|
|
17898
|
+
};
|
|
17899
|
+
}
|
|
17900
|
+
});
|
|
17901
|
+
|
|
17627
17902
|
// src/coordination/handoff-routes.ts
|
|
17628
17903
|
function writeJSON6(res, status, payload) {
|
|
17629
17904
|
res.writeHead(status, {
|
|
@@ -17748,7 +18023,29 @@ async function handleCoordinationRoute(deps, req, res) {
|
|
|
17748
18023
|
target_agent_id: detail.entry.target_agent_id
|
|
17749
18024
|
}
|
|
17750
18025
|
);
|
|
17751
|
-
|
|
18026
|
+
let breakdown = null;
|
|
18027
|
+
try {
|
|
18028
|
+
breakdown = await extractContextTransferBreakdown(
|
|
18029
|
+
detail,
|
|
18030
|
+
deps.contextTransfer ?? {}
|
|
18031
|
+
);
|
|
18032
|
+
deps.auditLog.append(
|
|
18033
|
+
"l2",
|
|
18034
|
+
CONTEXT_TRANSFER_AUDIT_OPS.DECODED,
|
|
18035
|
+
deps.operatorId,
|
|
18036
|
+
{
|
|
18037
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
18038
|
+
entry_id: detail.entry.entry_id,
|
|
18039
|
+
extractor_path: breakdown.source,
|
|
18040
|
+
confidence: breakdown.confidence,
|
|
18041
|
+
transferred_count: breakdown.transferred.length,
|
|
18042
|
+
withheld_count: breakdown.withheld.length
|
|
18043
|
+
}
|
|
18044
|
+
);
|
|
18045
|
+
} catch {
|
|
18046
|
+
}
|
|
18047
|
+
const responseData = breakdown !== null ? { ...detail, context_transfer_breakdown: breakdown } : detail;
|
|
18048
|
+
writeJSON6(res, 200, { ok: true, data: responseData });
|
|
17752
18049
|
return true;
|
|
17753
18050
|
}
|
|
17754
18051
|
writeJSON6(res, 404, { ok: false, error: "not_found", path });
|
|
@@ -17764,6 +18061,7 @@ var init_handoff_routes = __esm({
|
|
|
17764
18061
|
"src/coordination/handoff-routes.ts"() {
|
|
17765
18062
|
init_auth_middleware();
|
|
17766
18063
|
init_handoff_log();
|
|
18064
|
+
init_context_transfer_extractor();
|
|
17767
18065
|
COORDINATION_API_PREFIX = "/api/coordination";
|
|
17768
18066
|
COORDINATION_HANDOFFS_PREFIX = "/api/coordination/handoffs";
|
|
17769
18067
|
COORDINATION_LIST_DEFAULT_LIMIT = 50;
|
|
@@ -22304,15 +22602,52 @@ var init_sentinel_dispatcher = __esm({
|
|
|
22304
22602
|
};
|
|
22305
22603
|
}
|
|
22306
22604
|
});
|
|
22605
|
+
var init_classifier_state_store = __esm({
|
|
22606
|
+
"src/anomaly-detection/classifier-state-store.ts"() {
|
|
22607
|
+
init_encryption();
|
|
22608
|
+
init_key_derivation();
|
|
22609
|
+
init_encoding();
|
|
22610
|
+
}
|
|
22611
|
+
});
|
|
22612
|
+
|
|
22613
|
+
// src/anomaly-detection/classifiers/cusum.ts
|
|
22614
|
+
var CUSUM_CLASSIFIER_ID;
|
|
22615
|
+
var init_cusum = __esm({
|
|
22616
|
+
"src/anomaly-detection/classifiers/cusum.ts"() {
|
|
22617
|
+
init_classifier_state_store();
|
|
22618
|
+
CUSUM_CLASSIFIER_ID = "cusum";
|
|
22619
|
+
}
|
|
22620
|
+
});
|
|
22621
|
+
|
|
22622
|
+
// src/anomaly-detection/classifiers/psi.ts
|
|
22623
|
+
var PSI_CLASSIFIER_ID;
|
|
22624
|
+
var init_psi = __esm({
|
|
22625
|
+
"src/anomaly-detection/classifiers/psi.ts"() {
|
|
22626
|
+
init_classifier_state_store();
|
|
22627
|
+
PSI_CLASSIFIER_ID = "psi";
|
|
22628
|
+
}
|
|
22629
|
+
});
|
|
22307
22630
|
|
|
22308
22631
|
// src/anomaly-detection/types.ts
|
|
22309
22632
|
var init_types4 = __esm({
|
|
22310
22633
|
"src/anomaly-detection/types.ts"() {
|
|
22311
22634
|
}
|
|
22312
22635
|
});
|
|
22636
|
+
function classifierSpecificAuditOp(classifierId) {
|
|
22637
|
+
if (classifierId === null) return null;
|
|
22638
|
+
if (classifierId === CUSUM_CLASSIFIER_ID) {
|
|
22639
|
+
return ANOMALY_AUDIT_OPS.CUSUM_DRIFT_DETECTED;
|
|
22640
|
+
}
|
|
22641
|
+
if (classifierId === PSI_CLASSIFIER_ID) {
|
|
22642
|
+
return ANOMALY_AUDIT_OPS.PSI_DISTRIBUTION_SHIFT_DETECTED;
|
|
22643
|
+
}
|
|
22644
|
+
return null;
|
|
22645
|
+
}
|
|
22313
22646
|
var ANOMALY_AUDIT_OPS, DEFAULT_TICK_INTERVAL_MS2, AnomalyPipelineDispatcher;
|
|
22314
22647
|
var init_anomaly_pipeline = __esm({
|
|
22315
22648
|
"src/anomaly-detection/anomaly-pipeline.ts"() {
|
|
22649
|
+
init_cusum();
|
|
22650
|
+
init_psi();
|
|
22316
22651
|
init_types4();
|
|
22317
22652
|
ANOMALY_AUDIT_OPS = {
|
|
22318
22653
|
DETECTOR_REGISTERED: "anomaly_detector_registered",
|
|
@@ -22320,7 +22655,15 @@ var init_anomaly_pipeline = __esm({
|
|
|
22320
22655
|
FINDING_EMITTED: "anomaly_finding_emitted",
|
|
22321
22656
|
EVALUATION_FAILED: "anomaly_evaluation_failed",
|
|
22322
22657
|
TRAINING_COMPLETED: "anomaly_training_completed",
|
|
22323
|
-
TRAINING_FAILED: "anomaly_training_failed"
|
|
22658
|
+
TRAINING_FAILED: "anomaly_training_failed",
|
|
22659
|
+
/** Chi-2: a classifier was attached to an existing detector. */
|
|
22660
|
+
CLASSIFIER_SUBSCRIBED: "anomaly_classifier_subscribed",
|
|
22661
|
+
/** Chi-2: a classifier was detached from an existing detector. */
|
|
22662
|
+
CLASSIFIER_UNSUBSCRIBED: "anomaly_classifier_unsubscribed",
|
|
22663
|
+
/** Chi-2: CUSUM-flagged mean-shift drift on a per-agent feature. */
|
|
22664
|
+
CUSUM_DRIFT_DETECTED: "anomaly_cusum_drift_detected",
|
|
22665
|
+
/** Chi-2: PSI-flagged distribution shift on a per-agent feature. */
|
|
22666
|
+
PSI_DISTRIBUTION_SHIFT_DETECTED: "anomaly_psi_distribution_shift_detected"
|
|
22324
22667
|
};
|
|
22325
22668
|
DEFAULT_TICK_INTERVAL_MS2 = 6e4;
|
|
22326
22669
|
AnomalyPipelineDispatcher = class {
|
|
@@ -22411,34 +22754,37 @@ var init_anomaly_pipeline = __esm({
|
|
|
22411
22754
|
const stamped = await this.routeFinding(detectorId, raw);
|
|
22412
22755
|
findings.push(stamped);
|
|
22413
22756
|
}
|
|
22414
|
-
|
|
22415
|
-
|
|
22416
|
-
|
|
22417
|
-
|
|
22418
|
-
|
|
22419
|
-
|
|
22420
|
-
|
|
22421
|
-
|
|
22422
|
-
|
|
22423
|
-
|
|
22424
|
-
|
|
22425
|
-
|
|
22426
|
-
|
|
22427
|
-
|
|
22428
|
-
|
|
22429
|
-
|
|
22430
|
-
|
|
22431
|
-
|
|
22432
|
-
|
|
22433
|
-
|
|
22434
|
-
|
|
22435
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
22438
|
-
|
|
22439
|
-
|
|
22440
|
-
|
|
22441
|
-
|
|
22757
|
+
for (const classifier of detector.getAllClassifiers()) {
|
|
22758
|
+
try {
|
|
22759
|
+
const trainingResult = await classifier.train();
|
|
22760
|
+
this.auditLog.append(
|
|
22761
|
+
"l2",
|
|
22762
|
+
ANOMALY_AUDIT_OPS.TRAINING_COMPLETED,
|
|
22763
|
+
this.identityId,
|
|
22764
|
+
{
|
|
22765
|
+
detector_id: detectorId,
|
|
22766
|
+
classifier_id: classifier.classifierId,
|
|
22767
|
+
trained_at: trainingResult.trained_at,
|
|
22768
|
+
sample_count: trainingResult.sample_count,
|
|
22769
|
+
agent_count: trainingResult.agent_count,
|
|
22770
|
+
fortress_id: this.fortressId
|
|
22771
|
+
}
|
|
22772
|
+
);
|
|
22773
|
+
} catch (trainErr) {
|
|
22774
|
+
const message = trainErr instanceof Error ? trainErr.message : String(trainErr);
|
|
22775
|
+
this.auditLog.append(
|
|
22776
|
+
"l2",
|
|
22777
|
+
ANOMALY_AUDIT_OPS.TRAINING_FAILED,
|
|
22778
|
+
this.identityId,
|
|
22779
|
+
{
|
|
22780
|
+
detector_id: detectorId,
|
|
22781
|
+
classifier_id: classifier.classifierId,
|
|
22782
|
+
error_message: message,
|
|
22783
|
+
fortress_id: this.fortressId
|
|
22784
|
+
},
|
|
22785
|
+
"failure"
|
|
22786
|
+
);
|
|
22787
|
+
}
|
|
22442
22788
|
}
|
|
22443
22789
|
} catch (err) {
|
|
22444
22790
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -22501,6 +22847,7 @@ var init_anomaly_pipeline = __esm({
|
|
|
22501
22847
|
observed_at: raw.observed_at || this.now().toISOString()
|
|
22502
22848
|
};
|
|
22503
22849
|
await this.findingStore.saveFinding(stamped);
|
|
22850
|
+
const classifierId = stamped.details["classifier_id"] ?? null;
|
|
22504
22851
|
this.auditLog.append(
|
|
22505
22852
|
"l2",
|
|
22506
22853
|
ANOMALY_AUDIT_OPS.FINDING_EMITTED,
|
|
@@ -22510,13 +22857,79 @@ var init_anomaly_pipeline = __esm({
|
|
|
22510
22857
|
finding_id: stamped.finding_id,
|
|
22511
22858
|
severity: stamped.severity,
|
|
22512
22859
|
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
22860
|
+
...classifierId !== null ? { classifier_id: classifierId } : {},
|
|
22513
22861
|
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
22514
22862
|
fortress_id: this.fortressId
|
|
22515
22863
|
}
|
|
22516
22864
|
);
|
|
22865
|
+
const specificOp = classifierSpecificAuditOp(classifierId);
|
|
22866
|
+
if (specificOp !== null) {
|
|
22867
|
+
this.auditLog.append("l2", specificOp, this.identityId, {
|
|
22868
|
+
detector_id: detectorId,
|
|
22869
|
+
finding_id: stamped.finding_id,
|
|
22870
|
+
severity: stamped.severity,
|
|
22871
|
+
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
22872
|
+
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
22873
|
+
fortress_id: this.fortressId
|
|
22874
|
+
});
|
|
22875
|
+
}
|
|
22517
22876
|
this.emit({ type: "finding", finding: stamped });
|
|
22518
22877
|
return stamped;
|
|
22519
22878
|
}
|
|
22879
|
+
/**
|
|
22880
|
+
* Chi-2: attach an additional classifier to an already-registered
|
|
22881
|
+
* detector. Emits ANOMALY_CLASSIFIER_SUBSCRIBED on success. The
|
|
22882
|
+
* factory is called with the fortress AnomalyContext so the
|
|
22883
|
+
* classifier can build its own state-store binding. Idempotent: a
|
|
22884
|
+
* second call with the same classifierId returns false.
|
|
22885
|
+
*/
|
|
22886
|
+
async addClassifierToDetector(detectorId, factory) {
|
|
22887
|
+
const detector = this.detectors.get(detectorId);
|
|
22888
|
+
if (!detector) return false;
|
|
22889
|
+
const context = {
|
|
22890
|
+
fortressId: this.fortressId,
|
|
22891
|
+
auditLog: this.auditLog,
|
|
22892
|
+
storage: this.storage,
|
|
22893
|
+
masterKey: this.masterKey,
|
|
22894
|
+
now: this.now
|
|
22895
|
+
};
|
|
22896
|
+
const classifier = factory(context);
|
|
22897
|
+
const added = detector.addClassifier(classifier);
|
|
22898
|
+
if (!added) return false;
|
|
22899
|
+
this.auditLog.append(
|
|
22900
|
+
"l2",
|
|
22901
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_SUBSCRIBED,
|
|
22902
|
+
this.identityId,
|
|
22903
|
+
{
|
|
22904
|
+
detector_id: detectorId,
|
|
22905
|
+
classifier_id: classifier.classifierId,
|
|
22906
|
+
fortress_id: this.fortressId
|
|
22907
|
+
}
|
|
22908
|
+
);
|
|
22909
|
+
return true;
|
|
22910
|
+
}
|
|
22911
|
+
/**
|
|
22912
|
+
* Chi-2: detach an additional classifier from an already-registered
|
|
22913
|
+
* detector. Emits ANOMALY_CLASSIFIER_UNSUBSCRIBED on success. The
|
|
22914
|
+
* primary classifier cannot be detached (returns false).
|
|
22915
|
+
*/
|
|
22916
|
+
async removeClassifierFromDetector(detectorId, classifierId) {
|
|
22917
|
+
const detector = this.detectors.get(detectorId);
|
|
22918
|
+
if (!detector) return false;
|
|
22919
|
+
const removed = detector.removeClassifier(classifierId);
|
|
22920
|
+
if (!removed) return false;
|
|
22921
|
+
this.auditLog.append(
|
|
22922
|
+
"l2",
|
|
22923
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_UNSUBSCRIBED,
|
|
22924
|
+
this.identityId,
|
|
22925
|
+
{
|
|
22926
|
+
detector_id: detectorId,
|
|
22927
|
+
classifier_id: classifierId,
|
|
22928
|
+
fortress_id: this.fortressId
|
|
22929
|
+
}
|
|
22930
|
+
);
|
|
22931
|
+
return true;
|
|
22932
|
+
}
|
|
22520
22933
|
emit(event) {
|
|
22521
22934
|
for (const listener of this.listeners) {
|
|
22522
22935
|
try {
|
|
@@ -39826,6 +40239,141 @@ ${redactedItems.map((r) => `- ${r.redacted}`).join("\n")}`,
|
|
|
39826
40239
|
}
|
|
39827
40240
|
});
|
|
39828
40241
|
|
|
40242
|
+
// src/query-anonymity/header-strip.ts
|
|
40243
|
+
function stripHeaders(headers) {
|
|
40244
|
+
const stripped = {};
|
|
40245
|
+
const removed = [];
|
|
40246
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
40247
|
+
const lower = name.toLowerCase();
|
|
40248
|
+
if (REQUIRED_HEADER_SET.has(lower)) {
|
|
40249
|
+
stripped[name] = value;
|
|
40250
|
+
continue;
|
|
40251
|
+
}
|
|
40252
|
+
const reason = STRIP_REASON_BY_NAME.get(lower);
|
|
40253
|
+
if (reason !== void 0) {
|
|
40254
|
+
removed.push({ name, reason });
|
|
40255
|
+
continue;
|
|
40256
|
+
}
|
|
40257
|
+
stripped[name] = value;
|
|
40258
|
+
}
|
|
40259
|
+
return { stripped, removed };
|
|
40260
|
+
}
|
|
40261
|
+
function defeatUndiciDefaultsInto(headers) {
|
|
40262
|
+
if (headers["user-agent"] === void 0 && headers["User-Agent"] === void 0) {
|
|
40263
|
+
headers["User-Agent"] = "";
|
|
40264
|
+
}
|
|
40265
|
+
if (headers["accept-language"] === void 0 && headers["Accept-Language"] === void 0) {
|
|
40266
|
+
headers["Accept-Language"] = "";
|
|
40267
|
+
}
|
|
40268
|
+
return headers;
|
|
40269
|
+
}
|
|
40270
|
+
function createAnonymizedFetch(baseFetch, onAudit) {
|
|
40271
|
+
const wrapped = async (input, init) => {
|
|
40272
|
+
const headers = normalizeHeadersInit(init?.headers);
|
|
40273
|
+
const result = stripHeaders(headers);
|
|
40274
|
+
defeatUndiciDefaultsInto(result.stripped);
|
|
40275
|
+
const preservedRequired = Object.keys(result.stripped).filter(
|
|
40276
|
+
(k) => REQUIRED_HEADER_SET.has(k.toLowerCase())
|
|
40277
|
+
);
|
|
40278
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
40279
|
+
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
40280
|
+
if (onAudit) {
|
|
40281
|
+
onAudit({
|
|
40282
|
+
url,
|
|
40283
|
+
method,
|
|
40284
|
+
stripped_count: result.removed.length,
|
|
40285
|
+
removed: result.removed,
|
|
40286
|
+
required_preserved: preservedRequired
|
|
40287
|
+
});
|
|
40288
|
+
}
|
|
40289
|
+
return baseFetch(input, { ...init, headers: result.stripped });
|
|
40290
|
+
};
|
|
40291
|
+
return wrapped;
|
|
40292
|
+
}
|
|
40293
|
+
function normalizeHeadersInit(raw) {
|
|
40294
|
+
if (raw === void 0) return {};
|
|
40295
|
+
if (typeof Headers !== "undefined" && raw instanceof Headers) {
|
|
40296
|
+
const out = {};
|
|
40297
|
+
raw.forEach((value, key) => {
|
|
40298
|
+
out[key] = value;
|
|
40299
|
+
});
|
|
40300
|
+
return out;
|
|
40301
|
+
}
|
|
40302
|
+
if (Array.isArray(raw)) {
|
|
40303
|
+
const out = {};
|
|
40304
|
+
for (const [k, v] of raw) {
|
|
40305
|
+
if (k !== void 0 && v !== void 0) out[k] = v;
|
|
40306
|
+
}
|
|
40307
|
+
return out;
|
|
40308
|
+
}
|
|
40309
|
+
return { ...raw };
|
|
40310
|
+
}
|
|
40311
|
+
var QUERY_ANONYMITY_AUDIT_OPS, CANONICAL_STRIP_LIST, REQUIRED_HEADERS, REQUIRED_HEADER_SET, STRIP_REASON_BY_NAME;
|
|
40312
|
+
var init_header_strip = __esm({
|
|
40313
|
+
"src/query-anonymity/header-strip.ts"() {
|
|
40314
|
+
QUERY_ANONYMITY_AUDIT_OPS = {
|
|
40315
|
+
HEADERS_STRIPPED: "query_anonymity_headers_stripped"
|
|
40316
|
+
};
|
|
40317
|
+
CANONICAL_STRIP_LIST = [
|
|
40318
|
+
// Browser / runtime fingerprinting.
|
|
40319
|
+
{ name: "user-agent", reason: "user-agent" },
|
|
40320
|
+
{ name: "sec-ch-ua", reason: "fingerprintable-extension" },
|
|
40321
|
+
{ name: "sec-ch-ua-mobile", reason: "fingerprintable-extension" },
|
|
40322
|
+
{ name: "sec-ch-ua-platform", reason: "fingerprintable-extension" },
|
|
40323
|
+
{ name: "sec-ch-ua-platform-version", reason: "fingerprintable-extension" },
|
|
40324
|
+
{ name: "sec-ch-ua-arch", reason: "fingerprintable-extension" },
|
|
40325
|
+
{ name: "sec-ch-ua-bitness", reason: "fingerprintable-extension" },
|
|
40326
|
+
{ name: "sec-ch-ua-model", reason: "fingerprintable-extension" },
|
|
40327
|
+
{ name: "sec-ch-ua-full-version-list", reason: "fingerprintable-extension" },
|
|
40328
|
+
// Locale fingerprint.
|
|
40329
|
+
{ name: "accept-language", reason: "locale-fingerprint" },
|
|
40330
|
+
// Request-origin leak.
|
|
40331
|
+
{ name: "referer", reason: "leaking-network-info" },
|
|
40332
|
+
{ name: "referrer-policy", reason: "leaking-network-info" },
|
|
40333
|
+
{ name: "origin", reason: "leaking-network-info" },
|
|
40334
|
+
// Forwarded-by / IP-derived network info.
|
|
40335
|
+
{ name: "via", reason: "leaking-network-info" },
|
|
40336
|
+
{ name: "forwarded", reason: "leaking-network-info" },
|
|
40337
|
+
{ name: "x-forwarded-for", reason: "leaking-network-info" },
|
|
40338
|
+
{ name: "x-real-ip", reason: "leaking-network-info" },
|
|
40339
|
+
{ name: "x-client-ip", reason: "leaking-network-info" },
|
|
40340
|
+
// DNT / GPC are technically anti-tracking signals but they
|
|
40341
|
+
// themselves form a fingerprint (operators who set DNT=1 are a
|
|
40342
|
+
// smaller subset). Strip to keep the substrate ignorant of
|
|
40343
|
+
// operator preferences.
|
|
40344
|
+
{ name: "dnt", reason: "unnecessary-metadata" },
|
|
40345
|
+
{ name: "sec-gpc", reason: "unnecessary-metadata" }
|
|
40346
|
+
];
|
|
40347
|
+
REQUIRED_HEADERS = [
|
|
40348
|
+
"authorization",
|
|
40349
|
+
"content-type",
|
|
40350
|
+
"content-length",
|
|
40351
|
+
"host",
|
|
40352
|
+
"accept",
|
|
40353
|
+
"x-api-key",
|
|
40354
|
+
// Anthropic API auth
|
|
40355
|
+
"anthropic-version",
|
|
40356
|
+
// Anthropic API contract version
|
|
40357
|
+
"anthropic-beta",
|
|
40358
|
+
// optional Anthropic beta opt-in
|
|
40359
|
+
"openai-organization",
|
|
40360
|
+
// optional OpenAI org id
|
|
40361
|
+
"x-stainless-package-version",
|
|
40362
|
+
// allowed for Anthropic + OpenAI SDK contract compat
|
|
40363
|
+
"x-goog-api-key",
|
|
40364
|
+
// Google AI Studio
|
|
40365
|
+
"x-goog-user-project"
|
|
40366
|
+
// Google AI Studio
|
|
40367
|
+
];
|
|
40368
|
+
REQUIRED_HEADER_SET = new Set(
|
|
40369
|
+
REQUIRED_HEADERS.map((h) => h.toLowerCase())
|
|
40370
|
+
);
|
|
40371
|
+
STRIP_REASON_BY_NAME = new Map(
|
|
40372
|
+
CANONICAL_STRIP_LIST.map((h) => [h.name.toLowerCase(), h.reason])
|
|
40373
|
+
);
|
|
40374
|
+
}
|
|
40375
|
+
});
|
|
40376
|
+
|
|
39829
40377
|
// src/intelligence/substrates/hybrid/per-surface-router.ts
|
|
39830
40378
|
function resolveHybridChoice(rules, surface) {
|
|
39831
40379
|
if (!rules) return null;
|
|
@@ -39947,6 +40495,7 @@ var init_selector = __esm({
|
|
|
39947
40495
|
init_local();
|
|
39948
40496
|
init_venice();
|
|
39949
40497
|
init_frontier();
|
|
40498
|
+
init_header_strip();
|
|
39950
40499
|
init_per_surface_router();
|
|
39951
40500
|
DISABLED_CAPABILITY = {
|
|
39952
40501
|
summarize: false,
|
|
@@ -39981,7 +40530,21 @@ var init_selector = __esm({
|
|
|
39981
40530
|
this.auditLog = cfg.auditLog;
|
|
39982
40531
|
this.identityId = cfg.identityId;
|
|
39983
40532
|
this.redactor = cfg.redactor ?? IDENTITY_REDACTOR;
|
|
39984
|
-
|
|
40533
|
+
const baseFetch = cfg.fetchImpl ?? globalThis.fetch;
|
|
40534
|
+
this.fetchImpl = createAnonymizedFetch(baseFetch, (event) => {
|
|
40535
|
+
this.auditLog.append(
|
|
40536
|
+
"l2",
|
|
40537
|
+
QUERY_ANONYMITY_AUDIT_OPS.HEADERS_STRIPPED,
|
|
40538
|
+
this.identityId,
|
|
40539
|
+
{
|
|
40540
|
+
url: event.url,
|
|
40541
|
+
method: event.method,
|
|
40542
|
+
stripped_count: event.stripped_count,
|
|
40543
|
+
removed: event.removed,
|
|
40544
|
+
required_preserved: event.required_preserved
|
|
40545
|
+
}
|
|
40546
|
+
);
|
|
40547
|
+
});
|
|
39985
40548
|
this.config = buildDefaultConfig();
|
|
39986
40549
|
}
|
|
39987
40550
|
/**
|