@remnic/core 10.0.84 → 10.0.86
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/access-admin-ops-surface.js +90 -88
- package/dist/access-authorization-probe.js +91 -89
- package/dist/access-boundary.d.ts.map +1 -1
- package/dist/access-boundary.js +90 -88
- package/dist/access-cli.js +198 -194
- package/dist/access-cli.js.map +1 -1
- package/dist/access-errors.d.ts +14 -0
- package/dist/access-errors.d.ts.map +1 -1
- package/dist/access-errors.js +5 -1
- package/dist/access-extraction-force-flush.js +90 -88
- package/dist/access-http-briefing.js +91 -89
- package/dist/access-http-query.js +92 -90
- package/dist/access-http.d.ts +12 -0
- package/dist/access-http.d.ts.map +1 -1
- package/dist/access-http.js +119 -116
- package/dist/access-identity-continuity-surface.js +90 -88
- package/dist/access-lcm-surface.js +90 -88
- package/dist/access-mcp-frames.d.ts +29 -0
- package/dist/access-mcp-frames.d.ts.map +1 -0
- package/dist/access-mcp-frames.js +10 -0
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.d.ts.map +1 -1
- package/dist/access-mcp.js +105 -102
- package/dist/access-memory-search-fanout.js +2 -2
- package/dist/access-namespace-preflight.js +90 -88
- package/dist/access-observe-write-category.js +15 -14
- package/dist/access-observe-write-surface.d.ts.map +1 -1
- package/dist/access-observe-write-surface.js +90 -88
- package/dist/access-offline-manifest.js +10 -10
- package/dist/access-operations-batch.js +94 -92
- package/dist/access-operations.js +101 -99
- package/dist/access-recall-concurrency.js +90 -88
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +90 -88
- package/dist/access-recall-surface.js +90 -88
- package/dist/access-schema.d.ts.map +1 -1
- package/dist/access-schema.js +10 -9
- package/dist/access-service.d.ts +3 -3
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +90 -88
- package/dist/access-surface-catalog.js +92 -90
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-token-capabilities.js +2 -2
- package/dist/active-recall.js +38 -38
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/{auto-sync-C7E6G7Y2.js → auto-sync-3AZW7MXI.js} +6 -6
- package/dist/briefing-deadline.d.ts +2 -2
- package/dist/briefing-deadline.d.ts.map +1 -1
- package/dist/briefing-deadline.js +1 -1
- package/dist/briefing.js +25 -25
- package/dist/buffer-admission.d.ts +22 -0
- package/dist/buffer-admission.d.ts.map +1 -0
- package/dist/buffer-admission.js +13 -0
- package/dist/buffer-eviction.d.ts +4 -5
- package/dist/buffer-eviction.d.ts.map +1 -1
- package/dist/buffer-eviction.js +1 -1
- package/dist/buffer-persistence.d.ts +8 -4
- package/dist/buffer-persistence.d.ts.map +1 -1
- package/dist/buffer-persistence.js +1 -1
- package/dist/buffer-turn-helpers.d.ts +12 -0
- package/dist/buffer-turn-helpers.d.ts.map +1 -1
- package/dist/buffer-turn-helpers.js +9 -1
- package/dist/buffer-types.d.ts +24 -1
- package/dist/buffer-types.d.ts.map +1 -1
- package/dist/buffer.d.ts +21 -19
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.js +17 -13
- package/dist/calibration.js +3 -3
- package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/capsule-gunzip-KGBDGF7P.js +11 -0
- package/dist/capsule-gunzip-KGBDGF7P.js.map +1 -0
- package/dist/capsule-import-gate.d.ts +11 -0
- package/dist/capsule-import-gate.d.ts.map +1 -0
- package/dist/capsule-import-gate.js +12 -0
- package/dist/capsule-import-gate.js.map +1 -0
- package/dist/{capsule-merge-XVTQJJ6R.js → capsule-merge-2IIXFXN5.js} +5 -11
- package/dist/capsule-merge-2IIXFXN5.js.map +1 -0
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +27 -27
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-MSIRVXQ3.js → chunk-2G4TV2ML.js} +12 -12
- package/dist/{chunk-B74NPUHT.js → chunk-2JG2NI7C.js} +54 -54
- package/dist/chunk-2JG2NI7C.js.map +1 -0
- package/dist/{chunk-IR4C3DP2.js → chunk-2K3AUDH7.js} +2 -2
- package/dist/{chunk-2IW5PT7U.js → chunk-2N4OUSIA.js} +2 -2
- package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-QZSIDSB2.js → chunk-2NUDHVYM.js} +2 -2
- package/dist/{chunk-HPFVZPRH.js → chunk-2U4LMSEX.js} +3 -3
- package/dist/{chunk-WHQXWFH7.js → chunk-2XOFVTTT.js} +2 -2
- package/dist/{chunk-I6ORDT54.js → chunk-32CA7B6L.js} +2 -2
- package/dist/{chunk-T77AX6DG.js → chunk-32YX7EJ3.js} +4 -4
- package/dist/{chunk-HLKUZW42.js → chunk-3CTKEXXF.js} +144 -156
- package/dist/chunk-3CTKEXXF.js.map +1 -0
- package/dist/{chunk-HLWXCDUQ.js → chunk-3DAWHP5K.js} +5 -5
- package/dist/{chunk-ZJJFUEPO.js → chunk-3PJEDHLD.js} +2 -2
- package/dist/{chunk-PJYK7HH2.js → chunk-3UZ2VMKD.js} +2 -2
- package/dist/{chunk-IN4OFAHX.js → chunk-3Y5X6YFH.js} +2 -2
- package/dist/{chunk-YUTT4ZTI.js → chunk-45VUHDV2.js} +2 -2
- package/dist/{chunk-T6T2RMWW.js → chunk-4GMI5HFH.js} +12 -12
- package/dist/{chunk-YOEYL6CH.js → chunk-4LCVA2LW.js} +3 -3
- package/dist/{chunk-66JOLMWS.js → chunk-4X7HQKAG.js} +2 -2
- package/dist/{chunk-65SKM4BF.js → chunk-4XYAWK5H.js} +2 -2
- package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
- package/dist/{chunk-TPX7XXY4.js → chunk-5SOSQTVE.js} +2 -2
- package/dist/{chunk-G3T6YMBO.js → chunk-64S6X4IU.js} +7 -7
- package/dist/{chunk-BK7AJUWB.js → chunk-6BCWFCDG.js} +7 -7
- package/dist/{chunk-V27FK6D6.js → chunk-6XTUZKCZ.js} +2 -2
- package/dist/{chunk-KASJJGRG.js → chunk-6ZELOK6O.js} +3 -8
- package/dist/chunk-6ZELOK6O.js.map +1 -0
- package/dist/{chunk-LECSS7EE.js → chunk-73UZZFJC.js} +3 -3
- package/dist/{chunk-4EACCIPO.js → chunk-77PDJ4OE.js} +3 -3
- package/dist/{chunk-GQZSGXR6.js → chunk-7GSL4LBG.js} +2 -2
- package/dist/{chunk-B6SPPYGJ.js → chunk-7IWRLYFJ.js} +2 -2
- package/dist/{chunk-R45L4TV6.js → chunk-7LCGFUMB.js} +6 -6
- package/dist/{chunk-A7BM2JTH.js → chunk-AJHNXIQU.js} +2 -2
- package/dist/{chunk-2D7BTSDW.js → chunk-ANZZLRUX.js} +2 -2
- package/dist/{chunk-ZXF3O7P4.js → chunk-ARRTLPRC.js} +2 -2
- package/dist/{chunk-S5CQI2KF.js → chunk-B3GKQ6DU.js} +2 -2
- package/dist/{chunk-XRBHIR7Q.js → chunk-B56LORLY.js} +2 -2
- package/dist/{chunk-KO3YBHOV.js → chunk-BIVKPQ6Q.js} +3 -3
- package/dist/{chunk-QZBTIYKD.js → chunk-BLSHFIR6.js} +7 -6
- package/dist/chunk-BLSHFIR6.js.map +1 -0
- package/dist/{chunk-54FDG7K7.js → chunk-C2HORX76.js} +3 -3
- package/dist/{chunk-WAD32CZG.js → chunk-CC4V7HNP.js} +43 -30
- package/dist/chunk-CC4V7HNP.js.map +1 -0
- package/dist/{chunk-LGEH473S.js → chunk-CJCTKL6Y.js} +9 -1
- package/dist/chunk-CJCTKL6Y.js.map +1 -0
- package/dist/{chunk-E33UJHY3.js → chunk-CN7Q3T2J.js} +4 -4
- package/dist/{chunk-YUTG35M4.js → chunk-CYCEROPR.js} +3 -3
- package/dist/{chunk-TFLPDNQV.js → chunk-D5EV6Y2L.js} +3 -3
- package/dist/{chunk-BFBS7OFQ.js → chunk-DC55RIEZ.js} +4 -4
- package/dist/{chunk-B4ZU34JQ.js → chunk-DT7SNJH6.js} +3 -3
- package/dist/{chunk-VLMBSGQF.js → chunk-DZ7DPDVW.js} +10 -8
- package/dist/chunk-DZ7DPDVW.js.map +1 -0
- package/dist/{chunk-FVRTCYZ3.js → chunk-EA2LA5RI.js} +2 -2
- package/dist/{chunk-WBN66HPI.js → chunk-ELHJK7LM.js} +6 -6
- package/dist/{chunk-77R7BQZ2.js → chunk-EQ4U73UH.js} +77 -24
- package/dist/chunk-EQ4U73UH.js.map +1 -0
- package/dist/{chunk-3JPTUCD7.js → chunk-EUBDYOLD.js} +32 -23
- package/dist/chunk-EUBDYOLD.js.map +1 -0
- package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
- package/dist/{chunk-YAUHSNPB.js → chunk-F74G4KIH.js} +2 -2
- package/dist/{chunk-MPGLM2VU.js → chunk-FF3EFLUT.js} +7 -5
- package/dist/chunk-FF3EFLUT.js.map +1 -0
- package/dist/{chunk-BV2BRHD4.js → chunk-FHGWKODN.js} +2 -2
- package/dist/chunk-FKBGK3NC.js +62 -0
- package/dist/chunk-FKBGK3NC.js.map +1 -0
- package/dist/{chunk-X2KO4FK5.js → chunk-FNFURZBZ.js} +5 -5
- package/dist/chunk-FNFURZBZ.js.map +1 -0
- package/dist/{chunk-KESJ5XX3.js → chunk-G54BOKZ6.js} +2 -2
- package/dist/{chunk-YK7GOPIE.js → chunk-G67EUQAB.js} +9 -7
- package/dist/chunk-G67EUQAB.js.map +1 -0
- package/dist/{chunk-K36RMINQ.js → chunk-GOZXQNIM.js} +3 -3
- package/dist/{chunk-OQSSQOKQ.js → chunk-GULUWOA5.js} +2 -2
- package/dist/{chunk-K6RTQZA4.js → chunk-HFUKXOUW.js} +2 -2
- package/dist/{chunk-WV254W4V.js → chunk-HLN2HOXX.js} +2 -2
- package/dist/{chunk-FUOAIJKQ.js → chunk-IBDWYRDR.js} +3 -3
- package/dist/{chunk-Z3DDQXM4.js → chunk-IBGU6AN6.js} +45 -45
- package/dist/chunk-IBGU6AN6.js.map +1 -0
- package/dist/{chunk-AJG2TAMR.js → chunk-IEEV27BC.js} +2 -2
- package/dist/chunk-IGLJNHOX.js +62 -0
- package/dist/chunk-IGLJNHOX.js.map +1 -0
- package/dist/{chunk-LTDLJCMQ.js → chunk-IJ3OEECW.js} +4 -4
- package/dist/{chunk-BK4FBHZ3.js → chunk-IPD5GC7C.js} +3 -3
- package/dist/{chunk-KFLD7ZZG.js → chunk-IUKYFTGW.js} +3 -3
- package/dist/{chunk-GCAQ3VUJ.js → chunk-JM2YZKCQ.js} +2 -2
- package/dist/{chunk-BNQJKWWZ.js → chunk-K3FH3LAQ.js} +4 -4
- package/dist/{chunk-LU66I56Q.js → chunk-KVSOEVAF.js} +61 -12
- package/dist/chunk-KVSOEVAF.js.map +1 -0
- package/dist/chunk-M3BEJJNV.js +31 -0
- package/dist/chunk-M3BEJJNV.js.map +1 -0
- package/dist/{chunk-RZH5RVJC.js → chunk-MTTYIXSU.js} +2 -2
- package/dist/{chunk-XHGYZRVW.js → chunk-NIVKG3DS.js} +5 -5
- package/dist/{chunk-VZELUMKK.js → chunk-NQP4ZYGG.js} +2 -2
- package/dist/{chunk-7PMOCQOL.js → chunk-NT7F7WJQ.js} +192 -63
- package/dist/chunk-NT7F7WJQ.js.map +1 -0
- package/dist/{chunk-YO2JEX2Z.js → chunk-OGBQMY46.js} +2 -2
- package/dist/{chunk-TLHF75OR.js → chunk-OL553AWT.js} +12 -12
- package/dist/{chunk-CLVILSBR.js → chunk-OZNBZJ3S.js} +22 -22
- package/dist/{chunk-VUROWXFL.js → chunk-P452SEKO.js} +2 -2
- package/dist/{chunk-JX3E4XCW.js → chunk-PDOOUXCS.js} +2 -2
- package/dist/{chunk-6QYPL6NI.js → chunk-PKZ274PI.js} +3 -3
- package/dist/{chunk-KJCL2FZO.js → chunk-QD5R6U5J.js} +2 -2
- package/dist/{chunk-JRVMCZE3.js → chunk-QEYTRFR3.js} +2 -2
- package/dist/{chunk-VKDAJJQP.js → chunk-QEZ3DW5O.js} +11 -11
- package/dist/{chunk-WYPCJK6K.js → chunk-QKERFEJS.js} +2 -2
- package/dist/{chunk-BDN3TDGV.js → chunk-QKES7GU6.js} +2 -2
- package/dist/{chunk-PCQWKMOL.js → chunk-QNSZYTSG.js} +2 -2
- package/dist/chunk-QV2VZKD5.js +31 -0
- package/dist/chunk-QV2VZKD5.js.map +1 -0
- package/dist/{chunk-IZJQNDGI.js → chunk-R6HMAIKM.js} +2 -2
- package/dist/{chunk-CIIHIAJ2.js → chunk-ROGO7FRA.js} +6 -5
- package/dist/{chunk-CIIHIAJ2.js.map → chunk-ROGO7FRA.js.map} +1 -1
- package/dist/{chunk-NUSAAN75.js → chunk-ROKDHO74.js} +2 -2
- package/dist/{chunk-D5SSBCYY.js → chunk-RWGRSKN5.js} +7 -5
- package/dist/chunk-RWGRSKN5.js.map +1 -0
- package/dist/{chunk-FF6N7BXC.js → chunk-S45INSV3.js} +4 -4
- package/dist/{chunk-2RUTN7PR.js → chunk-S7GJNA3K.js} +2 -2
- package/dist/{chunk-XT45WCKX.js → chunk-SYKJBS7S.js} +10 -10
- package/dist/{chunk-5BE3FLKL.js → chunk-TAUHAP5J.js} +4 -4
- package/dist/{chunk-RJWL3RHB.js → chunk-TFEHSPGQ.js} +2 -2
- package/dist/{chunk-XYP5WBDO.js → chunk-TQ4SCPGQ.js} +76 -60
- package/dist/chunk-TQ4SCPGQ.js.map +1 -0
- package/dist/{chunk-K3B72DKJ.js → chunk-TRMZHGIX.js} +8 -8
- package/dist/{chunk-WBDIZWJQ.js → chunk-TSS3D7ZY.js} +2 -2
- package/dist/{chunk-6LCWKS62.js → chunk-UAUV3BWS.js} +104 -121
- package/dist/chunk-UAUV3BWS.js.map +1 -0
- package/dist/{chunk-KQUSP6LB.js → chunk-UDKWFDV2.js} +1 -1
- package/dist/chunk-UDKWFDV2.js.map +1 -0
- package/dist/{chunk-HQPFACXO.js → chunk-UH3FPX3L.js} +2 -2
- package/dist/{chunk-GGJFRVRD.js → chunk-US7KPQA5.js} +2 -2
- package/dist/{chunk-FJ2VJTGA.js → chunk-UWRHHRDK.js} +3 -3
- package/dist/{chunk-4KLQI3L2.js → chunk-UXXK523X.js} +40 -2
- package/dist/chunk-UXXK523X.js.map +1 -0
- package/dist/{chunk-SDESKFKT.js → chunk-UYHDMCY2.js} +2 -2
- package/dist/{chunk-3T3VHXUH.js → chunk-VKILERSL.js} +2 -2
- package/dist/{chunk-2TGIKMMZ.js → chunk-WXDTOE6F.js} +2 -2
- package/dist/{chunk-KQLBXUUQ.js → chunk-WYG5UNDY.js} +2 -2
- package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-MPDLLLOG.js → chunk-XO23OKMK.js} +9 -5
- package/dist/chunk-XO23OKMK.js.map +1 -0
- package/dist/{chunk-WC475JOG.js → chunk-XU37EJTW.js} +24 -24
- package/dist/chunk-XU37EJTW.js.map +1 -0
- package/dist/{chunk-FZVROZKC.js → chunk-XVZA6VXC.js} +4 -4
- package/dist/{chunk-QA3Y2O6H.js → chunk-YAVIBVCU.js} +2 -2
- package/dist/{chunk-2XJZLSXE.js → chunk-YL4UKMD7.js} +124 -58
- package/dist/chunk-YL4UKMD7.js.map +1 -0
- package/dist/{chunk-VPEIWMUT.js → chunk-YLTU2DC4.js} +2 -2
- package/dist/{chunk-HWHNQVRV.js → chunk-YMJRLT7S.js} +28 -8
- package/dist/chunk-YMJRLT7S.js.map +1 -0
- package/dist/{chunk-EBOHFZI4.js → chunk-YRZPBN46.js} +3 -3
- package/dist/{chunk-FMFCQRDM.js → chunk-ZANNIXXE.js} +3 -3
- package/dist/{chunk-HQGATKG2.js → chunk-ZBFLV657.js} +3 -3
- package/dist/{chunk-6L63IN3M.js → chunk-ZOJUWVAU.js} +1 -1
- package/dist/cli.js +144 -141
- package/dist/coding/export-okf-codegraph.js +24 -24
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +26 -26
- package/dist/config.js +35 -35
- package/dist/connectors/codex-materialize-runner.js +24 -24
- package/dist/connectors/index.js +28 -28
- package/dist/contradiction/index.js +4 -4
- package/dist/convergence-refresh.js +26 -26
- package/dist/corpus-watermark.js +28 -28
- package/dist/dashboard-runtime.js +2 -2
- package/dist/deep-recall-config.js +2 -2
- package/dist/deep-recall-http-glue.js +12 -12
- package/dist/entity-retrieval.js +25 -25
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.js +6 -6
- package/dist/external-wiki-access.js +91 -89
- package/dist/extraction-evidence-class.js +2 -2
- package/dist/extraction-quote-grounding.d.ts +5 -1
- package/dist/extraction-quote-grounding.d.ts.map +1 -1
- package/dist/extraction-quote-grounding.js +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +3 -1
- package/dist/extraction-source-grounding-rules.d.ts.map +1 -1
- package/dist/extraction-source-grounding-rules.js +2 -2
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts.map +1 -1
- package/dist/extraction-source-grounding.js +5 -5
- package/dist/extraction-span-materialize.js +2 -2
- package/dist/extraction.d.ts.map +1 -1
- package/dist/extraction.js +43 -43
- package/dist/{first-start-migration-QVD22WWS.js → first-start-migration-A6PHIBUQ.js} +4 -4
- package/dist/{graph-edge-decay-CXTNJ7IQ.js → graph-edge-decay-EKWXRBWF.js} +5 -5
- package/dist/graph-edge-decay-EKWXRBWF.js.map +1 -0
- package/dist/graph-jsonl.js +3 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +24 -24
- package/dist/index.js +255 -251
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +5 -5
- package/dist/local-llm.js +3 -3
- package/dist/location/index.js +28 -28
- package/dist/maintenance/memory-governance.js +24 -24
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +24 -24
- package/dist/maintenance/rebuild-memory-projection-runner.js +26 -26
- package/dist/maintenance/rebuild-memory-projection.js +25 -25
- package/dist/memory-browse-http-glue.js +2 -2
- package/dist/memory-browse-operations.js +91 -89
- package/dist/memory-browse.js +5 -5
- package/dist/memory-subject.js +2 -2
- package/dist/namespaces/migrate.js +25 -25
- package/dist/namespaces/search.d.ts +9 -0
- package/dist/namespaces/search.d.ts.map +1 -1
- package/dist/namespaces/search.js +13 -7
- package/dist/namespaces/storage.js +24 -24
- package/dist/offline-sync-changeset-generations.js +3 -3
- package/dist/offline-sync-embedding-generation.js +2 -2
- package/dist/offline-sync-impression-drain.js +2 -2
- package/dist/offline-sync-snapshot-stream.js +6 -6
- package/dist/offline-sync.js +5 -5
- package/dist/operator-doctor-corpus.js +31 -31
- package/dist/operator-doctor-replica.js +4 -4
- package/dist/operator-toolkit.js +49 -49
- package/dist/orchestration/backlog-scheduler.d.ts +3 -2
- package/dist/orchestration/backlog-scheduler.d.ts.map +1 -1
- package/dist/orchestration/backlog-scheduler.js +209 -205
- package/dist/orchestration/backlog-scheduler.js.map +1 -1
- package/dist/orchestration/buffer-drain-runner.d.ts +6 -1
- package/dist/orchestration/buffer-drain-runner.d.ts.map +1 -1
- package/dist/orchestration/buffer-drain-runner.js +199 -195
- package/dist/orchestration/extraction-persist.d.ts.map +1 -1
- package/dist/orchestration/fact-dedup-window.d.ts +1 -4
- package/dist/orchestration/fact-dedup-window.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +41 -41
- package/dist/orchestration/turn-ingestion.d.ts +2 -9
- package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
- package/dist/orchestrator.js +198 -194
- package/dist/provenance.js +2 -2
- package/dist/qmd.js +4 -4
- package/dist/recall-navigation-http-glue.js +2 -2
- package/dist/recall-navigation-operations.js +91 -89
- package/dist/recall-navigation.js +90 -88
- package/dist/recall-state-view-admission.js +5 -5
- package/dist/recall-why-service.js +5 -5
- package/dist/reconcile/manifest.js +2 -2
- package/dist/replica-divergence.js +3 -3
- package/dist/{resolution-BNWE5Y25.js → resolution-23ZBDM6A.js} +5 -5
- package/dist/resolution-23ZBDM6A.js.map +1 -0
- package/dist/resume-bundles.js +36 -36
- package/dist/salvage-envelope.js +4 -4
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +12 -12
- package/dist/semantic-consolidation.js +25 -25
- package/dist/semantic-rule-promotion.js +24 -24
- package/dist/semantic-rule-verifier.js +24 -24
- package/dist/source-agent-qualifier.d.ts +2 -0
- package/dist/source-agent-qualifier.d.ts.map +1 -1
- package/dist/source-agent-qualifier.js +36 -36
- package/dist/standup/build.js +25 -25
- package/dist/storage/buffer-drain-claims.d.ts +18 -6
- package/dist/storage/buffer-drain-claims.d.ts.map +1 -1
- package/dist/storage/buffer-drain-claims.js +2 -2
- package/dist/storage/buffer-session-files.js +2 -2
- package/dist/storage/content-hash-index.d.ts +8 -0
- package/dist/storage/content-hash-index.d.ts.map +1 -1
- package/dist/storage.d.ts +10 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +23 -23
- package/dist/subject-config.js +3 -3
- package/dist/summarizer.js +4 -4
- package/dist/support-passport/index.js +93 -91
- package/dist/tokens.js +3 -3
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +3 -3
- package/dist/transfer/capsule-gunzip.d.ts +14 -0
- package/dist/transfer/capsule-gunzip.d.ts.map +1 -0
- package/dist/transfer/capsule-import.d.ts.map +1 -1
- package/dist/transfer/capsule-import.js +3 -2
- package/dist/transfer/capsule-merge.d.ts.map +1 -1
- package/dist/transfer/export-okf.js +24 -24
- package/dist/verified-recall.js +24 -24
- package/dist/who-knows-cli.js +26 -26
- package/dist/who-knows.js +25 -25
- package/dist/write-envelope.js +3 -3
- package/package.json +2 -2
- package/src/access-boundary.ts +15 -0
- package/src/access-errors.ts +22 -0
- package/src/access-fleet-wide-work-peer.test.ts +236 -0
- package/src/access-http-peer-fleet-wide.test.ts +192 -0
- package/src/access-http.test.ts +249 -4
- package/src/access-http.ts +114 -39
- package/src/access-mcp-frames.test.ts +47 -0
- package/src/access-mcp-frames.ts +74 -0
- package/src/access-mcp.test.ts +210 -0
- package/src/access-mcp.ts +47 -37
- package/src/access-observe-replay-durability.test.ts +40 -4
- package/src/access-observe-write-surface.ts +4 -4
- package/src/access-operations-batch.ts +23 -12
- package/src/access-proto-injection.test.ts +340 -0
- package/src/access-schema.ts +31 -5
- package/src/access-service-capsule-import.test.ts +235 -0
- package/src/access-service.ts +6 -45
- package/src/backlog-scheduler.test.ts +443 -3
- package/src/briefing-deadline.ts +5 -4
- package/src/buffer-admission.ts +45 -0
- package/src/buffer-eviction-backpressure.test.ts +211 -0
- package/src/buffer-eviction.ts +8 -14
- package/src/buffer-incremental-persistence.test.ts +25 -37
- package/src/buffer-persistence.ts +15 -6
- package/src/buffer-session.test.ts +32 -16
- package/src/buffer-turn-helpers.ts +47 -0
- package/src/buffer-types.ts +28 -1
- package/src/buffer.ts +83 -91
- package/src/capsule-import-gate.ts +109 -0
- package/src/cli.ts +4 -4
- package/src/extraction-quote-grounding.test.ts +125 -0
- package/src/extraction-quote-grounding.ts +99 -25
- package/src/extraction-source-grounding-rules.ts +6 -1
- package/src/extraction-source-grounding.ts +2 -0
- package/src/extraction.ts +3 -4
- package/src/fact-dedup-window.test.ts +103 -20
- package/src/namespaces/search.test.ts +480 -1
- package/src/namespaces/search.ts +93 -10
- package/src/orchestration/backlog-scheduler.ts +13 -12
- package/src/orchestration/buffer-drain-runner.ts +40 -16
- package/src/orchestration/extraction-persist.ts +2 -10
- package/src/orchestration/fact-dedup-window.ts +5 -12
- package/src/orchestration/turn-ingestion.ts +38 -39
- package/src/recall-navigation-operations.ts +9 -2
- package/src/source-agent-qualifier.ts +3 -0
- package/src/storage/buffer-drain-claims.test.ts +330 -6
- package/src/storage/buffer-drain-claims.ts +226 -80
- package/src/storage/buffer-session-files.ts +2 -2
- package/src/storage/content-hash-index.ts +9 -0
- package/src/storage.ts +15 -0
- package/src/transfer/capsule-gunzip.ts +39 -0
- package/src/transfer/capsule-import.test.ts +73 -0
- package/src/transfer/capsule-import.ts +2 -2
- package/src/transfer/capsule-merge.test.ts +34 -0
- package/src/transfer/capsule-merge.ts +2 -10
- package/dist/capsule-merge-XVTQJJ6R.js.map +0 -1
- package/dist/chunk-2XJZLSXE.js.map +0 -1
- package/dist/chunk-3JPTUCD7.js.map +0 -1
- package/dist/chunk-4KLQI3L2.js.map +0 -1
- package/dist/chunk-6LCWKS62.js.map +0 -1
- package/dist/chunk-77R7BQZ2.js.map +0 -1
- package/dist/chunk-7PMOCQOL.js.map +0 -1
- package/dist/chunk-B74NPUHT.js.map +0 -1
- package/dist/chunk-D5SSBCYY.js.map +0 -1
- package/dist/chunk-HLKUZW42.js.map +0 -1
- package/dist/chunk-HWHNQVRV.js.map +0 -1
- package/dist/chunk-KASJJGRG.js.map +0 -1
- package/dist/chunk-KQUSP6LB.js.map +0 -1
- package/dist/chunk-LGEH473S.js.map +0 -1
- package/dist/chunk-LU66I56Q.js.map +0 -1
- package/dist/chunk-MPDLLLOG.js.map +0 -1
- package/dist/chunk-MPGLM2VU.js.map +0 -1
- package/dist/chunk-QZBTIYKD.js.map +0 -1
- package/dist/chunk-VLMBSGQF.js.map +0 -1
- package/dist/chunk-WAD32CZG.js.map +0 -1
- package/dist/chunk-WC475JOG.js.map +0 -1
- package/dist/chunk-X2KO4FK5.js.map +0 -1
- package/dist/chunk-XYP5WBDO.js.map +0 -1
- package/dist/chunk-YK7GOPIE.js.map +0 -1
- package/dist/chunk-Z3DDQXM4.js.map +0 -1
- /package/dist/{capsule-crypto-YO5QJ6L3.js.map → access-mcp-frames.js.map} +0 -0
- /package/dist/{auto-sync-C7E6G7Y2.js.map → auto-sync-3AZW7MXI.js.map} +0 -0
- /package/dist/{graph-edge-decay-CXTNJ7IQ.js.map → buffer-admission.js.map} +0 -0
- /package/dist/{resolution-BNWE5Y25.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-MSIRVXQ3.js.map → chunk-2G4TV2ML.js.map} +0 -0
- /package/dist/{chunk-IR4C3DP2.js.map → chunk-2K3AUDH7.js.map} +0 -0
- /package/dist/{chunk-2IW5PT7U.js.map → chunk-2N4OUSIA.js.map} +0 -0
- /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-QZSIDSB2.js.map → chunk-2NUDHVYM.js.map} +0 -0
- /package/dist/{chunk-HPFVZPRH.js.map → chunk-2U4LMSEX.js.map} +0 -0
- /package/dist/{chunk-WHQXWFH7.js.map → chunk-2XOFVTTT.js.map} +0 -0
- /package/dist/{chunk-I6ORDT54.js.map → chunk-32CA7B6L.js.map} +0 -0
- /package/dist/{chunk-T77AX6DG.js.map → chunk-32YX7EJ3.js.map} +0 -0
- /package/dist/{chunk-HLWXCDUQ.js.map → chunk-3DAWHP5K.js.map} +0 -0
- /package/dist/{chunk-ZJJFUEPO.js.map → chunk-3PJEDHLD.js.map} +0 -0
- /package/dist/{chunk-PJYK7HH2.js.map → chunk-3UZ2VMKD.js.map} +0 -0
- /package/dist/{chunk-IN4OFAHX.js.map → chunk-3Y5X6YFH.js.map} +0 -0
- /package/dist/{chunk-YUTT4ZTI.js.map → chunk-45VUHDV2.js.map} +0 -0
- /package/dist/{chunk-T6T2RMWW.js.map → chunk-4GMI5HFH.js.map} +0 -0
- /package/dist/{chunk-YOEYL6CH.js.map → chunk-4LCVA2LW.js.map} +0 -0
- /package/dist/{chunk-66JOLMWS.js.map → chunk-4X7HQKAG.js.map} +0 -0
- /package/dist/{chunk-65SKM4BF.js.map → chunk-4XYAWK5H.js.map} +0 -0
- /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
- /package/dist/{chunk-TPX7XXY4.js.map → chunk-5SOSQTVE.js.map} +0 -0
- /package/dist/{chunk-G3T6YMBO.js.map → chunk-64S6X4IU.js.map} +0 -0
- /package/dist/{chunk-BK7AJUWB.js.map → chunk-6BCWFCDG.js.map} +0 -0
- /package/dist/{chunk-V27FK6D6.js.map → chunk-6XTUZKCZ.js.map} +0 -0
- /package/dist/{chunk-LECSS7EE.js.map → chunk-73UZZFJC.js.map} +0 -0
- /package/dist/{chunk-4EACCIPO.js.map → chunk-77PDJ4OE.js.map} +0 -0
- /package/dist/{chunk-GQZSGXR6.js.map → chunk-7GSL4LBG.js.map} +0 -0
- /package/dist/{chunk-B6SPPYGJ.js.map → chunk-7IWRLYFJ.js.map} +0 -0
- /package/dist/{chunk-R45L4TV6.js.map → chunk-7LCGFUMB.js.map} +0 -0
- /package/dist/{chunk-A7BM2JTH.js.map → chunk-AJHNXIQU.js.map} +0 -0
- /package/dist/{chunk-2D7BTSDW.js.map → chunk-ANZZLRUX.js.map} +0 -0
- /package/dist/{chunk-ZXF3O7P4.js.map → chunk-ARRTLPRC.js.map} +0 -0
- /package/dist/{chunk-S5CQI2KF.js.map → chunk-B3GKQ6DU.js.map} +0 -0
- /package/dist/{chunk-XRBHIR7Q.js.map → chunk-B56LORLY.js.map} +0 -0
- /package/dist/{chunk-KO3YBHOV.js.map → chunk-BIVKPQ6Q.js.map} +0 -0
- /package/dist/{chunk-54FDG7K7.js.map → chunk-C2HORX76.js.map} +0 -0
- /package/dist/{chunk-E33UJHY3.js.map → chunk-CN7Q3T2J.js.map} +0 -0
- /package/dist/{chunk-YUTG35M4.js.map → chunk-CYCEROPR.js.map} +0 -0
- /package/dist/{chunk-TFLPDNQV.js.map → chunk-D5EV6Y2L.js.map} +0 -0
- /package/dist/{chunk-BFBS7OFQ.js.map → chunk-DC55RIEZ.js.map} +0 -0
- /package/dist/{chunk-B4ZU34JQ.js.map → chunk-DT7SNJH6.js.map} +0 -0
- /package/dist/{chunk-FVRTCYZ3.js.map → chunk-EA2LA5RI.js.map} +0 -0
- /package/dist/{chunk-WBN66HPI.js.map → chunk-ELHJK7LM.js.map} +0 -0
- /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
- /package/dist/{chunk-YAUHSNPB.js.map → chunk-F74G4KIH.js.map} +0 -0
- /package/dist/{chunk-BV2BRHD4.js.map → chunk-FHGWKODN.js.map} +0 -0
- /package/dist/{chunk-KESJ5XX3.js.map → chunk-G54BOKZ6.js.map} +0 -0
- /package/dist/{chunk-K36RMINQ.js.map → chunk-GOZXQNIM.js.map} +0 -0
- /package/dist/{chunk-OQSSQOKQ.js.map → chunk-GULUWOA5.js.map} +0 -0
- /package/dist/{chunk-K6RTQZA4.js.map → chunk-HFUKXOUW.js.map} +0 -0
- /package/dist/{chunk-WV254W4V.js.map → chunk-HLN2HOXX.js.map} +0 -0
- /package/dist/{chunk-FUOAIJKQ.js.map → chunk-IBDWYRDR.js.map} +0 -0
- /package/dist/{chunk-AJG2TAMR.js.map → chunk-IEEV27BC.js.map} +0 -0
- /package/dist/{chunk-LTDLJCMQ.js.map → chunk-IJ3OEECW.js.map} +0 -0
- /package/dist/{chunk-BK4FBHZ3.js.map → chunk-IPD5GC7C.js.map} +0 -0
- /package/dist/{chunk-KFLD7ZZG.js.map → chunk-IUKYFTGW.js.map} +0 -0
- /package/dist/{chunk-GCAQ3VUJ.js.map → chunk-JM2YZKCQ.js.map} +0 -0
- /package/dist/{chunk-BNQJKWWZ.js.map → chunk-K3FH3LAQ.js.map} +0 -0
- /package/dist/{chunk-RZH5RVJC.js.map → chunk-MTTYIXSU.js.map} +0 -0
- /package/dist/{chunk-XHGYZRVW.js.map → chunk-NIVKG3DS.js.map} +0 -0
- /package/dist/{chunk-VZELUMKK.js.map → chunk-NQP4ZYGG.js.map} +0 -0
- /package/dist/{chunk-YO2JEX2Z.js.map → chunk-OGBQMY46.js.map} +0 -0
- /package/dist/{chunk-TLHF75OR.js.map → chunk-OL553AWT.js.map} +0 -0
- /package/dist/{chunk-CLVILSBR.js.map → chunk-OZNBZJ3S.js.map} +0 -0
- /package/dist/{chunk-VUROWXFL.js.map → chunk-P452SEKO.js.map} +0 -0
- /package/dist/{chunk-JX3E4XCW.js.map → chunk-PDOOUXCS.js.map} +0 -0
- /package/dist/{chunk-6QYPL6NI.js.map → chunk-PKZ274PI.js.map} +0 -0
- /package/dist/{chunk-KJCL2FZO.js.map → chunk-QD5R6U5J.js.map} +0 -0
- /package/dist/{chunk-JRVMCZE3.js.map → chunk-QEYTRFR3.js.map} +0 -0
- /package/dist/{chunk-VKDAJJQP.js.map → chunk-QEZ3DW5O.js.map} +0 -0
- /package/dist/{chunk-WYPCJK6K.js.map → chunk-QKERFEJS.js.map} +0 -0
- /package/dist/{chunk-BDN3TDGV.js.map → chunk-QKES7GU6.js.map} +0 -0
- /package/dist/{chunk-PCQWKMOL.js.map → chunk-QNSZYTSG.js.map} +0 -0
- /package/dist/{chunk-IZJQNDGI.js.map → chunk-R6HMAIKM.js.map} +0 -0
- /package/dist/{chunk-NUSAAN75.js.map → chunk-ROKDHO74.js.map} +0 -0
- /package/dist/{chunk-FF6N7BXC.js.map → chunk-S45INSV3.js.map} +0 -0
- /package/dist/{chunk-2RUTN7PR.js.map → chunk-S7GJNA3K.js.map} +0 -0
- /package/dist/{chunk-XT45WCKX.js.map → chunk-SYKJBS7S.js.map} +0 -0
- /package/dist/{chunk-5BE3FLKL.js.map → chunk-TAUHAP5J.js.map} +0 -0
- /package/dist/{chunk-RJWL3RHB.js.map → chunk-TFEHSPGQ.js.map} +0 -0
- /package/dist/{chunk-K3B72DKJ.js.map → chunk-TRMZHGIX.js.map} +0 -0
- /package/dist/{chunk-WBDIZWJQ.js.map → chunk-TSS3D7ZY.js.map} +0 -0
- /package/dist/{chunk-HQPFACXO.js.map → chunk-UH3FPX3L.js.map} +0 -0
- /package/dist/{chunk-GGJFRVRD.js.map → chunk-US7KPQA5.js.map} +0 -0
- /package/dist/{chunk-FJ2VJTGA.js.map → chunk-UWRHHRDK.js.map} +0 -0
- /package/dist/{chunk-SDESKFKT.js.map → chunk-UYHDMCY2.js.map} +0 -0
- /package/dist/{chunk-3T3VHXUH.js.map → chunk-VKILERSL.js.map} +0 -0
- /package/dist/{chunk-2TGIKMMZ.js.map → chunk-WXDTOE6F.js.map} +0 -0
- /package/dist/{chunk-KQLBXUUQ.js.map → chunk-WYG5UNDY.js.map} +0 -0
- /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-FZVROZKC.js.map → chunk-XVZA6VXC.js.map} +0 -0
- /package/dist/{chunk-QA3Y2O6H.js.map → chunk-YAVIBVCU.js.map} +0 -0
- /package/dist/{chunk-VPEIWMUT.js.map → chunk-YLTU2DC4.js.map} +0 -0
- /package/dist/{chunk-EBOHFZI4.js.map → chunk-YRZPBN46.js.map} +0 -0
- /package/dist/{chunk-FMFCQRDM.js.map → chunk-ZANNIXXE.js.map} +0 -0
- /package/dist/{chunk-HQGATKG2.js.map → chunk-ZBFLV657.js.map} +0 -0
- /package/dist/{chunk-6L63IN3M.js.map → chunk-ZOJUWVAU.js.map} +0 -0
- /package/dist/{first-start-migration-QVD22WWS.js.map → first-start-migration-A6PHIBUQ.js.map} +0 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, readdir, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import "./access-operations-batch.js"; // registration side effect: the real operations
|
|
8
|
+
import { getOperation } from "./access-boundary.js";
|
|
9
|
+
import { EngramAccessService } from "./access-service.js";
|
|
10
|
+
import { EngramAccessForbiddenError } from "./access-errors.js";
|
|
11
|
+
import { tokenCapabilityStore, type TokenCapabilities } from "./access-token-capabilities.js";
|
|
12
|
+
import { Orchestrator } from "./orchestrator.js";
|
|
13
|
+
import { parseConfig } from "./config.js";
|
|
14
|
+
import { writePeer, writePeerProfile } from "./peers/index.js";
|
|
15
|
+
import { WorkStorage } from "./work/storage.js";
|
|
16
|
+
|
|
17
|
+
// Issue #3225 B3: work_task / work_project / work_board and the six peer
|
|
18
|
+
// operations run against GLOBAL stores, so a namespace argument cannot
|
|
19
|
+
// isolate them. They must carry fleetWide: true like the other cross-fleet
|
|
20
|
+
// operations, and the HTTP peer routes must enforce the same policy.
|
|
21
|
+
|
|
22
|
+
const PEER_ID = "b3-target-peer";
|
|
23
|
+
const NOW = "2026-11-11T00:00:00.000Z";
|
|
24
|
+
|
|
25
|
+
/** The nine operations that touch a global store (issue #3225 B3). */
|
|
26
|
+
const GLOBAL_OPS = [
|
|
27
|
+
"work_task",
|
|
28
|
+
"work_project",
|
|
29
|
+
"work_board",
|
|
30
|
+
"peer_list",
|
|
31
|
+
"peer_get",
|
|
32
|
+
"peer_set",
|
|
33
|
+
"peer_delete",
|
|
34
|
+
"peer_profile_get",
|
|
35
|
+
"peer_forget",
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
type GlobalOpName = (typeof GLOBAL_OPS)[number];
|
|
39
|
+
|
|
40
|
+
/** Envelope fields the operations under test read; their schemas pass open objects through. */
|
|
41
|
+
interface OpEnvelope {
|
|
42
|
+
action?: string;
|
|
43
|
+
id?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
projectId?: string;
|
|
47
|
+
snapshotJson?: string;
|
|
48
|
+
kind?: string;
|
|
49
|
+
displayName?: string;
|
|
50
|
+
confirm?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Every registered handler answers with a `result` envelope. */
|
|
54
|
+
interface OpOutput<T> {
|
|
55
|
+
result: T;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface Fixture {
|
|
59
|
+
root: string;
|
|
60
|
+
service: EngramAccessService;
|
|
61
|
+
cleanup: () => Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function createFixture(): Promise<Fixture> {
|
|
65
|
+
const root = await mkdtemp(path.join(tmpdir(), "remnic-b3-fleet-wide-"));
|
|
66
|
+
const orchestrator = new Orchestrator(
|
|
67
|
+
parseConfig({ memoryDir: root, namespacesEnabled: false, defaultNamespace: "global" }),
|
|
68
|
+
);
|
|
69
|
+
const storage = await orchestrator.getStorage();
|
|
70
|
+
await storage.ensureDirectories();
|
|
71
|
+
const service = new EngramAccessService(orchestrator);
|
|
72
|
+
return { root, service, cleanup: () => rm(root, { recursive: true, force: true }) };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Seed one synthetic record in each global store the nine operations touch. */
|
|
76
|
+
async function seedGlobalRecords(root: string): Promise<void> {
|
|
77
|
+
const work = new WorkStorage(root);
|
|
78
|
+
await work.ensureDirectories();
|
|
79
|
+
await work.createTask({ title: "seeded task", description: "seeded" });
|
|
80
|
+
await work.createProject({ name: "seeded project", description: "seeded" });
|
|
81
|
+
await writePeer(root, {
|
|
82
|
+
id: PEER_ID,
|
|
83
|
+
kind: "agent",
|
|
84
|
+
displayName: "seeded peer",
|
|
85
|
+
createdAt: NOW,
|
|
86
|
+
updatedAt: NOW,
|
|
87
|
+
});
|
|
88
|
+
await writePeerProfile(root, {
|
|
89
|
+
peerId: PEER_ID,
|
|
90
|
+
updatedAt: NOW,
|
|
91
|
+
fields: { communication_style: "seeded" },
|
|
92
|
+
provenance: {},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Sorted relpath:content lines for every file under root (mutation detector). */
|
|
97
|
+
async function snapshotDir(root: string): Promise<string[]> {
|
|
98
|
+
const entries = await readdir(root, { recursive: true, withFileTypes: true });
|
|
99
|
+
const lines: string[] = [];
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
if (!entry.isFile()) continue;
|
|
102
|
+
const abs = path.join(entry.parentPath, entry.name);
|
|
103
|
+
const content = await readFile(abs, "utf8");
|
|
104
|
+
lines.push(`${path.relative(root, abs)}:${content}`);
|
|
105
|
+
}
|
|
106
|
+
return lines.sort();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Run the real registered operation under an optional capability record.
|
|
111
|
+
* The generic T names the registered handler's documented result shape.
|
|
112
|
+
*/
|
|
113
|
+
async function runOp<T>(
|
|
114
|
+
name: GlobalOpName,
|
|
115
|
+
input: OpEnvelope,
|
|
116
|
+
service: EngramAccessService,
|
|
117
|
+
capabilities?: TokenCapabilities,
|
|
118
|
+
): Promise<OpOutput<T>> {
|
|
119
|
+
const op = getOperation(name);
|
|
120
|
+
assert.ok(op, `operation must be registered: ${name}`);
|
|
121
|
+
const run = () => op.run(input, { service });
|
|
122
|
+
// SAFETY: the boundary validates the envelope, then the handler returns its
|
|
123
|
+
// documented `{ result }` shape; T is that shape as named by the caller.
|
|
124
|
+
const output = (capabilities === undefined ? await run() : await tokenCapabilityStore.run(capabilities, run)) as OpOutput<T>;
|
|
125
|
+
return output;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
test("B3: a one-namespace token is denied on every global work and peer op BEFORE any read or mutation", async () => {
|
|
129
|
+
const fixture = await createFixture();
|
|
130
|
+
try {
|
|
131
|
+
await seedGlobalRecords(fixture.root);
|
|
132
|
+
const before = await snapshotDir(fixture.root);
|
|
133
|
+
|
|
134
|
+
const mutatingInput = {
|
|
135
|
+
work_task: { action: "create", title: "intruder task" },
|
|
136
|
+
work_project: { action: "create", name: "intruder project" },
|
|
137
|
+
work_board: { action: "import_snapshot", projectId: "proj-x", snapshotJson: "{}" },
|
|
138
|
+
peer_list: {},
|
|
139
|
+
peer_get: { id: PEER_ID },
|
|
140
|
+
peer_set: { id: PEER_ID, displayName: "hijacked" },
|
|
141
|
+
peer_delete: { id: PEER_ID },
|
|
142
|
+
peer_profile_get: { id: PEER_ID },
|
|
143
|
+
peer_forget: { id: PEER_ID, confirm: "yes" },
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
for (const namespaces of [["ns_a"], []]) {
|
|
147
|
+
const caps: TokenCapabilities = { version: 1, namespaces };
|
|
148
|
+
for (const name of GLOBAL_OPS) {
|
|
149
|
+
await assert.rejects(
|
|
150
|
+
() => runOp(name, mutatingInput[name], fixture.service, caps),
|
|
151
|
+
(err: Error) =>
|
|
152
|
+
err instanceof EngramAccessForbiddenError && /scoped to specific namespaces/.test(err.message),
|
|
153
|
+
`${name} must reject a token restricted to ${JSON.stringify(namespaces)}`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const after = await snapshotDir(fixture.root);
|
|
159
|
+
assert.deepEqual(after, before, "denials must not change any file in any global store");
|
|
160
|
+
} finally {
|
|
161
|
+
await fixture.cleanup();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("B3: an ops-scoped token without a namespace axis may use its permitted global ops", async () => {
|
|
166
|
+
const fixture = await createFixture();
|
|
167
|
+
try {
|
|
168
|
+
const caps: TokenCapabilities = { version: 1, ops: [...GLOBAL_OPS] };
|
|
169
|
+
|
|
170
|
+
const created = await runOp<{ task: { id: string } }>(
|
|
171
|
+
"work_task",
|
|
172
|
+
{ action: "create", title: "ops token task" },
|
|
173
|
+
fixture.service,
|
|
174
|
+
caps,
|
|
175
|
+
);
|
|
176
|
+
assert.ok(created.result.task.id, "ops-scoped token creates a work task");
|
|
177
|
+
|
|
178
|
+
const listed = await runOp<{ count: number }>("work_task", { action: "list" }, fixture.service, caps);
|
|
179
|
+
assert.equal(listed.result.count, 1, "ops-scoped token reads its own created task");
|
|
180
|
+
|
|
181
|
+
const peer = await runOp<{ created: boolean }>(
|
|
182
|
+
"peer_set",
|
|
183
|
+
{ id: "ops-token-peer", kind: "agent" },
|
|
184
|
+
fixture.service,
|
|
185
|
+
caps,
|
|
186
|
+
);
|
|
187
|
+
assert.equal(peer.result.created, true, "ops-scoped token registers a peer");
|
|
188
|
+
|
|
189
|
+
const got = await runOp<{ found: boolean }>("peer_get", { id: "ops-token-peer" }, fixture.service, caps);
|
|
190
|
+
assert.equal(got.result.found, true, "ops-scoped token reads a peer");
|
|
191
|
+
|
|
192
|
+
const forgotten = await runOp<{ purged: boolean }>(
|
|
193
|
+
"peer_forget",
|
|
194
|
+
{ id: "ops-token-peer", confirm: "yes" },
|
|
195
|
+
fixture.service,
|
|
196
|
+
caps,
|
|
197
|
+
);
|
|
198
|
+
assert.equal(forgotten.result.purged, true, "ops-scoped token may run the destructive purge it is granted");
|
|
199
|
+
} finally {
|
|
200
|
+
await fixture.cleanup();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("B3: a legacy unrestricted token (no capability record) retains access to global ops", async () => {
|
|
205
|
+
const fixture = await createFixture();
|
|
206
|
+
try {
|
|
207
|
+
await seedGlobalRecords(fixture.root);
|
|
208
|
+
|
|
209
|
+
const listed = await runOp<{ count: number }>("work_task", { action: "list" }, fixture.service);
|
|
210
|
+
assert.equal(listed.result.count, 1, "legacy token lists work tasks");
|
|
211
|
+
|
|
212
|
+
const peers = await runOp<{ peers: { id: string }[] }>("peer_list", {}, fixture.service);
|
|
213
|
+
assert.deepEqual(
|
|
214
|
+
peers.result.peers.map((p) => p.id),
|
|
215
|
+
[PEER_ID],
|
|
216
|
+
"legacy token lists the seeded peer",
|
|
217
|
+
);
|
|
218
|
+
} finally {
|
|
219
|
+
await fixture.cleanup();
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("B3: peer_forget confirmation requirement is unchanged through the boundary", async () => {
|
|
224
|
+
const fixture = await createFixture();
|
|
225
|
+
try {
|
|
226
|
+
await seedGlobalRecords(fixture.root);
|
|
227
|
+
await assert.rejects(
|
|
228
|
+
() => runOp("peer_forget", { id: PEER_ID, confirm: "no" }, fixture.service),
|
|
229
|
+
(err: Error) => /confirm must be 'yes'/.test(err.message),
|
|
230
|
+
);
|
|
231
|
+
const files = await snapshotDir(fixture.root);
|
|
232
|
+
assert.ok(files.some((line) => line.includes(`${PEER_ID}/identity.md`)), "peer survives a rejected confirmation");
|
|
233
|
+
} finally {
|
|
234
|
+
await fixture.cleanup();
|
|
235
|
+
}
|
|
236
|
+
});
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, readdir, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { EngramAccessHttpServer } from "./access-http.js";
|
|
8
|
+
import { EngramAccessService } from "./access-service.js";
|
|
9
|
+
import { Orchestrator } from "./orchestrator.js";
|
|
10
|
+
import { parseConfig } from "./config.js";
|
|
11
|
+
import { writePeer, writePeerProfile } from "./peers/index.js";
|
|
12
|
+
|
|
13
|
+
// Issue #3225 B3: the HTTP peer routes dispatch to global stores, so REST
|
|
14
|
+
// must enforce the same operation policy as MCP — a namespace-scoped token
|
|
15
|
+
// (any namespaces axis, including []) must be denied before any file in the
|
|
16
|
+
// store changes, while ops-scoped and legacy tokens keep working.
|
|
17
|
+
|
|
18
|
+
const PEER_ID = "b3-target-peer";
|
|
19
|
+
const NOW = "2026-11-11T00:00:00.000Z";
|
|
20
|
+
|
|
21
|
+
async function createService(): Promise<{ root: string; service: EngramAccessService; cleanup: () => Promise<void> }> {
|
|
22
|
+
const root = await mkdtemp(path.join(tmpdir(), "remnic-http-peer-fleet-wide-"));
|
|
23
|
+
const orchestrator = new Orchestrator(
|
|
24
|
+
parseConfig({ memoryDir: root, namespacesEnabled: false, defaultNamespace: "global" }),
|
|
25
|
+
);
|
|
26
|
+
const storage = await orchestrator.getStorage();
|
|
27
|
+
await storage.ensureDirectories();
|
|
28
|
+
await writePeer(root, {
|
|
29
|
+
id: PEER_ID,
|
|
30
|
+
kind: "agent",
|
|
31
|
+
displayName: "seeded peer",
|
|
32
|
+
createdAt: NOW,
|
|
33
|
+
updatedAt: NOW,
|
|
34
|
+
});
|
|
35
|
+
await writePeerProfile(root, {
|
|
36
|
+
peerId: PEER_ID,
|
|
37
|
+
updatedAt: NOW,
|
|
38
|
+
fields: { communication_style: "seeded" },
|
|
39
|
+
provenance: {},
|
|
40
|
+
});
|
|
41
|
+
return { root, service: new EngramAccessService(orchestrator), cleanup: () => rm(root, { recursive: true, force: true }) };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Sorted relpath:content lines for every file under root (mutation detector). */
|
|
45
|
+
async function snapshotDir(root: string): Promise<string[]> {
|
|
46
|
+
const entries = await readdir(root, { recursive: true, withFileTypes: true });
|
|
47
|
+
const lines: string[] = [];
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (!entry.isFile()) continue;
|
|
50
|
+
const abs = path.join(entry.parentPath, entry.name);
|
|
51
|
+
const content = await readFile(abs, "utf8");
|
|
52
|
+
lines.push(`${path.relative(root, abs)}:${content}`);
|
|
53
|
+
}
|
|
54
|
+
return lines.sort();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
test("HTTP peer routes deny namespace-scoped tokens before the stores, REST policy matches MCP (issue #3225 B3)", async () => {
|
|
58
|
+
const { root, service, cleanup } = await createService();
|
|
59
|
+
const server = new EngramAccessHttpServer({
|
|
60
|
+
service,
|
|
61
|
+
port: 0,
|
|
62
|
+
authToken: "legacy-operator",
|
|
63
|
+
authTokenEntriesGetter: () => [
|
|
64
|
+
{ token: "ns-scoped", capabilities: { version: 1, namespaces: ["ns_a"] } },
|
|
65
|
+
{ token: "ns-empty", capabilities: { version: 1, namespaces: [] } },
|
|
66
|
+
{
|
|
67
|
+
token: "ops-peer",
|
|
68
|
+
capabilities: {
|
|
69
|
+
version: 1,
|
|
70
|
+
ops: ["peer_list", "peer_get", "peer_set", "peer_delete", "peer_profile_get", "peer_forget"],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
adminConsoleEnabled: false,
|
|
75
|
+
});
|
|
76
|
+
const status = await server.start();
|
|
77
|
+
const call = (token: string, pathname: string, init?: RequestInit) =>
|
|
78
|
+
fetch(`http://127.0.0.1:${status.port}${pathname}`, {
|
|
79
|
+
...init,
|
|
80
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}`, ...(init?.headers ?? {}) },
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const before = await snapshotDir(root);
|
|
85
|
+
|
|
86
|
+
// Namespace-scoped token (single namespace): every peer route is denied
|
|
87
|
+
// BEFORE the store is touched — including the destructive purge.
|
|
88
|
+
assert.equal((await call("ns-scoped", "/engram/v1/peers")).status, 403, "peer_list denied");
|
|
89
|
+
assert.equal((await call("ns-scoped", `/engram/v1/peers/${PEER_ID}`)).status, 403, "peer_get denied");
|
|
90
|
+
assert.equal(
|
|
91
|
+
(await call("ns-scoped", `/engram/v1/peers/${PEER_ID}`, { method: "PUT", body: JSON.stringify({ displayName: "hijack" }) })).status,
|
|
92
|
+
403,
|
|
93
|
+
"peer_set denied",
|
|
94
|
+
);
|
|
95
|
+
assert.equal((await call("ns-scoped", `/engram/v1/peers/${PEER_ID}`, { method: "DELETE" })).status, 403, "peer_delete denied");
|
|
96
|
+
assert.equal(
|
|
97
|
+
(
|
|
98
|
+
await call("ns-scoped", `/engram/v1/peers/${PEER_ID}?forget=true`, {
|
|
99
|
+
method: "DELETE",
|
|
100
|
+
body: JSON.stringify({ confirm: "yes" }),
|
|
101
|
+
})
|
|
102
|
+
).status,
|
|
103
|
+
403,
|
|
104
|
+
"peer_forget denied",
|
|
105
|
+
);
|
|
106
|
+
assert.equal((await call("ns-scoped", `/engram/v1/peers/${PEER_ID}/profile`)).status, 403, "peer_profile_get denied");
|
|
107
|
+
|
|
108
|
+
// Empty namespace allow-list: denied too.
|
|
109
|
+
assert.equal((await call("ns-empty", "/engram/v1/peers")).status, 403, "empty namespace list denied");
|
|
110
|
+
|
|
111
|
+
// Denials never reached the stores — no file read effect, no mutation.
|
|
112
|
+
assert.deepEqual(await snapshotDir(root), before, "denied requests must not change any peer file");
|
|
113
|
+
|
|
114
|
+
// An ops-scoped token without a namespace axis keeps full peer access.
|
|
115
|
+
const listed = await call("ops-peer", "/engram/v1/peers");
|
|
116
|
+
assert.equal(listed.status, 200, "ops-scoped token lists peers");
|
|
117
|
+
// SAFETY: the peer_list REST route returns the service envelope { peers }.
|
|
118
|
+
const listedBody = (await listed.json()) as { peers: { id: string }[] };
|
|
119
|
+
assert.deepEqual(listedBody.peers.map((p) => p.id), [PEER_ID], "ops-scoped token sees the seeded peer");
|
|
120
|
+
|
|
121
|
+
const created = await call("ops-peer", "/engram/v1/peers/ops-peer-1", {
|
|
122
|
+
method: "PUT",
|
|
123
|
+
body: JSON.stringify({ displayName: "ops token peer" }),
|
|
124
|
+
});
|
|
125
|
+
assert.equal(created.status, 201, "ops-scoped token registers a peer");
|
|
126
|
+
// SAFETY: the peer_set REST route returns the upsert outcome { created, peer }.
|
|
127
|
+
const createdBody = (await created.json()) as { created: boolean; peer: { displayName: string } };
|
|
128
|
+
assert.equal(createdBody.created, true);
|
|
129
|
+
assert.equal(createdBody.peer.displayName, "ops token peer");
|
|
130
|
+
|
|
131
|
+
const purged = await call("ops-peer", "/engram/v1/peers/ops-peer-1?forget=true", {
|
|
132
|
+
method: "DELETE",
|
|
133
|
+
body: JSON.stringify({ confirm: "yes" }),
|
|
134
|
+
});
|
|
135
|
+
assert.equal(purged.status, 200, "ops-scoped token purges a peer");
|
|
136
|
+
await purged.text();
|
|
137
|
+
const afterPurge = await snapshotDir(root);
|
|
138
|
+
assert.ok(
|
|
139
|
+
!afterPurge.some((line) => line.startsWith("peers/ops-peer-1/")),
|
|
140
|
+
"the destructive purge removed the peer directory",
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Legacy unrestricted token (static authToken, no capability record).
|
|
144
|
+
const legacyList = await call("legacy-operator", "/engram/v1/peers");
|
|
145
|
+
assert.equal(legacyList.status, 200, "legacy token lists peers");
|
|
146
|
+
await legacyList.text();
|
|
147
|
+
|
|
148
|
+
// Peer-forget confirmation behavior is unchanged: no confirm body, no purge.
|
|
149
|
+
const unconfirmed = await call("legacy-operator", `/engram/v1/peers/${PEER_ID}?forget=true`, {
|
|
150
|
+
method: "DELETE",
|
|
151
|
+
body: JSON.stringify({}),
|
|
152
|
+
});
|
|
153
|
+
assert.equal(unconfirmed.status, 400, "missing confirm still fails with 400");
|
|
154
|
+
assert.match(await unconfirmed.text(), /confirm_required/);
|
|
155
|
+
const seededIntact = await snapshotDir(root);
|
|
156
|
+
assert.ok(
|
|
157
|
+
seededIntact.some((line) => line.startsWith(`peers/${PEER_ID}/identity.md`)),
|
|
158
|
+
"the seeded peer survived the rejected confirmation",
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// A malformed PUT body still fails loudly instead of silently defaulting.
|
|
162
|
+
const malformed = await call("legacy-operator", "/engram/v1/peers/malformed-peer", {
|
|
163
|
+
method: "PUT",
|
|
164
|
+
body: JSON.stringify({ displayName: 5 }),
|
|
165
|
+
});
|
|
166
|
+
assert.equal(malformed.status, 400, "a non-string displayName is rejected");
|
|
167
|
+
assert.match(await malformed.text(), /displayName/);
|
|
168
|
+
assert.ok(
|
|
169
|
+
!(await snapshotDir(root)).some((line) => line.startsWith("peers/malformed-peer/")),
|
|
170
|
+
"the rejected write created no peer file",
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// An explicit null is a malformed field too (rule 51): the operation
|
|
174
|
+
// schema strips nulls, so the route must reject them before dispatch
|
|
175
|
+
// instead of registering the peer with default kind/name/notes.
|
|
176
|
+
for (const field of ["kind", "displayName", "notes"]) {
|
|
177
|
+
const nullField = await call("legacy-operator", `/engram/v1/peers/null-${field}-peer`, {
|
|
178
|
+
method: "PUT",
|
|
179
|
+
body: JSON.stringify({ [field]: null }),
|
|
180
|
+
});
|
|
181
|
+
assert.equal(nullField.status, 400, `an explicit null ${field} is rejected`);
|
|
182
|
+
assert.match(await nullField.text(), new RegExp(field));
|
|
183
|
+
assert.ok(
|
|
184
|
+
!(await snapshotDir(root)).some((line) => line.startsWith(`peers/null-${field}-peer/`)),
|
|
185
|
+
`the null ${field} request created no peer file`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
} finally {
|
|
189
|
+
await server.stop();
|
|
190
|
+
await cleanup();
|
|
191
|
+
}
|
|
192
|
+
});
|