@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/cli.cjs
CHANGED
|
@@ -17480,6 +17480,616 @@ var init_sentinel_routes = __esm({
|
|
|
17480
17480
|
FINDINGS_MAX_LIMIT = 500;
|
|
17481
17481
|
}
|
|
17482
17482
|
});
|
|
17483
|
+
function makeEntryId(auditEventId) {
|
|
17484
|
+
return crypto.createHash("sha256").update(auditEventId).digest("hex").slice(0, 32);
|
|
17485
|
+
}
|
|
17486
|
+
function optString(details, key) {
|
|
17487
|
+
if (!details) return null;
|
|
17488
|
+
const value = details[key];
|
|
17489
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
17490
|
+
return value;
|
|
17491
|
+
}
|
|
17492
|
+
function auditEventIdFallback(audit) {
|
|
17493
|
+
return `${audit.timestamp}:${audit.operation}`;
|
|
17494
|
+
}
|
|
17495
|
+
function localHandoffSummary(details, sender, recipient) {
|
|
17496
|
+
const taskScope = optString(details, "task_scope");
|
|
17497
|
+
const reasonClass = optString(details, "reason_class");
|
|
17498
|
+
if (taskScope) {
|
|
17499
|
+
return `${sender} -> ${recipient} handoff: ${taskScope}`;
|
|
17500
|
+
}
|
|
17501
|
+
if (reasonClass) {
|
|
17502
|
+
return `${sender} -> ${recipient} handoff (${reasonClass})`;
|
|
17503
|
+
}
|
|
17504
|
+
return `${sender} -> ${recipient} handoff`;
|
|
17505
|
+
}
|
|
17506
|
+
function crossHarnessSummary(details, sender) {
|
|
17507
|
+
const policyRule = optString(details, "policy_rule_id");
|
|
17508
|
+
if (policyRule) {
|
|
17509
|
+
return `${sender} -> operator approval (${policyRule})`;
|
|
17510
|
+
}
|
|
17511
|
+
return `${sender} -> operator approval`;
|
|
17512
|
+
}
|
|
17513
|
+
var HANDOFF_LOG_OBSERVED_OPS, OBSERVED_OP_LIST, OPERATOR_PSEUDO_AGENT, DEFAULT_LIMIT, MAX_LIMIT, AUDIT_QUERY_LIMIT, HandoffLog, COORDINATION_VIEW_AUDIT_OPS;
|
|
17514
|
+
var init_handoff_log = __esm({
|
|
17515
|
+
"src/coordination/handoff-log.ts"() {
|
|
17516
|
+
HANDOFF_LOG_OBSERVED_OPS = {
|
|
17517
|
+
/** Tau-3 in-process coordination handoff. */
|
|
17518
|
+
LOCAL_HANDOFF: "v1.1_local_handoff",
|
|
17519
|
+
/** Upsilon-1 cross-harness approval (wrapped-agent -> operator). */
|
|
17520
|
+
CROSS_HARNESS_APPROVAL: "cross_harness_approval_aggregated"
|
|
17521
|
+
};
|
|
17522
|
+
OBSERVED_OP_LIST = [
|
|
17523
|
+
HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF,
|
|
17524
|
+
HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL
|
|
17525
|
+
];
|
|
17526
|
+
OPERATOR_PSEUDO_AGENT = "operator";
|
|
17527
|
+
DEFAULT_LIMIT = 50;
|
|
17528
|
+
MAX_LIMIT = 500;
|
|
17529
|
+
AUDIT_QUERY_LIMIT = 1e4;
|
|
17530
|
+
HandoffLog = class {
|
|
17531
|
+
auditLog;
|
|
17532
|
+
fortressId;
|
|
17533
|
+
constructor(opts) {
|
|
17534
|
+
this.auditLog = opts.auditLog;
|
|
17535
|
+
this.fortressId = opts.fortressId;
|
|
17536
|
+
}
|
|
17537
|
+
/** Stable fortress id this HandoffLog reads. */
|
|
17538
|
+
getFortressId() {
|
|
17539
|
+
return this.fortressId;
|
|
17540
|
+
}
|
|
17541
|
+
/**
|
|
17542
|
+
* Query handoffs in chronological-newest-first order. Filters
|
|
17543
|
+
* applied after normalization so the per-event-class shape
|
|
17544
|
+
* differences (sender field name, recipient inference) are handled
|
|
17545
|
+
* once.
|
|
17546
|
+
*/
|
|
17547
|
+
async query(opts) {
|
|
17548
|
+
const limit = Math.min(opts.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
|
|
17549
|
+
const queryResult = await this.auditLog.query({
|
|
17550
|
+
...opts.since !== void 0 ? { since: opts.since } : {},
|
|
17551
|
+
layer: "l2",
|
|
17552
|
+
limit: AUDIT_QUERY_LIMIT
|
|
17553
|
+
});
|
|
17554
|
+
const normalized = [];
|
|
17555
|
+
for (const entry of queryResult.entries) {
|
|
17556
|
+
if (!OBSERVED_OP_LIST.includes(entry.operation)) continue;
|
|
17557
|
+
const handoff = this.normalize(entry);
|
|
17558
|
+
if (!handoff) continue;
|
|
17559
|
+
if (opts.until && handoff.observed_at > opts.until) continue;
|
|
17560
|
+
if (opts.since && handoff.observed_at < opts.since) continue;
|
|
17561
|
+
if (opts.agent_id) {
|
|
17562
|
+
if (handoff.source_agent_id !== opts.agent_id && handoff.target_agent_id !== opts.agent_id) {
|
|
17563
|
+
continue;
|
|
17564
|
+
}
|
|
17565
|
+
}
|
|
17566
|
+
normalized.push(handoff);
|
|
17567
|
+
}
|
|
17568
|
+
normalized.sort((a, b) => a.observed_at < b.observed_at ? 1 : -1);
|
|
17569
|
+
return normalized.slice(0, limit);
|
|
17570
|
+
}
|
|
17571
|
+
/**
|
|
17572
|
+
* Look up a single entry by id. Returns the normalized entry +
|
|
17573
|
+
* the source audit payload for operator-facing detail rendering.
|
|
17574
|
+
* Returns null when no audit entry maps to the given id.
|
|
17575
|
+
*/
|
|
17576
|
+
async getEntry(entryId) {
|
|
17577
|
+
const queryResult = await this.auditLog.query({
|
|
17578
|
+
layer: "l2",
|
|
17579
|
+
limit: AUDIT_QUERY_LIMIT
|
|
17580
|
+
});
|
|
17581
|
+
for (const audit of queryResult.entries) {
|
|
17582
|
+
if (!OBSERVED_OP_LIST.includes(audit.operation)) continue;
|
|
17583
|
+
const handoff = this.normalize(audit);
|
|
17584
|
+
if (!handoff) continue;
|
|
17585
|
+
if (handoff.entry_id === entryId) {
|
|
17586
|
+
return { entry: handoff, source_audit_entry: audit };
|
|
17587
|
+
}
|
|
17588
|
+
}
|
|
17589
|
+
return null;
|
|
17590
|
+
}
|
|
17591
|
+
normalize(audit) {
|
|
17592
|
+
const details = audit.details;
|
|
17593
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF) {
|
|
17594
|
+
const sender = optString(details, "sender_agent_id");
|
|
17595
|
+
const recipient = optString(details, "recipient_agent_id");
|
|
17596
|
+
if (!sender || !recipient || sender === recipient) return null;
|
|
17597
|
+
const auditEventId = optString(details, "event_id") ?? auditEventIdFallback(audit);
|
|
17598
|
+
return {
|
|
17599
|
+
entry_id: makeEntryId(auditEventId),
|
|
17600
|
+
audit_event_id: auditEventId,
|
|
17601
|
+
source_agent_id: sender,
|
|
17602
|
+
target_agent_id: recipient,
|
|
17603
|
+
observed_at: audit.timestamp,
|
|
17604
|
+
event_class: audit.operation,
|
|
17605
|
+
context_transfer_summary: localHandoffSummary(details, sender, recipient),
|
|
17606
|
+
workflow_link: null
|
|
17607
|
+
};
|
|
17608
|
+
}
|
|
17609
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL) {
|
|
17610
|
+
const sender = optString(details, "source_harness") ?? optString(details, "source_agent_id");
|
|
17611
|
+
if (!sender) return null;
|
|
17612
|
+
const auditEventId = optString(details, "aggregator_id") ?? auditEventIdFallback(audit);
|
|
17613
|
+
return {
|
|
17614
|
+
entry_id: makeEntryId(auditEventId),
|
|
17615
|
+
audit_event_id: auditEventId,
|
|
17616
|
+
source_agent_id: sender,
|
|
17617
|
+
target_agent_id: OPERATOR_PSEUDO_AGENT,
|
|
17618
|
+
observed_at: audit.timestamp,
|
|
17619
|
+
event_class: audit.operation,
|
|
17620
|
+
context_transfer_summary: crossHarnessSummary(details, sender),
|
|
17621
|
+
workflow_link: null
|
|
17622
|
+
};
|
|
17623
|
+
}
|
|
17624
|
+
return null;
|
|
17625
|
+
}
|
|
17626
|
+
};
|
|
17627
|
+
COORDINATION_VIEW_AUDIT_OPS = {
|
|
17628
|
+
VIEW_OPENED: "operator_coordination_view_opened",
|
|
17629
|
+
ENTRY_DRILLED: "operator_handoff_entry_drilled"
|
|
17630
|
+
};
|
|
17631
|
+
}
|
|
17632
|
+
});
|
|
17633
|
+
|
|
17634
|
+
// src/coordination/context-transfer-extractor.ts
|
|
17635
|
+
async function extractContextTransferBreakdown(detail, deps = {}) {
|
|
17636
|
+
const pathA = tryStructuredPath(detail);
|
|
17637
|
+
if (pathA) return pathA;
|
|
17638
|
+
const pathB = tryCompositionPath(detail);
|
|
17639
|
+
if (pathB) return pathB;
|
|
17640
|
+
const pathC = tryHeuristicPath(detail);
|
|
17641
|
+
if (pathC.confidence >= 0.5 || !deps.substrateSelector) {
|
|
17642
|
+
return pathC;
|
|
17643
|
+
}
|
|
17644
|
+
const assist = await tryLlmAssistPath(detail, deps.substrateSelector);
|
|
17645
|
+
return assist ?? pathC;
|
|
17646
|
+
}
|
|
17647
|
+
function tryStructuredPath(detail) {
|
|
17648
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
17649
|
+
if (!details) return null;
|
|
17650
|
+
const transferredRaw = details["transferred"];
|
|
17651
|
+
const withheldRaw = details["withheld"];
|
|
17652
|
+
if (transferredRaw === void 0 && withheldRaw === void 0) return null;
|
|
17653
|
+
const transferred = parseExplicitContextItems(transferredRaw);
|
|
17654
|
+
const withheld = parseExplicitContextItems(withheldRaw);
|
|
17655
|
+
return {
|
|
17656
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
17657
|
+
transferred,
|
|
17658
|
+
withheld,
|
|
17659
|
+
source: "structured",
|
|
17660
|
+
confidence: 1
|
|
17661
|
+
};
|
|
17662
|
+
}
|
|
17663
|
+
function tryCompositionPath(detail) {
|
|
17664
|
+
const op = detail.source_audit_entry.operation;
|
|
17665
|
+
if (!op.startsWith("composition_completed")) return null;
|
|
17666
|
+
const details = sourceDetails(detail.source_audit_entry);
|
|
17667
|
+
if (!details) return null;
|
|
17668
|
+
const receiptRaw = details["receipt"];
|
|
17669
|
+
const sourceStateRaw = details["source_state_snapshot"];
|
|
17670
|
+
if (receiptRaw === void 0) return null;
|
|
17671
|
+
const transferred = parseExplicitContextItems(receiptRaw);
|
|
17672
|
+
const withheld = [];
|
|
17673
|
+
if (Array.isArray(sourceStateRaw)) {
|
|
17674
|
+
const transferredKeys = new Set(
|
|
17675
|
+
transferred.map((t) => `${t.category}:${t.summary}`)
|
|
17676
|
+
);
|
|
17677
|
+
for (const item of parseExplicitContextItems(sourceStateRaw)) {
|
|
17678
|
+
const key = `${item.category}:${item.summary}`;
|
|
17679
|
+
if (!transferredKeys.has(key)) withheld.push(item);
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
return {
|
|
17683
|
+
handoff_entry_id: detail.entry.entry_id,
|
|
17684
|
+
transferred,
|
|
17685
|
+
withheld,
|
|
17686
|
+
source: "composition",
|
|
17687
|
+
confidence: 0.9
|
|
17688
|
+
};
|
|
17689
|
+
}
|
|
17690
|
+
function tryHeuristicPath(detail) {
|
|
17691
|
+
const entry = detail.entry;
|
|
17692
|
+
const audit = detail.source_audit_entry;
|
|
17693
|
+
const details = sourceDetails(audit);
|
|
17694
|
+
if (audit.operation === "cross_harness_approval_aggregated") {
|
|
17695
|
+
const ruleId = optString2(details, "policy_rule_id");
|
|
17696
|
+
if (ruleId) {
|
|
17697
|
+
const category = categoryFromPolicyRuleId(ruleId);
|
|
17698
|
+
const summary = `${ruleId} (${entry.source_agent_id} -> operator)`;
|
|
17699
|
+
return {
|
|
17700
|
+
handoff_entry_id: entry.entry_id,
|
|
17701
|
+
transferred: [
|
|
17702
|
+
{
|
|
17703
|
+
category,
|
|
17704
|
+
summary: truncate(summary, SUMMARY_MAX_CHARS),
|
|
17705
|
+
size_hint: "minimal"
|
|
17706
|
+
}
|
|
17707
|
+
],
|
|
17708
|
+
withheld: [],
|
|
17709
|
+
source: "heuristic",
|
|
17710
|
+
confidence: 0.5
|
|
17711
|
+
};
|
|
17712
|
+
}
|
|
17713
|
+
}
|
|
17714
|
+
if (audit.operation === "v1.1_local_handoff") {
|
|
17715
|
+
const reasonClass = optString2(details, "reason_class");
|
|
17716
|
+
const newStatus = optString2(details, "new_status");
|
|
17717
|
+
const previousStatus = optString2(details, "previous_status");
|
|
17718
|
+
const transferred = [];
|
|
17719
|
+
const withheld = [];
|
|
17720
|
+
if (newStatus === "denied" || newStatus === "failed") {
|
|
17721
|
+
withheld.push({
|
|
17722
|
+
category: "other",
|
|
17723
|
+
summary: truncate(
|
|
17724
|
+
`handoff ${newStatus}${reasonClass ? ` (${reasonClass})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17725
|
+
SUMMARY_MAX_CHARS
|
|
17726
|
+
),
|
|
17727
|
+
size_hint: "minimal"
|
|
17728
|
+
});
|
|
17729
|
+
} else if (newStatus === "accepted" || newStatus === "completed") {
|
|
17730
|
+
transferred.push({
|
|
17731
|
+
category: "other",
|
|
17732
|
+
summary: truncate(
|
|
17733
|
+
`handoff ${newStatus}${previousStatus ? ` (from ${previousStatus})` : ""}: ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17734
|
+
SUMMARY_MAX_CHARS
|
|
17735
|
+
),
|
|
17736
|
+
size_hint: "small"
|
|
17737
|
+
});
|
|
17738
|
+
} else {
|
|
17739
|
+
transferred.push({
|
|
17740
|
+
category: "other",
|
|
17741
|
+
summary: truncate(
|
|
17742
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}${newStatus ? ` (${newStatus})` : ""}`,
|
|
17743
|
+
SUMMARY_MAX_CHARS
|
|
17744
|
+
),
|
|
17745
|
+
size_hint: "minimal"
|
|
17746
|
+
});
|
|
17747
|
+
}
|
|
17748
|
+
return {
|
|
17749
|
+
handoff_entry_id: entry.entry_id,
|
|
17750
|
+
transferred,
|
|
17751
|
+
withheld,
|
|
17752
|
+
source: "heuristic",
|
|
17753
|
+
confidence: reasonClass || newStatus ? 0.5 : 0.3
|
|
17754
|
+
};
|
|
17755
|
+
}
|
|
17756
|
+
return {
|
|
17757
|
+
handoff_entry_id: entry.entry_id,
|
|
17758
|
+
transferred: [
|
|
17759
|
+
{
|
|
17760
|
+
category: "other",
|
|
17761
|
+
summary: truncate(
|
|
17762
|
+
`handoff ${entry.source_agent_id} -> ${entry.target_agent_id}`,
|
|
17763
|
+
SUMMARY_MAX_CHARS
|
|
17764
|
+
),
|
|
17765
|
+
size_hint: "minimal"
|
|
17766
|
+
}
|
|
17767
|
+
],
|
|
17768
|
+
withheld: [],
|
|
17769
|
+
source: "heuristic",
|
|
17770
|
+
confidence: 0.3
|
|
17771
|
+
};
|
|
17772
|
+
}
|
|
17773
|
+
async function tryLlmAssistPath(detail, selector) {
|
|
17774
|
+
const entry = detail.entry;
|
|
17775
|
+
const audit = detail.source_audit_entry;
|
|
17776
|
+
const probe = `event=${audit.operation} sender=${entry.source_agent_id} target=${entry.target_agent_id} summary=${entry.context_transfer_summary}`;
|
|
17777
|
+
try {
|
|
17778
|
+
const response = await selector.invokeClassify("sentinel-scoring", {
|
|
17779
|
+
kind: "classify",
|
|
17780
|
+
items: [probe],
|
|
17781
|
+
categories: [...CATEGORY_VALUES]
|
|
17782
|
+
});
|
|
17783
|
+
if (response.body.kind !== "classify") return null;
|
|
17784
|
+
const top = response.body.results[0];
|
|
17785
|
+
if (!top || !isCategory(top.category) || top.confidence < 0.4) {
|
|
17786
|
+
return null;
|
|
17787
|
+
}
|
|
17788
|
+
return {
|
|
17789
|
+
handoff_entry_id: entry.entry_id,
|
|
17790
|
+
transferred: [
|
|
17791
|
+
{
|
|
17792
|
+
category: top.category,
|
|
17793
|
+
summary: truncate(
|
|
17794
|
+
`LLM-classified handoff ${entry.source_agent_id} -> ${entry.target_agent_id}: ${top.category} (confidence ${top.confidence.toFixed(2)})`,
|
|
17795
|
+
SUMMARY_MAX_CHARS
|
|
17796
|
+
),
|
|
17797
|
+
size_hint: "minimal"
|
|
17798
|
+
}
|
|
17799
|
+
],
|
|
17800
|
+
withheld: [],
|
|
17801
|
+
source: "llm-assist",
|
|
17802
|
+
confidence: 0.6
|
|
17803
|
+
};
|
|
17804
|
+
} catch {
|
|
17805
|
+
return null;
|
|
17806
|
+
}
|
|
17807
|
+
}
|
|
17808
|
+
function sourceDetails(audit) {
|
|
17809
|
+
return audit.details;
|
|
17810
|
+
}
|
|
17811
|
+
function optString2(details, key) {
|
|
17812
|
+
if (!details) return null;
|
|
17813
|
+
const value = details[key];
|
|
17814
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
17815
|
+
return value;
|
|
17816
|
+
}
|
|
17817
|
+
function isCategory(value) {
|
|
17818
|
+
return CATEGORY_VALUES.includes(value);
|
|
17819
|
+
}
|
|
17820
|
+
function truncate(s, cap) {
|
|
17821
|
+
return s.length <= cap ? s : `${s.slice(0, cap - 3)}...`;
|
|
17822
|
+
}
|
|
17823
|
+
function parseExplicitContextItems(raw) {
|
|
17824
|
+
if (raw === null || raw === void 0) return [];
|
|
17825
|
+
if (Array.isArray(raw)) {
|
|
17826
|
+
const out = [];
|
|
17827
|
+
for (const entry of raw) {
|
|
17828
|
+
if (typeof entry === "string") {
|
|
17829
|
+
out.push({
|
|
17830
|
+
category: "other",
|
|
17831
|
+
summary: truncate(entry, SUMMARY_MAX_CHARS),
|
|
17832
|
+
size_hint: "minimal"
|
|
17833
|
+
});
|
|
17834
|
+
continue;
|
|
17835
|
+
}
|
|
17836
|
+
if (entry && typeof entry === "object") {
|
|
17837
|
+
const obj = entry;
|
|
17838
|
+
const category = isCategoryValue(obj["category"]) ? obj["category"] : "other";
|
|
17839
|
+
const summary = typeof obj["summary"] === "string" ? truncate(obj["summary"], SUMMARY_MAX_CHARS) : "(unspecified)";
|
|
17840
|
+
const sizeHint = isSizeHintValue(obj["size_hint"]) ? obj["size_hint"] : "minimal";
|
|
17841
|
+
out.push({ category, summary, size_hint: sizeHint });
|
|
17842
|
+
}
|
|
17843
|
+
}
|
|
17844
|
+
return out;
|
|
17845
|
+
}
|
|
17846
|
+
if (typeof raw === "object" && raw !== null) {
|
|
17847
|
+
const out = [];
|
|
17848
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
17849
|
+
const category = isCategoryValue(k) ? k : "other";
|
|
17850
|
+
if (Array.isArray(v)) {
|
|
17851
|
+
for (const item of v) {
|
|
17852
|
+
if (typeof item === "string") {
|
|
17853
|
+
out.push({
|
|
17854
|
+
category,
|
|
17855
|
+
summary: truncate(item, SUMMARY_MAX_CHARS),
|
|
17856
|
+
size_hint: "minimal"
|
|
17857
|
+
});
|
|
17858
|
+
}
|
|
17859
|
+
}
|
|
17860
|
+
}
|
|
17861
|
+
}
|
|
17862
|
+
return out;
|
|
17863
|
+
}
|
|
17864
|
+
return [];
|
|
17865
|
+
}
|
|
17866
|
+
function isCategoryValue(v) {
|
|
17867
|
+
return typeof v === "string" && CATEGORY_VALUES.includes(v);
|
|
17868
|
+
}
|
|
17869
|
+
function isSizeHintValue(v) {
|
|
17870
|
+
return typeof v === "string" && (v === "minimal" || v === "small" || v === "medium" || v === "large");
|
|
17871
|
+
}
|
|
17872
|
+
function categoryFromPolicyRuleId(ruleId) {
|
|
17873
|
+
const lower = ruleId.toLowerCase();
|
|
17874
|
+
if (lower.includes("credential") || lower.includes("broker_secret")) {
|
|
17875
|
+
return "credentials";
|
|
17876
|
+
}
|
|
17877
|
+
if (lower.includes("memory") || lower.includes("state_read")) {
|
|
17878
|
+
return "memory";
|
|
17879
|
+
}
|
|
17880
|
+
if (lower.includes("plan")) {
|
|
17881
|
+
return "plans";
|
|
17882
|
+
}
|
|
17883
|
+
if (lower.includes("export") || lower.includes("output")) {
|
|
17884
|
+
return "outputs";
|
|
17885
|
+
}
|
|
17886
|
+
if (lower.includes("audit")) {
|
|
17887
|
+
return "audit-refs";
|
|
17888
|
+
}
|
|
17889
|
+
return "other";
|
|
17890
|
+
}
|
|
17891
|
+
var SUMMARY_MAX_CHARS, CATEGORY_VALUES, CONTEXT_TRANSFER_AUDIT_OPS;
|
|
17892
|
+
var init_context_transfer_extractor = __esm({
|
|
17893
|
+
"src/coordination/context-transfer-extractor.ts"() {
|
|
17894
|
+
SUMMARY_MAX_CHARS = 240;
|
|
17895
|
+
CATEGORY_VALUES = [
|
|
17896
|
+
"memory",
|
|
17897
|
+
"credentials",
|
|
17898
|
+
"plans",
|
|
17899
|
+
"outputs",
|
|
17900
|
+
"audit-refs",
|
|
17901
|
+
"other"
|
|
17902
|
+
];
|
|
17903
|
+
CONTEXT_TRANSFER_AUDIT_OPS = {
|
|
17904
|
+
DECODED: "operator_handoff_context_transfer_decoded"
|
|
17905
|
+
};
|
|
17906
|
+
}
|
|
17907
|
+
});
|
|
17908
|
+
|
|
17909
|
+
// src/coordination/handoff-routes.ts
|
|
17910
|
+
function writeJSON6(res, status, payload) {
|
|
17911
|
+
res.writeHead(status, {
|
|
17912
|
+
"Content-Type": "application/json",
|
|
17913
|
+
"Cache-Control": "no-store"
|
|
17914
|
+
});
|
|
17915
|
+
res.end(JSON.stringify(payload));
|
|
17916
|
+
}
|
|
17917
|
+
function parseLimit4(raw, defaultValue, max) {
|
|
17918
|
+
if (raw === null || raw === "") return defaultValue;
|
|
17919
|
+
const parsed = Number.parseInt(raw, 10);
|
|
17920
|
+
if (Number.isNaN(parsed) || parsed < 0) return defaultValue;
|
|
17921
|
+
return Math.min(parsed, max);
|
|
17922
|
+
}
|
|
17923
|
+
function matchEntryRoute2(path) {
|
|
17924
|
+
const prefix = `${COORDINATION_HANDOFFS_PREFIX}/`;
|
|
17925
|
+
if (!path.startsWith(prefix)) return null;
|
|
17926
|
+
const rest = path.slice(prefix.length);
|
|
17927
|
+
if (rest.length === 0 || rest === "stream") return null;
|
|
17928
|
+
if (rest.includes("/")) return null;
|
|
17929
|
+
return { entryId: decodeURIComponent(rest) };
|
|
17930
|
+
}
|
|
17931
|
+
async function handleStream3(deps, res) {
|
|
17932
|
+
res.writeHead(200, {
|
|
17933
|
+
"Content-Type": "text/event-stream",
|
|
17934
|
+
"Cache-Control": "no-cache, no-transform",
|
|
17935
|
+
Connection: "keep-alive",
|
|
17936
|
+
"X-Accel-Buffering": "no"
|
|
17937
|
+
});
|
|
17938
|
+
const snapshot = await deps.handoffLog.query({ limit: 50 });
|
|
17939
|
+
res.write(
|
|
17940
|
+
`event: handoff_snapshot
|
|
17941
|
+
data: ${JSON.stringify({ entries: snapshot })}
|
|
17942
|
+
|
|
17943
|
+
`
|
|
17944
|
+
);
|
|
17945
|
+
const unsubscribe = deps.events.subscribe((entry) => {
|
|
17946
|
+
try {
|
|
17947
|
+
res.write(
|
|
17948
|
+
`event: handoff_added
|
|
17949
|
+
data: ${JSON.stringify(entry)}
|
|
17950
|
+
|
|
17951
|
+
`
|
|
17952
|
+
);
|
|
17953
|
+
} catch {
|
|
17954
|
+
}
|
|
17955
|
+
});
|
|
17956
|
+
const keepAlive = setInterval(() => {
|
|
17957
|
+
try {
|
|
17958
|
+
res.write(": keepalive\n\n");
|
|
17959
|
+
} catch {
|
|
17960
|
+
}
|
|
17961
|
+
}, 25e3);
|
|
17962
|
+
const cleanup = () => {
|
|
17963
|
+
clearInterval(keepAlive);
|
|
17964
|
+
unsubscribe();
|
|
17965
|
+
};
|
|
17966
|
+
res.on("close", cleanup);
|
|
17967
|
+
res.on("error", cleanup);
|
|
17968
|
+
}
|
|
17969
|
+
async function handleCoordinationRoute(deps, req, res) {
|
|
17970
|
+
const host = req.headers.host || "localhost";
|
|
17971
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
17972
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
17973
|
+
const path = url.pathname;
|
|
17974
|
+
if (path !== COORDINATION_API_PREFIX && !path.startsWith(`${COORDINATION_API_PREFIX}/`)) {
|
|
17975
|
+
return false;
|
|
17976
|
+
}
|
|
17977
|
+
const checkAuth = authMiddleware(deps.authConfig);
|
|
17978
|
+
if (!checkAuth(req, res, url)) return true;
|
|
17979
|
+
try {
|
|
17980
|
+
if (method === "GET" && path === `${COORDINATION_HANDOFFS_PREFIX}/stream`) {
|
|
17981
|
+
await handleStream3(deps, res);
|
|
17982
|
+
return true;
|
|
17983
|
+
}
|
|
17984
|
+
if (method === "GET" && path === COORDINATION_HANDOFFS_PREFIX) {
|
|
17985
|
+
const limit = parseLimit4(
|
|
17986
|
+
url.searchParams.get("limit"),
|
|
17987
|
+
COORDINATION_LIST_DEFAULT_LIMIT,
|
|
17988
|
+
COORDINATION_LIST_MAX_LIMIT
|
|
17989
|
+
);
|
|
17990
|
+
const since = url.searchParams.get("since") ?? void 0;
|
|
17991
|
+
const until = url.searchParams.get("until") ?? void 0;
|
|
17992
|
+
const agentId = url.searchParams.get("agent_id") ?? void 0;
|
|
17993
|
+
const entries = await deps.handoffLog.query({
|
|
17994
|
+
limit,
|
|
17995
|
+
...since !== void 0 ? { since } : {},
|
|
17996
|
+
...until !== void 0 ? { until } : {},
|
|
17997
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
17998
|
+
});
|
|
17999
|
+
deps.auditLog.append(
|
|
18000
|
+
"l2",
|
|
18001
|
+
COORDINATION_VIEW_AUDIT_OPS.VIEW_OPENED,
|
|
18002
|
+
deps.operatorId,
|
|
18003
|
+
{
|
|
18004
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
18005
|
+
result_count: entries.length,
|
|
18006
|
+
...since !== void 0 ? { since } : {},
|
|
18007
|
+
...until !== void 0 ? { until } : {},
|
|
18008
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
18009
|
+
}
|
|
18010
|
+
);
|
|
18011
|
+
writeJSON6(res, 200, { ok: true, data: { entries } });
|
|
18012
|
+
return true;
|
|
18013
|
+
}
|
|
18014
|
+
const entryMatch = matchEntryRoute2(path);
|
|
18015
|
+
if (method === "GET" && entryMatch) {
|
|
18016
|
+
const detail = await deps.handoffLog.getEntry(entryMatch.entryId);
|
|
18017
|
+
if (!detail) {
|
|
18018
|
+
writeJSON6(res, 404, { ok: false, error: "not_found" });
|
|
18019
|
+
return true;
|
|
18020
|
+
}
|
|
18021
|
+
deps.auditLog.append(
|
|
18022
|
+
"l2",
|
|
18023
|
+
COORDINATION_VIEW_AUDIT_OPS.ENTRY_DRILLED,
|
|
18024
|
+
deps.operatorId,
|
|
18025
|
+
{
|
|
18026
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
18027
|
+
entry_id: detail.entry.entry_id,
|
|
18028
|
+
event_class: detail.entry.event_class,
|
|
18029
|
+
source_agent_id: detail.entry.source_agent_id,
|
|
18030
|
+
target_agent_id: detail.entry.target_agent_id
|
|
18031
|
+
}
|
|
18032
|
+
);
|
|
18033
|
+
let breakdown = null;
|
|
18034
|
+
try {
|
|
18035
|
+
breakdown = await extractContextTransferBreakdown(
|
|
18036
|
+
detail,
|
|
18037
|
+
deps.contextTransfer ?? {}
|
|
18038
|
+
);
|
|
18039
|
+
deps.auditLog.append(
|
|
18040
|
+
"l2",
|
|
18041
|
+
CONTEXT_TRANSFER_AUDIT_OPS.DECODED,
|
|
18042
|
+
deps.operatorId,
|
|
18043
|
+
{
|
|
18044
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
18045
|
+
entry_id: detail.entry.entry_id,
|
|
18046
|
+
extractor_path: breakdown.source,
|
|
18047
|
+
confidence: breakdown.confidence,
|
|
18048
|
+
transferred_count: breakdown.transferred.length,
|
|
18049
|
+
withheld_count: breakdown.withheld.length
|
|
18050
|
+
}
|
|
18051
|
+
);
|
|
18052
|
+
} catch {
|
|
18053
|
+
}
|
|
18054
|
+
const responseData = breakdown !== null ? { ...detail, context_transfer_breakdown: breakdown } : detail;
|
|
18055
|
+
writeJSON6(res, 200, { ok: true, data: responseData });
|
|
18056
|
+
return true;
|
|
18057
|
+
}
|
|
18058
|
+
writeJSON6(res, 404, { ok: false, error: "not_found", path });
|
|
18059
|
+
return true;
|
|
18060
|
+
} catch (err) {
|
|
18061
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18062
|
+
writeJSON6(res, 500, { ok: false, error: "internal", detail: msg });
|
|
18063
|
+
return true;
|
|
18064
|
+
}
|
|
18065
|
+
}
|
|
18066
|
+
var COORDINATION_API_PREFIX, COORDINATION_HANDOFFS_PREFIX, COORDINATION_LIST_DEFAULT_LIMIT, COORDINATION_LIST_MAX_LIMIT, HandoffEventBridge;
|
|
18067
|
+
var init_handoff_routes = __esm({
|
|
18068
|
+
"src/coordination/handoff-routes.ts"() {
|
|
18069
|
+
init_auth_middleware();
|
|
18070
|
+
init_handoff_log();
|
|
18071
|
+
init_context_transfer_extractor();
|
|
18072
|
+
COORDINATION_API_PREFIX = "/api/coordination";
|
|
18073
|
+
COORDINATION_HANDOFFS_PREFIX = "/api/coordination/handoffs";
|
|
18074
|
+
COORDINATION_LIST_DEFAULT_LIMIT = 50;
|
|
18075
|
+
COORDINATION_LIST_MAX_LIMIT = 500;
|
|
18076
|
+
HandoffEventBridge = class {
|
|
18077
|
+
listeners = /* @__PURE__ */ new Set();
|
|
18078
|
+
subscribe(listener) {
|
|
18079
|
+
this.listeners.add(listener);
|
|
18080
|
+
return () => this.listeners.delete(listener);
|
|
18081
|
+
}
|
|
18082
|
+
emit(entry) {
|
|
18083
|
+
for (const listener of this.listeners) {
|
|
18084
|
+
try {
|
|
18085
|
+
listener(entry);
|
|
18086
|
+
} catch {
|
|
18087
|
+
}
|
|
18088
|
+
}
|
|
18089
|
+
}
|
|
18090
|
+
};
|
|
18091
|
+
}
|
|
18092
|
+
});
|
|
17483
18093
|
function isDashboardViewRoute(method, path) {
|
|
17484
18094
|
if (method !== "GET") return false;
|
|
17485
18095
|
return path === "/" || path === "/dashboard" || path === "/v1.0" || path === "/fortress" || path === "/events";
|
|
@@ -17495,6 +18105,7 @@ var init_dashboard = __esm({
|
|
|
17495
18105
|
init_dispatch();
|
|
17496
18106
|
init_approval_aggregator_routes();
|
|
17497
18107
|
init_sentinel_routes();
|
|
18108
|
+
init_handoff_routes();
|
|
17498
18109
|
SESSION_TTL_REMOTE_MS = 5 * 60 * 1e3;
|
|
17499
18110
|
SESSION_TTL_LOCAL_MS = 24 * 60 * 60 * 1e3;
|
|
17500
18111
|
MAX_SESSIONS = 1e3;
|
|
@@ -17569,6 +18180,17 @@ var init_dashboard = __esm({
|
|
|
17569
18180
|
* dispatcher's audited paths.
|
|
17570
18181
|
*/
|
|
17571
18182
|
sentinelDispatcher = null;
|
|
18183
|
+
/**
|
|
18184
|
+
* v1.3 WP-V1.3-3 Omega-1 Coordination Handoff Visualization.
|
|
18185
|
+
* Mounted additively at `/api/coordination/*` when set. Read-only
|
|
18186
|
+
* against the audit log; the only writes are operator-action audit
|
|
18187
|
+
* events (operator_coordination_view_opened,
|
|
18188
|
+
* operator_handoff_entry_drilled).
|
|
18189
|
+
*/
|
|
18190
|
+
handoffLog = null;
|
|
18191
|
+
handoffEventBridge = null;
|
|
18192
|
+
handoffAuditLog = null;
|
|
18193
|
+
handoffOperatorId = null;
|
|
17572
18194
|
constructor(config) {
|
|
17573
18195
|
this.config = config;
|
|
17574
18196
|
this.authToken = config.auth_token;
|
|
@@ -17636,6 +18258,18 @@ var init_dashboard = __esm({
|
|
|
17636
18258
|
setSentinelDispatcher(dispatcher) {
|
|
17637
18259
|
this.sentinelDispatcher = dispatcher;
|
|
17638
18260
|
}
|
|
18261
|
+
/**
|
|
18262
|
+
* v1.3 WP-V1.3-3 Omega-1: bind the Coordination handoff log +
|
|
18263
|
+
* event bridge + audit log + operator id. Once set, requests to
|
|
18264
|
+
* `/api/coordination/*` route through `handleCoordinationRoute`.
|
|
18265
|
+
* Pass `null` for any field to detach.
|
|
18266
|
+
*/
|
|
18267
|
+
setHandoffLog(opts) {
|
|
18268
|
+
this.handoffLog = opts.handoffLog;
|
|
18269
|
+
this.handoffEventBridge = opts.eventBridge ?? null;
|
|
18270
|
+
this.handoffAuditLog = opts.auditLog ?? null;
|
|
18271
|
+
this.handoffOperatorId = opts.operatorId ?? null;
|
|
18272
|
+
}
|
|
17639
18273
|
/**
|
|
17640
18274
|
* v1.3 WP-V1.3-10 dispatch entry point. Called from `handleRequest`
|
|
17641
18275
|
* before the legacy approval route table. Returns true when served.
|
|
@@ -17674,6 +18308,30 @@ var init_dashboard = __esm({
|
|
|
17674
18308
|
res
|
|
17675
18309
|
);
|
|
17676
18310
|
}
|
|
18311
|
+
/**
|
|
18312
|
+
* v1.3 WP-V1.3-3 Omega-1 dispatch entry point. Routes
|
|
18313
|
+
* `/api/coordination/*` requests through the coordination router
|
|
18314
|
+
* when a HandoffLog has been bound. Returns true when served.
|
|
18315
|
+
*/
|
|
18316
|
+
async dispatchCoordination(req, res) {
|
|
18317
|
+
if (!this.handoffLog || !this.handoffEventBridge || !this.handoffAuditLog) {
|
|
18318
|
+
return false;
|
|
18319
|
+
}
|
|
18320
|
+
return handleCoordinationRoute(
|
|
18321
|
+
{
|
|
18322
|
+
authConfig: {
|
|
18323
|
+
loopbackAutoAuth: this._autoAuthLocalhost,
|
|
18324
|
+
...this.authToken !== void 0 ? { authToken: this.authToken } : {}
|
|
18325
|
+
},
|
|
18326
|
+
handoffLog: this.handoffLog,
|
|
18327
|
+
auditLog: this.handoffAuditLog,
|
|
18328
|
+
operatorId: this.handoffOperatorId ?? this.identityManager?.getPrimaryIdentityId() ?? "operator_dashboard",
|
|
18329
|
+
events: this.handoffEventBridge
|
|
18330
|
+
},
|
|
18331
|
+
req,
|
|
18332
|
+
res
|
|
18333
|
+
);
|
|
18334
|
+
}
|
|
17677
18335
|
/**
|
|
17678
18336
|
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
17679
18337
|
* legacy route table. Returns true when the request was served by v1.1
|
|
@@ -18073,6 +18731,18 @@ var init_dashboard = __esm({
|
|
|
18073
18731
|
});
|
|
18074
18732
|
return;
|
|
18075
18733
|
}
|
|
18734
|
+
if (this.handoffLog && url.pathname.startsWith(COORDINATION_API_PREFIX)) {
|
|
18735
|
+
this.dispatchCoordination(req, res).then((handled) => {
|
|
18736
|
+
if (handled) return;
|
|
18737
|
+
this.handleLegacyRequest(req, res, url, method);
|
|
18738
|
+
}).catch(() => {
|
|
18739
|
+
if (!res.headersSent) {
|
|
18740
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
18741
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
18742
|
+
}
|
|
18743
|
+
});
|
|
18744
|
+
return;
|
|
18745
|
+
}
|
|
18076
18746
|
if (this.v11Bindings) {
|
|
18077
18747
|
this.dispatchV11(req, res, url, method).then((handled) => {
|
|
18078
18748
|
if (handled) return;
|
|
@@ -21939,15 +22609,52 @@ var init_sentinel_dispatcher = __esm({
|
|
|
21939
22609
|
};
|
|
21940
22610
|
}
|
|
21941
22611
|
});
|
|
22612
|
+
var init_classifier_state_store = __esm({
|
|
22613
|
+
"src/anomaly-detection/classifier-state-store.ts"() {
|
|
22614
|
+
init_encryption();
|
|
22615
|
+
init_key_derivation();
|
|
22616
|
+
init_encoding();
|
|
22617
|
+
}
|
|
22618
|
+
});
|
|
22619
|
+
|
|
22620
|
+
// src/anomaly-detection/classifiers/cusum.ts
|
|
22621
|
+
var CUSUM_CLASSIFIER_ID;
|
|
22622
|
+
var init_cusum = __esm({
|
|
22623
|
+
"src/anomaly-detection/classifiers/cusum.ts"() {
|
|
22624
|
+
init_classifier_state_store();
|
|
22625
|
+
CUSUM_CLASSIFIER_ID = "cusum";
|
|
22626
|
+
}
|
|
22627
|
+
});
|
|
22628
|
+
|
|
22629
|
+
// src/anomaly-detection/classifiers/psi.ts
|
|
22630
|
+
var PSI_CLASSIFIER_ID;
|
|
22631
|
+
var init_psi = __esm({
|
|
22632
|
+
"src/anomaly-detection/classifiers/psi.ts"() {
|
|
22633
|
+
init_classifier_state_store();
|
|
22634
|
+
PSI_CLASSIFIER_ID = "psi";
|
|
22635
|
+
}
|
|
22636
|
+
});
|
|
21942
22637
|
|
|
21943
22638
|
// src/anomaly-detection/types.ts
|
|
21944
22639
|
var init_types4 = __esm({
|
|
21945
22640
|
"src/anomaly-detection/types.ts"() {
|
|
21946
22641
|
}
|
|
21947
22642
|
});
|
|
22643
|
+
function classifierSpecificAuditOp(classifierId) {
|
|
22644
|
+
if (classifierId === null) return null;
|
|
22645
|
+
if (classifierId === CUSUM_CLASSIFIER_ID) {
|
|
22646
|
+
return ANOMALY_AUDIT_OPS.CUSUM_DRIFT_DETECTED;
|
|
22647
|
+
}
|
|
22648
|
+
if (classifierId === PSI_CLASSIFIER_ID) {
|
|
22649
|
+
return ANOMALY_AUDIT_OPS.PSI_DISTRIBUTION_SHIFT_DETECTED;
|
|
22650
|
+
}
|
|
22651
|
+
return null;
|
|
22652
|
+
}
|
|
21948
22653
|
var ANOMALY_AUDIT_OPS, DEFAULT_TICK_INTERVAL_MS2, AnomalyPipelineDispatcher;
|
|
21949
22654
|
var init_anomaly_pipeline = __esm({
|
|
21950
22655
|
"src/anomaly-detection/anomaly-pipeline.ts"() {
|
|
22656
|
+
init_cusum();
|
|
22657
|
+
init_psi();
|
|
21951
22658
|
init_types4();
|
|
21952
22659
|
ANOMALY_AUDIT_OPS = {
|
|
21953
22660
|
DETECTOR_REGISTERED: "anomaly_detector_registered",
|
|
@@ -21955,7 +22662,15 @@ var init_anomaly_pipeline = __esm({
|
|
|
21955
22662
|
FINDING_EMITTED: "anomaly_finding_emitted",
|
|
21956
22663
|
EVALUATION_FAILED: "anomaly_evaluation_failed",
|
|
21957
22664
|
TRAINING_COMPLETED: "anomaly_training_completed",
|
|
21958
|
-
TRAINING_FAILED: "anomaly_training_failed"
|
|
22665
|
+
TRAINING_FAILED: "anomaly_training_failed",
|
|
22666
|
+
/** Chi-2: a classifier was attached to an existing detector. */
|
|
22667
|
+
CLASSIFIER_SUBSCRIBED: "anomaly_classifier_subscribed",
|
|
22668
|
+
/** Chi-2: a classifier was detached from an existing detector. */
|
|
22669
|
+
CLASSIFIER_UNSUBSCRIBED: "anomaly_classifier_unsubscribed",
|
|
22670
|
+
/** Chi-2: CUSUM-flagged mean-shift drift on a per-agent feature. */
|
|
22671
|
+
CUSUM_DRIFT_DETECTED: "anomaly_cusum_drift_detected",
|
|
22672
|
+
/** Chi-2: PSI-flagged distribution shift on a per-agent feature. */
|
|
22673
|
+
PSI_DISTRIBUTION_SHIFT_DETECTED: "anomaly_psi_distribution_shift_detected"
|
|
21959
22674
|
};
|
|
21960
22675
|
DEFAULT_TICK_INTERVAL_MS2 = 6e4;
|
|
21961
22676
|
AnomalyPipelineDispatcher = class {
|
|
@@ -22046,34 +22761,37 @@ var init_anomaly_pipeline = __esm({
|
|
|
22046
22761
|
const stamped = await this.routeFinding(detectorId, raw);
|
|
22047
22762
|
findings.push(stamped);
|
|
22048
22763
|
}
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
|
|
22073
|
-
|
|
22074
|
-
|
|
22075
|
-
|
|
22076
|
-
|
|
22764
|
+
for (const classifier of detector.getAllClassifiers()) {
|
|
22765
|
+
try {
|
|
22766
|
+
const trainingResult = await classifier.train();
|
|
22767
|
+
this.auditLog.append(
|
|
22768
|
+
"l2",
|
|
22769
|
+
ANOMALY_AUDIT_OPS.TRAINING_COMPLETED,
|
|
22770
|
+
this.identityId,
|
|
22771
|
+
{
|
|
22772
|
+
detector_id: detectorId,
|
|
22773
|
+
classifier_id: classifier.classifierId,
|
|
22774
|
+
trained_at: trainingResult.trained_at,
|
|
22775
|
+
sample_count: trainingResult.sample_count,
|
|
22776
|
+
agent_count: trainingResult.agent_count,
|
|
22777
|
+
fortress_id: this.fortressId
|
|
22778
|
+
}
|
|
22779
|
+
);
|
|
22780
|
+
} catch (trainErr) {
|
|
22781
|
+
const message = trainErr instanceof Error ? trainErr.message : String(trainErr);
|
|
22782
|
+
this.auditLog.append(
|
|
22783
|
+
"l2",
|
|
22784
|
+
ANOMALY_AUDIT_OPS.TRAINING_FAILED,
|
|
22785
|
+
this.identityId,
|
|
22786
|
+
{
|
|
22787
|
+
detector_id: detectorId,
|
|
22788
|
+
classifier_id: classifier.classifierId,
|
|
22789
|
+
error_message: message,
|
|
22790
|
+
fortress_id: this.fortressId
|
|
22791
|
+
},
|
|
22792
|
+
"failure"
|
|
22793
|
+
);
|
|
22794
|
+
}
|
|
22077
22795
|
}
|
|
22078
22796
|
} catch (err) {
|
|
22079
22797
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -22136,6 +22854,7 @@ var init_anomaly_pipeline = __esm({
|
|
|
22136
22854
|
observed_at: raw.observed_at || this.now().toISOString()
|
|
22137
22855
|
};
|
|
22138
22856
|
await this.findingStore.saveFinding(stamped);
|
|
22857
|
+
const classifierId = stamped.details["classifier_id"] ?? null;
|
|
22139
22858
|
this.auditLog.append(
|
|
22140
22859
|
"l2",
|
|
22141
22860
|
ANOMALY_AUDIT_OPS.FINDING_EMITTED,
|
|
@@ -22145,13 +22864,79 @@ var init_anomaly_pipeline = __esm({
|
|
|
22145
22864
|
finding_id: stamped.finding_id,
|
|
22146
22865
|
severity: stamped.severity,
|
|
22147
22866
|
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
22867
|
+
...classifierId !== null ? { classifier_id: classifierId } : {},
|
|
22148
22868
|
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
22149
22869
|
fortress_id: this.fortressId
|
|
22150
22870
|
}
|
|
22151
22871
|
);
|
|
22872
|
+
const specificOp = classifierSpecificAuditOp(classifierId);
|
|
22873
|
+
if (specificOp !== null) {
|
|
22874
|
+
this.auditLog.append("l2", specificOp, this.identityId, {
|
|
22875
|
+
detector_id: detectorId,
|
|
22876
|
+
finding_id: stamped.finding_id,
|
|
22877
|
+
severity: stamped.severity,
|
|
22878
|
+
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
22879
|
+
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
22880
|
+
fortress_id: this.fortressId
|
|
22881
|
+
});
|
|
22882
|
+
}
|
|
22152
22883
|
this.emit({ type: "finding", finding: stamped });
|
|
22153
22884
|
return stamped;
|
|
22154
22885
|
}
|
|
22886
|
+
/**
|
|
22887
|
+
* Chi-2: attach an additional classifier to an already-registered
|
|
22888
|
+
* detector. Emits ANOMALY_CLASSIFIER_SUBSCRIBED on success. The
|
|
22889
|
+
* factory is called with the fortress AnomalyContext so the
|
|
22890
|
+
* classifier can build its own state-store binding. Idempotent: a
|
|
22891
|
+
* second call with the same classifierId returns false.
|
|
22892
|
+
*/
|
|
22893
|
+
async addClassifierToDetector(detectorId, factory) {
|
|
22894
|
+
const detector = this.detectors.get(detectorId);
|
|
22895
|
+
if (!detector) return false;
|
|
22896
|
+
const context = {
|
|
22897
|
+
fortressId: this.fortressId,
|
|
22898
|
+
auditLog: this.auditLog,
|
|
22899
|
+
storage: this.storage,
|
|
22900
|
+
masterKey: this.masterKey,
|
|
22901
|
+
now: this.now
|
|
22902
|
+
};
|
|
22903
|
+
const classifier = factory(context);
|
|
22904
|
+
const added = detector.addClassifier(classifier);
|
|
22905
|
+
if (!added) return false;
|
|
22906
|
+
this.auditLog.append(
|
|
22907
|
+
"l2",
|
|
22908
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_SUBSCRIBED,
|
|
22909
|
+
this.identityId,
|
|
22910
|
+
{
|
|
22911
|
+
detector_id: detectorId,
|
|
22912
|
+
classifier_id: classifier.classifierId,
|
|
22913
|
+
fortress_id: this.fortressId
|
|
22914
|
+
}
|
|
22915
|
+
);
|
|
22916
|
+
return true;
|
|
22917
|
+
}
|
|
22918
|
+
/**
|
|
22919
|
+
* Chi-2: detach an additional classifier from an already-registered
|
|
22920
|
+
* detector. Emits ANOMALY_CLASSIFIER_UNSUBSCRIBED on success. The
|
|
22921
|
+
* primary classifier cannot be detached (returns false).
|
|
22922
|
+
*/
|
|
22923
|
+
async removeClassifierFromDetector(detectorId, classifierId) {
|
|
22924
|
+
const detector = this.detectors.get(detectorId);
|
|
22925
|
+
if (!detector) return false;
|
|
22926
|
+
const removed = detector.removeClassifier(classifierId);
|
|
22927
|
+
if (!removed) return false;
|
|
22928
|
+
this.auditLog.append(
|
|
22929
|
+
"l2",
|
|
22930
|
+
ANOMALY_AUDIT_OPS.CLASSIFIER_UNSUBSCRIBED,
|
|
22931
|
+
this.identityId,
|
|
22932
|
+
{
|
|
22933
|
+
detector_id: detectorId,
|
|
22934
|
+
classifier_id: classifierId,
|
|
22935
|
+
fortress_id: this.fortressId
|
|
22936
|
+
}
|
|
22937
|
+
);
|
|
22938
|
+
return true;
|
|
22939
|
+
}
|
|
22155
22940
|
emit(event) {
|
|
22156
22941
|
for (const listener of this.listeners) {
|
|
22157
22942
|
try {
|
|
@@ -22428,7 +23213,7 @@ function extractInterAgentEvents(entries) {
|
|
|
22428
23213
|
if (!sender) continue;
|
|
22429
23214
|
out.push({
|
|
22430
23215
|
sender,
|
|
22431
|
-
recipient:
|
|
23216
|
+
recipient: OPERATOR_PSEUDO_AGENT2,
|
|
22432
23217
|
timestampMs: Date.parse(entry.timestamp),
|
|
22433
23218
|
auditId: `${entry.timestamp}:${entry.operation}`
|
|
22434
23219
|
});
|
|
@@ -22442,7 +23227,7 @@ function optionalString(details, key) {
|
|
|
22442
23227
|
if (typeof value !== "string" || value.length === 0) return null;
|
|
22443
23228
|
return value;
|
|
22444
23229
|
}
|
|
22445
|
-
var CROSS_AGENT_CHATTER_SENTINEL_ID, WARN_SIGMA2, ALERT_SIGMA2, BASELINE_WINDOWS2, QUERY_LIMIT2, MULTI_NEW_PARTNER_ALERT_THRESHOLD,
|
|
23230
|
+
var CROSS_AGENT_CHATTER_SENTINEL_ID, WARN_SIGMA2, ALERT_SIGMA2, BASELINE_WINDOWS2, QUERY_LIMIT2, MULTI_NEW_PARTNER_ALERT_THRESHOLD, OPERATOR_PSEUDO_AGENT2, HANDOFF_OP, CROSS_HARNESS_OPS, CrossAgentChatterWatcher;
|
|
22446
23231
|
var init_cross_agent_chatter_watcher = __esm({
|
|
22447
23232
|
"src/sentinel/sentinels/cross-agent-chatter-watcher.ts"() {
|
|
22448
23233
|
init_sentinel();
|
|
@@ -22452,7 +23237,7 @@ var init_cross_agent_chatter_watcher = __esm({
|
|
|
22452
23237
|
BASELINE_WINDOWS2 = 7;
|
|
22453
23238
|
QUERY_LIMIT2 = 1e4;
|
|
22454
23239
|
MULTI_NEW_PARTNER_ALERT_THRESHOLD = 3;
|
|
22455
|
-
|
|
23240
|
+
OPERATOR_PSEUDO_AGENT2 = "operator";
|
|
22456
23241
|
HANDOFF_OP = "v1.1_local_handoff";
|
|
22457
23242
|
CROSS_HARNESS_OPS = /* @__PURE__ */ new Set([
|
|
22458
23243
|
"cross_harness_approval_aggregated",
|
|
@@ -25514,7 +26299,7 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25514
26299
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25515
26300
|
const canonicalBytes = canonicalize2(outcome);
|
|
25516
26301
|
const canonicalString = new TextDecoder().decode(canonicalBytes);
|
|
25517
|
-
const
|
|
26302
|
+
const sha25612 = createCommitment(canonicalString);
|
|
25518
26303
|
let pedersenData;
|
|
25519
26304
|
if (includePedersen && Number.isInteger(outcome.rounds) && outcome.rounds >= 0) {
|
|
25520
26305
|
const pedersen = createPedersenCommitment(outcome.rounds);
|
|
@@ -25526,7 +26311,7 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25526
26311
|
const commitmentPayload = {
|
|
25527
26312
|
bridge_commitment_id: commitmentId,
|
|
25528
26313
|
session_id: outcome.session_id,
|
|
25529
|
-
sha256_commitment:
|
|
26314
|
+
sha256_commitment: sha25612.commitment,
|
|
25530
26315
|
terms_hash: outcome.terms_hash,
|
|
25531
26316
|
committer_did: identity.did,
|
|
25532
26317
|
committed_at: now,
|
|
@@ -25537,8 +26322,8 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25537
26322
|
return {
|
|
25538
26323
|
bridge_commitment_id: commitmentId,
|
|
25539
26324
|
session_id: outcome.session_id,
|
|
25540
|
-
sha256_commitment:
|
|
25541
|
-
blinding_factor:
|
|
26325
|
+
sha256_commitment: sha25612.commitment,
|
|
26326
|
+
blinding_factor: sha25612.blinding_factor,
|
|
25542
26327
|
committer_did: identity.did,
|
|
25543
26328
|
signature: toBase64url(signature),
|
|
25544
26329
|
pedersen_commitment: pedersenData,
|
|
@@ -39461,6 +40246,141 @@ ${redactedItems.map((r) => `- ${r.redacted}`).join("\n")}`,
|
|
|
39461
40246
|
}
|
|
39462
40247
|
});
|
|
39463
40248
|
|
|
40249
|
+
// src/query-anonymity/header-strip.ts
|
|
40250
|
+
function stripHeaders(headers) {
|
|
40251
|
+
const stripped = {};
|
|
40252
|
+
const removed = [];
|
|
40253
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
40254
|
+
const lower = name.toLowerCase();
|
|
40255
|
+
if (REQUIRED_HEADER_SET.has(lower)) {
|
|
40256
|
+
stripped[name] = value;
|
|
40257
|
+
continue;
|
|
40258
|
+
}
|
|
40259
|
+
const reason = STRIP_REASON_BY_NAME.get(lower);
|
|
40260
|
+
if (reason !== void 0) {
|
|
40261
|
+
removed.push({ name, reason });
|
|
40262
|
+
continue;
|
|
40263
|
+
}
|
|
40264
|
+
stripped[name] = value;
|
|
40265
|
+
}
|
|
40266
|
+
return { stripped, removed };
|
|
40267
|
+
}
|
|
40268
|
+
function defeatUndiciDefaultsInto(headers) {
|
|
40269
|
+
if (headers["user-agent"] === void 0 && headers["User-Agent"] === void 0) {
|
|
40270
|
+
headers["User-Agent"] = "";
|
|
40271
|
+
}
|
|
40272
|
+
if (headers["accept-language"] === void 0 && headers["Accept-Language"] === void 0) {
|
|
40273
|
+
headers["Accept-Language"] = "";
|
|
40274
|
+
}
|
|
40275
|
+
return headers;
|
|
40276
|
+
}
|
|
40277
|
+
function createAnonymizedFetch(baseFetch, onAudit) {
|
|
40278
|
+
const wrapped = async (input, init) => {
|
|
40279
|
+
const headers = normalizeHeadersInit(init?.headers);
|
|
40280
|
+
const result = stripHeaders(headers);
|
|
40281
|
+
defeatUndiciDefaultsInto(result.stripped);
|
|
40282
|
+
const preservedRequired = Object.keys(result.stripped).filter(
|
|
40283
|
+
(k) => REQUIRED_HEADER_SET.has(k.toLowerCase())
|
|
40284
|
+
);
|
|
40285
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
40286
|
+
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
40287
|
+
if (onAudit) {
|
|
40288
|
+
onAudit({
|
|
40289
|
+
url,
|
|
40290
|
+
method,
|
|
40291
|
+
stripped_count: result.removed.length,
|
|
40292
|
+
removed: result.removed,
|
|
40293
|
+
required_preserved: preservedRequired
|
|
40294
|
+
});
|
|
40295
|
+
}
|
|
40296
|
+
return baseFetch(input, { ...init, headers: result.stripped });
|
|
40297
|
+
};
|
|
40298
|
+
return wrapped;
|
|
40299
|
+
}
|
|
40300
|
+
function normalizeHeadersInit(raw) {
|
|
40301
|
+
if (raw === void 0) return {};
|
|
40302
|
+
if (typeof Headers !== "undefined" && raw instanceof Headers) {
|
|
40303
|
+
const out = {};
|
|
40304
|
+
raw.forEach((value, key) => {
|
|
40305
|
+
out[key] = value;
|
|
40306
|
+
});
|
|
40307
|
+
return out;
|
|
40308
|
+
}
|
|
40309
|
+
if (Array.isArray(raw)) {
|
|
40310
|
+
const out = {};
|
|
40311
|
+
for (const [k, v] of raw) {
|
|
40312
|
+
if (k !== void 0 && v !== void 0) out[k] = v;
|
|
40313
|
+
}
|
|
40314
|
+
return out;
|
|
40315
|
+
}
|
|
40316
|
+
return { ...raw };
|
|
40317
|
+
}
|
|
40318
|
+
var QUERY_ANONYMITY_AUDIT_OPS, CANONICAL_STRIP_LIST, REQUIRED_HEADERS, REQUIRED_HEADER_SET, STRIP_REASON_BY_NAME;
|
|
40319
|
+
var init_header_strip = __esm({
|
|
40320
|
+
"src/query-anonymity/header-strip.ts"() {
|
|
40321
|
+
QUERY_ANONYMITY_AUDIT_OPS = {
|
|
40322
|
+
HEADERS_STRIPPED: "query_anonymity_headers_stripped"
|
|
40323
|
+
};
|
|
40324
|
+
CANONICAL_STRIP_LIST = [
|
|
40325
|
+
// Browser / runtime fingerprinting.
|
|
40326
|
+
{ name: "user-agent", reason: "user-agent" },
|
|
40327
|
+
{ name: "sec-ch-ua", reason: "fingerprintable-extension" },
|
|
40328
|
+
{ name: "sec-ch-ua-mobile", reason: "fingerprintable-extension" },
|
|
40329
|
+
{ name: "sec-ch-ua-platform", reason: "fingerprintable-extension" },
|
|
40330
|
+
{ name: "sec-ch-ua-platform-version", reason: "fingerprintable-extension" },
|
|
40331
|
+
{ name: "sec-ch-ua-arch", reason: "fingerprintable-extension" },
|
|
40332
|
+
{ name: "sec-ch-ua-bitness", reason: "fingerprintable-extension" },
|
|
40333
|
+
{ name: "sec-ch-ua-model", reason: "fingerprintable-extension" },
|
|
40334
|
+
{ name: "sec-ch-ua-full-version-list", reason: "fingerprintable-extension" },
|
|
40335
|
+
// Locale fingerprint.
|
|
40336
|
+
{ name: "accept-language", reason: "locale-fingerprint" },
|
|
40337
|
+
// Request-origin leak.
|
|
40338
|
+
{ name: "referer", reason: "leaking-network-info" },
|
|
40339
|
+
{ name: "referrer-policy", reason: "leaking-network-info" },
|
|
40340
|
+
{ name: "origin", reason: "leaking-network-info" },
|
|
40341
|
+
// Forwarded-by / IP-derived network info.
|
|
40342
|
+
{ name: "via", reason: "leaking-network-info" },
|
|
40343
|
+
{ name: "forwarded", reason: "leaking-network-info" },
|
|
40344
|
+
{ name: "x-forwarded-for", reason: "leaking-network-info" },
|
|
40345
|
+
{ name: "x-real-ip", reason: "leaking-network-info" },
|
|
40346
|
+
{ name: "x-client-ip", reason: "leaking-network-info" },
|
|
40347
|
+
// DNT / GPC are technically anti-tracking signals but they
|
|
40348
|
+
// themselves form a fingerprint (operators who set DNT=1 are a
|
|
40349
|
+
// smaller subset). Strip to keep the substrate ignorant of
|
|
40350
|
+
// operator preferences.
|
|
40351
|
+
{ name: "dnt", reason: "unnecessary-metadata" },
|
|
40352
|
+
{ name: "sec-gpc", reason: "unnecessary-metadata" }
|
|
40353
|
+
];
|
|
40354
|
+
REQUIRED_HEADERS = [
|
|
40355
|
+
"authorization",
|
|
40356
|
+
"content-type",
|
|
40357
|
+
"content-length",
|
|
40358
|
+
"host",
|
|
40359
|
+
"accept",
|
|
40360
|
+
"x-api-key",
|
|
40361
|
+
// Anthropic API auth
|
|
40362
|
+
"anthropic-version",
|
|
40363
|
+
// Anthropic API contract version
|
|
40364
|
+
"anthropic-beta",
|
|
40365
|
+
// optional Anthropic beta opt-in
|
|
40366
|
+
"openai-organization",
|
|
40367
|
+
// optional OpenAI org id
|
|
40368
|
+
"x-stainless-package-version",
|
|
40369
|
+
// allowed for Anthropic + OpenAI SDK contract compat
|
|
40370
|
+
"x-goog-api-key",
|
|
40371
|
+
// Google AI Studio
|
|
40372
|
+
"x-goog-user-project"
|
|
40373
|
+
// Google AI Studio
|
|
40374
|
+
];
|
|
40375
|
+
REQUIRED_HEADER_SET = new Set(
|
|
40376
|
+
REQUIRED_HEADERS.map((h) => h.toLowerCase())
|
|
40377
|
+
);
|
|
40378
|
+
STRIP_REASON_BY_NAME = new Map(
|
|
40379
|
+
CANONICAL_STRIP_LIST.map((h) => [h.name.toLowerCase(), h.reason])
|
|
40380
|
+
);
|
|
40381
|
+
}
|
|
40382
|
+
});
|
|
40383
|
+
|
|
39464
40384
|
// src/intelligence/substrates/hybrid/per-surface-router.ts
|
|
39465
40385
|
function resolveHybridChoice(rules, surface) {
|
|
39466
40386
|
if (!rules) return null;
|
|
@@ -39582,6 +40502,7 @@ var init_selector = __esm({
|
|
|
39582
40502
|
init_local();
|
|
39583
40503
|
init_venice();
|
|
39584
40504
|
init_frontier();
|
|
40505
|
+
init_header_strip();
|
|
39585
40506
|
init_per_surface_router();
|
|
39586
40507
|
DISABLED_CAPABILITY = {
|
|
39587
40508
|
summarize: false,
|
|
@@ -39616,7 +40537,21 @@ var init_selector = __esm({
|
|
|
39616
40537
|
this.auditLog = cfg.auditLog;
|
|
39617
40538
|
this.identityId = cfg.identityId;
|
|
39618
40539
|
this.redactor = cfg.redactor ?? IDENTITY_REDACTOR;
|
|
39619
|
-
|
|
40540
|
+
const baseFetch = cfg.fetchImpl ?? globalThis.fetch;
|
|
40541
|
+
this.fetchImpl = createAnonymizedFetch(baseFetch, (event) => {
|
|
40542
|
+
this.auditLog.append(
|
|
40543
|
+
"l2",
|
|
40544
|
+
QUERY_ANONYMITY_AUDIT_OPS.HEADERS_STRIPPED,
|
|
40545
|
+
this.identityId,
|
|
40546
|
+
{
|
|
40547
|
+
url: event.url,
|
|
40548
|
+
method: event.method,
|
|
40549
|
+
stripped_count: event.stripped_count,
|
|
40550
|
+
removed: event.removed,
|
|
40551
|
+
required_preserved: event.required_preserved
|
|
40552
|
+
}
|
|
40553
|
+
);
|
|
40554
|
+
});
|
|
39620
40555
|
this.config = buildDefaultConfig();
|
|
39621
40556
|
}
|
|
39622
40557
|
/**
|
|
@@ -42660,6 +43595,19 @@ ${err.message}
|
|
|
42660
43595
|
identityId: aggregatorIdentityId
|
|
42661
43596
|
});
|
|
42662
43597
|
anomalyDispatcher.start();
|
|
43598
|
+
const handoffLog = new HandoffLog({
|
|
43599
|
+
auditLog,
|
|
43600
|
+
fortressId: fortressIdForAggregator
|
|
43601
|
+
});
|
|
43602
|
+
const handoffEventBridge = new HandoffEventBridge();
|
|
43603
|
+
if (dashboard) {
|
|
43604
|
+
dashboard.setHandoffLog({
|
|
43605
|
+
handoffLog,
|
|
43606
|
+
eventBridge: handoffEventBridge,
|
|
43607
|
+
auditLog,
|
|
43608
|
+
operatorId: aggregatorIdentityId
|
|
43609
|
+
});
|
|
43610
|
+
}
|
|
42663
43611
|
const policyTools = createPrincipalPolicyTools(policy, baseline, auditLog);
|
|
42664
43612
|
const { tools: sanctuaryMetaTools } = createSanctuaryTools({
|
|
42665
43613
|
config,
|
|
@@ -42857,6 +43805,8 @@ var init_src = __esm({
|
|
|
42857
43805
|
init_sentinel_registry();
|
|
42858
43806
|
init_sentinel_dispatcher();
|
|
42859
43807
|
init_anomaly_pipeline();
|
|
43808
|
+
init_handoff_log();
|
|
43809
|
+
init_handoff_routes();
|
|
42860
43810
|
init_sentinels();
|
|
42861
43811
|
init_subscription_store();
|
|
42862
43812
|
init_tools4();
|
|
@@ -44957,32 +45907,32 @@ endstream`;
|
|
|
44957
45907
|
const offsets = new Array(totalObjects + 1).fill(0);
|
|
44958
45908
|
const chunks = [];
|
|
44959
45909
|
let bytePos = 0;
|
|
44960
|
-
const
|
|
45910
|
+
const write4 = (s) => {
|
|
44961
45911
|
const buf = Buffer.from(s, "latin1");
|
|
44962
45912
|
chunks.push(buf);
|
|
44963
45913
|
bytePos += buf.length;
|
|
44964
45914
|
};
|
|
44965
|
-
|
|
45915
|
+
write4("%PDF-1.4\n%\xE2\xE3\xCF\xD3\n");
|
|
44966
45916
|
for (let i = 1; i <= totalObjects; i++) {
|
|
44967
45917
|
offsets[i] = bytePos;
|
|
44968
|
-
|
|
45918
|
+
write4(`${i} 0 obj
|
|
44969
45919
|
${objectBodies[i]}
|
|
44970
45920
|
endobj
|
|
44971
45921
|
`);
|
|
44972
45922
|
}
|
|
44973
45923
|
const xrefPos = bytePos;
|
|
44974
|
-
|
|
45924
|
+
write4(`xref
|
|
44975
45925
|
0 ${totalObjects + 1}
|
|
44976
45926
|
`);
|
|
44977
|
-
|
|
45927
|
+
write4("0000000000 65535 f \n");
|
|
44978
45928
|
for (let i = 1; i <= totalObjects; i++) {
|
|
44979
|
-
|
|
45929
|
+
write4(`${offsets[i].toString().padStart(10, "0")} 00000 n
|
|
44980
45930
|
`);
|
|
44981
45931
|
}
|
|
44982
|
-
|
|
45932
|
+
write4(`trailer
|
|
44983
45933
|
<< /Size ${totalObjects + 1} /Root 1 0 R >>
|
|
44984
45934
|
`);
|
|
44985
|
-
|
|
45935
|
+
write4(`startxref
|
|
44986
45936
|
${xrefPos}
|
|
44987
45937
|
%%EOF
|
|
44988
45938
|
`);
|
|
@@ -48253,6 +49203,365 @@ var init_sentinel2 = __esm({
|
|
|
48253
49203
|
init_sentinels();
|
|
48254
49204
|
}
|
|
48255
49205
|
});
|
|
49206
|
+
async function issueDidWeb(opts) {
|
|
49207
|
+
if (!opts.authority_host || !HOST_RE.test(opts.authority_host)) {
|
|
49208
|
+
throw new Error(
|
|
49209
|
+
`did-web: authority_host '${opts.authority_host}' is not a valid DNS host`
|
|
49210
|
+
);
|
|
49211
|
+
}
|
|
49212
|
+
if (!FORTRESS_LABEL_RE.test(opts.fortress_id)) {
|
|
49213
|
+
throw new Error(
|
|
49214
|
+
`did-web: fortress_id '${opts.fortress_id}' is not a valid label`
|
|
49215
|
+
);
|
|
49216
|
+
}
|
|
49217
|
+
if (opts.agent_label !== void 0 && !AGENT_LABEL_RE.test(opts.agent_label)) {
|
|
49218
|
+
throw new Error(
|
|
49219
|
+
`did-web: agent_label '${opts.agent_label}' is not a valid label`
|
|
49220
|
+
);
|
|
49221
|
+
}
|
|
49222
|
+
if (opts.public_key.length !== 32) {
|
|
49223
|
+
throw new Error(
|
|
49224
|
+
`did-web: public_key must be exactly 32 bytes (Ed25519), got ${opts.public_key.length}`
|
|
49225
|
+
);
|
|
49226
|
+
}
|
|
49227
|
+
const did = buildDid(opts);
|
|
49228
|
+
const verificationMethodId = `${did}#key-1`;
|
|
49229
|
+
const verificationMethod = {
|
|
49230
|
+
id: verificationMethodId,
|
|
49231
|
+
type: "JsonWebKey2020",
|
|
49232
|
+
controller: did,
|
|
49233
|
+
publicKeyJwk: {
|
|
49234
|
+
kty: "OKP",
|
|
49235
|
+
crv: "Ed25519",
|
|
49236
|
+
x: toBase64url(opts.public_key)
|
|
49237
|
+
}
|
|
49238
|
+
};
|
|
49239
|
+
const didDocument = {
|
|
49240
|
+
"@context": [...DID_CONTEXT],
|
|
49241
|
+
id: did,
|
|
49242
|
+
verificationMethod: [verificationMethod],
|
|
49243
|
+
authentication: [verificationMethodId],
|
|
49244
|
+
assertionMethod: [verificationMethodId]
|
|
49245
|
+
};
|
|
49246
|
+
const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
49247
|
+
return {
|
|
49248
|
+
did,
|
|
49249
|
+
did_document: didDocument,
|
|
49250
|
+
public_key: opts.public_key,
|
|
49251
|
+
created_at: now.toISOString(),
|
|
49252
|
+
authority_host: opts.authority_host,
|
|
49253
|
+
fortress_id: opts.fortress_id,
|
|
49254
|
+
...opts.agent_label !== void 0 ? { agent_label: opts.agent_label } : {}
|
|
49255
|
+
};
|
|
49256
|
+
}
|
|
49257
|
+
function publishDidWebDocument(identifier, opts = {}) {
|
|
49258
|
+
const path = opts.publish_path ?? canonicalPublishPath(identifier);
|
|
49259
|
+
const artifact = canonicalSerializeDidDocument(identifier.did_document);
|
|
49260
|
+
const digest = sha256.sha256(stringToBytes(artifact));
|
|
49261
|
+
const url = `https://${identifier.authority_host}${path}`;
|
|
49262
|
+
return {
|
|
49263
|
+
url,
|
|
49264
|
+
publish_path: path,
|
|
49265
|
+
artifact,
|
|
49266
|
+
sha256: hashToString(digest)
|
|
49267
|
+
};
|
|
49268
|
+
}
|
|
49269
|
+
function buildDid(opts) {
|
|
49270
|
+
if (opts.agent_label === void 0) {
|
|
49271
|
+
return `did:web:${opts.authority_host}`;
|
|
49272
|
+
}
|
|
49273
|
+
return `did:web:${opts.authority_host}:fortress:${opts.fortress_id}:agent:${opts.agent_label}`;
|
|
49274
|
+
}
|
|
49275
|
+
function canonicalPublishPath(identifier) {
|
|
49276
|
+
if (identifier.agent_label === void 0) {
|
|
49277
|
+
return "/.well-known/did.json";
|
|
49278
|
+
}
|
|
49279
|
+
return `/fortress/${identifier.fortress_id}/agent/${identifier.agent_label}/did.json`;
|
|
49280
|
+
}
|
|
49281
|
+
function canonicalSerializeDidDocument(doc) {
|
|
49282
|
+
return JSON.stringify(
|
|
49283
|
+
{
|
|
49284
|
+
"@context": doc["@context"],
|
|
49285
|
+
id: doc.id,
|
|
49286
|
+
verificationMethod: doc.verificationMethod,
|
|
49287
|
+
authentication: doc.authentication,
|
|
49288
|
+
assertionMethod: doc.assertionMethod
|
|
49289
|
+
},
|
|
49290
|
+
null,
|
|
49291
|
+
2
|
|
49292
|
+
);
|
|
49293
|
+
}
|
|
49294
|
+
var DID_CONTEXT, HOST_RE, FORTRESS_LABEL_RE, AGENT_LABEL_RE;
|
|
49295
|
+
var init_did_web = __esm({
|
|
49296
|
+
"src/recognition/did-web.ts"() {
|
|
49297
|
+
init_encoding();
|
|
49298
|
+
init_hashing();
|
|
49299
|
+
DID_CONTEXT = [
|
|
49300
|
+
"https://www.w3.org/ns/did/v1",
|
|
49301
|
+
"https://w3id.org/security/suites/jws-2020/v1"
|
|
49302
|
+
];
|
|
49303
|
+
HOST_RE = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/i;
|
|
49304
|
+
FORTRESS_LABEL_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
49305
|
+
AGENT_LABEL_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
49306
|
+
}
|
|
49307
|
+
});
|
|
49308
|
+
|
|
49309
|
+
// src/cli/did-web.ts
|
|
49310
|
+
var did_web_exports = {};
|
|
49311
|
+
__export(did_web_exports, {
|
|
49312
|
+
runDidWebCommand: () => runDidWebCommand
|
|
49313
|
+
});
|
|
49314
|
+
function write3(stream, text) {
|
|
49315
|
+
stream.write(text);
|
|
49316
|
+
}
|
|
49317
|
+
function flagValue3(argv, name) {
|
|
49318
|
+
const i = argv.indexOf(name);
|
|
49319
|
+
if (i === -1) return void 0;
|
|
49320
|
+
return argv[i + 1];
|
|
49321
|
+
}
|
|
49322
|
+
function hasFlag3(argv, name) {
|
|
49323
|
+
return argv.includes(name);
|
|
49324
|
+
}
|
|
49325
|
+
function printUsage7(out) {
|
|
49326
|
+
write3(
|
|
49327
|
+
out,
|
|
49328
|
+
`Usage: sanctuary did-web <command> [options]
|
|
49329
|
+
|
|
49330
|
+
Commands:
|
|
49331
|
+
issue --authority-host <host> [--agent-label <label>] [--json]
|
|
49332
|
+
Generate a did:web identifier bound to the operator's
|
|
49333
|
+
fortress Ed25519 public key. Writes the DID Document
|
|
49334
|
+
artifact to <storage>/recognition/did-web.json and
|
|
49335
|
+
prints publication instructions for the operator's
|
|
49336
|
+
HTTPS server.
|
|
49337
|
+
|
|
49338
|
+
show [--json] Display the previously issued did:web identifier.
|
|
49339
|
+
Exits non-zero if none issued.
|
|
49340
|
+
|
|
49341
|
+
Options:
|
|
49342
|
+
--authority-host <host> HTTPS host the operator controls and will
|
|
49343
|
+
serve /.well-known/did.json from.
|
|
49344
|
+
--agent-label <label> Optional agent-scoped identifier (label-safe;
|
|
49345
|
+
alphanumeric + dash + underscore, 1-64 chars).
|
|
49346
|
+
--fortress <path> Override the storage path.
|
|
49347
|
+
--passphrase <val> Passphrase for master-key derivation.
|
|
49348
|
+
--json Output as JSON.
|
|
49349
|
+
--help, -h Show this help.
|
|
49350
|
+
|
|
49351
|
+
Castle-walking note: did:web resolution is outbound HTTPS by design.
|
|
49352
|
+
This CLI never opens an outbound socket. The opt-in surface is your
|
|
49353
|
+
choice to run "did-web issue" with --authority-host; the resulting
|
|
49354
|
+
artifact is yours to publish on your own infrastructure. Sanctuary
|
|
49355
|
+
does not phone home.
|
|
49356
|
+
`
|
|
49357
|
+
);
|
|
49358
|
+
}
|
|
49359
|
+
async function runDidWebCommand(args) {
|
|
49360
|
+
const argv = args.argv;
|
|
49361
|
+
const out = args.out ?? process.stdout;
|
|
49362
|
+
const err = args.err ?? process.stderr;
|
|
49363
|
+
const env = args.env ?? process.env;
|
|
49364
|
+
if (argv.length === 0 || hasFlag3(argv, "--help") || hasFlag3(argv, "-h")) {
|
|
49365
|
+
printUsage7(out);
|
|
49366
|
+
return 0;
|
|
49367
|
+
}
|
|
49368
|
+
const command = argv[0];
|
|
49369
|
+
if (command === "issue") {
|
|
49370
|
+
return await cmdIssue(argv.slice(1), out, err, env);
|
|
49371
|
+
}
|
|
49372
|
+
if (command === "show") {
|
|
49373
|
+
return await cmdShow3(argv.slice(1), out, err);
|
|
49374
|
+
}
|
|
49375
|
+
write3(err, `Unknown did-web command: ${command}
|
|
49376
|
+
`);
|
|
49377
|
+
write3(err, `Run "sanctuary did-web --help" for usage.
|
|
49378
|
+
`);
|
|
49379
|
+
return 2;
|
|
49380
|
+
}
|
|
49381
|
+
async function loadFortressIdentity(argv, env, err) {
|
|
49382
|
+
const fortressFlag = flagValue3(argv, "--fortress");
|
|
49383
|
+
if (fortressFlag) {
|
|
49384
|
+
process.env.SANCTUARY_STORAGE_PATH = fortressFlag;
|
|
49385
|
+
}
|
|
49386
|
+
const passphrase = flagValue3(argv, "--passphrase") ?? env.SANCTUARY_PASSPHRASE;
|
|
49387
|
+
const recoveryKey = env.SANCTUARY_RECOVERY_KEY;
|
|
49388
|
+
if (!passphrase && !recoveryKey) {
|
|
49389
|
+
write3(
|
|
49390
|
+
err,
|
|
49391
|
+
"Error: sanctuary did-web requires SANCTUARY_PASSPHRASE, --passphrase, or SANCTUARY_RECOVERY_KEY.\n"
|
|
49392
|
+
);
|
|
49393
|
+
return null;
|
|
49394
|
+
}
|
|
49395
|
+
const config = await loadConfig();
|
|
49396
|
+
await promises.mkdir(config.storage_path, { recursive: true, mode: 448 });
|
|
49397
|
+
const stateStoragePath = path.join(config.storage_path, "state");
|
|
49398
|
+
const storage = new FilesystemStorage(stateStoragePath);
|
|
49399
|
+
let masterKey;
|
|
49400
|
+
if (passphrase) {
|
|
49401
|
+
let existingParams;
|
|
49402
|
+
const raw = await storage.read("_meta", "key-params");
|
|
49403
|
+
if (raw) {
|
|
49404
|
+
existingParams = JSON.parse(bytesToString(raw));
|
|
49405
|
+
}
|
|
49406
|
+
const derivation = await deriveMasterKey(passphrase, existingParams);
|
|
49407
|
+
masterKey = derivation.key;
|
|
49408
|
+
} else if (recoveryKey) {
|
|
49409
|
+
masterKey = fromBase64url(recoveryKey);
|
|
49410
|
+
} else {
|
|
49411
|
+
return null;
|
|
49412
|
+
}
|
|
49413
|
+
const identityManager = new IdentityManager(storage, masterKey);
|
|
49414
|
+
const loadResult = await identityManager.load();
|
|
49415
|
+
if (loadResult.loaded === 0) {
|
|
49416
|
+
write3(
|
|
49417
|
+
err,
|
|
49418
|
+
loadResult.total > 0 ? "Error: identity files found but none could be decrypted. Wrong passphrase?\n" : "Error: no identities on this fortress yet. Run sanctuary wrap first.\n"
|
|
49419
|
+
);
|
|
49420
|
+
return null;
|
|
49421
|
+
}
|
|
49422
|
+
const primary = identityManager.getDefault();
|
|
49423
|
+
if (!primary) {
|
|
49424
|
+
write3(err, "Error: no primary identity on this fortress yet. Run sanctuary wrap first.\n");
|
|
49425
|
+
return null;
|
|
49426
|
+
}
|
|
49427
|
+
return {
|
|
49428
|
+
publicKey: fromBase64url(primary.public_key),
|
|
49429
|
+
identityId: primary.identity_id,
|
|
49430
|
+
storagePath: config.storage_path
|
|
49431
|
+
};
|
|
49432
|
+
}
|
|
49433
|
+
async function cmdIssue(argv, out, err, env) {
|
|
49434
|
+
const authorityHost = flagValue3(argv, "--authority-host");
|
|
49435
|
+
const agentLabel = flagValue3(argv, "--agent-label");
|
|
49436
|
+
const json = hasFlag3(argv, "--json");
|
|
49437
|
+
if (!authorityHost) {
|
|
49438
|
+
write3(err, "Error: --authority-host is required.\n");
|
|
49439
|
+
write3(err, "Example: sanctuary did-web issue --authority-host alice.example.com\n");
|
|
49440
|
+
return 1;
|
|
49441
|
+
}
|
|
49442
|
+
const snapshot = await loadFortressIdentity(argv, env, err);
|
|
49443
|
+
if (!snapshot) return 1;
|
|
49444
|
+
let identifier;
|
|
49445
|
+
try {
|
|
49446
|
+
identifier = await issueDidWeb({
|
|
49447
|
+
fortress_id: snapshot.identityId,
|
|
49448
|
+
authority_host: authorityHost,
|
|
49449
|
+
public_key: snapshot.publicKey,
|
|
49450
|
+
...agentLabel !== void 0 ? { agent_label: agentLabel } : {}
|
|
49451
|
+
});
|
|
49452
|
+
} catch (e) {
|
|
49453
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
49454
|
+
write3(err, `Error: ${message}
|
|
49455
|
+
`);
|
|
49456
|
+
return 1;
|
|
49457
|
+
}
|
|
49458
|
+
const artifact = publishDidWebDocument(identifier);
|
|
49459
|
+
const persistDir = path.join(snapshot.storagePath, "recognition");
|
|
49460
|
+
await promises.mkdir(persistDir, { recursive: true, mode: 448 });
|
|
49461
|
+
const persistPath = path.join(persistDir, "did-web.json");
|
|
49462
|
+
const record = {
|
|
49463
|
+
version: 1,
|
|
49464
|
+
identifier: {
|
|
49465
|
+
did: identifier.did,
|
|
49466
|
+
created_at: identifier.created_at,
|
|
49467
|
+
authority_host: identifier.authority_host,
|
|
49468
|
+
fortress_id: identifier.fortress_id,
|
|
49469
|
+
...identifier.agent_label !== void 0 ? { agent_label: identifier.agent_label } : {},
|
|
49470
|
+
did_document: identifier.did_document
|
|
49471
|
+
},
|
|
49472
|
+
artifact: {
|
|
49473
|
+
url: artifact.url,
|
|
49474
|
+
publish_path: artifact.publish_path,
|
|
49475
|
+
sha256: artifact.sha256
|
|
49476
|
+
}
|
|
49477
|
+
};
|
|
49478
|
+
await promises.writeFile(persistPath, JSON.stringify(record, null, 2), {
|
|
49479
|
+
mode: 384
|
|
49480
|
+
});
|
|
49481
|
+
if (json) {
|
|
49482
|
+
write3(out, JSON.stringify(record, null, 2) + "\n");
|
|
49483
|
+
return 0;
|
|
49484
|
+
}
|
|
49485
|
+
write3(out, `did:web identifier issued.
|
|
49486
|
+
`);
|
|
49487
|
+
write3(out, ` DID: ${identifier.did}
|
|
49488
|
+
`);
|
|
49489
|
+
write3(out, ` Authority host: ${identifier.authority_host}
|
|
49490
|
+
`);
|
|
49491
|
+
write3(out, ` Created at: ${identifier.created_at}
|
|
49492
|
+
`);
|
|
49493
|
+
write3(out, ` Persisted: ${persistPath}
|
|
49494
|
+
`);
|
|
49495
|
+
write3(out, `
|
|
49496
|
+
Next step: publish the DID Document to your HTTPS host.
|
|
49497
|
+
`);
|
|
49498
|
+
write3(out, ` Target URL: ${artifact.url}
|
|
49499
|
+
`);
|
|
49500
|
+
write3(out, ` SHA-256: ${artifact.sha256}
|
|
49501
|
+
`);
|
|
49502
|
+
write3(out, ` Artifact: ${path.join(persistDir, "did.json")}
|
|
49503
|
+
`);
|
|
49504
|
+
const artifactPath = path.join(persistDir, "did.json");
|
|
49505
|
+
await promises.writeFile(artifactPath, artifact.artifact, { mode: 420 });
|
|
49506
|
+
write3(out, `
|
|
49507
|
+
Castle-walking note: this CLI never opens an outbound socket.
|
|
49508
|
+
`);
|
|
49509
|
+
write3(out, `Publishing the DID Document is your operation; serve the artifact
|
|
49510
|
+
`);
|
|
49511
|
+
write3(out, `at the URL above from infrastructure you control.
|
|
49512
|
+
`);
|
|
49513
|
+
return 0;
|
|
49514
|
+
}
|
|
49515
|
+
async function cmdShow3(argv, out, err, _env) {
|
|
49516
|
+
const json = hasFlag3(argv, "--json");
|
|
49517
|
+
const fortressFlag = flagValue3(argv, "--fortress");
|
|
49518
|
+
if (fortressFlag) {
|
|
49519
|
+
process.env.SANCTUARY_STORAGE_PATH = fortressFlag;
|
|
49520
|
+
}
|
|
49521
|
+
const config = await loadConfig();
|
|
49522
|
+
const persistPath = path.join(config.storage_path, "recognition", "did-web.json");
|
|
49523
|
+
let bytes;
|
|
49524
|
+
try {
|
|
49525
|
+
bytes = await promises.readFile(persistPath);
|
|
49526
|
+
} catch {
|
|
49527
|
+
write3(
|
|
49528
|
+
err,
|
|
49529
|
+
`No did:web identifier configured on this fortress.
|
|
49530
|
+
Run "sanctuary did-web issue --authority-host <host>" to issue one.
|
|
49531
|
+
`
|
|
49532
|
+
);
|
|
49533
|
+
return 1;
|
|
49534
|
+
}
|
|
49535
|
+
if (json) {
|
|
49536
|
+
write3(out, bytes.toString("utf-8"));
|
|
49537
|
+
if (!bytes.toString("utf-8").endsWith("\n")) write3(out, "\n");
|
|
49538
|
+
return 0;
|
|
49539
|
+
}
|
|
49540
|
+
const parsed = JSON.parse(bytes.toString("utf-8"));
|
|
49541
|
+
write3(out, `did:web identifier on this fortress:
|
|
49542
|
+
`);
|
|
49543
|
+
write3(out, ` DID: ${parsed.identifier.did}
|
|
49544
|
+
`);
|
|
49545
|
+
write3(out, ` Authority host: ${parsed.identifier.authority_host}
|
|
49546
|
+
`);
|
|
49547
|
+
write3(out, ` Created at: ${parsed.identifier.created_at}
|
|
49548
|
+
`);
|
|
49549
|
+
write3(out, ` Publish URL: ${parsed.artifact.url}
|
|
49550
|
+
`);
|
|
49551
|
+
write3(out, ` SHA-256: ${parsed.artifact.sha256}
|
|
49552
|
+
`);
|
|
49553
|
+
return 0;
|
|
49554
|
+
}
|
|
49555
|
+
var init_did_web2 = __esm({
|
|
49556
|
+
"src/cli/did-web.ts"() {
|
|
49557
|
+
init_filesystem();
|
|
49558
|
+
init_tools();
|
|
49559
|
+
init_key_derivation();
|
|
49560
|
+
init_encoding();
|
|
49561
|
+
init_config();
|
|
49562
|
+
init_did_web();
|
|
49563
|
+
}
|
|
49564
|
+
});
|
|
48256
49565
|
|
|
48257
49566
|
// src/mcp/broker-server.ts
|
|
48258
49567
|
var broker_server_exports = {};
|
|
@@ -49118,6 +50427,11 @@ async function main() {
|
|
|
49118
50427
|
const code = await runSentinelCommand2({ argv: args.slice(1) });
|
|
49119
50428
|
process.exit(code);
|
|
49120
50429
|
}
|
|
50430
|
+
if (args[0] === "did-web") {
|
|
50431
|
+
const { runDidWebCommand: runDidWebCommand2 } = await Promise.resolve().then(() => (init_did_web2(), did_web_exports));
|
|
50432
|
+
const code = await runDidWebCommand2({ argv: args.slice(1) });
|
|
50433
|
+
process.exit(code);
|
|
50434
|
+
}
|
|
49121
50435
|
if (args[0] === "broker-server") {
|
|
49122
50436
|
const { openBroker: openBroker2 } = await Promise.resolve().then(() => (init_open(), open_exports));
|
|
49123
50437
|
const { createBrokerMcpServer: createBrokerMcpServer2 } = await Promise.resolve().then(() => (init_broker_server(), broker_server_exports));
|