@sentropic/h2a 0.85.25 → 0.87.0
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/bin.js +51 -2
- package/dist/bin.js.map +1 -1
- package/dist/cli-command-map.d.ts +119 -0
- package/dist/cli-command-map.d.ts.map +1 -0
- package/dist/cli-command-map.js +396 -0
- package/dist/cli-command-map.js.map +1 -0
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli-contract.js +39 -1
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli.d.ts +25 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +356 -7
- package/dist/cli.js.map +1 -1
- package/dist/identity.d.ts +37 -3
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -0
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/enrollment/ceremony.d.ts +542 -0
- package/dist/runtime/enrollment/ceremony.d.ts.map +1 -0
- package/dist/runtime/enrollment/ceremony.js +777 -0
- package/dist/runtime/enrollment/ceremony.js.map +1 -0
- package/dist/runtime/enrollment/index.d.ts +16 -0
- package/dist/runtime/enrollment/index.d.ts.map +1 -0
- package/dist/runtime/enrollment/index.js +16 -0
- package/dist/runtime/enrollment/index.js.map +1 -0
- package/dist/runtime/feed/descriptors.d.ts +261 -0
- package/dist/runtime/feed/descriptors.d.ts.map +1 -0
- package/dist/runtime/feed/descriptors.js +425 -0
- package/dist/runtime/feed/descriptors.js.map +1 -0
- package/dist/runtime/feed/index.d.ts +12 -0
- package/dist/runtime/feed/index.d.ts.map +1 -0
- package/dist/runtime/feed/index.js +12 -0
- package/dist/runtime/feed/index.js.map +1 -0
- package/dist/runtime/identity/index.d.ts +3 -3
- package/dist/runtime/identity/index.d.ts.map +1 -1
- package/dist/runtime/identity/index.js +2 -2
- package/dist/runtime/identity/index.js.map +1 -1
- package/dist/runtime/identity/live.d.ts +68 -0
- package/dist/runtime/identity/live.d.ts.map +1 -1
- package/dist/runtime/identity/live.js +78 -2
- package/dist/runtime/identity/live.js.map +1 -1
- package/dist/runtime/identity/readers.d.ts +89 -5
- package/dist/runtime/identity/readers.d.ts.map +1 -1
- package/dist/runtime/identity/readers.js +242 -33
- package/dist/runtime/identity/readers.js.map +1 -1
- package/dist/runtime/local-files/presence.d.ts +16 -1
- package/dist/runtime/local-files/presence.d.ts.map +1 -1
- package/dist/runtime/local-files/presence.js +32 -20
- package/dist/runtime/local-files/presence.js.map +1 -1
- package/dist/runtime/loop/index.d.ts +5 -0
- package/dist/runtime/loop/index.d.ts.map +1 -1
- package/dist/runtime/loop/index.js +48 -5
- package/dist/runtime/loop/index.js.map +1 -1
- package/dist/runtime/mcp/agent-launch.d.ts +15 -1
- package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
- package/dist/runtime/mcp/agent-launch.js +45 -4
- package/dist/runtime/mcp/agent-launch.js.map +1 -1
- package/dist/runtime/mcp/index.d.ts +1 -1
- package/dist/runtime/mcp/index.d.ts.map +1 -1
- package/dist/runtime/mcp/index.js +1 -1
- package/dist/runtime/mcp/index.js.map +1 -1
- package/dist/runtime/mcp/server.d.ts +3 -1
- package/dist/runtime/mcp/server.d.ts.map +1 -1
- package/dist/runtime/mcp/server.js +7 -2
- package/dist/runtime/mcp/server.js.map +1 -1
- package/dist/runtime/mcp/sessions.d.ts +19 -0
- package/dist/runtime/mcp/sessions.d.ts.map +1 -1
- package/dist/runtime/mcp/sessions.js +44 -2
- package/dist/runtime/mcp/sessions.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +8 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +42 -0
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/dist/runtime/mcp-registry/broker.d.ts +175 -0
- package/dist/runtime/mcp-registry/broker.d.ts.map +1 -0
- package/dist/runtime/mcp-registry/broker.js +203 -0
- package/dist/runtime/mcp-registry/broker.js.map +1 -0
- package/dist/runtime/mcp-registry/broker.typecheck.d.ts +2 -0
- package/dist/runtime/mcp-registry/broker.typecheck.d.ts.map +1 -0
- package/dist/runtime/mcp-registry/broker.typecheck.js +48 -0
- package/dist/runtime/mcp-registry/broker.typecheck.js.map +1 -0
- package/dist/runtime/mirror/accept.d.ts +43 -5
- package/dist/runtime/mirror/accept.d.ts.map +1 -1
- package/dist/runtime/mirror/accept.js +55 -7
- package/dist/runtime/mirror/accept.js.map +1 -1
- package/dist/runtime/mirror/build.d.ts +23 -4
- package/dist/runtime/mirror/build.d.ts.map +1 -1
- package/dist/runtime/mirror/build.js +34 -4
- package/dist/runtime/mirror/build.js.map +1 -1
- package/dist/runtime/mirror/index.d.ts +3 -0
- package/dist/runtime/mirror/index.d.ts.map +1 -1
- package/dist/runtime/mirror/index.js +3 -0
- package/dist/runtime/mirror/index.js.map +1 -1
- package/dist/runtime/mirror/ingest.d.ts +109 -0
- package/dist/runtime/mirror/ingest.d.ts.map +1 -0
- package/dist/runtime/mirror/ingest.js +117 -0
- package/dist/runtime/mirror/ingest.js.map +1 -0
- package/dist/runtime/mirror/push-daemon.d.ts +376 -0
- package/dist/runtime/mirror/push-daemon.d.ts.map +1 -0
- package/dist/runtime/mirror/push-daemon.js +644 -0
- package/dist/runtime/mirror/push-daemon.js.map +1 -0
- package/dist/runtime/mirror/sanitize.d.ts +477 -0
- package/dist/runtime/mirror/sanitize.d.ts.map +1 -0
- package/dist/runtime/mirror/sanitize.js +625 -0
- package/dist/runtime/mirror/sanitize.js.map +1 -0
- package/dist/runtime/mirror/serve.d.ts.map +1 -1
- package/dist/runtime/mirror/serve.js +104 -24
- package/dist/runtime/mirror/serve.js.map +1 -1
- package/dist/runtime/reporting/report-ai.d.ts.map +1 -1
- package/dist/runtime/reporting/report-ai.js +1 -0
- package/dist/runtime/reporting/report-ai.js.map +1 -1
- package/dist/runtime/reporting/stdin.d.ts +2 -0
- package/dist/runtime/reporting/stdin.d.ts.map +1 -0
- package/dist/runtime/reporting/stdin.js +8 -0
- package/dist/runtime/reporting/stdin.js.map +1 -0
- package/dist/status-surface.d.ts +167 -0
- package/dist/status-surface.d.ts.map +1 -0
- package/dist/status-surface.js +670 -0
- package/dist/status-surface.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/vendor/harness/skills/manifest.d.ts.map +1 -1
- package/dist/vendor/harness/skills/manifest.js +2 -0
- package/dist/vendor/harness/skills/manifest.js.map +1 -1
- package/focus-app/client/_app/immutable/assets/{0.BdzHFb9q.css → 0.CgEVz9YW.css} +1 -1
- package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css +1 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css +1 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css +1 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{Cj6wo28J.js → 1NK_OeRJ.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{Bs3f1UbD.js → B1veta3r.js} +2 -2
- package/focus-app/client/_app/immutable/chunks/B1veta3r.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/B1veta3r.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{DEmooz0s.js → BZ4lcC0v.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js +2 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js +1 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js +1 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js +2 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/iXQate3J.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/{ZxFklh9T.js → kCE9wz0g.js} +1 -1
- package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js +1 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js +2 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js +1 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.br +2 -0
- package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js +5 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js +1 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js +1 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js +12 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.gz +0 -0
- package/focus-app/client/_app/version.json +1 -1
- package/focus-app/client/_app/version.json.br +0 -0
- package/focus-app/client/_app/version.json.gz +0 -0
- package/focus-app/h2a-focus.json +108 -80
- package/focus-app/handler.js +7 -7
- package/focus-app/index.js +7 -7
- package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js +1353 -0
- package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js.map +1 -0
- package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js +1036 -0
- package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js.map +1 -0
- package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js → exports.js-CdqPbjm1.js} +3 -3
- package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js.map → exports.js-CdqPbjm1.js.map} +1 -1
- package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js +233 -0
- package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js.map +1 -0
- package/focus-app/server/chunks/chunks/{index.js-Di21TltP.js → index.js-laGHLarB.js} +5 -2
- package/focus-app/server/chunks/chunks/index.js-laGHLarB.js.map +1 -0
- package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js → internal.js-C6T8nHkl.js} +4 -4
- package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js.map → internal.js-C6T8nHkl.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js → root.js-CtVQOgDw.js} +2 -2
- package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js.map → root.js-CtVQOgDw.js.map} +1 -1
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-j0NNcOSZ.js → _server.ts.js-hrbMnsV0.js} +13 -42
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-hrbMnsV0.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js +138 -0
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js +41 -0
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js.map +1 -0
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js → error.svelte.js-RbeaNF5a.js} +4 -4
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js.map → error.svelte.js-RbeaNF5a.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js → _layout.svelte.js-e1E_I04z.js} +2 -2
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js.map → _layout.svelte.js-e1E_I04z.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_page.svelte.js-QDldMYhk.js → _page.svelte.js-DbaEG23x.js} +31 -1373
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-DbaEG23x.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js +88 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js.map +1 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js +1574 -0
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js.map +1 -0
- package/focus-app/server/chunks/{handler-Cp_5hLyY.js → handler-Be3dyNi0.js} +3 -3
- package/focus-app/server/chunks/{handler-Cp_5hLyY.js.map → handler-Be3dyNi0.js.map} +1 -1
- package/focus-app/server/chunks/{index.js-CBh7Wjqp.js → index.js-siUxMMnK.js} +3 -3
- package/focus-app/server/chunks/{index.js-CBh7Wjqp.js.map → index.js-siUxMMnK.js.map} +1 -1
- package/focus-app/server/chunks/manifest.js-CXJqSHHn.js +78 -0
- package/focus-app/server/chunks/manifest.js-CXJqSHHn.js.map +1 -0
- package/focus-app/server/chunks/nodes/0.js-leU6sfRR.js +9 -0
- package/focus-app/server/chunks/nodes/{0.js-4wlmdsk8.js.map → 0.js-leU6sfRR.js.map} +1 -1
- package/focus-app/server/chunks/nodes/1.js-os6QXm6B.js +9 -0
- package/focus-app/server/chunks/nodes/{1.js-B-LpY-lC.js.map → 1.js-os6QXm6B.js.map} +1 -1
- package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js +19 -0
- package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js.map +1 -0
- package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js +18 -0
- package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js.map +1 -0
- package/package.json +5 -5
- package/skills/h2a-run/SKILL.md +100 -0
- package/skills/harness/SKILL.md +3 -1
- package/skills/harness/review/SKILL.md +99 -8
- package/skills/harness/security/SKILL.md +55 -0
- package/skills/harness/track-report/SKILL.md +103 -0
- package/skills/harness/using-harness/SKILL.md +3 -1
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.br +0 -2
- package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.gz +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css +0 -1
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.br +0 -0
- package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js +0 -1
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js +0 -2
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js +0 -2
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.gz +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js +0 -1
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js +0 -2
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js +0 -1
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.br +0 -2
- package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js +0 -5
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js +0 -1
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js +0 -1
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.gz +0 -0
- package/focus-app/server/chunks/chunks/index.js-Di21TltP.js.map +0 -1
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-j0NNcOSZ.js.map +0 -1
- package/focus-app/server/chunks/entries/pages/_page.svelte.js-QDldMYhk.js.map +0 -1
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js +0 -56
- package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js.map +0 -1
- package/focus-app/server/chunks/nodes/0.js-4wlmdsk8.js +0 -9
- package/focus-app/server/chunks/nodes/1.js-B-LpY-lC.js +0 -9
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js +0 -19
- package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js.map +0 -1
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* P1: instances only. Core stays dep-free; this lives in @sentropic/h2a.
|
|
5
5
|
*/
|
|
6
6
|
export { buildInstanceMirror, H2A_MIRROR_BODY_KIND } from "./build.js";
|
|
7
|
+
export { MIRROR_ENDPOINT_PLAN, MIRROR_INTERESTS_PLAN, MIRROR_PRESENCE_PLAN, MIRROR_REGISTRATION_PLAN, MIRROR_SUBAGENT_PLAN, MIRROR_TEST_HOOKS, MIRROR_VERSION_PLAN, MIRROR_WORKSPACE_PLAN, sanitizeActorForMirror, sanitizePresenceForMirror, sanitizeRegistrationForMirror, sanitizeSubagentForMirror, sanitizeWorkspaceRefForMirror, unclassifiedMirrorFields } from "./sanitize.js";
|
|
7
8
|
export { acceptMirrorEnvelope } from "./accept.js";
|
|
9
|
+
export { INGEST_NARROWERS, createNarrowingTally, droppedKeyPaths, narrowIngestedPresence, narrowIngestedRegistration, narrowIngestedSubagent } from "./ingest.js";
|
|
8
10
|
export { mirrorServerForStore, mirrorRejectionStatus } from "./serve.js";
|
|
11
|
+
export { createMirrorPushRunner, isPushableHttpUrl, mirrorPushGloballyDisabled, redactEndpoint, runMirrorPushDaemon, sanitizeForLog, DEFAULT_MIRROR_AUTH_FAILURE_LIMIT, DEFAULT_MIRROR_BUILD_FAILURE_LIMIT, DEFAULT_MIRROR_PUSH_INTERVAL_MS, DEFAULT_MIRROR_REJECT_LIMIT, MIN_MIRROR_PUSH_INTERVAL_MS, MIRROR_PUSH_BACKOFF_BASE_MS, MIRROR_PUSH_BACKOFF_MAX_MS, MIRROR_PUSH_BUILD_FAILED_MESSAGE, MIRROR_PUSH_INVALID_URL_MESSAGE, MIRROR_PUSH_JITTER_FRACTION, MIRROR_PUSH_OFF_ENV, MIRROR_PUSH_REENROLLMENT_MESSAGE, MIRROR_PUSH_REJECTED_MESSAGE } from "./push-daemon.js";
|
|
9
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/mirror/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EAEtB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/mirror/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,6BAA6B,EAC7B,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EASzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EAGvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,iCAAiC,EACjC,kCAAkC,EAClC,+BAA+B,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EAChC,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,EACnB,gCAAgC,EAChC,4BAA4B,EAW7B,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { H2AInstanceMirrorBody } from "./build.js";
|
|
2
|
+
import { sanitizePresenceForMirror, sanitizeRegistrationForMirror, sanitizeSubagentForMirror, type H2AMirroredRegistration as SanitizedRegistration, type H2AMirroredSession as SanitizedSession, type H2AMirroredSubagentBinding as SanitizedSubagentBinding } from "./sanitize.js";
|
|
3
|
+
/**
|
|
4
|
+
* An ingest-only nominal marker. The send-side types deliberately describe the
|
|
5
|
+
* shape of a serializable record, so raw local records with extra fields are
|
|
6
|
+
* structurally assignable to them. Callbacks need a stronger guarantee: only a
|
|
7
|
+
* value returned by one of this module's narrowers may reach a store writer.
|
|
8
|
+
*
|
|
9
|
+
* `declare` keeps the marker type-only: it never becomes a field in a mirrored
|
|
10
|
+
* record or on disk. The casts below are the sole fabrication points.
|
|
11
|
+
*/
|
|
12
|
+
declare const MIRROR_INGEST_NARROWED: unique symbol;
|
|
13
|
+
export type H2AMirroredRegistration = SanitizedRegistration & {
|
|
14
|
+
readonly [MIRROR_INGEST_NARROWED]: true;
|
|
15
|
+
};
|
|
16
|
+
export type H2AMirroredSession = SanitizedSession & {
|
|
17
|
+
readonly [MIRROR_INGEST_NARROWED]: true;
|
|
18
|
+
};
|
|
19
|
+
export type H2AMirroredSubagentBinding = SanitizedSubagentBinding & {
|
|
20
|
+
readonly [MIRROR_INGEST_NARROWED]: true;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Members of the mirror body that carry RECORDS — i.e. whose type is an array of
|
|
24
|
+
* objects. `kind` (a string literal) and `seq` (a number) are excluded by the
|
|
25
|
+
* conditional, so the map below is not asked to narrow a scalar.
|
|
26
|
+
*
|
|
27
|
+
* `-?` strips optionality before the test, so `presence?` and `subagents?` are
|
|
28
|
+
* required entries in the map: an OPTIONAL member is still a member that lands
|
|
29
|
+
* records when it is present, and the ratchet must not be dodgeable by adding a
|
|
30
|
+
* `?`.
|
|
31
|
+
*/
|
|
32
|
+
export type MirrorBodyRecordMember = {
|
|
33
|
+
[K in keyof H2AInstanceMirrorBody]-?: NonNullable<H2AInstanceMirrorBody[K]> extends readonly object[] ? K : never;
|
|
34
|
+
}[keyof H2AInstanceMirrorBody];
|
|
35
|
+
/**
|
|
36
|
+
* The narrowing applied to each record-carrying body member on arrival.
|
|
37
|
+
*
|
|
38
|
+
* This map is not documentation — it is the only route by which a record reaches
|
|
39
|
+
* a store writer, so deleting an entry breaks the build at its use site rather
|
|
40
|
+
* than silently disabling a boundary. Each value is the SEND-side function,
|
|
41
|
+
* reused verbatim; see the module header for why there is no ingest-side copy.
|
|
42
|
+
*/
|
|
43
|
+
export declare const INGEST_NARROWERS: {
|
|
44
|
+
registrations: typeof sanitizeRegistrationForMirror;
|
|
45
|
+
presence: typeof sanitizePresenceForMirror;
|
|
46
|
+
subagents: typeof sanitizeSubagentForMirror;
|
|
47
|
+
};
|
|
48
|
+
/** Narrow an arriving registration to the fields the mirror boundary permits. */
|
|
49
|
+
export declare function narrowIngestedRegistration(registration: Parameters<typeof INGEST_NARROWERS.registrations>[0]): H2AMirroredRegistration;
|
|
50
|
+
/** Narrow an arriving presence record to the fields the mirror boundary permits. */
|
|
51
|
+
export declare function narrowIngestedPresence(session: Parameters<typeof INGEST_NARROWERS.presence>[0]): H2AMirroredSession;
|
|
52
|
+
/** Narrow an arriving subagent binding to the fields the mirror boundary permits. */
|
|
53
|
+
export declare function narrowIngestedSubagent(binding: Parameters<typeof INGEST_NARROWERS.subagents>[0]): H2AMirroredSubagentBinding;
|
|
54
|
+
/** What narrowing removed from one mirror push. */
|
|
55
|
+
export interface MirrorNarrowingReport {
|
|
56
|
+
/** Records that lost at least one key path. Zero ⇒ the sender is up to date. */
|
|
57
|
+
readonly records: number;
|
|
58
|
+
/** Sorted, de-duplicated key paths that were dropped. Names only, never values. */
|
|
59
|
+
readonly fields: readonly string[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Key paths present in `before` and absent from `after` — i.e. what the plans
|
|
63
|
+
* actually removed.
|
|
64
|
+
*
|
|
65
|
+
* Deliberately an OBSERVATION of the narrowing rather than a second reading of
|
|
66
|
+
* the plans. Re-deriving "what is withheld" from `MIRROR_*_PLAN` here would
|
|
67
|
+
* reintroduce the duplication this module exists to avoid, and would miss the
|
|
68
|
+
* two things the plans do not express as withheld fields at all: nested
|
|
69
|
+
* composites rebuilt by their own plan (`workspace.path` is withheld by
|
|
70
|
+
* `WORKSPACE_PLAN`, not by `PRESENCE_PLAN`), and endpoints removed by the scheme
|
|
71
|
+
* filter, which is not a field classification at all. Diffing catches both for
|
|
72
|
+
* free and cannot drift from the plans, because it has no opinion of its own.
|
|
73
|
+
*
|
|
74
|
+
* ── EXACT WHERE IT MATTERS, INDICATIVE WHERE IT DOES NOT ───────────────────
|
|
75
|
+
*
|
|
76
|
+
* This value is a DIAGNOSTIC — it gates nothing and authorizes nothing — so it is
|
|
77
|
+
* worth being precise about which parts are load-bearing:
|
|
78
|
+
*
|
|
79
|
+
* - **Exact**: whether the list is empty. It is empty iff narrowing removed no
|
|
80
|
+
* key path, which is the property the operator signal rests on. Object keys
|
|
81
|
+
* and array-length shrinkage are both compared directly.
|
|
82
|
+
* - **Exact**: object key paths, at every depth (`workspace.path`,
|
|
83
|
+
* `launchContext`).
|
|
84
|
+
* - **Indicative**: an index inside an array path. Elements are compared
|
|
85
|
+
* positionally, and the endpoint scheme filter REMOVES elements, so after a
|
|
86
|
+
* filtered element the survivors shift left and `endpoints[0].x` names a
|
|
87
|
+
* position, not a stable address. The length-shrink marker `endpoints[]` is
|
|
88
|
+
* exact; the per-element paths after it are a hint. Today this is moot —
|
|
89
|
+
* `ENDPOINT_PLAN` withholds nothing, so a surviving element loses no keys —
|
|
90
|
+
* and it is written down so that stops being an accident.
|
|
91
|
+
*
|
|
92
|
+
* `null`/`undefined` in `before` are not reported: `applyPlan` omits them by
|
|
93
|
+
* design, so treating an absent-because-empty field as "dropped" would report
|
|
94
|
+
* every optional field a sender left unset and drown the real signal.
|
|
95
|
+
*/
|
|
96
|
+
export declare function droppedKeyPaths(before: unknown, after: unknown, prefix?: string): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Accumulates {@link MirrorNarrowingReport} across the records of one push.
|
|
99
|
+
*
|
|
100
|
+
* Stateful on purpose and scoped to a single envelope: `accept.ts` is otherwise
|
|
101
|
+
* pure, and this keeps the impurity in one named, obviously-per-request object
|
|
102
|
+
* instead of threading counters through the accept logic.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createNarrowingTally(): {
|
|
105
|
+
note: (before: unknown, after: unknown) => void;
|
|
106
|
+
report: () => MirrorNarrowingReport;
|
|
107
|
+
};
|
|
108
|
+
export {};
|
|
109
|
+
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/ingest.ts"],"names":[],"mappings":"AAiGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,yBAAyB,EACzB,KAAK,uBAAuB,IAAI,qBAAqB,EACrD,KAAK,kBAAkB,IAAI,gBAAgB,EAC3C,KAAK,0BAA0B,IAAI,wBAAwB,EAC5D,MAAM,eAAe,CAAC;AAEvB;;;;;;;;GAQG;AACH,OAAO,CAAC,MAAM,sBAAsB,EAAE,OAAO,MAAM,CAAC;AAEpD,MAAM,MAAM,uBAAuB,GAAG,qBAAqB,GAAG;IAC5D,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;CACzC,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,GAAG;IAClD,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;CACzC,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG,wBAAwB,GAAG;IAClE,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;CACzC,CAAC;AAgBF;;;;;;;;;GASG;AACH,MAAM,MAAM,sBAAsB,GAAG;KAClC,CAAC,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAAG,WAAW,CAC/C,qBAAqB,CAAC,CAAC,CAAC,CACzB,SAAS,SAAS,MAAM,EAAE,GACvB,CAAC,GACD,KAAK;CACV,CAAC,MAAM,qBAAqB,CAAC,CAAC;AAE/B;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;CAIoD,CAAC;AAElF,iFAAiF;AACjF,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GACjE,uBAAuB,CAEzB;AAED,oFAAoF;AACpF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GACvD,kBAAkB,CAEpB;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACxD,0BAA0B,CAE5B;AAED,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAK,GAAG,MAAM,EAAE,CAuBtF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI;IACtC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,MAAM,EAAE,MAAM,qBAAqB,CAAC;CACrC,CAYA"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { sanitizePresenceForMirror, sanitizeRegistrationForMirror, sanitizeSubagentForMirror } from "./sanitize.js";
|
|
2
|
+
/**
|
|
3
|
+
* The narrowing applied to each record-carrying body member on arrival.
|
|
4
|
+
*
|
|
5
|
+
* This map is not documentation — it is the only route by which a record reaches
|
|
6
|
+
* a store writer, so deleting an entry breaks the build at its use site rather
|
|
7
|
+
* than silently disabling a boundary. Each value is the SEND-side function,
|
|
8
|
+
* reused verbatim; see the module header for why there is no ingest-side copy.
|
|
9
|
+
*/
|
|
10
|
+
export const INGEST_NARROWERS = {
|
|
11
|
+
registrations: sanitizeRegistrationForMirror,
|
|
12
|
+
presence: sanitizePresenceForMirror,
|
|
13
|
+
subagents: sanitizeSubagentForMirror
|
|
14
|
+
};
|
|
15
|
+
/** Narrow an arriving registration to the fields the mirror boundary permits. */
|
|
16
|
+
export function narrowIngestedRegistration(registration) {
|
|
17
|
+
return INGEST_NARROWERS.registrations(registration);
|
|
18
|
+
}
|
|
19
|
+
/** Narrow an arriving presence record to the fields the mirror boundary permits. */
|
|
20
|
+
export function narrowIngestedPresence(session) {
|
|
21
|
+
return INGEST_NARROWERS.presence(session);
|
|
22
|
+
}
|
|
23
|
+
/** Narrow an arriving subagent binding to the fields the mirror boundary permits. */
|
|
24
|
+
export function narrowIngestedSubagent(binding) {
|
|
25
|
+
return INGEST_NARROWERS.subagents(binding);
|
|
26
|
+
}
|
|
27
|
+
function isPlainObject(value) {
|
|
28
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Key paths present in `before` and absent from `after` — i.e. what the plans
|
|
32
|
+
* actually removed.
|
|
33
|
+
*
|
|
34
|
+
* Deliberately an OBSERVATION of the narrowing rather than a second reading of
|
|
35
|
+
* the plans. Re-deriving "what is withheld" from `MIRROR_*_PLAN` here would
|
|
36
|
+
* reintroduce the duplication this module exists to avoid, and would miss the
|
|
37
|
+
* two things the plans do not express as withheld fields at all: nested
|
|
38
|
+
* composites rebuilt by their own plan (`workspace.path` is withheld by
|
|
39
|
+
* `WORKSPACE_PLAN`, not by `PRESENCE_PLAN`), and endpoints removed by the scheme
|
|
40
|
+
* filter, which is not a field classification at all. Diffing catches both for
|
|
41
|
+
* free and cannot drift from the plans, because it has no opinion of its own.
|
|
42
|
+
*
|
|
43
|
+
* ── EXACT WHERE IT MATTERS, INDICATIVE WHERE IT DOES NOT ───────────────────
|
|
44
|
+
*
|
|
45
|
+
* This value is a DIAGNOSTIC — it gates nothing and authorizes nothing — so it is
|
|
46
|
+
* worth being precise about which parts are load-bearing:
|
|
47
|
+
*
|
|
48
|
+
* - **Exact**: whether the list is empty. It is empty iff narrowing removed no
|
|
49
|
+
* key path, which is the property the operator signal rests on. Object keys
|
|
50
|
+
* and array-length shrinkage are both compared directly.
|
|
51
|
+
* - **Exact**: object key paths, at every depth (`workspace.path`,
|
|
52
|
+
* `launchContext`).
|
|
53
|
+
* - **Indicative**: an index inside an array path. Elements are compared
|
|
54
|
+
* positionally, and the endpoint scheme filter REMOVES elements, so after a
|
|
55
|
+
* filtered element the survivors shift left and `endpoints[0].x` names a
|
|
56
|
+
* position, not a stable address. The length-shrink marker `endpoints[]` is
|
|
57
|
+
* exact; the per-element paths after it are a hint. Today this is moot —
|
|
58
|
+
* `ENDPOINT_PLAN` withholds nothing, so a surviving element loses no keys —
|
|
59
|
+
* and it is written down so that stops being an accident.
|
|
60
|
+
*
|
|
61
|
+
* `null`/`undefined` in `before` are not reported: `applyPlan` omits them by
|
|
62
|
+
* design, so treating an absent-because-empty field as "dropped" would report
|
|
63
|
+
* every optional field a sender left unset and drown the real signal.
|
|
64
|
+
*/
|
|
65
|
+
export function droppedKeyPaths(before, after, prefix = "") {
|
|
66
|
+
const dropped = [];
|
|
67
|
+
if (Array.isArray(before)) {
|
|
68
|
+
if (!Array.isArray(after))
|
|
69
|
+
return prefix ? [prefix] : [];
|
|
70
|
+
if (after.length < before.length)
|
|
71
|
+
dropped.push(`${prefix}[]`);
|
|
72
|
+
for (let i = 0; i < Math.min(before.length, after.length); i += 1) {
|
|
73
|
+
dropped.push(...droppedKeyPaths(before[i], after[i], `${prefix}[${i}]`));
|
|
74
|
+
}
|
|
75
|
+
return dropped;
|
|
76
|
+
}
|
|
77
|
+
if (isPlainObject(before)) {
|
|
78
|
+
if (!isPlainObject(after))
|
|
79
|
+
return prefix ? [prefix] : [];
|
|
80
|
+
for (const [key, value] of Object.entries(before)) {
|
|
81
|
+
// Absent-and-empty is how `applyPlan` represents "nothing to send", not a
|
|
82
|
+
// removal. Reporting it would make every unset optional field look stale.
|
|
83
|
+
if (value === undefined || value === null)
|
|
84
|
+
continue;
|
|
85
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
86
|
+
if (!(key in after))
|
|
87
|
+
dropped.push(path);
|
|
88
|
+
else
|
|
89
|
+
dropped.push(...droppedKeyPaths(value, after[key], path));
|
|
90
|
+
}
|
|
91
|
+
return dropped;
|
|
92
|
+
}
|
|
93
|
+
return dropped;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Accumulates {@link MirrorNarrowingReport} across the records of one push.
|
|
97
|
+
*
|
|
98
|
+
* Stateful on purpose and scoped to a single envelope: `accept.ts` is otherwise
|
|
99
|
+
* pure, and this keeps the impurity in one named, obviously-per-request object
|
|
100
|
+
* instead of threading counters through the accept logic.
|
|
101
|
+
*/
|
|
102
|
+
export function createNarrowingTally() {
|
|
103
|
+
let records = 0;
|
|
104
|
+
const fields = new Set();
|
|
105
|
+
return {
|
|
106
|
+
note: (before, after) => {
|
|
107
|
+
const paths = droppedKeyPaths(before, after);
|
|
108
|
+
if (paths.length === 0)
|
|
109
|
+
return;
|
|
110
|
+
records += 1;
|
|
111
|
+
for (const path of paths)
|
|
112
|
+
fields.add(path);
|
|
113
|
+
},
|
|
114
|
+
report: () => ({ records, fields: [...fields].sort() })
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=ingest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../../src/runtime/mirror/ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EVO-13 / feed-contract P1 step 4a — the mirror push as an OPT-IN live daemon.
|
|
3
|
+
*
|
|
4
|
+
* `h2a remote mirror` is a ONE-SHOT push (build → sign → POST once). The
|
|
5
|
+
* ratified feed contract
|
|
6
|
+
* (`docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md`,
|
|
7
|
+
* Part C) needs that same push to run continuously on a 15–30s beat, so the
|
|
8
|
+
* hosted read-only store stays warm for a UI that only ever pulls. A laptop
|
|
9
|
+
* behind NAT cannot accept inbound, so the data path must be push — the daemon
|
|
10
|
+
* is the pipeline, not a new trust boundary.
|
|
11
|
+
*
|
|
12
|
+
* This module changes NOTHING about what is pushed. It wraps the existing
|
|
13
|
+
* one-shot cycle (`buildInstanceMirror` → `sendRemoteEnvelope`) in the same
|
|
14
|
+
* supervisor idioms already shipped for the L1 objective loop
|
|
15
|
+
* (`runtime/loop/supervisor.ts`): opt-in only, a global kill-switch, an
|
|
16
|
+
* injectable clock, a drainable abort signal, and a per-beat summary that is
|
|
17
|
+
* observability — never control. The signed-envelope trust boundary, the
|
|
18
|
+
* payload shape, the sequence fencing and the accept-side verification are
|
|
19
|
+
* untouched.
|
|
20
|
+
*
|
|
21
|
+
* Safety properties, in the order they matter:
|
|
22
|
+
*
|
|
23
|
+
* - OPT-IN, NEVER DEFAULT-ON. Nothing here runs unless a caller explicitly
|
|
24
|
+
* asks for an interval. `h2a remote mirror` with no `--interval-ms` still
|
|
25
|
+
* takes the byte-identical one-shot path it took before this module existed.
|
|
26
|
+
* The global kill-switch `H2A_MIRROR_PUSH_OFF` hard-disables the loop even
|
|
27
|
+
* when a unit file or an operator asked for it — checked before the FIRST
|
|
28
|
+
* cycle, so a frozen daemon never emits a single request.
|
|
29
|
+
*
|
|
30
|
+
* - AUTH FAILURE STOPS, IT DOES NOT RETRY FOREVER. A 401/403 means the
|
|
31
|
+
* receiving side does not trust this instance's signing key (never enrolled,
|
|
32
|
+
* revoked, or — the live case today — the agent re-anchored and mints a
|
|
33
|
+
* different keypair than the one enrolled). No amount of retrying fixes
|
|
34
|
+
* that: it needs a human re-enrollment ceremony. So consecutive auth
|
|
35
|
+
* rejections are backed off and then the daemon STOPS with an actionable
|
|
36
|
+
* message, instead of hammering a rejecting endpoint indefinitely. Only a
|
|
37
|
+
* genuinely accepted push (`ok`) clears the counter — a transient error in
|
|
38
|
+
* between does NOT, because "network flap between two 401s" must not be a
|
|
39
|
+
* way to loop forever against a server that is refusing us.
|
|
40
|
+
*
|
|
41
|
+
* - NO OVERLAP. The daemon cannot overlap itself: it awaits each cycle before
|
|
42
|
+
* scheduling the next, so a slow push delays the next beat rather than
|
|
43
|
+
* stacking on top of it (and the slot arithmetic below then skips the beats
|
|
44
|
+
* that were missed). The exported runner ALSO carries an in-flight guard, for
|
|
45
|
+
* the different case of two concurrent callers sharing one runner: the second
|
|
46
|
+
* gets `skipped-overlap` without building or sending anything. That guard is
|
|
47
|
+
* defence for external callers, not what protects the daemon's own loop.
|
|
48
|
+
*
|
|
49
|
+
* - NO DRIFT. Cycles are scheduled against a monotonic slot anchor
|
|
50
|
+
* (`anchor + n × interval`), not by sleeping a fixed interval after each
|
|
51
|
+
* cycle, so per-cycle duration does not accumulate into lateness. Slots
|
|
52
|
+
* already in the past are skipped rather than fired back-to-back. A small
|
|
53
|
+
* bounded jitter de-synchronises several agents pushing to one endpoint.
|
|
54
|
+
*
|
|
55
|
+
* - TRANSIENT ERRORS KEEP LOOPING. A network throw, a 5xx or a 429 is the
|
|
56
|
+
* endpoint's problem, not ours: exponential backoff (capped), then carry on.
|
|
57
|
+
*
|
|
58
|
+
* - A STATUS MUST NOT BE WIDER THAN ITS EVIDENCE. The dividing line for every
|
|
59
|
+
* stop rule above is "can this self-heal": a network outage can, a refused
|
|
60
|
+
* key / a refused request / a root that cannot build this instance's mirror
|
|
61
|
+
* cannot. The non-self-healing cases therefore TERMINATE rather than idle,
|
|
62
|
+
* because idling would make this process the dishonest layer. Consider a
|
|
63
|
+
* wrong `H2A_ROOT`: nothing is ever sent, so the feed downstream correctly
|
|
64
|
+
* starts reporting those rows `stale` once `mirroredAt` stops advancing —
|
|
65
|
+
* while `systemctl status` would still read `active (running)`. The two
|
|
66
|
+
* layers would disagree and the only honest signal would be the one FURTHEST
|
|
67
|
+
* from the operator, in a UI nobody is watching. The signal nearest the fault
|
|
68
|
+
* has to be at least as honest as the far one, so we exit 1 and say why.
|
|
69
|
+
* Correspondingly, the per-cycle line reports what the push CONTAINED (seq +
|
|
70
|
+
* counts), so a successful push of an empty mirror is never mistaken for a
|
|
71
|
+
* healthy feed.
|
|
72
|
+
*
|
|
73
|
+
* - DRAINABLE. `signal` is honored before each cycle and inside every sleep,
|
|
74
|
+
* so SIGTERM stops promptly instead of finishing the schedule.
|
|
75
|
+
*
|
|
76
|
+
* - LOGS ARE SAFE BY CONSTRUCTION. The per-cycle line carries an outcome, an
|
|
77
|
+
* HTTP status, a closed-vocabulary rejection reason and a redacted endpoint.
|
|
78
|
+
* It NEVER carries key material, a token, a request body or a response body.
|
|
79
|
+
* Everything free-form (an error message) goes through `sanitizeForLog`.
|
|
80
|
+
*/
|
|
81
|
+
import type { H2AEnvelope } from "@sentropic/h2a";
|
|
82
|
+
/**
|
|
83
|
+
* Default beat. The ratified contract asks for 15–30s; 20s sits in the middle
|
|
84
|
+
* and keeps a UI's worst-case staleness under the 90s presence keepalive
|
|
85
|
+
* window, so a `stale` row means the pipeline really is down.
|
|
86
|
+
*/
|
|
87
|
+
export declare const DEFAULT_MIRROR_PUSH_INTERVAL_MS = 20000;
|
|
88
|
+
/**
|
|
89
|
+
* Floor the CLI enforces on `--interval-ms`. The library itself accepts any
|
|
90
|
+
* positive interval (tests drive it at millisecond speed against a fake
|
|
91
|
+
* transport); the operator-facing surface refuses anything that would hammer a
|
|
92
|
+
* hosted endpoint faster than the contract's own range.
|
|
93
|
+
*/
|
|
94
|
+
export declare const MIN_MIRROR_PUSH_INTERVAL_MS = 5000;
|
|
95
|
+
/** Bounded de-synchronisation jitter, as a fraction of the interval (±10%). */
|
|
96
|
+
export declare const MIRROR_PUSH_JITTER_FRACTION = 0.1;
|
|
97
|
+
/** First transient-failure backoff; doubles per consecutive failure. */
|
|
98
|
+
export declare const MIRROR_PUSH_BACKOFF_BASE_MS = 5000;
|
|
99
|
+
/** Backoff ceiling — a long outage retries every 5 min, not every 5 hours. */
|
|
100
|
+
export declare const MIRROR_PUSH_BACKOFF_MAX_MS = 300000;
|
|
101
|
+
/**
|
|
102
|
+
* How many CONSECUTIVE auth rejections are tolerated (each backed off) before
|
|
103
|
+
* the daemon stops. 3 absorbs a key-rotation race on the accept side while
|
|
104
|
+
* still stopping in well under a minute of real rejection.
|
|
105
|
+
*/
|
|
106
|
+
export declare const DEFAULT_MIRROR_AUTH_FAILURE_LIMIT = 3;
|
|
107
|
+
/**
|
|
108
|
+
* How many CONSECUTIVE non-auth rejections (a 4xx that is not 401/403) are
|
|
109
|
+
* tolerated before the daemon stops. Some of these genuinely self-heal — a
|
|
110
|
+
* stale-sequence or replay rejection clears as `seq` advances — which is why the
|
|
111
|
+
* budget is looser than the auth one. But a permanently malformed request or a
|
|
112
|
+
* wrong path returning 404 will never heal, and retrying it forever is the same
|
|
113
|
+
* failure mode as retrying a refused key: a unit that reads "active (running)"
|
|
114
|
+
* while pushing nothing. 5 tolerates a real fencing race, then stops.
|
|
115
|
+
*/
|
|
116
|
+
export declare const DEFAULT_MIRROR_REJECT_LIMIT = 5;
|
|
117
|
+
/**
|
|
118
|
+
* How many CONSECUTIVE local build failures are tolerated before the daemon
|
|
119
|
+
* stops. `buildInstanceMirror` throwing means this root does not know this
|
|
120
|
+
* instance — overwhelmingly because `H2A_ROOT` points somewhere the agent never
|
|
121
|
+
* registered, the misconfiguration the shipped unit file explicitly warns about.
|
|
122
|
+
* A wrong root NEVER self-heals, and looping on it forever is the worst possible
|
|
123
|
+
* failure shape: no request is ever sent, yet `systemctl status` reads
|
|
124
|
+
* `active (running)` indefinitely, so monitoring keyed on systemd state reads
|
|
125
|
+
* green while the feed is dead. It must terminate loudly instead. 5 leaves room
|
|
126
|
+
* for a genuinely transient race (an agent re-registering, a root being created).
|
|
127
|
+
*
|
|
128
|
+
* The contract-level argument (from the feed contract's own architect): in this
|
|
129
|
+
* failure mode the feed WOULD report `stale` correctly, because `mirroredAt` stops
|
|
130
|
+
* advancing — so the honest signal exists, but only at the layer furthest from the
|
|
131
|
+
* operator. Idling here would ship a daemon that claims health next to a contract
|
|
132
|
+
* written specifically to refuse claiming it.
|
|
133
|
+
*/
|
|
134
|
+
export declare const DEFAULT_MIRROR_BUILD_FAILURE_LIMIT = 5;
|
|
135
|
+
/** Name of the global kill-switch env var. */
|
|
136
|
+
export declare const MIRROR_PUSH_OFF_ENV = "H2A_MIRROR_PUSH_OFF";
|
|
137
|
+
/**
|
|
138
|
+
* Global kill-switch for the live mirror push. When `H2A_MIRROR_PUSH_OFF` is
|
|
139
|
+
* set to any non-empty, non-"0"/"false" value, NO mirror push daemon runs
|
|
140
|
+
* anywhere, regardless of flags or unit files. Same semantics as
|
|
141
|
+
* `H2A_LOOP_AUTOTICK_OFF` for the objective-loop supervisor — one lever to
|
|
142
|
+
* freeze the pipeline without editing any invocation.
|
|
143
|
+
*/
|
|
144
|
+
export declare function mirrorPushGloballyDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Emitted when the daemon stops because the endpoint keeps rejecting the request
|
|
147
|
+
* itself (not the key). Like the auth stop, retrying cannot fix a permanently
|
|
148
|
+
* malformed request or a wrong path.
|
|
149
|
+
*/
|
|
150
|
+
export declare const MIRROR_PUSH_REJECTED_MESSAGE: string;
|
|
151
|
+
/**
|
|
152
|
+
* Emitted when the daemon is asked to push to something that is not a usable
|
|
153
|
+
* http(s) endpoint. Returned BEFORE any cycle runs, because a URL `fetch` cannot
|
|
154
|
+
* even parse would otherwise be retried forever as a transient network failure.
|
|
155
|
+
*/
|
|
156
|
+
/**
|
|
157
|
+
* Emitted when the daemon stops because it cannot even BUILD a mirror locally.
|
|
158
|
+
* Names the likely cause, because this failure never reaches the network and so
|
|
159
|
+
* leaves no server-side trace for the operator to correlate against.
|
|
160
|
+
*/
|
|
161
|
+
export declare const MIRROR_PUSH_BUILD_FAILED_MESSAGE: string;
|
|
162
|
+
export declare const MIRROR_PUSH_INVALID_URL_MESSAGE: string;
|
|
163
|
+
/**
|
|
164
|
+
* The actionable message emitted when the daemon stops on repeated auth
|
|
165
|
+
* rejection. Deliberately explicit: the failure is NOT retryable and the
|
|
166
|
+
* operator must know exactly which human act unblocks it.
|
|
167
|
+
*/
|
|
168
|
+
export declare const MIRROR_PUSH_REENROLLMENT_MESSAGE: string;
|
|
169
|
+
/** What one cycle did. `skipped-overlap` performed no build and no request. */
|
|
170
|
+
export type MirrorPushOutcome = "ok" | "auth-rejected" | "rejected" | "transient" | "build-failed" | "skipped-overlap";
|
|
171
|
+
/**
|
|
172
|
+
* Why the daemon returned. Every reason is a clean, intentional stop — the
|
|
173
|
+
* daemon never falls out of its loop by accident.
|
|
174
|
+
*
|
|
175
|
+
* `auth-stop`, `reject-stop`, `build-stop` and `config-invalid` are the four
|
|
176
|
+
* that need a human act; they are exactly the reasons that carry a `message`,
|
|
177
|
+
* and the CLI turns any `message` into exit 1 so systemd keeps the unit stopped.
|
|
178
|
+
* `log-unavailable` is a CLEAN stop (no message, exit 0): the status sink went
|
|
179
|
+
* away — a piped stdout closed — so the daemon stops rather than keep pushing
|
|
180
|
+
* with no way to report what it is doing.
|
|
181
|
+
*/
|
|
182
|
+
export type MirrorPushStopReason = "max-cycles" | "aborted" | "kill-switch" | "auth-stop" | "reject-stop" | "build-stop" | "config-invalid" | "log-unavailable";
|
|
183
|
+
export interface MirrorPushCycleResult {
|
|
184
|
+
readonly outcome: MirrorPushOutcome;
|
|
185
|
+
/** HTTP status, when a request actually completed. */
|
|
186
|
+
readonly status?: number;
|
|
187
|
+
/** Closed-vocabulary accept-side rejection reason, when the body carried one. */
|
|
188
|
+
readonly reason?: string;
|
|
189
|
+
/** Sanitized error text for `transient` / `build-failed`. Never secrets. */
|
|
190
|
+
readonly error?: string;
|
|
191
|
+
readonly durationMs: number;
|
|
192
|
+
/**
|
|
193
|
+
* What the pushed envelope actually CONTAINED. All non-secret: a monotonic
|
|
194
|
+
* sequence number and three cardinalities, never a body.
|
|
195
|
+
*
|
|
196
|
+
* Without these, a `200` says only "the endpoint accepted something" — a valid
|
|
197
|
+
* root whose instance has no live sessions pushes `presence: []` every cycle
|
|
198
|
+
* and logs a perfectly healthy `ok`, while the hosted UI shows nothing. These
|
|
199
|
+
* make "successfully pushed nothing" distinguishable from "pushed the mirror".
|
|
200
|
+
*/
|
|
201
|
+
readonly payload?: MirrorPushPayloadShape;
|
|
202
|
+
}
|
|
203
|
+
/** Non-secret shape of one pushed mirror: what it carried, never its content. */
|
|
204
|
+
export interface MirrorPushPayloadShape {
|
|
205
|
+
/** Per-instance monotonic sequence the receiver fences on. */
|
|
206
|
+
readonly seq?: number;
|
|
207
|
+
readonly registrations: number;
|
|
208
|
+
readonly presence: number;
|
|
209
|
+
readonly subagents: number;
|
|
210
|
+
}
|
|
211
|
+
/** The one-line-per-cycle status record. Safe to journal verbatim. */
|
|
212
|
+
export interface MirrorPushCycleLog {
|
|
213
|
+
readonly cycle: number;
|
|
214
|
+
readonly at: string;
|
|
215
|
+
readonly instance: string;
|
|
216
|
+
/** Redacted endpoint: scheme + host + path only. No query, no userinfo. */
|
|
217
|
+
readonly endpoint: string;
|
|
218
|
+
readonly outcome: MirrorPushOutcome;
|
|
219
|
+
readonly status?: number;
|
|
220
|
+
readonly reason?: string;
|
|
221
|
+
readonly error?: string;
|
|
222
|
+
readonly durationMs: number;
|
|
223
|
+
/** Sleep before the next cycle. Absent when the daemon is stopping. */
|
|
224
|
+
readonly nextInMs?: number;
|
|
225
|
+
/** Consecutive auth rejections so far — 0 unless the key is being refused. */
|
|
226
|
+
readonly authFailures?: number;
|
|
227
|
+
/** Consecutive non-auth rejections so far — 0 unless the request is refused. */
|
|
228
|
+
readonly rejections?: number;
|
|
229
|
+
/** Consecutive local build failures so far — 0 unless the root is wrong. */
|
|
230
|
+
readonly buildFailures?: number;
|
|
231
|
+
/** Sequence number of the pushed envelope (fencing anchor). */
|
|
232
|
+
readonly seq?: number;
|
|
233
|
+
/** How many registrations the pushed mirror carried. */
|
|
234
|
+
readonly registrations?: number;
|
|
235
|
+
/** How many presence sessions it carried — 0 means "pushed an empty mirror". */
|
|
236
|
+
readonly presence?: number;
|
|
237
|
+
/** How many subagent bindings it carried. */
|
|
238
|
+
readonly subagents?: number;
|
|
239
|
+
}
|
|
240
|
+
export interface MirrorPushDaemonSummary {
|
|
241
|
+
readonly cycles: number;
|
|
242
|
+
/** Cycles the endpoint accepted (2xx). */
|
|
243
|
+
readonly ok: number;
|
|
244
|
+
/** Cycles that did not push successfully (any non-ok, non-skipped outcome). */
|
|
245
|
+
readonly failures: number;
|
|
246
|
+
/**
|
|
247
|
+
* Cycles skipped because a previous push was still in flight. Always 0 for the
|
|
248
|
+
* daemon itself, which awaits each cycle and therefore cannot overlap itself;
|
|
249
|
+
* non-zero only when a `runner` is shared with another concurrent caller.
|
|
250
|
+
*/
|
|
251
|
+
readonly skippedOverlap: number;
|
|
252
|
+
/** Consecutive auth rejections at stop time. */
|
|
253
|
+
readonly authFailures: number;
|
|
254
|
+
/** Consecutive non-auth rejections at stop time. */
|
|
255
|
+
readonly rejections: number;
|
|
256
|
+
/** Consecutive local build failures at stop time. */
|
|
257
|
+
readonly buildFailures: number;
|
|
258
|
+
/**
|
|
259
|
+
* Times the status sink (`onCycle`) threw. Never affects the push itself —
|
|
260
|
+
* observability failures are counted, not propagated — but a non-zero value
|
|
261
|
+
* means the journal is an incomplete record of what this daemon did.
|
|
262
|
+
*/
|
|
263
|
+
readonly logFailures: number;
|
|
264
|
+
readonly stopReason: MirrorPushStopReason;
|
|
265
|
+
/**
|
|
266
|
+
* The actionable instruction for a stop that needs a human act. Present on
|
|
267
|
+
* exactly the four such stops — `auth-stop`
|
|
268
|
+
* ({@link MIRROR_PUSH_REENROLLMENT_MESSAGE}), `reject-stop`
|
|
269
|
+
* ({@link MIRROR_PUSH_REJECTED_MESSAGE}), `build-stop`
|
|
270
|
+
* ({@link MIRROR_PUSH_BUILD_FAILED_MESSAGE}) and `config-invalid`
|
|
271
|
+
* ({@link MIRROR_PUSH_INVALID_URL_MESSAGE}) — and absent on the clean stops
|
|
272
|
+
* (`max-cycles`, `aborted`, `kill-switch`, `log-unavailable`). Its presence is
|
|
273
|
+
* what the CLI keys exit 1 on, so systemd's `RestartPreventExitStatus=1` keeps
|
|
274
|
+
* the unit stopped instead of restarting into the same wall.
|
|
275
|
+
*/
|
|
276
|
+
readonly message?: string;
|
|
277
|
+
}
|
|
278
|
+
/** Builds the (unsigned) mirror envelope for a given clock reading. */
|
|
279
|
+
export type MirrorEnvelopeBuilder = (nowMs: number) => H2AEnvelope;
|
|
280
|
+
/** Signs + POSTs the envelope. Injected in tests; never a real socket there. */
|
|
281
|
+
export type MirrorEnvelopeSender = (url: string, envelope: H2AEnvelope, options: {
|
|
282
|
+
by: string;
|
|
283
|
+
privateKeyPem: string;
|
|
284
|
+
}) => Promise<{
|
|
285
|
+
status: number;
|
|
286
|
+
body: unknown;
|
|
287
|
+
}>;
|
|
288
|
+
/**
|
|
289
|
+
* Strip anything that could be secret out of free-form text before it is
|
|
290
|
+
* logged. Defence in depth: nothing here is SUPPOSED to see key material, but a
|
|
291
|
+
* thrown error can carry whatever the thrower put in it, and this daemon holds a
|
|
292
|
+
* private key in memory. PEM blocks, bearer tokens and token-ish query params
|
|
293
|
+
* are replaced; the result is length-capped so a giant blob cannot be smuggled
|
|
294
|
+
* out one line at a time.
|
|
295
|
+
*/
|
|
296
|
+
export declare function sanitizeForLog(text: string): string;
|
|
297
|
+
/**
|
|
298
|
+
* True when `url` is something a push could actually reach: parseable, and
|
|
299
|
+
* http(s). Anything else — an unfilled placeholder, a typo, a `file:` or `ws:`
|
|
300
|
+
* scheme — makes `fetch` throw a parse error that would otherwise be classified
|
|
301
|
+
* as a retryable network failure and retried forever.
|
|
302
|
+
*/
|
|
303
|
+
export declare function isPushableHttpUrl(url: string | undefined): boolean;
|
|
304
|
+
/**
|
|
305
|
+
* Reduce a URL to scheme + host + path. Drops query and userinfo, which are the
|
|
306
|
+
* two places a credential can hide in a URL, and keeps enough for an operator to
|
|
307
|
+
* recognise which endpoint is being pushed to.
|
|
308
|
+
*/
|
|
309
|
+
export declare function redactEndpoint(url: string): string;
|
|
310
|
+
export interface MirrorPushRunnerOptions {
|
|
311
|
+
/** h2a root the mirror is built from. */
|
|
312
|
+
readonly root: string;
|
|
313
|
+
/** Endpoint to POST the signed envelope to. */
|
|
314
|
+
readonly url: string;
|
|
315
|
+
/** Instance whose registration + presence is mirrored (also the signer). */
|
|
316
|
+
readonly instance: string;
|
|
317
|
+
/** Signer's ed25519 private-key PEM. Never logged, never sent. */
|
|
318
|
+
readonly privateKeyPem: string;
|
|
319
|
+
/** Injectable clock (ms). Default `Date.now`. */
|
|
320
|
+
readonly now?: () => number;
|
|
321
|
+
/** Injectable envelope builder. Default the real `buildInstanceMirror`. */
|
|
322
|
+
readonly buildImpl?: MirrorEnvelopeBuilder;
|
|
323
|
+
/** Injectable transport. Default the real `sendRemoteEnvelope`. */
|
|
324
|
+
readonly sendImpl?: MirrorEnvelopeSender;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Create the guarded one-cycle runner: build → sign → POST once, classified.
|
|
328
|
+
*
|
|
329
|
+
* The returned function is the ONLY thing that touches the network. It carries an
|
|
330
|
+
* in-flight guard for CONCURRENT callers of the same runner: while one cycle is
|
|
331
|
+
* running, a second call returns `skipped-overlap` immediately without building
|
|
332
|
+
* an envelope or issuing a request. (The daemon itself awaits each cycle, so it
|
|
333
|
+
* never trips this guard on its own — see the module header.) Exposed so a caller
|
|
334
|
+
* or a test can drive single cycles without the timer loop, exactly as
|
|
335
|
+
* `runSupervisorBeat` is exposed next to `runLoopSupervisor`.
|
|
336
|
+
*
|
|
337
|
+
* Never throws: every failure is classified into a {@link MirrorPushOutcome}.
|
|
338
|
+
*/
|
|
339
|
+
export declare function createMirrorPushRunner(options: MirrorPushRunnerOptions): () => Promise<MirrorPushCycleResult>;
|
|
340
|
+
export interface MirrorPushDaemonOptions extends MirrorPushRunnerOptions {
|
|
341
|
+
/** Beat interval. Default {@link DEFAULT_MIRROR_PUSH_INTERVAL_MS}. */
|
|
342
|
+
readonly intervalMs?: number;
|
|
343
|
+
/** Stop after this many cycles (testing / bounded ops runs). */
|
|
344
|
+
readonly max?: number;
|
|
345
|
+
/** Abort to stop the daemon between cycles and inside every sleep. */
|
|
346
|
+
readonly signal?: AbortSignal;
|
|
347
|
+
/** Environment for the kill-switch. Default `process.env`. */
|
|
348
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
349
|
+
/** Injectable randomness for the jitter. Default `Math.random`. */
|
|
350
|
+
readonly random?: () => number;
|
|
351
|
+
/** Injectable sleep, so tests advance a fake clock instead of waiting. */
|
|
352
|
+
readonly sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
353
|
+
/** Consecutive auth rejections tolerated. Default {@link DEFAULT_MIRROR_AUTH_FAILURE_LIMIT}. */
|
|
354
|
+
readonly authFailureLimit?: number;
|
|
355
|
+
/** Consecutive non-auth rejections tolerated. Default {@link DEFAULT_MIRROR_REJECT_LIMIT}. */
|
|
356
|
+
readonly rejectLimit?: number;
|
|
357
|
+
/** Consecutive local build failures tolerated. Default {@link DEFAULT_MIRROR_BUILD_FAILURE_LIMIT}. */
|
|
358
|
+
readonly buildFailureLimit?: number;
|
|
359
|
+
readonly backoffBaseMs?: number;
|
|
360
|
+
readonly backoffMaxMs?: number;
|
|
361
|
+
/** Pre-built runner (shares one overlap guard across callers). */
|
|
362
|
+
readonly runner?: () => Promise<MirrorPushCycleResult>;
|
|
363
|
+
/** Called once per cycle with the safe status line. */
|
|
364
|
+
readonly onCycle?: (log: MirrorPushCycleLog) => void | Promise<void>;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Run the live mirror push until `signal` aborts, `max` cycles elapse, or the
|
|
368
|
+
* endpoint has refused this key often enough to stop (see
|
|
369
|
+
* {@link MIRROR_PUSH_REENROLLMENT_MESSAGE}).
|
|
370
|
+
*
|
|
371
|
+
* This is what the systemd `--user` unit runs. It is NEVER on any default code
|
|
372
|
+
* path: no caller reaches it without an explicit interval, and the kill-switch
|
|
373
|
+
* short-circuits it before the first request.
|
|
374
|
+
*/
|
|
375
|
+
export declare function runMirrorPushDaemon(options: MirrorPushDaemonOptions): Promise<MirrorPushDaemonSummary>;
|
|
376
|
+
//# sourceMappingURL=push-daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-daemon.d.ts","sourceRoot":"","sources":["../../../src/runtime/mirror/push-daemon.ts"],"names":[],"mappings":"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"}
|