chainlesschain 0.162.147 → 0.162.148
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/README.md +1 -1
- package/package.json +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DywJ7xTv.js → AIOps-DwpCCp64.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BTlqcY-q.js → ActionButton-C9pBYocA.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-FdG1Mvwy.js → Analytics-BWAkeXxK.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CVsnbvN1.js → AppLayout-CivFGH6B.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-ITdpJ7vR.js → Audit-Cm8hRpZm.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BfXqnXo1.js → Backup-DXdFMsE8.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C09ip3_E.js → BaseInput-uAwSTeql.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-qdkhB42l.js → Chat-KU8eeJJE.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-j6WZCuff.js → Checkbox-C6AMDkjd.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CGZ-K3uK.js → Codegen-t2moDxcO.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CIlPOAu6.js → Col-DCcsRRhN.js} +1 -1
- package/src/assets/web-panel/assets/{Community-sY-i-hic.js → Community-DtB-8SAC.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DcoEfyL8.js → Compact-CZm8THYA.js} +1 -1
- package/src/assets/web-panel/assets/Compliance-LiQgC7g1.js +1 -0
- package/src/assets/web-panel/assets/{Cowork-DLY_fkLv.js → Cowork-CA8SAxht.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-D049pZBC.js → Cron-CtRaF1wD.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DCXdE8M9.js → Crosschain-6-br6Hub.js} +1 -1
- package/src/assets/web-panel/assets/{DID-JCvPZtjW.js → DID-Do2EccrL.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cg2xu3iE.js → Dashboard-wrXcbzGe.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DjJLjbLh.js → Dropdown-p3FsT245.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DugNcSLR.js → EmailListRenderer-D95A2L8q.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-J6Nb-E30.js → FamilyGuardDashboard-cLuJW2zo.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CQ3Ttpbl.js → Federation-Brgq_cbN.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Cz0NKag4.js → FormItemContext-DWLCkNgh.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-NYcMP6iz.js → GenericCardRenderer-BBqUfQd6.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B4hYN18N.js → Git-8F090w4I.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DOQPCcC0.js → Governance-CCogEbxb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-HtLF746W.js → Inference-CfLD7v7C.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BXrk8rMm.js → KnowledgeGraph-DDuHJewd.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DS0JnD3-.js → Logs-CE8KSEVC.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-Cqnjihrz.js → Marketplace-DmwpZmhT.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Cx3Psk-U.js → McpTools-Bf7AazU8.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BjyysPtj.js → Memory-D0QU_00S.js} +2 -2
- package/src/assets/web-panel/assets/MobileBridge-D3Arxfeg.css +1 -0
- package/src/assets/web-panel/assets/MobileBridge-yXS9xdhx.js +1 -0
- package/src/assets/web-panel/assets/{MobileProjects-Xwf-fdOQ.js → MobileProjects-BuDUoGUP.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Djkql5m5.js → Mtc-BYyHy28p.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D2BAZlu0.js → MtcAudit-CK0aqpiZ.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-ByqP1ZzH.js → Multisig-mNimKYeb.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C_kn0nE2.js → NLProgramming-AioAJ0YA.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-7l7eXHPq.js → Notes-CVVNCLHE.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BrCDoitw.js → NotificationSettings-C4ABj-TK.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CmtqIdwr.js → OrderTableRenderer-DIp8Xcbd.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DdoNAxsM.js → Organization-uozl_gWK.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bw7R6dE3.js → Overflow-BCZOM2hK.js} +1 -1
- package/src/assets/web-panel/assets/{OverrideContext-C2r4vyBb.js → OverrideContext-BlgL9440.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DJNtBugA.js → P2P-CArcaiaj.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dwhd5_ue.js → PdhVaultBrowser-Sgq2Srr8.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYoSfhPR.js → Permissions-BYrQrXnH.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-aYCYJbnH.js → PersonalDataHub-BzHStAbz.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-DJp6CprF.js → Pipeline-k7KqxX1M.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Cq9HZweR.js → Privacy-IumTUWqx.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CmF0HsSt.js → ProjectInit-BRyImYTf.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-P8V5Aea2.js → ProjectSettings-BFIqTBFk.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DPd5-lNS.js → Projects-Dpid9CDg.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D589v0q2.js → Providers-CyyFnUPs.js} +1 -1
- package/src/assets/web-panel/assets/QrScannerModal-C82cRx-X.js +1 -0
- package/src/assets/web-panel/assets/{MobileBridge-zJpPuf4E.css → QrScannerModal-NwAHNfiJ.css} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-lvRV2osB.js → QuickAsk-DGxDF521.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-sb84MTpY.js → Recommend-Cns-Am1y.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-R7OqAIlg.js +4 -0
- package/src/assets/web-panel/assets/{Reputation-d9Y3vy-W.js → Reputation-D7mgPIYV.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DMdhLUTp.js → Row-B3lEURyd.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-OL-SMDkz.js → RssFeed-9_UVrpBt.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BjStLKq1.js → Search-ClZeO80q.js} +1 -1
- package/src/assets/web-panel/assets/{Security-MeI411qr.js → Security-BNNJczEp.js} +3 -3
- package/src/assets/web-panel/assets/{Services-UajosuhT.js → Services-C5SjrWUj.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CGpG-QJ1.js → Skeleton-Ci_obQ-g.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C6P2RPY-.js → Skills-DdebN15P.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-B_fPprgw.js → Sla-OinZP2vi.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CqxLjSlQ.js → SpeechSettings-CxzbNF51.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DixSfFOQ.js → SyncSettings-D06N_66b.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-PavzPBxc.js → Tasks-BdEdW0AZ.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BYdGRnfX.js → Templates-F1ctKmPa.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BQLgnarD.js → Tenant-CVz1Urot.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BzOHpq-B.js → Terminal-BvAK_Zel.js} +2 -2
- package/src/assets/web-panel/assets/TimelineRenderer-Doitzjmf.js +1 -0
- package/src/assets/web-panel/assets/{Tokens-DxhgszRJ.js → Tokens-BpyVRpVA.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-nQYHayuc.js → Trigger-nWhWYTbU.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CvqZDuZ4.js → Trust-DK_G-wLx.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DaR8GV2I.js → UkeySign-B5yBUojO.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C6Mpsokw.js → VideoEditing-C5D51qAe.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-B57VRrWc.js → Wallet-CLbL9K7v.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BbtEEtpq.js → WebAuthn-DZUelI3V.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-C5LwvKmH.js → WorkflowEditor-8RPxt4KW.js} +1 -1
- package/src/assets/web-panel/assets/{chat-MzuPR5jh.js → chat-4N4tOA3d.js} +1 -1
- package/src/assets/web-panel/assets/{collapseMotion-mxzzcDsg.js → collapseMotion-DVfhbsdP.js} +1 -1
- package/src/assets/web-panel/assets/{colors-HyW8mi_y.js → colors-zbbGVrua.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DvUSzWAp.js → compact-item-D7iMkbnE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-4MppZl7X.js → createContext-CBzPJv-w.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +1 -0
- package/src/assets/web-panel/assets/{echarts-jxgIOFUZ.js → echarts-CL0F2SnX.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-D9q3CJ-u.js → hasIn-bHdrQSqZ.js} +1 -1
- package/src/assets/web-panel/assets/{icons-DP3uiYxy.js → icons-BsDmGpcT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Caqtu6Et.js → index-308gCGh7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgIfXOD9.js → index-B1s0Bz9O.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcunsBIx.js → index-B7b1hGry.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDZ6fP5Z.js → index-BBNr77E1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BF2JsbiX.js → index-BCr0geV9.js} +1 -1
- package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +1 -0
- package/src/assets/web-panel/assets/{index-CucRo4Vz.js → index-BJ4ZGyW0.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bl-E4W4q.js → index-BS4_Mwk6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dv7ffI2g.js → index-BTIjjXry.js} +1 -1
- package/src/assets/web-panel/assets/index-BXiw9dQf.js +1 -0
- package/src/assets/web-panel/assets/{index-CifKUNtV.js → index-BZb8F8YG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Btz8pU68.js → index-BnBOpqv3.js} +1 -1
- package/src/assets/web-panel/assets/{index-m0b6Fj9q.js → index-Bqmx24kh.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dvg5xYuP.js → index-BsKehmmS.js} +1 -1
- package/src/assets/web-panel/assets/{index-UUMCA2Sq.js → index-BtbbdLnf.js} +4 -4
- package/src/assets/web-panel/assets/{index-CvAqCAo9.js → index-CPxkoKgA.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5E4DhVc.js → index-CQ6NcfWz.js} +1 -1
- package/src/assets/web-panel/assets/{index-B994UQfE.js → index-CQfu1U78.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLAZs1Vd.js → index-CahryTX0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFGfC5RS.js → index-CdmMoYN1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcMkjb92.js → index-Ci009ijp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNYqw0MO.js → index-CiG1IZao.js} +1 -1
- package/src/assets/web-panel/assets/{index--Bm6OqmU.js → index-CkxK86vf.js} +1 -1
- package/src/assets/web-panel/assets/{index-zLwYpvX0.js → index-CqdPyWm5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Zvtru2oE.js → index-CvRMA9uT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmCo2Xdp.js → index-D1YDh7Wr.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2jrnaq3.js → index-D4XKpj6c.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7TDMMfu.js → index-DE9j5YgT.js} +1 -1
- package/src/assets/web-panel/assets/{index-ryFLxB1p.js → index-DISWAYce.js} +1 -1
- package/src/assets/web-panel/assets/{index-xvUVuFnA.js → index-DUyjUkY7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9I5MuJ0.js → index-DbE5D0WL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGQtFso0.js → index-DmqlJed-.js} +1 -1
- package/src/assets/web-panel/assets/{index-SDblbKj6.js → index-DyoNgbXl.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci6adKh8.js → index-QFObYeo1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs-RKRUM.js → index-QNAG4JtR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFqvWeGc.js → index-S74FpAIn.js} +1 -1
- package/src/assets/web-panel/assets/{index-eOQO6KnV.js → index-kmh1TxRa.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmZ6-suL.js → index-oDKNgCsP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0DiL97c.js → index-xYCm6W2h.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CC--PMsC.js → initDefaultProps-BD55yNBt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DdrBjRF1.js → motion-B5Bbe77U.js} +1 -1
- package/src/assets/web-panel/assets/{move-D712Gwl2.js → move-CTvIqHEH.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-39y-keKO.js → mtc-parser-BkNyPQKB.js} +1 -1
- package/src/assets/web-panel/assets/{omit-6Y51gDB9.js → omit-BaXJXgHA.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Cy6EHbq9.js → pickAttrs-Bw6-YTxH.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BYxdAm0p.js → placementArrow-BLdbkLqJ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C9R6q_cr.js → responsiveObserve-IVYkzntU.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CXUJlilB.js → slide-DFMFwwtY.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DOtrOeql.js → statusUtils-CURYRtZ1.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-D5r39o92.js → styleChecker-Cfz63s1r.js} +1 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-COJL0KE3.js +1 -0
- package/src/assets/web-panel/assets/{useFs-BkrT-Zbc.js → useFs-YLLojQQf.js} +1 -1
- package/src/assets/web-panel/assets/{useMergedState-Cl2q1fes.js → useMergedState-Dc9sO2d7.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BwnnnZjU.js → usePersonalDataHub-BF_21qUC.js} +1 -1
- package/src/assets/web-panel/assets/{useRefs-DD9q4mOT.js → useRefs-CAeFRzPf.js} +1 -1
- package/src/assets/web-panel/assets/{useState-BK4hy8Ma.js → useState-LwExUYDO.js} +1 -1
- package/src/assets/web-panel/assets/{vendor-BvqAck49.js → vendor-BMxUs6UX.js} +16 -16
- package/src/assets/web-panel/assets/{vnode-SU-N4pum.js → vnode-9ZpkA7bb.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DHScfpTP.js → zoom-DhtAfhl8.js} +1 -1
- package/src/assets/web-panel/index.html +3 -3
- package/src/commands/serve.js +10 -0
- package/src/gateways/remote-session-relay.js +160 -0
- package/src/gateways/ws/message-dispatcher.js +32 -0
- package/src/gateways/ws/remote-session-protocol.js +429 -0
- package/src/gateways/ws/ws-server.js +299 -0
- package/src/harness/golden-transcript.js +65 -0
- package/src/harness/mcp-client.js +6 -2
- package/src/harness/remote-session-audit-sink.js +132 -0
- package/src/harness/remote-session-audit.js +110 -0
- package/src/harness/remote-session-crypto.js +217 -0
- package/src/harness/remote-session-push-fcm.js +254 -0
- package/src/harness/remote-session-push.js +104 -0
- package/src/harness/remote-session-registry.js +420 -0
- package/src/lib/did-manager.js +6 -4
- package/src/lib/mcp-oauth.js +23 -6
- package/src/lib/session-manager.js +7 -3
- package/src/runtime/agent-runtime.js +8 -13
- package/src/runtime/policies/agent-policy.js +2 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-D2KfETZD.js +0 -1
- package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +0 -1
- package/src/assets/web-panel/assets/MobileBridge-CYaITZ7w.js +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-Bv7uZRM7.js +0 -1
- package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +0 -1
- package/src/assets/web-panel/assets/index-D_oeGLr6.js +0 -1
- package/src/assets/web-panel/assets/index-Qa57YG19.js +0 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-DfAD5U4Z.js +0 -1
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "crypto";
|
|
2
|
+
|
|
3
|
+
export const REMOTE_SESSION_PROTOCOL_VERSION = "1.0";
|
|
4
|
+
export const REMOTE_SESSION_SCOPES = Object.freeze([
|
|
5
|
+
"observe",
|
|
6
|
+
"prompt",
|
|
7
|
+
"approve",
|
|
8
|
+
"interrupt",
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
const DEFAULT_TOKEN_TTL_MS = 5 * 60 * 1000;
|
|
12
|
+
const DEFAULT_SESSION_TTL_MS = 12 * 60 * 60 * 1000;
|
|
13
|
+
|
|
14
|
+
function hashToken(token) {
|
|
15
|
+
return createHash("sha256").update(String(token), "utf8").digest();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function tokensMatch(token, digest) {
|
|
19
|
+
const candidate = hashToken(token);
|
|
20
|
+
return (
|
|
21
|
+
candidate.length === digest.length && timingSafeEqual(candidate, digest)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizeScopes(scopes) {
|
|
26
|
+
const requested = scopes || REMOTE_SESSION_SCOPES;
|
|
27
|
+
if (!Array.isArray(requested) || requested.length === 0) {
|
|
28
|
+
throw new TypeError("Remote session scopes must be a non-empty array");
|
|
29
|
+
}
|
|
30
|
+
const unique = [...new Set(requested)];
|
|
31
|
+
for (const scope of unique) {
|
|
32
|
+
if (!REMOTE_SESSION_SCOPES.includes(scope)) {
|
|
33
|
+
throw new Error(`Unsupported remote session scope: ${scope}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return unique;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Org-level constraints an administrator can impose on Remote Sessions. Lives
|
|
41
|
+
* next to the registry (its single enforcement point) so both the direct WS
|
|
42
|
+
* join and the relay pairing path go through the same checks. Permissive by
|
|
43
|
+
* default — an unconfigured policy is a no-op.
|
|
44
|
+
*/
|
|
45
|
+
export class RemoteSessionPolicy {
|
|
46
|
+
constructor({
|
|
47
|
+
allowedScopes = null,
|
|
48
|
+
maxDevices = null,
|
|
49
|
+
maxSessionTtlMs = null,
|
|
50
|
+
maxTokenTtlMs = null,
|
|
51
|
+
allowRelayPairing = true,
|
|
52
|
+
} = {}) {
|
|
53
|
+
this.allowedScopes = allowedScopes ? [...new Set(allowedScopes)] : null;
|
|
54
|
+
if (this.allowedScopes) {
|
|
55
|
+
if (this.allowedScopes.length === 0) {
|
|
56
|
+
throw new Error("allowedScopes cannot be empty");
|
|
57
|
+
}
|
|
58
|
+
for (const scope of this.allowedScopes) {
|
|
59
|
+
if (!REMOTE_SESSION_SCOPES.includes(scope)) {
|
|
60
|
+
throw new Error(`Unknown scope in org policy: ${scope}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
this.maxDevices =
|
|
65
|
+
maxDevices == null ? null : Math.max(0, Math.floor(maxDevices));
|
|
66
|
+
this.maxSessionTtlMs =
|
|
67
|
+
maxSessionTtlMs == null ? null : Math.max(1, Math.floor(maxSessionTtlMs));
|
|
68
|
+
this.maxTokenTtlMs =
|
|
69
|
+
maxTokenTtlMs == null ? null : Math.max(1, Math.floor(maxTokenTtlMs));
|
|
70
|
+
this.allowRelayPairing = allowRelayPairing !== false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Narrow requested scopes to the org-allowed set. Throws only when the request
|
|
75
|
+
* and the allow-list are wholly disjoint (i.e. nothing could be granted).
|
|
76
|
+
*/
|
|
77
|
+
applyScopes(requestedScopes) {
|
|
78
|
+
if (!this.allowedScopes) {
|
|
79
|
+
return { scopes: requestedScopes || null, narrowed: false };
|
|
80
|
+
}
|
|
81
|
+
const requested =
|
|
82
|
+
requestedScopes && requestedScopes.length
|
|
83
|
+
? [...new Set(requestedScopes)]
|
|
84
|
+
: [...REMOTE_SESSION_SCOPES];
|
|
85
|
+
const granted = requested.filter((scope) =>
|
|
86
|
+
this.allowedScopes.includes(scope),
|
|
87
|
+
);
|
|
88
|
+
if (granted.length === 0) {
|
|
89
|
+
throw new Error("Remote session scopes are not permitted by org policy");
|
|
90
|
+
}
|
|
91
|
+
return { scopes: granted, narrowed: granted.length !== requested.length };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
capSessionTtl(ttlMs) {
|
|
95
|
+
return this.maxSessionTtlMs == null
|
|
96
|
+
? ttlMs
|
|
97
|
+
: Math.min(ttlMs, this.maxSessionTtlMs);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
capTokenTtl(ttlMs) {
|
|
101
|
+
return this.maxTokenTtlMs == null
|
|
102
|
+
? ttlMs
|
|
103
|
+
: Math.min(ttlMs, this.maxTokenTtlMs);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
enforceJoin({ deviceCount, via } = {}) {
|
|
107
|
+
if (via === "relay" && !this.allowRelayPairing) {
|
|
108
|
+
throw new Error("Relay pairing is disabled by org policy");
|
|
109
|
+
}
|
|
110
|
+
if (this.maxDevices != null && deviceCount >= this.maxDevices) {
|
|
111
|
+
throw new Error("Org policy device limit reached");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
describe() {
|
|
116
|
+
return {
|
|
117
|
+
allowedScopes: this.allowedScopes,
|
|
118
|
+
maxDevices: this.maxDevices,
|
|
119
|
+
maxSessionTtlMs: this.maxSessionTtlMs,
|
|
120
|
+
maxTokenTtlMs: this.maxTokenTtlMs,
|
|
121
|
+
allowRelayPairing: this.allowRelayPairing,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static fromEnv(env = {}) {
|
|
126
|
+
const options = {};
|
|
127
|
+
const scopes = env.CHAINLESSCHAIN_REMOTE_SESSION_ALLOWED_SCOPES;
|
|
128
|
+
if (scopes) {
|
|
129
|
+
options.allowedScopes = scopes
|
|
130
|
+
.split(",")
|
|
131
|
+
.map((scope) => scope.trim())
|
|
132
|
+
.filter(Boolean);
|
|
133
|
+
}
|
|
134
|
+
const num = (value) => {
|
|
135
|
+
const parsed = Number(value);
|
|
136
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
137
|
+
};
|
|
138
|
+
if (env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_DEVICES != null) {
|
|
139
|
+
options.maxDevices = num(env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_DEVICES);
|
|
140
|
+
}
|
|
141
|
+
if (env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_SESSION_TTL_MS != null) {
|
|
142
|
+
options.maxSessionTtlMs = num(
|
|
143
|
+
env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_SESSION_TTL_MS,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_TOKEN_TTL_MS != null) {
|
|
147
|
+
options.maxTokenTtlMs = num(
|
|
148
|
+
env.CHAINLESSCHAIN_REMOTE_SESSION_MAX_TOKEN_TTL_MS,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
if (env.CHAINLESSCHAIN_REMOTE_SESSION_ALLOW_RELAY != null) {
|
|
152
|
+
options.allowRelayPairing = !/^(0|false|no|off)$/i.test(
|
|
153
|
+
String(env.CHAINLESSCHAIN_REMOTE_SESSION_ALLOW_RELAY).trim(),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return new RemoteSessionPolicy(options);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function publicSession(session) {
|
|
161
|
+
return {
|
|
162
|
+
protocolVersion: REMOTE_SESSION_PROTOCOL_VERSION,
|
|
163
|
+
sessionId: session.sessionId,
|
|
164
|
+
agentSessionId: session.agentSessionId,
|
|
165
|
+
name: session.name,
|
|
166
|
+
hostClientId: session.hostClientId,
|
|
167
|
+
createdAt: session.createdAt,
|
|
168
|
+
expiresAt: session.expiresAt,
|
|
169
|
+
memberCount: session.members.size,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** In-memory authorization state for one local CLI process. */
|
|
174
|
+
export class RemoteSessionRegistry {
|
|
175
|
+
constructor(options = {}) {
|
|
176
|
+
this.now = options.now || Date.now;
|
|
177
|
+
this.tokenTtlMs = options.tokenTtlMs || DEFAULT_TOKEN_TTL_MS;
|
|
178
|
+
this.sessionTtlMs = options.sessionTtlMs || DEFAULT_SESSION_TTL_MS;
|
|
179
|
+
this.policy = options.policy || new RemoteSessionPolicy();
|
|
180
|
+
this.sessions = new Map();
|
|
181
|
+
this.tokens = new Map();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
create({ hostClientId, agentSessionId, name, scopes } = {}) {
|
|
185
|
+
if (!hostClientId) throw new Error("hostClientId is required");
|
|
186
|
+
if (!agentSessionId) throw new Error("agentSessionId is required");
|
|
187
|
+
const now = this.now();
|
|
188
|
+
const session = {
|
|
189
|
+
sessionId: randomUUID(),
|
|
190
|
+
agentSessionId,
|
|
191
|
+
name: name || agentSessionId,
|
|
192
|
+
hostClientId,
|
|
193
|
+
createdAt: now,
|
|
194
|
+
expiresAt: now + this.policy.capSessionTtl(this.sessionTtlMs),
|
|
195
|
+
members: new Map([
|
|
196
|
+
[
|
|
197
|
+
hostClientId,
|
|
198
|
+
{
|
|
199
|
+
clientId: hostClientId,
|
|
200
|
+
scopes: REMOTE_SESSION_SCOPES,
|
|
201
|
+
joinedAt: now,
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
]),
|
|
205
|
+
};
|
|
206
|
+
this.sessions.set(session.sessionId, session);
|
|
207
|
+
return {
|
|
208
|
+
session: publicSession(session),
|
|
209
|
+
pairing: this.issuePairingToken(session.sessionId, { scopes }),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
issuePairingToken(sessionId, { scopes } = {}) {
|
|
214
|
+
const session = this.requireSession(sessionId);
|
|
215
|
+
const token = randomBytes(32).toString("base64url");
|
|
216
|
+
const now = this.now();
|
|
217
|
+
const { scopes: applied, narrowed } = this.policy.applyScopes(scopes);
|
|
218
|
+
const grantedScopes = normalizeScopes(applied);
|
|
219
|
+
this.tokens.set(sessionId, {
|
|
220
|
+
digest: hashToken(token),
|
|
221
|
+
scopes: grantedScopes,
|
|
222
|
+
createdAt: now,
|
|
223
|
+
expiresAt: Math.min(
|
|
224
|
+
now + this.policy.capTokenTtl(this.tokenTtlMs),
|
|
225
|
+
session.expiresAt,
|
|
226
|
+
),
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
token,
|
|
230
|
+
expiresAt: this.tokens.get(sessionId).expiresAt,
|
|
231
|
+
scopes: grantedScopes,
|
|
232
|
+
policyNarrowed: narrowed,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
join({
|
|
237
|
+
sessionId,
|
|
238
|
+
clientId,
|
|
239
|
+
token,
|
|
240
|
+
via = "direct",
|
|
241
|
+
pushToken = null,
|
|
242
|
+
pushProvider = null,
|
|
243
|
+
} = {}) {
|
|
244
|
+
if (!clientId) throw new Error("clientId is required");
|
|
245
|
+
const session = this.requireSession(sessionId);
|
|
246
|
+
const pairing = this.tokens.get(sessionId);
|
|
247
|
+
if (!pairing || pairing.expiresAt <= this.now()) {
|
|
248
|
+
this.tokens.delete(sessionId);
|
|
249
|
+
throw new Error("Pairing token is missing or expired");
|
|
250
|
+
}
|
|
251
|
+
if (!tokensMatch(token, pairing.digest)) {
|
|
252
|
+
throw new Error("Invalid pairing token");
|
|
253
|
+
}
|
|
254
|
+
// Org policy is enforced only after the token proves the caller is invited,
|
|
255
|
+
// so a device-limit / relay-disabled message never leaks to unauthenticated
|
|
256
|
+
// probes. Existing (non-host) devices count against the limit.
|
|
257
|
+
const deviceCount = [...session.members.values()].filter(
|
|
258
|
+
(member) => member.clientId !== session.hostClientId,
|
|
259
|
+
).length;
|
|
260
|
+
this.policy.enforceJoin({ deviceCount, via });
|
|
261
|
+
// Pairing credentials are deliberately one-time. The host must explicitly
|
|
262
|
+
// issue another token for each additional device.
|
|
263
|
+
this.tokens.delete(sessionId);
|
|
264
|
+
const member = {
|
|
265
|
+
clientId,
|
|
266
|
+
scopes: pairing.scopes,
|
|
267
|
+
joinedAt: this.now(),
|
|
268
|
+
pushToken: pushToken || null,
|
|
269
|
+
pushProvider: pushToken ? pushProvider || null : null,
|
|
270
|
+
};
|
|
271
|
+
session.members.set(clientId, member);
|
|
272
|
+
return { session: publicSession(session), member: { ...member } };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* A device registers (or refreshes / clears) its own vendor push token after
|
|
277
|
+
* pairing — e.g. once FCM assigns one. Only an existing member may set its own
|
|
278
|
+
* token. A null token clears push for that device.
|
|
279
|
+
*/
|
|
280
|
+
registerPush(sessionId, clientId, { token = null, provider = null } = {}) {
|
|
281
|
+
const session = this.requireSession(sessionId);
|
|
282
|
+
const member = session.members.get(clientId);
|
|
283
|
+
if (!member) {
|
|
284
|
+
throw new Error("Device is not paired with this remote session");
|
|
285
|
+
}
|
|
286
|
+
member.pushToken = token || null;
|
|
287
|
+
member.pushProvider = token ? provider || null : null;
|
|
288
|
+
return {
|
|
289
|
+
clientId,
|
|
290
|
+
hasPush: Boolean(member.pushToken),
|
|
291
|
+
provider: member.pushProvider,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Non-host members that carry a push token, for wake-up dispatch. */
|
|
296
|
+
pushTargets(sessionId, { excludeClientId } = {}) {
|
|
297
|
+
const session = this.requireSession(sessionId);
|
|
298
|
+
const targets = [];
|
|
299
|
+
for (const member of session.members.values()) {
|
|
300
|
+
if (member.clientId === session.hostClientId) continue;
|
|
301
|
+
if (member.clientId === excludeClientId) continue;
|
|
302
|
+
if (!member.pushToken) continue;
|
|
303
|
+
targets.push({
|
|
304
|
+
clientId: member.clientId,
|
|
305
|
+
pushToken: member.pushToken,
|
|
306
|
+
pushProvider: member.pushProvider,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return targets;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
authorize(sessionId, clientId, scope) {
|
|
313
|
+
const session = this.requireSession(sessionId);
|
|
314
|
+
const member = session.members.get(clientId);
|
|
315
|
+
if (!member)
|
|
316
|
+
throw new Error("Client is not paired with this remote session");
|
|
317
|
+
if (!member.scopes.includes(scope)) {
|
|
318
|
+
throw new Error(`Remote session scope required: ${scope}`);
|
|
319
|
+
}
|
|
320
|
+
return { session, member };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
members(sessionId) {
|
|
324
|
+
const session = this.requireSession(sessionId);
|
|
325
|
+
return [...session.members.values()].map((member) => ({ ...member }));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Host-only view of every paired device on a session. The host flag lets the
|
|
330
|
+
* UI keep the host row un-revocable and label it distinctly.
|
|
331
|
+
*/
|
|
332
|
+
listDevices(sessionId, hostClientId) {
|
|
333
|
+
const session = this.requireSession(sessionId);
|
|
334
|
+
if (hostClientId && session.hostClientId !== hostClientId) {
|
|
335
|
+
throw new Error("Only the host can list paired devices");
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
session: publicSession(session),
|
|
339
|
+
devices: [...session.members.values()].map((member) => ({
|
|
340
|
+
clientId: member.clientId,
|
|
341
|
+
scopes: [...member.scopes],
|
|
342
|
+
joinedAt: member.joinedAt,
|
|
343
|
+
isHost: member.clientId === session.hostClientId,
|
|
344
|
+
hasPush: Boolean(member.pushToken),
|
|
345
|
+
pushProvider: member.pushProvider || null,
|
|
346
|
+
})),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Host-initiated revocation of a single paired device. The host cannot revoke
|
|
352
|
+
* itself (use close() to end the whole session). Returns the removed member so
|
|
353
|
+
* callers can push a revocation notice to that device.
|
|
354
|
+
*/
|
|
355
|
+
revokeMember(sessionId, hostClientId, clientId) {
|
|
356
|
+
if (!clientId) throw new Error("clientId is required");
|
|
357
|
+
const session = this.requireSession(sessionId);
|
|
358
|
+
if (session.hostClientId !== hostClientId) {
|
|
359
|
+
throw new Error("Only the host can revoke devices");
|
|
360
|
+
}
|
|
361
|
+
if (clientId === session.hostClientId) {
|
|
362
|
+
throw new Error("Cannot revoke the host device");
|
|
363
|
+
}
|
|
364
|
+
const member = session.members.get(clientId);
|
|
365
|
+
if (!member)
|
|
366
|
+
throw new Error("Device is not paired with this remote session");
|
|
367
|
+
session.members.delete(clientId);
|
|
368
|
+
return { session: publicSession(session), member: { ...member } };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
findHosted(agentSessionId, hostClientId) {
|
|
372
|
+
const matches = [];
|
|
373
|
+
for (const session of this.sessions.values()) {
|
|
374
|
+
if (
|
|
375
|
+
session.agentSessionId === agentSessionId &&
|
|
376
|
+
session.hostClientId === hostClientId &&
|
|
377
|
+
session.expiresAt > this.now()
|
|
378
|
+
) {
|
|
379
|
+
matches.push(session);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return matches;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
removeClient(clientId) {
|
|
386
|
+
const affected = [];
|
|
387
|
+
for (const [sessionId, session] of this.sessions) {
|
|
388
|
+
if (!session.members.delete(clientId)) continue;
|
|
389
|
+
if (session.hostClientId === clientId) {
|
|
390
|
+
this.sessions.delete(sessionId);
|
|
391
|
+
this.tokens.delete(sessionId);
|
|
392
|
+
affected.push({ sessionId, closed: true });
|
|
393
|
+
} else {
|
|
394
|
+
affected.push({ sessionId, closed: false });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return affected;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
close(sessionId, clientId) {
|
|
401
|
+
const session = this.requireSession(sessionId);
|
|
402
|
+
if (session.hostClientId !== clientId) {
|
|
403
|
+
throw new Error("Only the host can close a Remote Session");
|
|
404
|
+
}
|
|
405
|
+
this.sessions.delete(sessionId);
|
|
406
|
+
this.tokens.delete(sessionId);
|
|
407
|
+
return publicSession(session);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
requireSession(sessionId) {
|
|
411
|
+
const session = this.sessions.get(sessionId);
|
|
412
|
+
if (!session) throw new Error("Remote session not found");
|
|
413
|
+
if (session.expiresAt <= this.now()) {
|
|
414
|
+
this.sessions.delete(sessionId);
|
|
415
|
+
this.tokens.delete(sessionId);
|
|
416
|
+
throw new Error("Remote session expired");
|
|
417
|
+
}
|
|
418
|
+
return session;
|
|
419
|
+
}
|
|
420
|
+
}
|
package/src/lib/did-manager.js
CHANGED
|
@@ -163,10 +163,12 @@ export function setDefaultIdentity(db, did) {
|
|
|
163
163
|
const identity = getIdentity(db, did);
|
|
164
164
|
if (!identity) return false;
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
// Clear the current default(s). Match on is_default rather than `did LIKE '%'`
|
|
167
|
+
// so there's no wildcard pattern here that a reader/scanner could mistake for
|
|
168
|
+
// LIKE-injection — the target below is set via exact `did = ?` regardless.
|
|
169
|
+
db.prepare(
|
|
170
|
+
"UPDATE did_identities SET is_default = 0 WHERE is_default = 1",
|
|
171
|
+
).run();
|
|
170
172
|
db.prepare("UPDATE did_identities SET is_default = ? WHERE did = ?").run(
|
|
171
173
|
1,
|
|
172
174
|
identity.did,
|
package/src/lib/mcp-oauth.js
CHANGED
|
@@ -35,6 +35,7 @@ export const _deps = {
|
|
|
35
35
|
sha256: (s) => crypto.createHash("sha256").update(s).digest(),
|
|
36
36
|
createServer: (h) => http.createServer(h),
|
|
37
37
|
openBrowser: defaultOpenBrowser,
|
|
38
|
+
spawn: (...a) => spawn(...a),
|
|
38
39
|
now: () => Date.now(),
|
|
39
40
|
// Backoff sleep seam (tests override with a no-op so the retry doesn't wait).
|
|
40
41
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
@@ -648,13 +649,29 @@ export async function ensureValidToken(
|
|
|
648
649
|
|
|
649
650
|
// ── interactive orchestrator ──────────────────────────────────────────────
|
|
650
651
|
|
|
651
|
-
function defaultOpenBrowser(url) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
652
|
+
export function defaultOpenBrowser(url, platform = process.platform) {
|
|
653
|
+
// The authorize URL derives from REMOTE OAuth server metadata, so treat it
|
|
654
|
+
// as untrusted: only http(s) may reach the OS opener (no file:/ms-settings:/
|
|
655
|
+
// custom-scheme handlers), and it must never pass through cmd.exe's line
|
|
656
|
+
// parser — `cmd /c start "" <url>` truncates at the first unquoted `&` and
|
|
657
|
+
// EXECUTES the remainder as commands (query strings always contain `&`).
|
|
658
|
+
let parsed;
|
|
656
659
|
try {
|
|
657
|
-
|
|
660
|
+
parsed = new URL(url);
|
|
661
|
+
} catch {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
|
|
665
|
+
// win32: rundll32 is a plain executable — the URL arrives as a verbatim
|
|
666
|
+
// argv entry with no shell metacharacter interpretation.
|
|
667
|
+
const [cmd, args] =
|
|
668
|
+
platform === "win32"
|
|
669
|
+
? ["rundll32", ["url.dll,FileProtocolHandler", parsed.href]]
|
|
670
|
+
: platform === "darwin"
|
|
671
|
+
? ["open", [parsed.href]]
|
|
672
|
+
: ["xdg-open", [parsed.href]];
|
|
673
|
+
try {
|
|
674
|
+
const child = _deps.spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
658
675
|
child.unref?.();
|
|
659
676
|
return true;
|
|
660
677
|
} catch {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { createHash } from "crypto";
|
|
9
9
|
import { safeJsonParse } from "./safe-json.js";
|
|
10
|
+
import { likePrefix } from "./sql-like.js";
|
|
10
11
|
|
|
11
12
|
function ensureSessionsTable(db) {
|
|
12
13
|
db.exec(`
|
|
@@ -115,10 +116,13 @@ export function getSession(db, sessionId) {
|
|
|
115
116
|
.prepare("SELECT * FROM llm_sessions WHERE id = ?")
|
|
116
117
|
.get(sessionId);
|
|
117
118
|
|
|
118
|
-
if (!session) {
|
|
119
|
+
if (!session && sessionId) {
|
|
120
|
+
// Prefix match as a fallback. Escape LIKE metachars (% _ \) in the id and
|
|
121
|
+
// pair with ESCAPE '\' so a value containing them can't wildcard-match the
|
|
122
|
+
// WRONG session — getSession resolves the id that resume writes back to.
|
|
119
123
|
session = db
|
|
120
|
-
.prepare("SELECT * FROM llm_sessions WHERE id LIKE ? LIMIT 1")
|
|
121
|
-
.get(
|
|
124
|
+
.prepare("SELECT * FROM llm_sessions WHERE id LIKE ? ESCAPE '\\' LIMIT 1")
|
|
125
|
+
.get(likePrefix(sessionId));
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
if (!session) return null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import {
|
|
2
|
+
import { defaultOpenBrowser } from "../lib/mcp-oauth.js";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import {
|
|
5
5
|
RuntimeEventEmitter,
|
|
@@ -41,19 +41,10 @@ const BUILTIN_CODING_AGENT_MCP_REGISTRY = Object.freeze({
|
|
|
41
41
|
],
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// Shared safe opener: validates http(s) and never routes the URL through a
|
|
45
|
+
// shell (execSync `start "" "${url}"` let `"`/`$()` in a URL reach cmd.exe/sh).
|
|
44
46
|
function openBrowser(url) {
|
|
45
|
-
|
|
46
|
-
const platform = process.platform;
|
|
47
|
-
if (platform === "win32") {
|
|
48
|
-
execSync(`start "" "${url}"`, { stdio: "ignore" });
|
|
49
|
-
} else if (platform === "darwin") {
|
|
50
|
-
execSync(`open "${url}"`, { stdio: "ignore" });
|
|
51
|
-
} else {
|
|
52
|
-
execSync(`xdg-open "${url}"`, { stdio: "ignore" });
|
|
53
|
-
}
|
|
54
|
-
} catch (_err) {
|
|
55
|
-
// Non-critical.
|
|
56
|
-
}
|
|
47
|
+
defaultOpenBrowser(url);
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
export class AgentRuntime {
|
|
@@ -211,6 +202,8 @@ export class AgentRuntime {
|
|
|
211
202
|
allowRemote,
|
|
212
203
|
project,
|
|
213
204
|
httpPort,
|
|
205
|
+
remoteSessionRelayUrl,
|
|
206
|
+
remoteSessionPeerId,
|
|
214
207
|
} = this.policy;
|
|
215
208
|
let { host } = this.policy;
|
|
216
209
|
|
|
@@ -325,6 +318,8 @@ export class AgentRuntime {
|
|
|
325
318
|
maxConnections,
|
|
326
319
|
timeout,
|
|
327
320
|
sessionManager,
|
|
321
|
+
remoteSessionRelayUrl,
|
|
322
|
+
remoteSessionPeerId,
|
|
328
323
|
envelopeBus,
|
|
329
324
|
});
|
|
330
325
|
|
|
@@ -26,6 +26,8 @@ export function resolveAgentPolicy({
|
|
|
26
26
|
noStream: overrides.noStream === true,
|
|
27
27
|
parkOnExit: overrides.parkOnExit === false ? false : true,
|
|
28
28
|
bundlePath: overrides.bundlePath || null,
|
|
29
|
+
remoteSessionRelayUrl: overrides.remoteSessionRelayUrl || null,
|
|
30
|
+
remoteSessionPeerId: overrides.remoteSessionPeerId || null,
|
|
29
31
|
additionalDirectories: Array.isArray(overrides.additionalDirectories)
|
|
30
32
|
? overrides.additionalDirectories
|
|
31
33
|
: [],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as h,P as u,J as S,U as n,R as a,S as y,K as C,Q as x,V as w,_ as B,b as s}from"./vendor-BvqAck49.js";import{_ as k}from"./index-UUMCA2Sq.js";import"./icons-DP3uiYxy.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),b=String(e.getMonth()+1).padStart(2,"0"),f=String(e.getDate()).padStart(2,"0"),g=String(e.getHours()).padStart(2,"0"),v=String(e.getMinutes()).padStart(2,"0");return`${p}-${b}-${f} ${g}:${v}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},q={class:"meta"},M={class:"actor"},R={class:"time"},V={class:"body"};function D(c,d,t,r,i,l){const o=h("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",T,[n("div",q,[n("span",M,a(r.actorLabel),1),n("span",R,a(r.formattedTime),1)]),n("div",V,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[x(a(t.event.source.adapter),1)]),_:1},8,["color"])):w("v-if",!0)])],2)}const A=k(N,[["render",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-GZtvqb/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as p,J as m,U as g,R as r,c as a,K as o,V as c,S as _,o as ne,a as X,b as E,r as h,P as s,Q as b,F as R,Z,$ as ie}from"./vendor-BvqAck49.js";import{t as G,_ as he,u as re,b as se,d as v}from"./index-UUMCA2Sq.js";import{s as _e,am as ke,ak as xe,G as ze,Z as Ae,b2 as Se,D as Te,b3 as Ce,as as Oe,R as Fe}from"./icons-DP3uiYxy.js";const Re=Object.freeze(["file-md5","file-sha1","file-sha256","file-sha512","ipv4","ipv6","domain","url","email"]);function T(e,l=0){return typeof e=="number"&&Number.isFinite(e)?e:l}function ye(e,l=0){if(!e||typeof e!="object")return null;const d=e.id||"";if(!d)return null;const t=Array.isArray(e.labels)?e.labels:[];return{key:d,id:d,type:String(e.type||""),value:String(e.value||""),labels:t,confidence:e.confidence!=null?T(e.confidence,null):null,sourceId:e.sourceId??e.source_id??null,sourceName:e.sourceName??e.source_name??null,validFrom:e.validFrom??e.valid_from??null,validUntil:e.validUntil??e.valid_until??null,firstSeenAt:e.firstSeenAt??e.first_seen_at??null,lastSeenAt:e.lastSeenAt??e.last_seen_at??null,_idx:l}}function ce(e){const l=G(e);return Array.isArray(l)?l.map(ye).filter(Boolean):[]}function ue(e){const l=G(e);return!l||typeof l!="object"||Array.isArray(l)?null:{matched:!!l.matched,type:String(l.type||"unknown"),indicator:l.indicator?ye(l.indicator):null}}function de(e){const l={total:0,byType:{}},d=G(e);if(!d||typeof d!="object"||Array.isArray(d))return l;if(l.total=T(d.total,0),d.byType&&typeof d.byType=="object")for(const[t,C]of Object.entries(d.byType))typeof C=="number"&&Number.isFinite(C)&&(l.byType[t]=C);return l}function we(e,l=0){if(!e||typeof e!="object")return null;const d=e.entity||"";return d?{key:d,entity:d,eventCount:T(e.eventCount??e.event_count,0),failureRate:T(e.failureRate??e.failure_rate,0),uniqueResources:T(e.uniqueResources??e.unique_resources,0),uniqueActions:T(e.uniqueActions??e.unique_actions,0),burstiness:T(e.burstiness,0),riskScore:T(e.riskScore??e.risk_score,0),_idx:l}:null}function me(e){const l=G(e);return Array.isArray(l)?l.map(we).filter(Boolean):[]}function Ue(e,l=0){return!e||typeof e!="object"?null:{key:l,score:T(e.score,0),reasons:Array.isArray(e.reasons)?e.reasons:[],event:e.event&&typeof e.event=="object"?e.event:null,_idx:l}}function pe(e){const l=G(e);return Array.isArray(l)?l.map(Ue).filter(Boolean):[]}function $(e){if(!e)return{noAuditLog:!1,error:""};const l=/no such table:\s*audit_log/i.test(e),d=e.match(/Failed:\s*(.+?)(?:\r?\n|$)/i);return{noAuditLog:l,error:d?d[1].trim():""}}function je(e){if(e==null||e==="")return"—";const l=typeof e=="number"?new Date(e):new Date(String(e));return isNaN(l.getTime())?String(e):l.toLocaleString("zh-CN",{hour12:!1})}const Be={__name:"Compliance",setup(e,{expose:l}){l();const d=re(),{t}=se(),C=h(!1),J=h(!1),w=h(!1),U=h(!1),I=h([]),M=h({total:0,byType:{}}),L=h([]),z=h([]),k=h({noAuditLog:!1,error:""}),S=h("threat"),D=h(""),x=h(!1),j=h(!1),N=h(!1),H=X({observable:""}),B=h(null),O=X({entity:"",days:30}),A=X({entity:"",threshold:.7,days:1}),ee=E(()=>[{title:t("compliance.cols.type"),key:"type",width:"120px"},{title:t("compliance.cols.value"),key:"value"},{title:t("compliance.cols.labels"),key:"labels",width:"160px"},{title:t("compliance.cols.confidence"),key:"confidence",width:"90px"},{title:t("compliance.cols.source"),key:"source",width:"160px"},{title:t("compliance.cols.lastSeen"),key:"lastSeen",width:"160px"},{title:t("compliance.cols.action"),key:"action",width:"90px"}]),te=E(()=>[{title:t("compliance.cols.entity"),key:"entity",width:"180px"},{title:t("compliance.cols.riskScore"),key:"riskScore"},{title:t("compliance.cols.eventCount"),key:"eventCount",width:"90px"},{title:t("compliance.cols.failureRate"),key:"failureRate",width:"90px"},{title:t("compliance.cols.uniqueResources"),key:"uniqueResources",width:"90px"},{title:t("compliance.cols.burstiness"),key:"burstiness",width:"90px"}]),ae=E(()=>D.value?I.value.filter(i=>i.type===D.value):I.value),oe=E(()=>Object.keys(M.value.byType).length),W=E(()=>Object.entries(M.value.byType).sort((i,y)=>y[1]-i[1])),F=E(()=>L.value.filter(i=>i.riskScore>=70).length),P={ipv4:"blue",ipv6:"cyan",domain:"purple",url:"magenta",email:"gold","file-md5":"orange","file-sha1":"orange","file-sha256":"red","file-sha512":"red",unknown:"default"};function V(i){return P[i]||"default"}function K(i){return i>=80?"#ff4d4f":i>=50?"#faad14":"#52c41a"}function n(i){return i>=70?"#ff4d4f":i>=40?"#faad14":"#52c41a"}function u(i,y){return i?i.length>y?i.slice(0,y)+"...":i:""}function Y({key:i}){i==="match"?(B.value=null,x.value=!0):i==="ueba-build"?j.value=!0:i==="ueba-analyze"&&(N.value=!0)}async function Q(){C.value=!0;try{const[i,y,f]=await Promise.all([d.execute("compliance threat-intel list --limit 200 --json",1e4).catch(()=>({output:""})),d.execute("compliance threat-intel stats --json",8e3).catch(()=>({output:""})),d.execute("compliance ueba top --top-k 20 --json",1e4).catch(()=>({output:""}))]);I.value=ce(i.output),M.value=de(y.output),k.value=$(f.output),L.value=k.value.noAuditLog?[]:me(f.output)}catch(i){v.error(t("compliance.msg.loadFailed")+": "+(i?.message||i))}finally{C.value=!1}}async function fe(){const i=H.observable.trim();if(!i){v.warning(t("compliance.msg.matchEmpty"));return}J.value=!0,B.value=null;try{const y=`compliance threat-intel match "${i.replace(/"/g,'\\"')}" --json`,{output:f}=await d.execute(y,8e3),q=ue(f);if(!q){v.error(t("compliance.msg.matchFailed")+": "+f.slice(0,120));return}B.value=q,q.matched?v.warning(t("compliance.msg.matchHit",{type:q.type})):q.type==="unknown"?v.info(t("compliance.msg.matchUnknownType")):v.success(t("compliance.msg.matchMiss",{type:q.type}))}catch(y){v.error(t("compliance.msg.matchFailed")+": "+(y?.message||y))}finally{J.value=!1}}async function be(i){try{const y=`compliance threat-intel remove ${i.type} "${i.value.replace(/"/g,'\\"')}" --json`,{output:f}=await d.execute(y,8e3);if(/error|失败/i.test(f)&&!/"removed"/.test(f)){v.error(t("compliance.msg.deleteFailed")+": "+f.slice(0,120));return}v.success(t("compliance.msg.deleteSuccess")),await Q()}catch(y){v.error(t("compliance.msg.deleteFailed")+": "+(y?.message||y))}}async function ve(){w.value=!0;try{const i=["compliance ueba baseline"];O.entity.trim()&&i.push(`--entity "${O.entity.trim().replace(/"/g,'\\"')}"`),O.days!=null&&i.push(`--days ${O.days}`),i.push("--json");const{output:y}=await d.execute(i.join(" "),3e4),f=$(y);if(f.noAuditLog){k.value=f,v.warning(t("compliance.msg.auditEmptyBuild")),j.value=!1;return}if(f.error){v.error(t("compliance.msg.buildFailed")+": "+f.error);return}v.success(t("compliance.msg.buildSuccess")),j.value=!1,S.value="ueba",await Q()}catch(i){v.error(t("compliance.msg.buildFailed")+": "+(i?.message||i))}finally{w.value=!1}}async function ge(){U.value=!0;try{const i=["compliance ueba analyze"];A.entity.trim()&&i.push(`--entity "${A.entity.trim().replace(/"/g,'\\"')}"`),A.threshold!=null&&i.push(`--threshold ${A.threshold}`),A.days!=null&&i.push(`--days ${A.days}`),i.push("--json");const{output:y}=await d.execute(i.join(" "),3e4),f=$(y);if(f.noAuditLog){k.value=f,v.warning(t("compliance.msg.auditEmptyAnalyze")),N.value=!1;return}if(f.error&&!y.includes("[")){v.error(t("compliance.msg.analyzeFailed")+": "+f.error);return}z.value=pe(y),v.success(t("compliance.msg.analyzeSuccess",{n:z.value.length})),N.value=!1,S.value="ueba"}catch(i){v.error(t("compliance.msg.analyzeFailed")+": "+(i?.message||i))}finally{U.value=!1}}ne(Q);const le={ws:d,t,loading:C,matching:J,building:w,analyzing:U,indicators:I,threatStats:M,uebaTop:L,anomalies:z,uebaError:k,activeTab:S,iocTypeFilter:D,showMatchModal:x,showBuildModal:j,showAnalyzeModal:N,matchForm:H,matchResult:B,buildForm:O,analyzeForm:A,indicatorColumns:ee,uebaColumns:te,filteredIndicators:ae,threatTypeCount:oe,typeBreakdown:W,highRiskCount:F,IOC_TYPE_COLORS:P,iocTypeColor:V,confidenceColor:K,riskColor:n,truncate:u,handleNewClick:Y,loadAll:Q,matchObservable:fe,removeIndicator:be,buildBaseline:ve,runAnalyze:ge,ref:h,computed:E,onMounted:ne,reactive:X,get ReloadOutlined(){return Fe},get PlusOutlined(){return Oe},get AimOutlined(){return Ce},get DatabaseOutlined(){return Te},get FundOutlined(){return Se},get SafetyCertificateOutlined(){return Ae},get BlockOutlined(){return ze},get UserOutlined(){return xe},get WarningOutlined(){return ke},get AlertOutlined(){return _e},get message(){return v},get useI18n(){return se},get useWsStore(){return re},get parseIndicators(){return ce},get parseMatchResult(){return ue},get parseThreatIntelStats(){return de},get parseUebaTop(){return me},get parseAnomalies(){return pe},get detectUebaError(){return $},get formatComplianceTime(){return je},get IOC_TYPES(){return Re}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},Ee={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ie={class:"page-title"},Me={class:"page-sub"},Le={class:"filter-bar"},Ne={key:1,style:{color:"var(--text-primary)","font-family":"monospace","font-size":"12px","word-break":"break-all"}},Pe={key:0,style:{color:"var(--text-muted)"}},qe={key:1,style:{color:"var(--text-muted)"}},De={key:0,style:{color:"var(--text-secondary)","font-size":"12px"}},We={key:1,style:{color:"var(--text-muted)"}},Ve={key:5,style:{color:"var(--text-secondary)","font-size":"11px"}},Ke={style:{padding:"40px",color:"var(--text-muted)","text-align":"center"}},Ye={style:{color:"var(--text-primary)",margin:"16px 0 8px","font-size":"14px"}},Ze={key:0,style:{color:"var(--text-primary)","font-family":"monospace","font-weight":"500"}},Ge={key:2,style:{color:"var(--text-secondary)"}},Je={key:5,style:{color:"var(--text-secondary)","font-family":"monospace","font-size":"11px"}},He={style:{padding:"30px",color:"var(--text-muted)","text-align":"center"}},Qe={key:2,style:{color:"var(--text-primary)",margin:"24px 0 8px","font-size":"14px"}},Xe={style:{flex:"1"}},$e={style:{display:"flex",gap:"8px","align-items":"center"}},et={key:0,style:{color:"var(--text-primary)","font-family":"monospace","font-size":"12px"}},tt={key:1,style:{color:"var(--text-secondary)","font-size":"11px"}},at={key:0,style:{"margin-top":"4px"}},ot={style:{"margin-top":"8px","font-size":"12px",color:"var(--text-secondary)"}},lt={key:0,style:{"margin-top":"12px","font-size":"12px"}},nt={style:{color:"var(--text-secondary)"}},it={style:{color:"var(--text-secondary)"}},rt={key:0,style:{"margin-top":"4px"}},st={style:{color:"var(--text-secondary)","font-size":"12px",margin:"0"}},ct={style:{color:"var(--text-secondary)","font-size":"12px",margin:"0"}};function ut(e,l,d,t,C,J){const w=p("a-button"),U=p("a-menu-item"),I=p("a-menu"),M=p("a-dropdown"),L=p("a-space"),z=p("a-statistic"),k=p("a-card"),S=p("a-col"),D=p("a-row"),x=p("a-tag"),j=p("a-radio-button"),N=p("a-radio-group"),H=p("a-popconfirm"),B=p("a-table"),O=p("a-tab-pane"),A=p("a-alert"),ee=p("a-progress"),te=p("a-list-item"),ae=p("a-list"),oe=p("a-tabs"),W=p("a-input"),F=p("a-form-item"),P=p("a-form"),V=p("a-modal"),K=p("a-input-number");return s(),m("div",null,[g("div",Ee,[g("div",null,[g("h2",Ie,r(e.$t("compliance.title")),1),g("p",Me,r(e.$t("compliance.subtitle")),1)]),a(L,null,{default:o(()=>[a(w,{loading:t.loading,onClick:t.loadAll},{icon:o(()=>[a(t.ReloadOutlined)]),default:o(()=>[b(" "+r(e.$t("compliance.refresh")),1)]),_:1},8,["loading"]),a(M,{trigger:["click"]},{overlay:o(()=>[a(I,{onClick:t.handleNewClick},{default:o(()=>[a(U,{key:"match"},{default:o(()=>[a(t.AimOutlined),b(" "+r(e.$t("compliance.actions.match")),1)]),_:1}),a(U,{key:"ueba-build"},{default:o(()=>[a(t.DatabaseOutlined),b(" "+r(e.$t("compliance.actions.uebaBuild")),1)]),_:1}),a(U,{key:"ueba-analyze"},{default:o(()=>[a(t.FundOutlined),b(" "+r(e.$t("compliance.actions.uebaAnalyze")),1)]),_:1})]),_:1})]),default:o(()=>[a(w,{type:"primary"},{icon:o(()=>[a(t.PlusOutlined)]),default:o(()=>[b(" "+r(e.$t("compliance.actionDropdown")),1)]),_:1})]),_:1})]),_:1})]),c(" Stats overview "),a(D,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:o(()=>[a(S,{xs:12,sm:8,lg:5},{default:o(()=>[a(k,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[a(z,{title:e.$t("compliance.stats.iocTotal"),value:t.threatStats.total,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:o(()=>[a(t.SafetyCertificateOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),a(S,{xs:12,sm:8,lg:5},{default:o(()=>[a(k,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[a(z,{title:e.$t("compliance.stats.iocTypes"),value:t.threatTypeCount,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:o(()=>[a(t.BlockOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),a(S,{xs:12,sm:8,lg:5},{default:o(()=>[a(k,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[a(z,{title:e.$t("compliance.stats.riskEntities"),value:t.uebaTop.length,"value-style":{color:"#722ed1",fontSize:"20px"}},{prefix:o(()=>[a(t.UserOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1}),a(S,{xs:12,sm:8,lg:5},{default:o(()=>[a(k,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[a(z,{title:e.$t("compliance.stats.highRisk"),value:t.highRiskCount,"value-style":{color:t.highRiskCount>0?"#ff4d4f":"#52c41a",fontSize:"20px"}},{prefix:o(()=>[a(t.WarningOutlined)]),_:1},8,["title","value","value-style"])]),_:1})]),_:1}),a(S,{xs:24,sm:8,lg:4},{default:o(()=>[a(k,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:o(()=>[a(z,{title:e.$t("compliance.stats.recentAnomalies"),value:t.anomalies.length,"value-style":{color:"#faad14",fontSize:"20px"}},{prefix:o(()=>[a(t.AlertOutlined)]),_:1},8,["title","value"])]),_:1})]),_:1})]),_:1}),c(" Type breakdown "),t.threatStats.total>0?(s(),_(k,{key:0,title:e.$t("compliance.typeBreakdown"),size:"small",style:{background:"var(--bg-card)","border-color":"var(--border-color)","margin-bottom":"20px"},"body-style":{padding:"12px 16px"}},{default:o(()=>[a(L,{size:[12,8],wrap:""},{default:o(()=>[(s(!0),m(R,null,Z(t.typeBreakdown,([n,u])=>(s(),_(x,{key:n,color:t.iocTypeColor(n)},{default:o(()=>[b(r(n)+": "+r(u),1)]),_:2},1032,["color"]))),128))]),_:1})]),_:1},8,["title"])):c("v-if",!0),c(" Tabs "),a(oe,{activeKey:t.activeTab,"onUpdate:activeKey":l[1]||(l[1]=n=>t.activeTab=n),class:"compliance-tabs"},{default:o(()=>[c(" ── Threat Intel tab ──────────────────────────────────────── "),a(O,{key:"threat",tab:e.$t("compliance.tabs.threat")},{default:o(()=>[g("div",Le,[a(N,{value:t.iocTypeFilter,"onUpdate:value":l[0]||(l[0]=n=>t.iocTypeFilter=n),size:"small"},{default:o(()=>[a(j,{value:""},{default:o(()=>[b(r(e.$t("compliance.filter.all")),1)]),_:1}),(s(!0),m(R,null,Z(t.IOC_TYPES,n=>(s(),_(j,{key:n,value:n},{default:o(()=>[b(r(n),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])]),a(B,{columns:t.indicatorColumns,"data-source":t.filteredIndicators,pagination:{pageSize:20,showTotal:n=>e.$t("compliance.table.totalSuffix",{n})},size:"small",loading:t.loading,style:{background:"var(--bg-card)"}},{bodyCell:o(({column:n,record:u})=>[n.key==="type"?(s(),_(x,{key:0,color:t.iocTypeColor(u.type),style:{"font-family":"monospace"}},{default:o(()=>[b(r(u.type),1)]),_:2},1032,["color"])):c("v-if",!0),n.key==="value"?(s(),m("span",Ne,r(t.truncate(u.value,64)),1)):c("v-if",!0),n.key==="labels"?(s(),m(R,{key:2},[(s(!0),m(R,null,Z(u.labels,Y=>(s(),_(x,{key:Y,color:"orange",style:{"font-size":"10px",margin:"1px"}},{default:o(()=>[b(r(Y),1)]),_:2},1024))),128)),u.labels.length?c("v-if",!0):(s(),m("span",Pe,"—"))],64)):c("v-if",!0),n.key==="confidence"?(s(),m(R,{key:3},[u.confidence!=null?(s(),m("span",{key:0,style:ie({color:t.confidenceColor(u.confidence),fontWeight:500})},r(u.confidence),5)):(s(),m("span",qe,"—"))],64)):c("v-if",!0),n.key==="source"?(s(),m(R,{key:4},[u.sourceName?(s(),m("span",De,r(u.sourceName),1)):(s(),m("span",We,"—"))],64)):c("v-if",!0),n.key==="lastSeen"?(s(),m("span",Ve,r(t.formatComplianceTime(u.lastSeenAt)),1)):c("v-if",!0),n.key==="action"?(s(),_(H,{key:6,title:e.$t("compliance.table.deleteConfirm"),"ok-text":e.$t("compliance.table.deleteOk"),"cancel-text":e.$t("compliance.table.cancel"),onConfirm:Y=>t.removeIndicator(u)},{default:o(()=>[a(w,{size:"small",type:"link",danger:""},{default:o(()=>[b(r(e.$t("compliance.table.delete")),1)]),_:1})]),_:1},8,["title","ok-text","cancel-text","onConfirm"])):c("v-if",!0)]),emptyText:o(()=>[g("div",Ke,[a(t.SafetyCertificateOutlined,{style:{"font-size":"36px","margin-bottom":"10px",display:"block"}}),b(" "+r(e.$t("compliance.table.emptyThreatsLine1"))+" ",1),l[11]||(l[11]=g("code",{style:{"font-size":"11px"}},"cc compliance threat-intel import <file.json>",-1))])]),_:1},8,["columns","data-source","pagination","loading"])]),_:1},8,["tab"]),c(" ── UEBA tab ──────────────────────────────────────────────── "),a(O,{key:"ueba",tab:e.$t("compliance.tabs.ueba")},{default:o(()=>[t.uebaError.noAuditLog?(s(),_(A,{key:0,type:"info","show-icon":"",message:e.$t("compliance.ueba.noAuditLog"),description:e.$t("compliance.ueba.noAuditLogDesc"),style:{"margin-bottom":"16px"}},null,8,["message","description"])):t.uebaError.error?(s(),_(A,{key:1,type:"error","show-icon":"",message:e.$t("compliance.ueba.errorMessage",{err:t.uebaError.error}),style:{"margin-bottom":"16px"}},null,8,["message"])):c("v-if",!0),g("h3",Ye,r(e.$t("compliance.ueba.topRiskTitle",{count:t.uebaTop.length})),1),a(B,{columns:t.uebaColumns,"data-source":t.uebaTop,pagination:!1,size:"small",loading:t.loading,style:{background:"var(--bg-card)"}},{bodyCell:o(({column:n,record:u})=>[n.key==="entity"?(s(),m("span",Ze,r(u.entity),1)):c("v-if",!0),n.key==="riskScore"?(s(),_(ee,{key:1,percent:Math.min(u.riskScore,100),"stroke-color":t.riskColor(u.riskScore),size:"small",format:()=>u.riskScore.toFixed(1)},null,8,["percent","stroke-color","format"])):c("v-if",!0),n.key==="eventCount"?(s(),m("span",Ge,r(u.eventCount),1)):c("v-if",!0),n.key==="failureRate"?(s(),m("span",{key:3,style:ie({color:u.failureRate>.3?"#ff4d4f":"var(--text-secondary)",fontFamily:"monospace"})},r((u.failureRate*100).toFixed(1))+"% ",5)):c("v-if",!0),n.key==="uniqueResources"?(s(),_(x,{key:4,color:"cyan",style:{"font-size":"11px"}},{default:o(()=>[b(r(u.uniqueResources),1)]),_:2},1024)):c("v-if",!0),n.key==="burstiness"?(s(),m("span",Je,r((u.burstiness*100).toFixed(0))+"% ",1)):c("v-if",!0)]),emptyText:o(()=>[g("div",He,[a(t.UserOutlined,{style:{"font-size":"32px","margin-bottom":"8px",display:"block"}}),b(" "+r(t.uebaError.noAuditLog?e.$t("compliance.table.emptyAuditEntities"):e.$t("compliance.table.emptyRiskEntities")),1)])]),_:1},8,["columns","data-source","loading"]),t.anomalies.length?(s(),m("h3",Qe,r(e.$t("compliance.ueba.anomalyTitle",{count:t.anomalies.length})),1)):c("v-if",!0),t.anomalies.length?(s(),_(ae,{key:3,size:"small","data-source":t.anomalies,locale:{emptyText:e.$t("compliance.table.noAnomalies")}},{renderItem:o(({item:n})=>[a(te,{style:{background:"var(--bg-card)",padding:"10px 16px"}},{default:o(()=>[g("div",Xe,[g("div",$e,[a(x,{color:t.riskColor(n.score*100)},{default:o(()=>[b("score "+r(n.score.toFixed(2)),1)]),_:2},1032,["color"]),n.event?.entity?(s(),m("span",et,r(n.event.entity),1)):c("v-if",!0),n.event?.action?(s(),m("span",tt," → "+r(n.event.action),1)):c("v-if",!0)]),n.reasons.length?(s(),m("div",at,[(s(!0),m(R,null,Z(n.reasons,u=>(s(),_(x,{key:u,color:"volcano",style:{"font-size":"10px",margin:"1px"}},{default:o(()=>[b(r(u),1)]),_:2},1024))),128))])):c("v-if",!0)])]),_:2},1024)]),_:1},8,["data-source","locale"])):c("v-if",!0)]),_:1},8,["tab"])]),_:1},8,["activeKey"]),c(" ── Match modal ───────────────────────────────────────────── "),a(V,{open:t.showMatchModal,"onUpdate:open":l[3]||(l[3]=n=>t.showMatchModal=n),title:e.$t("compliance.match.modalTitle"),"confirm-loading":t.matching,width:500,"ok-text":e.$t("compliance.match.ok"),"cancel-text":e.$t("compliance.match.close"),onOk:t.matchObservable},{default:o(()=>[a(P,{"label-col":{span:5},"wrapper-col":{span:19},style:{"margin-top":"16px"}},{default:o(()=>[a(F,{label:e.$t("compliance.match.label"),required:""},{default:o(()=>[a(W,{value:t.matchForm.observable,"onUpdate:value":l[2]||(l[2]=n=>t.matchForm.observable=n),placeholder:e.$t("compliance.match.placeholder"),"allow-clear":""},null,8,["value","placeholder"])]),_:1},8,["label"])]),_:1}),t.matchResult?(s(),_(k,{key:0,size:"small",style:{background:"var(--bg-base)","margin-top":"8px"}},{default:o(()=>[a(z,{title:e.$t("compliance.match.result"),value:t.matchResult.matched?e.$t("compliance.match.hit"):e.$t("compliance.match.miss"),"value-style":{color:t.matchResult.matched?"#ff4d4f":"#52c41a"}},null,8,["title","value","value-style"]),g("div",ot,[b(r(e.$t("compliance.match.detectType"))+" ",1),a(x,{color:t.iocTypeColor(t.matchResult.type)},{default:o(()=>[b(r(t.matchResult.type),1)]),_:1},8,["color"])]),t.matchResult.indicator?(s(),m("div",lt,[g("div",nt,r(e.$t("compliance.match.sourcePrefix"))+" "+r(t.matchResult.indicator.sourceName||"—"),1),g("div",it,r(e.$t("compliance.match.confidencePrefix"))+" "+r(t.matchResult.indicator.confidence??"—"),1),t.matchResult.indicator.labels.length?(s(),m("div",rt,[(s(!0),m(R,null,Z(t.matchResult.indicator.labels,n=>(s(),_(x,{key:n,color:"orange",style:{"font-size":"10px"}},{default:o(()=>[b(r(n),1)]),_:2},1024))),128))])):c("v-if",!0)])):c("v-if",!0)]),_:1})):c("v-if",!0)]),_:1},8,["open","title","confirm-loading","ok-text","cancel-text"]),c(" ── UEBA build baseline modal ─────────────────────────────── "),a(V,{open:t.showBuildModal,"onUpdate:open":l[6]||(l[6]=n=>t.showBuildModal=n),title:e.$t("compliance.build.modalTitle"),"confirm-loading":t.building,width:480,"ok-text":e.$t("compliance.build.ok"),"cancel-text":e.$t("compliance.build.cancel"),onOk:t.buildBaseline},{default:o(()=>[a(P,{"label-col":{span:6},"wrapper-col":{span:18},style:{"margin-top":"16px"}},{default:o(()=>[a(F,{label:e.$t("compliance.build.entityLabel")},{default:o(()=>[a(W,{value:t.buildForm.entity,"onUpdate:value":l[4]||(l[4]=n=>t.buildForm.entity=n),placeholder:e.$t("compliance.build.entityPlaceholder")},null,8,["value","placeholder"])]),_:1},8,["label"]),a(F,{label:e.$t("compliance.build.daysLabel")},{default:o(()=>[a(K,{value:t.buildForm.days,"onUpdate:value":l[5]||(l[5]=n=>t.buildForm.days=n),min:1,max:365,placeholder:e.$t("compliance.build.daysPlaceholder"),style:{width:"100%"}},null,8,["value","placeholder"])]),_:1},8,["label"])]),_:1}),g("p",st,r(e.$t("compliance.build.footnote")),1)]),_:1},8,["open","title","confirm-loading","ok-text","cancel-text"]),c(" ── UEBA analyze modal ────────────────────────────────────── "),a(V,{open:t.showAnalyzeModal,"onUpdate:open":l[10]||(l[10]=n=>t.showAnalyzeModal=n),title:e.$t("compliance.analyze.modalTitle"),"confirm-loading":t.analyzing,width:480,"ok-text":e.$t("compliance.analyze.ok"),"cancel-text":e.$t("compliance.analyze.cancel"),onOk:t.runAnalyze},{default:o(()=>[a(P,{"label-col":{span:6},"wrapper-col":{span:18},style:{"margin-top":"16px"}},{default:o(()=>[a(F,{label:e.$t("compliance.analyze.entityLabel")},{default:o(()=>[a(W,{value:t.analyzeForm.entity,"onUpdate:value":l[7]||(l[7]=n=>t.analyzeForm.entity=n),placeholder:e.$t("compliance.analyze.entityPlaceholder")},null,8,["value","placeholder"])]),_:1},8,["label"]),a(F,{label:e.$t("compliance.analyze.thresholdLabel")},{default:o(()=>[a(K,{value:t.analyzeForm.threshold,"onUpdate:value":l[8]||(l[8]=n=>t.analyzeForm.threshold=n),min:0,max:1,step:.05,style:{width:"100%"}},null,8,["value"])]),_:1},8,["label"]),a(F,{label:e.$t("compliance.analyze.daysLabel")},{default:o(()=>[a(K,{value:t.analyzeForm.days,"onUpdate:value":l[9]||(l[9]=n=>t.analyzeForm.days=n),min:1,max:30,style:{width:"100%"}},null,8,["value"])]),_:1},8,["label"])]),_:1}),g("p",ct,r(e.$t("compliance.analyze.footnote")),1)]),_:1},8,["open","title","confirm-loading","ok-text","cancel-text"])])}const yt=he(Be,[["render",ut],["__scopeId","data-v-d3ffc3f8"],["__file","/tmp/cc-web-panel-GZtvqb/repo/packages/web-panel/src/views/Compliance.vue"]]);export{yt as default};
|