@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.js
CHANGED
|
@@ -17473,6 +17473,616 @@ var init_sentinel_routes = __esm({
|
|
|
17473
17473
|
FINDINGS_MAX_LIMIT = 500;
|
|
17474
17474
|
}
|
|
17475
17475
|
});
|
|
17476
|
+
function makeEntryId(auditEventId) {
|
|
17477
|
+
return createHash("sha256").update(auditEventId).digest("hex").slice(0, 32);
|
|
17478
|
+
}
|
|
17479
|
+
function optString(details, key) {
|
|
17480
|
+
if (!details) return null;
|
|
17481
|
+
const value = details[key];
|
|
17482
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
17483
|
+
return value;
|
|
17484
|
+
}
|
|
17485
|
+
function auditEventIdFallback(audit) {
|
|
17486
|
+
return `${audit.timestamp}:${audit.operation}`;
|
|
17487
|
+
}
|
|
17488
|
+
function localHandoffSummary(details, sender, recipient) {
|
|
17489
|
+
const taskScope = optString(details, "task_scope");
|
|
17490
|
+
const reasonClass = optString(details, "reason_class");
|
|
17491
|
+
if (taskScope) {
|
|
17492
|
+
return `${sender} -> ${recipient} handoff: ${taskScope}`;
|
|
17493
|
+
}
|
|
17494
|
+
if (reasonClass) {
|
|
17495
|
+
return `${sender} -> ${recipient} handoff (${reasonClass})`;
|
|
17496
|
+
}
|
|
17497
|
+
return `${sender} -> ${recipient} handoff`;
|
|
17498
|
+
}
|
|
17499
|
+
function crossHarnessSummary(details, sender) {
|
|
17500
|
+
const policyRule = optString(details, "policy_rule_id");
|
|
17501
|
+
if (policyRule) {
|
|
17502
|
+
return `${sender} -> operator approval (${policyRule})`;
|
|
17503
|
+
}
|
|
17504
|
+
return `${sender} -> operator approval`;
|
|
17505
|
+
}
|
|
17506
|
+
var HANDOFF_LOG_OBSERVED_OPS, OBSERVED_OP_LIST, OPERATOR_PSEUDO_AGENT, DEFAULT_LIMIT, MAX_LIMIT, AUDIT_QUERY_LIMIT, HandoffLog, COORDINATION_VIEW_AUDIT_OPS;
|
|
17507
|
+
var init_handoff_log = __esm({
|
|
17508
|
+
"src/coordination/handoff-log.ts"() {
|
|
17509
|
+
HANDOFF_LOG_OBSERVED_OPS = {
|
|
17510
|
+
/** Tau-3 in-process coordination handoff. */
|
|
17511
|
+
LOCAL_HANDOFF: "v1.1_local_handoff",
|
|
17512
|
+
/** Upsilon-1 cross-harness approval (wrapped-agent -> operator). */
|
|
17513
|
+
CROSS_HARNESS_APPROVAL: "cross_harness_approval_aggregated"
|
|
17514
|
+
};
|
|
17515
|
+
OBSERVED_OP_LIST = [
|
|
17516
|
+
HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF,
|
|
17517
|
+
HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL
|
|
17518
|
+
];
|
|
17519
|
+
OPERATOR_PSEUDO_AGENT = "operator";
|
|
17520
|
+
DEFAULT_LIMIT = 50;
|
|
17521
|
+
MAX_LIMIT = 500;
|
|
17522
|
+
AUDIT_QUERY_LIMIT = 1e4;
|
|
17523
|
+
HandoffLog = class {
|
|
17524
|
+
auditLog;
|
|
17525
|
+
fortressId;
|
|
17526
|
+
constructor(opts) {
|
|
17527
|
+
this.auditLog = opts.auditLog;
|
|
17528
|
+
this.fortressId = opts.fortressId;
|
|
17529
|
+
}
|
|
17530
|
+
/** Stable fortress id this HandoffLog reads. */
|
|
17531
|
+
getFortressId() {
|
|
17532
|
+
return this.fortressId;
|
|
17533
|
+
}
|
|
17534
|
+
/**
|
|
17535
|
+
* Query handoffs in chronological-newest-first order. Filters
|
|
17536
|
+
* applied after normalization so the per-event-class shape
|
|
17537
|
+
* differences (sender field name, recipient inference) are handled
|
|
17538
|
+
* once.
|
|
17539
|
+
*/
|
|
17540
|
+
async query(opts) {
|
|
17541
|
+
const limit = Math.min(opts.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
|
|
17542
|
+
const queryResult = await this.auditLog.query({
|
|
17543
|
+
...opts.since !== void 0 ? { since: opts.since } : {},
|
|
17544
|
+
layer: "l2",
|
|
17545
|
+
limit: AUDIT_QUERY_LIMIT
|
|
17546
|
+
});
|
|
17547
|
+
const normalized = [];
|
|
17548
|
+
for (const entry of queryResult.entries) {
|
|
17549
|
+
if (!OBSERVED_OP_LIST.includes(entry.operation)) continue;
|
|
17550
|
+
const handoff = this.normalize(entry);
|
|
17551
|
+
if (!handoff) continue;
|
|
17552
|
+
if (opts.until && handoff.observed_at > opts.until) continue;
|
|
17553
|
+
if (opts.since && handoff.observed_at < opts.since) continue;
|
|
17554
|
+
if (opts.agent_id) {
|
|
17555
|
+
if (handoff.source_agent_id !== opts.agent_id && handoff.target_agent_id !== opts.agent_id) {
|
|
17556
|
+
continue;
|
|
17557
|
+
}
|
|
17558
|
+
}
|
|
17559
|
+
normalized.push(handoff);
|
|
17560
|
+
}
|
|
17561
|
+
normalized.sort((a, b) => a.observed_at < b.observed_at ? 1 : -1);
|
|
17562
|
+
return normalized.slice(0, limit);
|
|
17563
|
+
}
|
|
17564
|
+
/**
|
|
17565
|
+
* Look up a single entry by id. Returns the normalized entry +
|
|
17566
|
+
* the source audit payload for operator-facing detail rendering.
|
|
17567
|
+
* Returns null when no audit entry maps to the given id.
|
|
17568
|
+
*/
|
|
17569
|
+
async getEntry(entryId) {
|
|
17570
|
+
const queryResult = await this.auditLog.query({
|
|
17571
|
+
layer: "l2",
|
|
17572
|
+
limit: AUDIT_QUERY_LIMIT
|
|
17573
|
+
});
|
|
17574
|
+
for (const audit of queryResult.entries) {
|
|
17575
|
+
if (!OBSERVED_OP_LIST.includes(audit.operation)) continue;
|
|
17576
|
+
const handoff = this.normalize(audit);
|
|
17577
|
+
if (!handoff) continue;
|
|
17578
|
+
if (handoff.entry_id === entryId) {
|
|
17579
|
+
return { entry: handoff, source_audit_entry: audit };
|
|
17580
|
+
}
|
|
17581
|
+
}
|
|
17582
|
+
return null;
|
|
17583
|
+
}
|
|
17584
|
+
normalize(audit) {
|
|
17585
|
+
const details = audit.details;
|
|
17586
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.LOCAL_HANDOFF) {
|
|
17587
|
+
const sender = optString(details, "sender_agent_id");
|
|
17588
|
+
const recipient = optString(details, "recipient_agent_id");
|
|
17589
|
+
if (!sender || !recipient || sender === recipient) return null;
|
|
17590
|
+
const auditEventId = optString(details, "event_id") ?? auditEventIdFallback(audit);
|
|
17591
|
+
return {
|
|
17592
|
+
entry_id: makeEntryId(auditEventId),
|
|
17593
|
+
audit_event_id: auditEventId,
|
|
17594
|
+
source_agent_id: sender,
|
|
17595
|
+
target_agent_id: recipient,
|
|
17596
|
+
observed_at: audit.timestamp,
|
|
17597
|
+
event_class: audit.operation,
|
|
17598
|
+
context_transfer_summary: localHandoffSummary(details, sender, recipient),
|
|
17599
|
+
workflow_link: null
|
|
17600
|
+
};
|
|
17601
|
+
}
|
|
17602
|
+
if (audit.operation === HANDOFF_LOG_OBSERVED_OPS.CROSS_HARNESS_APPROVAL) {
|
|
17603
|
+
const sender = optString(details, "source_harness") ?? optString(details, "source_agent_id");
|
|
17604
|
+
if (!sender) return null;
|
|
17605
|
+
const auditEventId = optString(details, "aggregator_id") ?? auditEventIdFallback(audit);
|
|
17606
|
+
return {
|
|
17607
|
+
entry_id: makeEntryId(auditEventId),
|
|
17608
|
+
audit_event_id: auditEventId,
|
|
17609
|
+
source_agent_id: sender,
|
|
17610
|
+
target_agent_id: OPERATOR_PSEUDO_AGENT,
|
|
17611
|
+
observed_at: audit.timestamp,
|
|
17612
|
+
event_class: audit.operation,
|
|
17613
|
+
context_transfer_summary: crossHarnessSummary(details, sender),
|
|
17614
|
+
workflow_link: null
|
|
17615
|
+
};
|
|
17616
|
+
}
|
|
17617
|
+
return null;
|
|
17618
|
+
}
|
|
17619
|
+
};
|
|
17620
|
+
COORDINATION_VIEW_AUDIT_OPS = {
|
|
17621
|
+
VIEW_OPENED: "operator_coordination_view_opened",
|
|
17622
|
+
ENTRY_DRILLED: "operator_handoff_entry_drilled"
|
|
17623
|
+
};
|
|
17624
|
+
}
|
|
17625
|
+
});
|
|
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
|
+
|
|
17902
|
+
// src/coordination/handoff-routes.ts
|
|
17903
|
+
function writeJSON6(res, status, payload) {
|
|
17904
|
+
res.writeHead(status, {
|
|
17905
|
+
"Content-Type": "application/json",
|
|
17906
|
+
"Cache-Control": "no-store"
|
|
17907
|
+
});
|
|
17908
|
+
res.end(JSON.stringify(payload));
|
|
17909
|
+
}
|
|
17910
|
+
function parseLimit4(raw, defaultValue, max) {
|
|
17911
|
+
if (raw === null || raw === "") return defaultValue;
|
|
17912
|
+
const parsed = Number.parseInt(raw, 10);
|
|
17913
|
+
if (Number.isNaN(parsed) || parsed < 0) return defaultValue;
|
|
17914
|
+
return Math.min(parsed, max);
|
|
17915
|
+
}
|
|
17916
|
+
function matchEntryRoute2(path) {
|
|
17917
|
+
const prefix = `${COORDINATION_HANDOFFS_PREFIX}/`;
|
|
17918
|
+
if (!path.startsWith(prefix)) return null;
|
|
17919
|
+
const rest = path.slice(prefix.length);
|
|
17920
|
+
if (rest.length === 0 || rest === "stream") return null;
|
|
17921
|
+
if (rest.includes("/")) return null;
|
|
17922
|
+
return { entryId: decodeURIComponent(rest) };
|
|
17923
|
+
}
|
|
17924
|
+
async function handleStream3(deps, res) {
|
|
17925
|
+
res.writeHead(200, {
|
|
17926
|
+
"Content-Type": "text/event-stream",
|
|
17927
|
+
"Cache-Control": "no-cache, no-transform",
|
|
17928
|
+
Connection: "keep-alive",
|
|
17929
|
+
"X-Accel-Buffering": "no"
|
|
17930
|
+
});
|
|
17931
|
+
const snapshot = await deps.handoffLog.query({ limit: 50 });
|
|
17932
|
+
res.write(
|
|
17933
|
+
`event: handoff_snapshot
|
|
17934
|
+
data: ${JSON.stringify({ entries: snapshot })}
|
|
17935
|
+
|
|
17936
|
+
`
|
|
17937
|
+
);
|
|
17938
|
+
const unsubscribe = deps.events.subscribe((entry) => {
|
|
17939
|
+
try {
|
|
17940
|
+
res.write(
|
|
17941
|
+
`event: handoff_added
|
|
17942
|
+
data: ${JSON.stringify(entry)}
|
|
17943
|
+
|
|
17944
|
+
`
|
|
17945
|
+
);
|
|
17946
|
+
} catch {
|
|
17947
|
+
}
|
|
17948
|
+
});
|
|
17949
|
+
const keepAlive = setInterval(() => {
|
|
17950
|
+
try {
|
|
17951
|
+
res.write(": keepalive\n\n");
|
|
17952
|
+
} catch {
|
|
17953
|
+
}
|
|
17954
|
+
}, 25e3);
|
|
17955
|
+
const cleanup = () => {
|
|
17956
|
+
clearInterval(keepAlive);
|
|
17957
|
+
unsubscribe();
|
|
17958
|
+
};
|
|
17959
|
+
res.on("close", cleanup);
|
|
17960
|
+
res.on("error", cleanup);
|
|
17961
|
+
}
|
|
17962
|
+
async function handleCoordinationRoute(deps, req, res) {
|
|
17963
|
+
const host = req.headers.host || "localhost";
|
|
17964
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
17965
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
17966
|
+
const path = url.pathname;
|
|
17967
|
+
if (path !== COORDINATION_API_PREFIX && !path.startsWith(`${COORDINATION_API_PREFIX}/`)) {
|
|
17968
|
+
return false;
|
|
17969
|
+
}
|
|
17970
|
+
const checkAuth = authMiddleware(deps.authConfig);
|
|
17971
|
+
if (!checkAuth(req, res, url)) return true;
|
|
17972
|
+
try {
|
|
17973
|
+
if (method === "GET" && path === `${COORDINATION_HANDOFFS_PREFIX}/stream`) {
|
|
17974
|
+
await handleStream3(deps, res);
|
|
17975
|
+
return true;
|
|
17976
|
+
}
|
|
17977
|
+
if (method === "GET" && path === COORDINATION_HANDOFFS_PREFIX) {
|
|
17978
|
+
const limit = parseLimit4(
|
|
17979
|
+
url.searchParams.get("limit"),
|
|
17980
|
+
COORDINATION_LIST_DEFAULT_LIMIT,
|
|
17981
|
+
COORDINATION_LIST_MAX_LIMIT
|
|
17982
|
+
);
|
|
17983
|
+
const since = url.searchParams.get("since") ?? void 0;
|
|
17984
|
+
const until = url.searchParams.get("until") ?? void 0;
|
|
17985
|
+
const agentId = url.searchParams.get("agent_id") ?? void 0;
|
|
17986
|
+
const entries = await deps.handoffLog.query({
|
|
17987
|
+
limit,
|
|
17988
|
+
...since !== void 0 ? { since } : {},
|
|
17989
|
+
...until !== void 0 ? { until } : {},
|
|
17990
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
17991
|
+
});
|
|
17992
|
+
deps.auditLog.append(
|
|
17993
|
+
"l2",
|
|
17994
|
+
COORDINATION_VIEW_AUDIT_OPS.VIEW_OPENED,
|
|
17995
|
+
deps.operatorId,
|
|
17996
|
+
{
|
|
17997
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
17998
|
+
result_count: entries.length,
|
|
17999
|
+
...since !== void 0 ? { since } : {},
|
|
18000
|
+
...until !== void 0 ? { until } : {},
|
|
18001
|
+
...agentId !== void 0 ? { agent_id: agentId } : {}
|
|
18002
|
+
}
|
|
18003
|
+
);
|
|
18004
|
+
writeJSON6(res, 200, { ok: true, data: { entries } });
|
|
18005
|
+
return true;
|
|
18006
|
+
}
|
|
18007
|
+
const entryMatch = matchEntryRoute2(path);
|
|
18008
|
+
if (method === "GET" && entryMatch) {
|
|
18009
|
+
const detail = await deps.handoffLog.getEntry(entryMatch.entryId);
|
|
18010
|
+
if (!detail) {
|
|
18011
|
+
writeJSON6(res, 404, { ok: false, error: "not_found" });
|
|
18012
|
+
return true;
|
|
18013
|
+
}
|
|
18014
|
+
deps.auditLog.append(
|
|
18015
|
+
"l2",
|
|
18016
|
+
COORDINATION_VIEW_AUDIT_OPS.ENTRY_DRILLED,
|
|
18017
|
+
deps.operatorId,
|
|
18018
|
+
{
|
|
18019
|
+
fortress_id: deps.handoffLog.getFortressId(),
|
|
18020
|
+
entry_id: detail.entry.entry_id,
|
|
18021
|
+
event_class: detail.entry.event_class,
|
|
18022
|
+
source_agent_id: detail.entry.source_agent_id,
|
|
18023
|
+
target_agent_id: detail.entry.target_agent_id
|
|
18024
|
+
}
|
|
18025
|
+
);
|
|
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 });
|
|
18049
|
+
return true;
|
|
18050
|
+
}
|
|
18051
|
+
writeJSON6(res, 404, { ok: false, error: "not_found", path });
|
|
18052
|
+
return true;
|
|
18053
|
+
} catch (err) {
|
|
18054
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18055
|
+
writeJSON6(res, 500, { ok: false, error: "internal", detail: msg });
|
|
18056
|
+
return true;
|
|
18057
|
+
}
|
|
18058
|
+
}
|
|
18059
|
+
var COORDINATION_API_PREFIX, COORDINATION_HANDOFFS_PREFIX, COORDINATION_LIST_DEFAULT_LIMIT, COORDINATION_LIST_MAX_LIMIT, HandoffEventBridge;
|
|
18060
|
+
var init_handoff_routes = __esm({
|
|
18061
|
+
"src/coordination/handoff-routes.ts"() {
|
|
18062
|
+
init_auth_middleware();
|
|
18063
|
+
init_handoff_log();
|
|
18064
|
+
init_context_transfer_extractor();
|
|
18065
|
+
COORDINATION_API_PREFIX = "/api/coordination";
|
|
18066
|
+
COORDINATION_HANDOFFS_PREFIX = "/api/coordination/handoffs";
|
|
18067
|
+
COORDINATION_LIST_DEFAULT_LIMIT = 50;
|
|
18068
|
+
COORDINATION_LIST_MAX_LIMIT = 500;
|
|
18069
|
+
HandoffEventBridge = class {
|
|
18070
|
+
listeners = /* @__PURE__ */ new Set();
|
|
18071
|
+
subscribe(listener) {
|
|
18072
|
+
this.listeners.add(listener);
|
|
18073
|
+
return () => this.listeners.delete(listener);
|
|
18074
|
+
}
|
|
18075
|
+
emit(entry) {
|
|
18076
|
+
for (const listener of this.listeners) {
|
|
18077
|
+
try {
|
|
18078
|
+
listener(entry);
|
|
18079
|
+
} catch {
|
|
18080
|
+
}
|
|
18081
|
+
}
|
|
18082
|
+
}
|
|
18083
|
+
};
|
|
18084
|
+
}
|
|
18085
|
+
});
|
|
17476
18086
|
function isDashboardViewRoute(method, path) {
|
|
17477
18087
|
if (method !== "GET") return false;
|
|
17478
18088
|
return path === "/" || path === "/dashboard" || path === "/v1.0" || path === "/fortress" || path === "/events";
|
|
@@ -17488,6 +18098,7 @@ var init_dashboard = __esm({
|
|
|
17488
18098
|
init_dispatch();
|
|
17489
18099
|
init_approval_aggregator_routes();
|
|
17490
18100
|
init_sentinel_routes();
|
|
18101
|
+
init_handoff_routes();
|
|
17491
18102
|
SESSION_TTL_REMOTE_MS = 5 * 60 * 1e3;
|
|
17492
18103
|
SESSION_TTL_LOCAL_MS = 24 * 60 * 60 * 1e3;
|
|
17493
18104
|
MAX_SESSIONS = 1e3;
|
|
@@ -17562,6 +18173,17 @@ var init_dashboard = __esm({
|
|
|
17562
18173
|
* dispatcher's audited paths.
|
|
17563
18174
|
*/
|
|
17564
18175
|
sentinelDispatcher = null;
|
|
18176
|
+
/**
|
|
18177
|
+
* v1.3 WP-V1.3-3 Omega-1 Coordination Handoff Visualization.
|
|
18178
|
+
* Mounted additively at `/api/coordination/*` when set. Read-only
|
|
18179
|
+
* against the audit log; the only writes are operator-action audit
|
|
18180
|
+
* events (operator_coordination_view_opened,
|
|
18181
|
+
* operator_handoff_entry_drilled).
|
|
18182
|
+
*/
|
|
18183
|
+
handoffLog = null;
|
|
18184
|
+
handoffEventBridge = null;
|
|
18185
|
+
handoffAuditLog = null;
|
|
18186
|
+
handoffOperatorId = null;
|
|
17565
18187
|
constructor(config) {
|
|
17566
18188
|
this.config = config;
|
|
17567
18189
|
this.authToken = config.auth_token;
|
|
@@ -17629,6 +18251,18 @@ var init_dashboard = __esm({
|
|
|
17629
18251
|
setSentinelDispatcher(dispatcher) {
|
|
17630
18252
|
this.sentinelDispatcher = dispatcher;
|
|
17631
18253
|
}
|
|
18254
|
+
/**
|
|
18255
|
+
* v1.3 WP-V1.3-3 Omega-1: bind the Coordination handoff log +
|
|
18256
|
+
* event bridge + audit log + operator id. Once set, requests to
|
|
18257
|
+
* `/api/coordination/*` route through `handleCoordinationRoute`.
|
|
18258
|
+
* Pass `null` for any field to detach.
|
|
18259
|
+
*/
|
|
18260
|
+
setHandoffLog(opts) {
|
|
18261
|
+
this.handoffLog = opts.handoffLog;
|
|
18262
|
+
this.handoffEventBridge = opts.eventBridge ?? null;
|
|
18263
|
+
this.handoffAuditLog = opts.auditLog ?? null;
|
|
18264
|
+
this.handoffOperatorId = opts.operatorId ?? null;
|
|
18265
|
+
}
|
|
17632
18266
|
/**
|
|
17633
18267
|
* v1.3 WP-V1.3-10 dispatch entry point. Called from `handleRequest`
|
|
17634
18268
|
* before the legacy approval route table. Returns true when served.
|
|
@@ -17667,6 +18301,30 @@ var init_dashboard = __esm({
|
|
|
17667
18301
|
res
|
|
17668
18302
|
);
|
|
17669
18303
|
}
|
|
18304
|
+
/**
|
|
18305
|
+
* v1.3 WP-V1.3-3 Omega-1 dispatch entry point. Routes
|
|
18306
|
+
* `/api/coordination/*` requests through the coordination router
|
|
18307
|
+
* when a HandoffLog has been bound. Returns true when served.
|
|
18308
|
+
*/
|
|
18309
|
+
async dispatchCoordination(req, res) {
|
|
18310
|
+
if (!this.handoffLog || !this.handoffEventBridge || !this.handoffAuditLog) {
|
|
18311
|
+
return false;
|
|
18312
|
+
}
|
|
18313
|
+
return handleCoordinationRoute(
|
|
18314
|
+
{
|
|
18315
|
+
authConfig: {
|
|
18316
|
+
loopbackAutoAuth: this._autoAuthLocalhost,
|
|
18317
|
+
...this.authToken !== void 0 ? { authToken: this.authToken } : {}
|
|
18318
|
+
},
|
|
18319
|
+
handoffLog: this.handoffLog,
|
|
18320
|
+
auditLog: this.handoffAuditLog,
|
|
18321
|
+
operatorId: this.handoffOperatorId ?? this.identityManager?.getPrimaryIdentityId() ?? "operator_dashboard",
|
|
18322
|
+
events: this.handoffEventBridge
|
|
18323
|
+
},
|
|
18324
|
+
req,
|
|
18325
|
+
res
|
|
18326
|
+
);
|
|
18327
|
+
}
|
|
17670
18328
|
/**
|
|
17671
18329
|
* v1.1 dispatch entry point. Called from `handleRequest` before the
|
|
17672
18330
|
* legacy route table. Returns true when the request was served by v1.1
|
|
@@ -18066,6 +18724,18 @@ var init_dashboard = __esm({
|
|
|
18066
18724
|
});
|
|
18067
18725
|
return;
|
|
18068
18726
|
}
|
|
18727
|
+
if (this.handoffLog && url.pathname.startsWith(COORDINATION_API_PREFIX)) {
|
|
18728
|
+
this.dispatchCoordination(req, res).then((handled) => {
|
|
18729
|
+
if (handled) return;
|
|
18730
|
+
this.handleLegacyRequest(req, res, url, method);
|
|
18731
|
+
}).catch(() => {
|
|
18732
|
+
if (!res.headersSent) {
|
|
18733
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
18734
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
18735
|
+
}
|
|
18736
|
+
});
|
|
18737
|
+
return;
|
|
18738
|
+
}
|
|
18069
18739
|
if (this.v11Bindings) {
|
|
18070
18740
|
this.dispatchV11(req, res, url, method).then((handled) => {
|
|
18071
18741
|
if (handled) return;
|
|
@@ -21932,15 +22602,52 @@ var init_sentinel_dispatcher = __esm({
|
|
|
21932
22602
|
};
|
|
21933
22603
|
}
|
|
21934
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
|
+
});
|
|
21935
22630
|
|
|
21936
22631
|
// src/anomaly-detection/types.ts
|
|
21937
22632
|
var init_types4 = __esm({
|
|
21938
22633
|
"src/anomaly-detection/types.ts"() {
|
|
21939
22634
|
}
|
|
21940
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
|
+
}
|
|
21941
22646
|
var ANOMALY_AUDIT_OPS, DEFAULT_TICK_INTERVAL_MS2, AnomalyPipelineDispatcher;
|
|
21942
22647
|
var init_anomaly_pipeline = __esm({
|
|
21943
22648
|
"src/anomaly-detection/anomaly-pipeline.ts"() {
|
|
22649
|
+
init_cusum();
|
|
22650
|
+
init_psi();
|
|
21944
22651
|
init_types4();
|
|
21945
22652
|
ANOMALY_AUDIT_OPS = {
|
|
21946
22653
|
DETECTOR_REGISTERED: "anomaly_detector_registered",
|
|
@@ -21948,7 +22655,15 @@ var init_anomaly_pipeline = __esm({
|
|
|
21948
22655
|
FINDING_EMITTED: "anomaly_finding_emitted",
|
|
21949
22656
|
EVALUATION_FAILED: "anomaly_evaluation_failed",
|
|
21950
22657
|
TRAINING_COMPLETED: "anomaly_training_completed",
|
|
21951
|
-
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"
|
|
21952
22667
|
};
|
|
21953
22668
|
DEFAULT_TICK_INTERVAL_MS2 = 6e4;
|
|
21954
22669
|
AnomalyPipelineDispatcher = class {
|
|
@@ -22039,34 +22754,37 @@ var init_anomaly_pipeline = __esm({
|
|
|
22039
22754
|
const stamped = await this.routeFinding(detectorId, raw);
|
|
22040
22755
|
findings.push(stamped);
|
|
22041
22756
|
}
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
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
|
+
}
|
|
22070
22788
|
}
|
|
22071
22789
|
} catch (err) {
|
|
22072
22790
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -22129,6 +22847,7 @@ var init_anomaly_pipeline = __esm({
|
|
|
22129
22847
|
observed_at: raw.observed_at || this.now().toISOString()
|
|
22130
22848
|
};
|
|
22131
22849
|
await this.findingStore.saveFinding(stamped);
|
|
22850
|
+
const classifierId = stamped.details["classifier_id"] ?? null;
|
|
22132
22851
|
this.auditLog.append(
|
|
22133
22852
|
"l2",
|
|
22134
22853
|
ANOMALY_AUDIT_OPS.FINDING_EMITTED,
|
|
@@ -22138,13 +22857,79 @@ var init_anomaly_pipeline = __esm({
|
|
|
22138
22857
|
finding_id: stamped.finding_id,
|
|
22139
22858
|
severity: stamped.severity,
|
|
22140
22859
|
anomaly_score: stamped.details["anomaly_score"] ?? null,
|
|
22860
|
+
...classifierId !== null ? { classifier_id: classifierId } : {},
|
|
22141
22861
|
...stamped.agent_id !== void 0 ? { agent_id: stamped.agent_id } : {},
|
|
22142
22862
|
fortress_id: this.fortressId
|
|
22143
22863
|
}
|
|
22144
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
|
+
}
|
|
22145
22876
|
this.emit({ type: "finding", finding: stamped });
|
|
22146
22877
|
return stamped;
|
|
22147
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
|
+
}
|
|
22148
22933
|
emit(event) {
|
|
22149
22934
|
for (const listener of this.listeners) {
|
|
22150
22935
|
try {
|
|
@@ -22421,7 +23206,7 @@ function extractInterAgentEvents(entries) {
|
|
|
22421
23206
|
if (!sender) continue;
|
|
22422
23207
|
out.push({
|
|
22423
23208
|
sender,
|
|
22424
|
-
recipient:
|
|
23209
|
+
recipient: OPERATOR_PSEUDO_AGENT2,
|
|
22425
23210
|
timestampMs: Date.parse(entry.timestamp),
|
|
22426
23211
|
auditId: `${entry.timestamp}:${entry.operation}`
|
|
22427
23212
|
});
|
|
@@ -22435,7 +23220,7 @@ function optionalString(details, key) {
|
|
|
22435
23220
|
if (typeof value !== "string" || value.length === 0) return null;
|
|
22436
23221
|
return value;
|
|
22437
23222
|
}
|
|
22438
|
-
var CROSS_AGENT_CHATTER_SENTINEL_ID, WARN_SIGMA2, ALERT_SIGMA2, BASELINE_WINDOWS2, QUERY_LIMIT2, MULTI_NEW_PARTNER_ALERT_THRESHOLD,
|
|
23223
|
+
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;
|
|
22439
23224
|
var init_cross_agent_chatter_watcher = __esm({
|
|
22440
23225
|
"src/sentinel/sentinels/cross-agent-chatter-watcher.ts"() {
|
|
22441
23226
|
init_sentinel();
|
|
@@ -22445,7 +23230,7 @@ var init_cross_agent_chatter_watcher = __esm({
|
|
|
22445
23230
|
BASELINE_WINDOWS2 = 7;
|
|
22446
23231
|
QUERY_LIMIT2 = 1e4;
|
|
22447
23232
|
MULTI_NEW_PARTNER_ALERT_THRESHOLD = 3;
|
|
22448
|
-
|
|
23233
|
+
OPERATOR_PSEUDO_AGENT2 = "operator";
|
|
22449
23234
|
HANDOFF_OP = "v1.1_local_handoff";
|
|
22450
23235
|
CROSS_HARNESS_OPS = /* @__PURE__ */ new Set([
|
|
22451
23236
|
"cross_harness_approval_aggregated",
|
|
@@ -25507,7 +26292,7 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25507
26292
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25508
26293
|
const canonicalBytes = canonicalize2(outcome);
|
|
25509
26294
|
const canonicalString = new TextDecoder().decode(canonicalBytes);
|
|
25510
|
-
const
|
|
26295
|
+
const sha25612 = createCommitment(canonicalString);
|
|
25511
26296
|
let pedersenData;
|
|
25512
26297
|
if (includePedersen && Number.isInteger(outcome.rounds) && outcome.rounds >= 0) {
|
|
25513
26298
|
const pedersen = createPedersenCommitment(outcome.rounds);
|
|
@@ -25519,7 +26304,7 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25519
26304
|
const commitmentPayload = {
|
|
25520
26305
|
bridge_commitment_id: commitmentId,
|
|
25521
26306
|
session_id: outcome.session_id,
|
|
25522
|
-
sha256_commitment:
|
|
26307
|
+
sha256_commitment: sha25612.commitment,
|
|
25523
26308
|
terms_hash: outcome.terms_hash,
|
|
25524
26309
|
committer_did: identity.did,
|
|
25525
26310
|
committed_at: now,
|
|
@@ -25530,8 +26315,8 @@ function createBridgeCommitment(outcome, identity, identityEncryptionKey, includ
|
|
|
25530
26315
|
return {
|
|
25531
26316
|
bridge_commitment_id: commitmentId,
|
|
25532
26317
|
session_id: outcome.session_id,
|
|
25533
|
-
sha256_commitment:
|
|
25534
|
-
blinding_factor:
|
|
26318
|
+
sha256_commitment: sha25612.commitment,
|
|
26319
|
+
blinding_factor: sha25612.blinding_factor,
|
|
25535
26320
|
committer_did: identity.did,
|
|
25536
26321
|
signature: toBase64url(signature),
|
|
25537
26322
|
pedersen_commitment: pedersenData,
|
|
@@ -39454,6 +40239,141 @@ ${redactedItems.map((r) => `- ${r.redacted}`).join("\n")}`,
|
|
|
39454
40239
|
}
|
|
39455
40240
|
});
|
|
39456
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
|
+
|
|
39457
40377
|
// src/intelligence/substrates/hybrid/per-surface-router.ts
|
|
39458
40378
|
function resolveHybridChoice(rules, surface) {
|
|
39459
40379
|
if (!rules) return null;
|
|
@@ -39575,6 +40495,7 @@ var init_selector = __esm({
|
|
|
39575
40495
|
init_local();
|
|
39576
40496
|
init_venice();
|
|
39577
40497
|
init_frontier();
|
|
40498
|
+
init_header_strip();
|
|
39578
40499
|
init_per_surface_router();
|
|
39579
40500
|
DISABLED_CAPABILITY = {
|
|
39580
40501
|
summarize: false,
|
|
@@ -39609,7 +40530,21 @@ var init_selector = __esm({
|
|
|
39609
40530
|
this.auditLog = cfg.auditLog;
|
|
39610
40531
|
this.identityId = cfg.identityId;
|
|
39611
40532
|
this.redactor = cfg.redactor ?? IDENTITY_REDACTOR;
|
|
39612
|
-
|
|
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
|
+
});
|
|
39613
40548
|
this.config = buildDefaultConfig();
|
|
39614
40549
|
}
|
|
39615
40550
|
/**
|
|
@@ -42653,6 +43588,19 @@ ${err.message}
|
|
|
42653
43588
|
identityId: aggregatorIdentityId
|
|
42654
43589
|
});
|
|
42655
43590
|
anomalyDispatcher.start();
|
|
43591
|
+
const handoffLog = new HandoffLog({
|
|
43592
|
+
auditLog,
|
|
43593
|
+
fortressId: fortressIdForAggregator
|
|
43594
|
+
});
|
|
43595
|
+
const handoffEventBridge = new HandoffEventBridge();
|
|
43596
|
+
if (dashboard) {
|
|
43597
|
+
dashboard.setHandoffLog({
|
|
43598
|
+
handoffLog,
|
|
43599
|
+
eventBridge: handoffEventBridge,
|
|
43600
|
+
auditLog,
|
|
43601
|
+
operatorId: aggregatorIdentityId
|
|
43602
|
+
});
|
|
43603
|
+
}
|
|
42656
43604
|
const policyTools = createPrincipalPolicyTools(policy, baseline, auditLog);
|
|
42657
43605
|
const { tools: sanctuaryMetaTools } = createSanctuaryTools({
|
|
42658
43606
|
config,
|
|
@@ -42850,6 +43798,8 @@ var init_src = __esm({
|
|
|
42850
43798
|
init_sentinel_registry();
|
|
42851
43799
|
init_sentinel_dispatcher();
|
|
42852
43800
|
init_anomaly_pipeline();
|
|
43801
|
+
init_handoff_log();
|
|
43802
|
+
init_handoff_routes();
|
|
42853
43803
|
init_sentinels();
|
|
42854
43804
|
init_subscription_store();
|
|
42855
43805
|
init_tools4();
|
|
@@ -44950,32 +45900,32 @@ endstream`;
|
|
|
44950
45900
|
const offsets = new Array(totalObjects + 1).fill(0);
|
|
44951
45901
|
const chunks = [];
|
|
44952
45902
|
let bytePos = 0;
|
|
44953
|
-
const
|
|
45903
|
+
const write4 = (s) => {
|
|
44954
45904
|
const buf = Buffer.from(s, "latin1");
|
|
44955
45905
|
chunks.push(buf);
|
|
44956
45906
|
bytePos += buf.length;
|
|
44957
45907
|
};
|
|
44958
|
-
|
|
45908
|
+
write4("%PDF-1.4\n%\xE2\xE3\xCF\xD3\n");
|
|
44959
45909
|
for (let i = 1; i <= totalObjects; i++) {
|
|
44960
45910
|
offsets[i] = bytePos;
|
|
44961
|
-
|
|
45911
|
+
write4(`${i} 0 obj
|
|
44962
45912
|
${objectBodies[i]}
|
|
44963
45913
|
endobj
|
|
44964
45914
|
`);
|
|
44965
45915
|
}
|
|
44966
45916
|
const xrefPos = bytePos;
|
|
44967
|
-
|
|
45917
|
+
write4(`xref
|
|
44968
45918
|
0 ${totalObjects + 1}
|
|
44969
45919
|
`);
|
|
44970
|
-
|
|
45920
|
+
write4("0000000000 65535 f \n");
|
|
44971
45921
|
for (let i = 1; i <= totalObjects; i++) {
|
|
44972
|
-
|
|
45922
|
+
write4(`${offsets[i].toString().padStart(10, "0")} 00000 n
|
|
44973
45923
|
`);
|
|
44974
45924
|
}
|
|
44975
|
-
|
|
45925
|
+
write4(`trailer
|
|
44976
45926
|
<< /Size ${totalObjects + 1} /Root 1 0 R >>
|
|
44977
45927
|
`);
|
|
44978
|
-
|
|
45928
|
+
write4(`startxref
|
|
44979
45929
|
${xrefPos}
|
|
44980
45930
|
%%EOF
|
|
44981
45931
|
`);
|
|
@@ -48246,6 +49196,365 @@ var init_sentinel2 = __esm({
|
|
|
48246
49196
|
init_sentinels();
|
|
48247
49197
|
}
|
|
48248
49198
|
});
|
|
49199
|
+
async function issueDidWeb(opts) {
|
|
49200
|
+
if (!opts.authority_host || !HOST_RE.test(opts.authority_host)) {
|
|
49201
|
+
throw new Error(
|
|
49202
|
+
`did-web: authority_host '${opts.authority_host}' is not a valid DNS host`
|
|
49203
|
+
);
|
|
49204
|
+
}
|
|
49205
|
+
if (!FORTRESS_LABEL_RE.test(opts.fortress_id)) {
|
|
49206
|
+
throw new Error(
|
|
49207
|
+
`did-web: fortress_id '${opts.fortress_id}' is not a valid label`
|
|
49208
|
+
);
|
|
49209
|
+
}
|
|
49210
|
+
if (opts.agent_label !== void 0 && !AGENT_LABEL_RE.test(opts.agent_label)) {
|
|
49211
|
+
throw new Error(
|
|
49212
|
+
`did-web: agent_label '${opts.agent_label}' is not a valid label`
|
|
49213
|
+
);
|
|
49214
|
+
}
|
|
49215
|
+
if (opts.public_key.length !== 32) {
|
|
49216
|
+
throw new Error(
|
|
49217
|
+
`did-web: public_key must be exactly 32 bytes (Ed25519), got ${opts.public_key.length}`
|
|
49218
|
+
);
|
|
49219
|
+
}
|
|
49220
|
+
const did = buildDid(opts);
|
|
49221
|
+
const verificationMethodId = `${did}#key-1`;
|
|
49222
|
+
const verificationMethod = {
|
|
49223
|
+
id: verificationMethodId,
|
|
49224
|
+
type: "JsonWebKey2020",
|
|
49225
|
+
controller: did,
|
|
49226
|
+
publicKeyJwk: {
|
|
49227
|
+
kty: "OKP",
|
|
49228
|
+
crv: "Ed25519",
|
|
49229
|
+
x: toBase64url(opts.public_key)
|
|
49230
|
+
}
|
|
49231
|
+
};
|
|
49232
|
+
const didDocument = {
|
|
49233
|
+
"@context": [...DID_CONTEXT],
|
|
49234
|
+
id: did,
|
|
49235
|
+
verificationMethod: [verificationMethod],
|
|
49236
|
+
authentication: [verificationMethodId],
|
|
49237
|
+
assertionMethod: [verificationMethodId]
|
|
49238
|
+
};
|
|
49239
|
+
const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
49240
|
+
return {
|
|
49241
|
+
did,
|
|
49242
|
+
did_document: didDocument,
|
|
49243
|
+
public_key: opts.public_key,
|
|
49244
|
+
created_at: now.toISOString(),
|
|
49245
|
+
authority_host: opts.authority_host,
|
|
49246
|
+
fortress_id: opts.fortress_id,
|
|
49247
|
+
...opts.agent_label !== void 0 ? { agent_label: opts.agent_label } : {}
|
|
49248
|
+
};
|
|
49249
|
+
}
|
|
49250
|
+
function publishDidWebDocument(identifier, opts = {}) {
|
|
49251
|
+
const path = opts.publish_path ?? canonicalPublishPath(identifier);
|
|
49252
|
+
const artifact = canonicalSerializeDidDocument(identifier.did_document);
|
|
49253
|
+
const digest = sha256(stringToBytes(artifact));
|
|
49254
|
+
const url = `https://${identifier.authority_host}${path}`;
|
|
49255
|
+
return {
|
|
49256
|
+
url,
|
|
49257
|
+
publish_path: path,
|
|
49258
|
+
artifact,
|
|
49259
|
+
sha256: hashToString(digest)
|
|
49260
|
+
};
|
|
49261
|
+
}
|
|
49262
|
+
function buildDid(opts) {
|
|
49263
|
+
if (opts.agent_label === void 0) {
|
|
49264
|
+
return `did:web:${opts.authority_host}`;
|
|
49265
|
+
}
|
|
49266
|
+
return `did:web:${opts.authority_host}:fortress:${opts.fortress_id}:agent:${opts.agent_label}`;
|
|
49267
|
+
}
|
|
49268
|
+
function canonicalPublishPath(identifier) {
|
|
49269
|
+
if (identifier.agent_label === void 0) {
|
|
49270
|
+
return "/.well-known/did.json";
|
|
49271
|
+
}
|
|
49272
|
+
return `/fortress/${identifier.fortress_id}/agent/${identifier.agent_label}/did.json`;
|
|
49273
|
+
}
|
|
49274
|
+
function canonicalSerializeDidDocument(doc) {
|
|
49275
|
+
return JSON.stringify(
|
|
49276
|
+
{
|
|
49277
|
+
"@context": doc["@context"],
|
|
49278
|
+
id: doc.id,
|
|
49279
|
+
verificationMethod: doc.verificationMethod,
|
|
49280
|
+
authentication: doc.authentication,
|
|
49281
|
+
assertionMethod: doc.assertionMethod
|
|
49282
|
+
},
|
|
49283
|
+
null,
|
|
49284
|
+
2
|
|
49285
|
+
);
|
|
49286
|
+
}
|
|
49287
|
+
var DID_CONTEXT, HOST_RE, FORTRESS_LABEL_RE, AGENT_LABEL_RE;
|
|
49288
|
+
var init_did_web = __esm({
|
|
49289
|
+
"src/recognition/did-web.ts"() {
|
|
49290
|
+
init_encoding();
|
|
49291
|
+
init_hashing();
|
|
49292
|
+
DID_CONTEXT = [
|
|
49293
|
+
"https://www.w3.org/ns/did/v1",
|
|
49294
|
+
"https://w3id.org/security/suites/jws-2020/v1"
|
|
49295
|
+
];
|
|
49296
|
+
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;
|
|
49297
|
+
FORTRESS_LABEL_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
49298
|
+
AGENT_LABEL_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
49299
|
+
}
|
|
49300
|
+
});
|
|
49301
|
+
|
|
49302
|
+
// src/cli/did-web.ts
|
|
49303
|
+
var did_web_exports = {};
|
|
49304
|
+
__export(did_web_exports, {
|
|
49305
|
+
runDidWebCommand: () => runDidWebCommand
|
|
49306
|
+
});
|
|
49307
|
+
function write3(stream, text) {
|
|
49308
|
+
stream.write(text);
|
|
49309
|
+
}
|
|
49310
|
+
function flagValue3(argv, name) {
|
|
49311
|
+
const i = argv.indexOf(name);
|
|
49312
|
+
if (i === -1) return void 0;
|
|
49313
|
+
return argv[i + 1];
|
|
49314
|
+
}
|
|
49315
|
+
function hasFlag3(argv, name) {
|
|
49316
|
+
return argv.includes(name);
|
|
49317
|
+
}
|
|
49318
|
+
function printUsage7(out) {
|
|
49319
|
+
write3(
|
|
49320
|
+
out,
|
|
49321
|
+
`Usage: sanctuary did-web <command> [options]
|
|
49322
|
+
|
|
49323
|
+
Commands:
|
|
49324
|
+
issue --authority-host <host> [--agent-label <label>] [--json]
|
|
49325
|
+
Generate a did:web identifier bound to the operator's
|
|
49326
|
+
fortress Ed25519 public key. Writes the DID Document
|
|
49327
|
+
artifact to <storage>/recognition/did-web.json and
|
|
49328
|
+
prints publication instructions for the operator's
|
|
49329
|
+
HTTPS server.
|
|
49330
|
+
|
|
49331
|
+
show [--json] Display the previously issued did:web identifier.
|
|
49332
|
+
Exits non-zero if none issued.
|
|
49333
|
+
|
|
49334
|
+
Options:
|
|
49335
|
+
--authority-host <host> HTTPS host the operator controls and will
|
|
49336
|
+
serve /.well-known/did.json from.
|
|
49337
|
+
--agent-label <label> Optional agent-scoped identifier (label-safe;
|
|
49338
|
+
alphanumeric + dash + underscore, 1-64 chars).
|
|
49339
|
+
--fortress <path> Override the storage path.
|
|
49340
|
+
--passphrase <val> Passphrase for master-key derivation.
|
|
49341
|
+
--json Output as JSON.
|
|
49342
|
+
--help, -h Show this help.
|
|
49343
|
+
|
|
49344
|
+
Castle-walking note: did:web resolution is outbound HTTPS by design.
|
|
49345
|
+
This CLI never opens an outbound socket. The opt-in surface is your
|
|
49346
|
+
choice to run "did-web issue" with --authority-host; the resulting
|
|
49347
|
+
artifact is yours to publish on your own infrastructure. Sanctuary
|
|
49348
|
+
does not phone home.
|
|
49349
|
+
`
|
|
49350
|
+
);
|
|
49351
|
+
}
|
|
49352
|
+
async function runDidWebCommand(args) {
|
|
49353
|
+
const argv = args.argv;
|
|
49354
|
+
const out = args.out ?? process.stdout;
|
|
49355
|
+
const err = args.err ?? process.stderr;
|
|
49356
|
+
const env = args.env ?? process.env;
|
|
49357
|
+
if (argv.length === 0 || hasFlag3(argv, "--help") || hasFlag3(argv, "-h")) {
|
|
49358
|
+
printUsage7(out);
|
|
49359
|
+
return 0;
|
|
49360
|
+
}
|
|
49361
|
+
const command = argv[0];
|
|
49362
|
+
if (command === "issue") {
|
|
49363
|
+
return await cmdIssue(argv.slice(1), out, err, env);
|
|
49364
|
+
}
|
|
49365
|
+
if (command === "show") {
|
|
49366
|
+
return await cmdShow3(argv.slice(1), out, err);
|
|
49367
|
+
}
|
|
49368
|
+
write3(err, `Unknown did-web command: ${command}
|
|
49369
|
+
`);
|
|
49370
|
+
write3(err, `Run "sanctuary did-web --help" for usage.
|
|
49371
|
+
`);
|
|
49372
|
+
return 2;
|
|
49373
|
+
}
|
|
49374
|
+
async function loadFortressIdentity(argv, env, err) {
|
|
49375
|
+
const fortressFlag = flagValue3(argv, "--fortress");
|
|
49376
|
+
if (fortressFlag) {
|
|
49377
|
+
process.env.SANCTUARY_STORAGE_PATH = fortressFlag;
|
|
49378
|
+
}
|
|
49379
|
+
const passphrase = flagValue3(argv, "--passphrase") ?? env.SANCTUARY_PASSPHRASE;
|
|
49380
|
+
const recoveryKey = env.SANCTUARY_RECOVERY_KEY;
|
|
49381
|
+
if (!passphrase && !recoveryKey) {
|
|
49382
|
+
write3(
|
|
49383
|
+
err,
|
|
49384
|
+
"Error: sanctuary did-web requires SANCTUARY_PASSPHRASE, --passphrase, or SANCTUARY_RECOVERY_KEY.\n"
|
|
49385
|
+
);
|
|
49386
|
+
return null;
|
|
49387
|
+
}
|
|
49388
|
+
const config = await loadConfig();
|
|
49389
|
+
await mkdir(config.storage_path, { recursive: true, mode: 448 });
|
|
49390
|
+
const stateStoragePath = join(config.storage_path, "state");
|
|
49391
|
+
const storage = new FilesystemStorage(stateStoragePath);
|
|
49392
|
+
let masterKey;
|
|
49393
|
+
if (passphrase) {
|
|
49394
|
+
let existingParams;
|
|
49395
|
+
const raw = await storage.read("_meta", "key-params");
|
|
49396
|
+
if (raw) {
|
|
49397
|
+
existingParams = JSON.parse(bytesToString(raw));
|
|
49398
|
+
}
|
|
49399
|
+
const derivation = await deriveMasterKey(passphrase, existingParams);
|
|
49400
|
+
masterKey = derivation.key;
|
|
49401
|
+
} else if (recoveryKey) {
|
|
49402
|
+
masterKey = fromBase64url(recoveryKey);
|
|
49403
|
+
} else {
|
|
49404
|
+
return null;
|
|
49405
|
+
}
|
|
49406
|
+
const identityManager = new IdentityManager(storage, masterKey);
|
|
49407
|
+
const loadResult = await identityManager.load();
|
|
49408
|
+
if (loadResult.loaded === 0) {
|
|
49409
|
+
write3(
|
|
49410
|
+
err,
|
|
49411
|
+
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"
|
|
49412
|
+
);
|
|
49413
|
+
return null;
|
|
49414
|
+
}
|
|
49415
|
+
const primary = identityManager.getDefault();
|
|
49416
|
+
if (!primary) {
|
|
49417
|
+
write3(err, "Error: no primary identity on this fortress yet. Run sanctuary wrap first.\n");
|
|
49418
|
+
return null;
|
|
49419
|
+
}
|
|
49420
|
+
return {
|
|
49421
|
+
publicKey: fromBase64url(primary.public_key),
|
|
49422
|
+
identityId: primary.identity_id,
|
|
49423
|
+
storagePath: config.storage_path
|
|
49424
|
+
};
|
|
49425
|
+
}
|
|
49426
|
+
async function cmdIssue(argv, out, err, env) {
|
|
49427
|
+
const authorityHost = flagValue3(argv, "--authority-host");
|
|
49428
|
+
const agentLabel = flagValue3(argv, "--agent-label");
|
|
49429
|
+
const json = hasFlag3(argv, "--json");
|
|
49430
|
+
if (!authorityHost) {
|
|
49431
|
+
write3(err, "Error: --authority-host is required.\n");
|
|
49432
|
+
write3(err, "Example: sanctuary did-web issue --authority-host alice.example.com\n");
|
|
49433
|
+
return 1;
|
|
49434
|
+
}
|
|
49435
|
+
const snapshot = await loadFortressIdentity(argv, env, err);
|
|
49436
|
+
if (!snapshot) return 1;
|
|
49437
|
+
let identifier;
|
|
49438
|
+
try {
|
|
49439
|
+
identifier = await issueDidWeb({
|
|
49440
|
+
fortress_id: snapshot.identityId,
|
|
49441
|
+
authority_host: authorityHost,
|
|
49442
|
+
public_key: snapshot.publicKey,
|
|
49443
|
+
...agentLabel !== void 0 ? { agent_label: agentLabel } : {}
|
|
49444
|
+
});
|
|
49445
|
+
} catch (e) {
|
|
49446
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
49447
|
+
write3(err, `Error: ${message}
|
|
49448
|
+
`);
|
|
49449
|
+
return 1;
|
|
49450
|
+
}
|
|
49451
|
+
const artifact = publishDidWebDocument(identifier);
|
|
49452
|
+
const persistDir = join(snapshot.storagePath, "recognition");
|
|
49453
|
+
await mkdir(persistDir, { recursive: true, mode: 448 });
|
|
49454
|
+
const persistPath = join(persistDir, "did-web.json");
|
|
49455
|
+
const record = {
|
|
49456
|
+
version: 1,
|
|
49457
|
+
identifier: {
|
|
49458
|
+
did: identifier.did,
|
|
49459
|
+
created_at: identifier.created_at,
|
|
49460
|
+
authority_host: identifier.authority_host,
|
|
49461
|
+
fortress_id: identifier.fortress_id,
|
|
49462
|
+
...identifier.agent_label !== void 0 ? { agent_label: identifier.agent_label } : {},
|
|
49463
|
+
did_document: identifier.did_document
|
|
49464
|
+
},
|
|
49465
|
+
artifact: {
|
|
49466
|
+
url: artifact.url,
|
|
49467
|
+
publish_path: artifact.publish_path,
|
|
49468
|
+
sha256: artifact.sha256
|
|
49469
|
+
}
|
|
49470
|
+
};
|
|
49471
|
+
await writeFile(persistPath, JSON.stringify(record, null, 2), {
|
|
49472
|
+
mode: 384
|
|
49473
|
+
});
|
|
49474
|
+
if (json) {
|
|
49475
|
+
write3(out, JSON.stringify(record, null, 2) + "\n");
|
|
49476
|
+
return 0;
|
|
49477
|
+
}
|
|
49478
|
+
write3(out, `did:web identifier issued.
|
|
49479
|
+
`);
|
|
49480
|
+
write3(out, ` DID: ${identifier.did}
|
|
49481
|
+
`);
|
|
49482
|
+
write3(out, ` Authority host: ${identifier.authority_host}
|
|
49483
|
+
`);
|
|
49484
|
+
write3(out, ` Created at: ${identifier.created_at}
|
|
49485
|
+
`);
|
|
49486
|
+
write3(out, ` Persisted: ${persistPath}
|
|
49487
|
+
`);
|
|
49488
|
+
write3(out, `
|
|
49489
|
+
Next step: publish the DID Document to your HTTPS host.
|
|
49490
|
+
`);
|
|
49491
|
+
write3(out, ` Target URL: ${artifact.url}
|
|
49492
|
+
`);
|
|
49493
|
+
write3(out, ` SHA-256: ${artifact.sha256}
|
|
49494
|
+
`);
|
|
49495
|
+
write3(out, ` Artifact: ${join(persistDir, "did.json")}
|
|
49496
|
+
`);
|
|
49497
|
+
const artifactPath = join(persistDir, "did.json");
|
|
49498
|
+
await writeFile(artifactPath, artifact.artifact, { mode: 420 });
|
|
49499
|
+
write3(out, `
|
|
49500
|
+
Castle-walking note: this CLI never opens an outbound socket.
|
|
49501
|
+
`);
|
|
49502
|
+
write3(out, `Publishing the DID Document is your operation; serve the artifact
|
|
49503
|
+
`);
|
|
49504
|
+
write3(out, `at the URL above from infrastructure you control.
|
|
49505
|
+
`);
|
|
49506
|
+
return 0;
|
|
49507
|
+
}
|
|
49508
|
+
async function cmdShow3(argv, out, err, _env) {
|
|
49509
|
+
const json = hasFlag3(argv, "--json");
|
|
49510
|
+
const fortressFlag = flagValue3(argv, "--fortress");
|
|
49511
|
+
if (fortressFlag) {
|
|
49512
|
+
process.env.SANCTUARY_STORAGE_PATH = fortressFlag;
|
|
49513
|
+
}
|
|
49514
|
+
const config = await loadConfig();
|
|
49515
|
+
const persistPath = join(config.storage_path, "recognition", "did-web.json");
|
|
49516
|
+
let bytes;
|
|
49517
|
+
try {
|
|
49518
|
+
bytes = await readFile(persistPath);
|
|
49519
|
+
} catch {
|
|
49520
|
+
write3(
|
|
49521
|
+
err,
|
|
49522
|
+
`No did:web identifier configured on this fortress.
|
|
49523
|
+
Run "sanctuary did-web issue --authority-host <host>" to issue one.
|
|
49524
|
+
`
|
|
49525
|
+
);
|
|
49526
|
+
return 1;
|
|
49527
|
+
}
|
|
49528
|
+
if (json) {
|
|
49529
|
+
write3(out, bytes.toString("utf-8"));
|
|
49530
|
+
if (!bytes.toString("utf-8").endsWith("\n")) write3(out, "\n");
|
|
49531
|
+
return 0;
|
|
49532
|
+
}
|
|
49533
|
+
const parsed = JSON.parse(bytes.toString("utf-8"));
|
|
49534
|
+
write3(out, `did:web identifier on this fortress:
|
|
49535
|
+
`);
|
|
49536
|
+
write3(out, ` DID: ${parsed.identifier.did}
|
|
49537
|
+
`);
|
|
49538
|
+
write3(out, ` Authority host: ${parsed.identifier.authority_host}
|
|
49539
|
+
`);
|
|
49540
|
+
write3(out, ` Created at: ${parsed.identifier.created_at}
|
|
49541
|
+
`);
|
|
49542
|
+
write3(out, ` Publish URL: ${parsed.artifact.url}
|
|
49543
|
+
`);
|
|
49544
|
+
write3(out, ` SHA-256: ${parsed.artifact.sha256}
|
|
49545
|
+
`);
|
|
49546
|
+
return 0;
|
|
49547
|
+
}
|
|
49548
|
+
var init_did_web2 = __esm({
|
|
49549
|
+
"src/cli/did-web.ts"() {
|
|
49550
|
+
init_filesystem();
|
|
49551
|
+
init_tools();
|
|
49552
|
+
init_key_derivation();
|
|
49553
|
+
init_encoding();
|
|
49554
|
+
init_config();
|
|
49555
|
+
init_did_web();
|
|
49556
|
+
}
|
|
49557
|
+
});
|
|
48249
49558
|
|
|
48250
49559
|
// src/mcp/broker-server.ts
|
|
48251
49560
|
var broker_server_exports = {};
|
|
@@ -49111,6 +50420,11 @@ async function main() {
|
|
|
49111
50420
|
const code = await runSentinelCommand2({ argv: args.slice(1) });
|
|
49112
50421
|
process.exit(code);
|
|
49113
50422
|
}
|
|
50423
|
+
if (args[0] === "did-web") {
|
|
50424
|
+
const { runDidWebCommand: runDidWebCommand2 } = await Promise.resolve().then(() => (init_did_web2(), did_web_exports));
|
|
50425
|
+
const code = await runDidWebCommand2({ argv: args.slice(1) });
|
|
50426
|
+
process.exit(code);
|
|
50427
|
+
}
|
|
49114
50428
|
if (args[0] === "broker-server") {
|
|
49115
50429
|
const { openBroker: openBroker2 } = await Promise.resolve().then(() => (init_open(), open_exports));
|
|
49116
50430
|
const { createBrokerMcpServer: createBrokerMcpServer2 } = await Promise.resolve().then(() => (init_broker_server(), broker_server_exports));
|