harnery 0.35.0 → 0.36.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/dist/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -96
- package/dist/commands/agents.d.ts +23 -3
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +379 -198
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +5 -4
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts.map +1 -1
- package/dist/commands/semantic.js +54 -2
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +67 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +244 -10
- package/dist/core/agents/live-lifecycle-v3.js +6 -1
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +6 -1
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +24 -7
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +94 -13
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +18 -0
- package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +15 -90
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/artifacts/index.d.ts +21 -0
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +46 -1
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +81 -41
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +17 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.js +3 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +4 -2
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +3 -1
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +13 -21
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +45 -41
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.js +1 -1
- package/dist/core/events/v3/producers/intake.d.ts +7 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +25 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +55 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +353 -24
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
- package/dist/core/hooks/cli.js +212 -30
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +8 -3
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
- package/dist/core/hooks/remediation-cap.js +3 -11
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +8 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +11 -0
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +11 -8
- package/dist/core/semantic/adapters.d.ts.map +1 -1
- package/dist/core/semantic/adapters.js +169 -31
- package/dist/core/semantic/contract.d.ts +532 -48
- package/dist/core/semantic/contract.d.ts.map +1 -1
- package/dist/core/semantic/contract.js +104 -3
- package/dist/core/semantic/index.d.ts +7 -3
- package/dist/core/semantic/index.d.ts.map +1 -1
- package/dist/core/semantic/index.js +7 -3
- package/dist/core/semantic/once.d.ts +6 -1
- package/dist/core/semantic/once.d.ts.map +1 -1
- package/dist/core/semantic/once.js +80 -9
- package/dist/core/semantic/prompt.d.ts.map +1 -1
- package/dist/core/semantic/prompt.js +14 -1
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +14 -3
- package/dist/core/semantic/scheduler.d.ts.map +1 -1
- package/dist/core/semantic/scheduler.js +30 -6
- package/dist/core/semantic/service-status.d.ts +20 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -1
- package/dist/core/semantic/service-status.js +60 -4
- package/dist/core/semantic/service.d.ts +1 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +104 -15
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +11 -1
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +4 -3
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +3 -1
- package/dist/core/semantic/validate.d.ts.map +1 -1
- package/dist/core/semantic/validate.js +34 -1
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +5 -0
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +29 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +324 -112
- package/src/commander.ts +462 -95
- package/src/commands/agents.ts +517 -190
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +6 -7
- package/src/commands/conversations.ts +279 -0
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +66 -1
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +77 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/live-authority-v3.ts +341 -10
- package/src/core/agents/live-lifecycle-v3.ts +6 -1
- package/src/core/agents/live-observation-v3.ts +6 -1
- package/src/core/agents/render/prompt-context.ts +27 -6
- package/src/core/agents/rules/stop-hook.ts +107 -16
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-writer.ts +27 -0
- package/src/core/agents/state/live-coordination-view.ts +16 -105
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/artifacts/index.ts +64 -1
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +17 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +3 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +5 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +64 -46
- package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +1 -1
- package/src/core/events/v3/producers/intake.ts +30 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +571 -33
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +58 -7
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
- package/src/core/hooks/cli.ts +226 -32
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +12 -6
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +18 -0
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +200 -41
- package/src/core/semantic/contract.ts +135 -3
- package/src/core/semantic/index.ts +76 -2
- package/src/core/semantic/once.ts +93 -7
- package/src/core/semantic/prompt.ts +13 -1
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +49 -5
- package/src/core/semantic/service-status.ts +99 -5
- package/src/core/semantic/service.ts +116 -15
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +20 -6
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +31 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/templates.ts +5 -0
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type EventV3SupportPackManifest, type EventV3SupportPackRecord } from "./pack-contract.js";
|
|
2
|
+
export interface EventV3SupportPackLimits {
|
|
3
|
+
max_manifest_bytes?: number;
|
|
4
|
+
max_payload_bytes?: number;
|
|
5
|
+
max_decompressed_bytes?: number;
|
|
6
|
+
max_record_line_bytes?: number;
|
|
7
|
+
max_entries?: number;
|
|
8
|
+
fault?: (boundary: "after_payload_digest", path: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface DecodedEventV3SupportPackRecord extends Omit<EventV3SupportPackRecord, "content_base64"> {
|
|
11
|
+
content: Buffer;
|
|
12
|
+
}
|
|
13
|
+
export interface ValidatedEventV3SupportPack {
|
|
14
|
+
manifest: EventV3SupportPackManifest;
|
|
15
|
+
records: DecodedEventV3SupportPackRecord[];
|
|
16
|
+
}
|
|
17
|
+
export interface VerifiedEventV3SupportPack {
|
|
18
|
+
manifest: EventV3SupportPackManifest;
|
|
19
|
+
entries: number;
|
|
20
|
+
uncompressed_bytes: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function readEventV3SupportPackManifest(manifestPath: string, limits?: EventV3SupportPackLimits): Promise<EventV3SupportPackManifest>;
|
|
23
|
+
/** Validate one pack and stream logical records to the caller one source file at a time. */
|
|
24
|
+
export declare function streamEventV3SupportPackRecords(manifestPath: string, limits?: EventV3SupportPackLimits): AsyncGenerator<DecodedEventV3SupportPackRecord>;
|
|
25
|
+
export declare function validateEventV3SupportPack(manifestPath: string, limits?: EventV3SupportPackLimits): Promise<ValidatedEventV3SupportPack>;
|
|
26
|
+
/** Verify the complete pack while retaining only one decoded source record at a time. */
|
|
27
|
+
export declare function verifyEventV3SupportPack(manifestPath: string, limits?: EventV3SupportPackLimits): Promise<VerifiedEventV3SupportPack>;
|
|
28
|
+
/** Unpack only into a destination that does not yet exist; never overlay an authority. */
|
|
29
|
+
export declare function unpackEventV3SupportPack(manifestPath: string, destination: string, limits?: EventV3SupportPackLimits): Promise<{
|
|
30
|
+
files: number;
|
|
31
|
+
bytes: number;
|
|
32
|
+
destination: string;
|
|
33
|
+
}>;
|
|
34
|
+
//# sourceMappingURL=pack-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-reader.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/support-storage/pack-reader.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,wBAAwB;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,+BACf,SAAQ,IAAI,CAAC,wBAAwB,EAAE,gBAAgB,CAAC;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,0BAA0B,CAAC;IACrC,OAAO,EAAE,+BAA+B,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAUD,wBAAsB,8BAA8B,CAClD,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,wBAA6B,GACpC,OAAO,CAAC,0BAA0B,CAAC,CAarC;AAED,4FAA4F;AAC5F,wBAAuB,+BAA+B,CACpD,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,wBAA6B,GACpC,cAAc,CAAC,+BAA+B,CAAC,CAGjD;AA2GD,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,wBAA6B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAWtC;AAED,yFAAyF;AACzF,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,EACpB,MAAM,GAAE,wBAA6B,GACpC,OAAO,CAAC,0BAA0B,CAAC,CAarC;AAED,0FAA0F;AAC1F,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,wBAA6B,GACpC,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BhE"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { constants, createReadStream } from "node:fs";
|
|
3
|
+
import { lstat, mkdir, open, realpath, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
5
|
+
import { StringDecoder } from "node:string_decoder";
|
|
6
|
+
import { createGunzip, createInflateRaw } from "node:zlib";
|
|
7
|
+
import { logicalEntriesDigestV3, validateEventV3SupportPackManifest, validateEventV3SupportPackRecord, } from "./pack-contract.js";
|
|
8
|
+
const DEFAULT_LIMITS = {
|
|
9
|
+
max_manifest_bytes: 1024 * 1024,
|
|
10
|
+
max_payload_bytes: 8 * 1024 * 1024 * 1024,
|
|
11
|
+
max_decompressed_bytes: 16 * 1024 * 1024 * 1024,
|
|
12
|
+
max_record_line_bytes: 128 * 1024 * 1024,
|
|
13
|
+
max_entries: 2_000_000,
|
|
14
|
+
};
|
|
15
|
+
export async function readEventV3SupportPackManifest(manifestPath, limits = {}) {
|
|
16
|
+
const bounded = { ...DEFAULT_LIMITS, ...limits };
|
|
17
|
+
const path = resolve(manifestPath);
|
|
18
|
+
const handle = await openStableRegularFile(path, undefined, "manifest");
|
|
19
|
+
try {
|
|
20
|
+
const stat = await handle.stat();
|
|
21
|
+
if (stat.size > bounded.max_manifest_bytes)
|
|
22
|
+
throw new Error("event_v3_support_manifest_too_large");
|
|
23
|
+
const value = JSON.parse(await handle.readFile("utf8"));
|
|
24
|
+
return validateEventV3SupportPackManifest(value);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await handle.close();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Validate one pack and stream logical records to the caller one source file at a time. */
|
|
31
|
+
export async function* streamEventV3SupportPackRecords(manifestPath, limits = {}) {
|
|
32
|
+
const manifest = await readEventV3SupportPackManifest(manifestPath, limits);
|
|
33
|
+
yield* streamEventV3SupportPackRecordsForManifest(manifestPath, manifest, limits);
|
|
34
|
+
}
|
|
35
|
+
async function* streamEventV3SupportPackRecordsForManifest(manifestPath, manifest, limits) {
|
|
36
|
+
const bounded = { ...DEFAULT_LIMITS, ...limits };
|
|
37
|
+
const manifestDirectory = await realDirectory(dirname(resolve(manifestPath)));
|
|
38
|
+
const payloadPath = resolve(manifestDirectory, manifest.payload.path);
|
|
39
|
+
const payloadHandle = await openStableRegularFile(payloadPath, manifestDirectory, "payload");
|
|
40
|
+
try {
|
|
41
|
+
const payloadStat = await payloadHandle.stat();
|
|
42
|
+
if (payloadStat.size !== manifest.payload.bytes)
|
|
43
|
+
throw new Error("event_v3_support_payload_length_mismatch");
|
|
44
|
+
if (payloadStat.size > bounded.max_payload_bytes)
|
|
45
|
+
throw new Error("event_v3_support_payload_too_large");
|
|
46
|
+
if ((await hashHandle(payloadPath, payloadHandle)) !== manifest.payload.digest) {
|
|
47
|
+
throw new Error("event_v3_support_payload_digest_mismatch");
|
|
48
|
+
}
|
|
49
|
+
limits.fault?.("after_payload_digest", payloadPath);
|
|
50
|
+
await assertCanonicalSingleGzipMember(payloadPath, payloadHandle, payloadStat.size, bounded.max_decompressed_bytes);
|
|
51
|
+
const gunzip = createGunzip();
|
|
52
|
+
const source = createReadStream(payloadPath, {
|
|
53
|
+
fd: payloadHandle.fd,
|
|
54
|
+
autoClose: false,
|
|
55
|
+
start: 0,
|
|
56
|
+
});
|
|
57
|
+
source.pipe(gunzip);
|
|
58
|
+
const decoder = new StringDecoder("utf8");
|
|
59
|
+
let pending = "";
|
|
60
|
+
let decompressedBytes = 0;
|
|
61
|
+
let entryCount = 0;
|
|
62
|
+
let uncompressedBytes = 0;
|
|
63
|
+
let priorPath;
|
|
64
|
+
const entries = [];
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
for await (const current of gunzip) {
|
|
67
|
+
const chunk = current;
|
|
68
|
+
decompressedBytes += chunk.length;
|
|
69
|
+
if (decompressedBytes > bounded.max_decompressed_bytes) {
|
|
70
|
+
throw new Error("event_v3_support_decompression_bound_exceeded");
|
|
71
|
+
}
|
|
72
|
+
pending += decoder.write(chunk);
|
|
73
|
+
if (Buffer.byteLength(pending) > bounded.max_record_line_bytes && !pending.includes("\n")) {
|
|
74
|
+
throw new Error("event_v3_support_record_bound_exceeded");
|
|
75
|
+
}
|
|
76
|
+
let newline = pending.indexOf("\n");
|
|
77
|
+
while (newline >= 0) {
|
|
78
|
+
const line = pending.slice(0, newline);
|
|
79
|
+
pending = pending.slice(newline + 1);
|
|
80
|
+
if (line.length === 0)
|
|
81
|
+
throw new Error("event_v3_support_trailing_data");
|
|
82
|
+
if (Buffer.byteLength(line) > bounded.max_record_line_bytes) {
|
|
83
|
+
throw new Error("event_v3_support_record_bound_exceeded");
|
|
84
|
+
}
|
|
85
|
+
const record = validateEventV3SupportPackRecord(JSON.parse(line));
|
|
86
|
+
entryCount += 1;
|
|
87
|
+
if (entryCount > bounded.max_entries)
|
|
88
|
+
throw new Error("event_v3_support_entry_bound_exceeded");
|
|
89
|
+
if (seen.has(record.path))
|
|
90
|
+
throw new Error("event_v3_support_duplicate_path");
|
|
91
|
+
if (priorPath !== undefined && priorPath.localeCompare(record.path) >= 0) {
|
|
92
|
+
throw new Error("event_v3_support_record_order_invalid");
|
|
93
|
+
}
|
|
94
|
+
seen.add(record.path);
|
|
95
|
+
priorPath = record.path;
|
|
96
|
+
const content = Buffer.from(record.content_base64, "base64");
|
|
97
|
+
if (content.toString("base64") !== record.content_base64) {
|
|
98
|
+
throw new Error("event_v3_support_record_base64_noncanonical");
|
|
99
|
+
}
|
|
100
|
+
if (content.length !== record.bytes)
|
|
101
|
+
throw new Error("event_v3_support_record_length_mismatch");
|
|
102
|
+
if (`sha256:${createHash("sha256").update(content).digest("hex")}` !== record.digest) {
|
|
103
|
+
throw new Error("event_v3_support_record_digest_mismatch");
|
|
104
|
+
}
|
|
105
|
+
uncompressedBytes += content.length;
|
|
106
|
+
entries.push({ path: record.path, bytes: record.bytes, digest: record.digest });
|
|
107
|
+
yield { path: record.path, bytes: record.bytes, digest: record.digest, content };
|
|
108
|
+
newline = pending.indexOf("\n");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
pending += decoder.end();
|
|
112
|
+
if (pending.length !== 0)
|
|
113
|
+
throw new Error("event_v3_support_payload_truncated_or_trailing");
|
|
114
|
+
if (entryCount !== manifest.entries.count ||
|
|
115
|
+
uncompressedBytes !== manifest.entries.uncompressed_bytes) {
|
|
116
|
+
throw new Error("event_v3_support_manifest_entry_mismatch");
|
|
117
|
+
}
|
|
118
|
+
const digest = logicalEntriesDigestV3(entries);
|
|
119
|
+
if (digest !== manifest.entries.logical_entries_digest ||
|
|
120
|
+
digest !== manifest.authority.source_files_digest) {
|
|
121
|
+
throw new Error("event_v3_support_logical_digest_mismatch");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await payloadHandle.close();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export async function validateEventV3SupportPack(manifestPath, limits = {}) {
|
|
129
|
+
const manifest = await readEventV3SupportPackManifest(manifestPath, limits);
|
|
130
|
+
const records = [];
|
|
131
|
+
for await (const record of streamEventV3SupportPackRecordsForManifest(manifestPath, manifest, limits)) {
|
|
132
|
+
records.push(record);
|
|
133
|
+
}
|
|
134
|
+
return { manifest, records };
|
|
135
|
+
}
|
|
136
|
+
/** Verify the complete pack while retaining only one decoded source record at a time. */
|
|
137
|
+
export async function verifyEventV3SupportPack(manifestPath, limits = {}) {
|
|
138
|
+
const manifest = await readEventV3SupportPackManifest(manifestPath, limits);
|
|
139
|
+
let entries = 0;
|
|
140
|
+
let bytes = 0;
|
|
141
|
+
for await (const record of streamEventV3SupportPackRecordsForManifest(manifestPath, manifest, limits)) {
|
|
142
|
+
entries += 1;
|
|
143
|
+
bytes += record.bytes;
|
|
144
|
+
}
|
|
145
|
+
return { manifest, entries, uncompressed_bytes: bytes };
|
|
146
|
+
}
|
|
147
|
+
/** Unpack only into a destination that does not yet exist; never overlay an authority. */
|
|
148
|
+
export async function unpackEventV3SupportPack(manifestPath, destination, limits = {}) {
|
|
149
|
+
const target = resolve(destination);
|
|
150
|
+
try {
|
|
151
|
+
await lstat(target);
|
|
152
|
+
throw new Error("event_v3_support_unpack_destination_exists");
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error.code !== "ENOENT")
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
await mkdir(target, { recursive: false, mode: 0o700 });
|
|
159
|
+
let files = 0;
|
|
160
|
+
let bytes = 0;
|
|
161
|
+
try {
|
|
162
|
+
for await (const record of streamEventV3SupportPackRecords(manifestPath, limits)) {
|
|
163
|
+
const path = resolve(target, ...record.path.split("/"));
|
|
164
|
+
if (relative(target, path).startsWith(".."))
|
|
165
|
+
throw new Error("event_v3_support_unpack_path_escape");
|
|
166
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
167
|
+
await writeFile(path, record.content, { flag: "wx", mode: 0o600 });
|
|
168
|
+
files += 1;
|
|
169
|
+
bytes += record.bytes;
|
|
170
|
+
}
|
|
171
|
+
return { files, bytes, destination: target };
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
await rm(target, { recursive: true, force: true });
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async function hashHandle(path, handle) {
|
|
179
|
+
const hash = createHash("sha256");
|
|
180
|
+
const stream = createReadStream(path, { fd: handle.fd, autoClose: false, start: 0 });
|
|
181
|
+
for await (const current of stream)
|
|
182
|
+
hash.update(current);
|
|
183
|
+
return `sha256:${hash.digest("hex")}`;
|
|
184
|
+
}
|
|
185
|
+
async function realDirectory(path) {
|
|
186
|
+
const stat = await lstat(path);
|
|
187
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
188
|
+
throw new Error("event_v3_support_pack_root_invalid");
|
|
189
|
+
return realpath(path);
|
|
190
|
+
}
|
|
191
|
+
async function assertCanonicalSingleGzipMember(path, handle, payloadBytes, maximumDecompressedBytes) {
|
|
192
|
+
if (payloadBytes < 18)
|
|
193
|
+
throw new Error("event_v3_support_gzip_truncated");
|
|
194
|
+
const header = Buffer.alloc(10);
|
|
195
|
+
const read = await handle.read(header, 0, header.length, 0);
|
|
196
|
+
if (read.bytesRead !== 10 ||
|
|
197
|
+
header[0] !== 0x1f ||
|
|
198
|
+
header[1] !== 0x8b ||
|
|
199
|
+
header[2] !== 0x08 ||
|
|
200
|
+
header[3] !== 0x00 ||
|
|
201
|
+
!header.subarray(4, 8).equals(Buffer.alloc(4))) {
|
|
202
|
+
throw new Error("event_v3_support_gzip_header_noncanonical");
|
|
203
|
+
}
|
|
204
|
+
const inflate = createInflateRaw();
|
|
205
|
+
createReadStream(path, { fd: handle.fd, autoClose: false, start: 10 }).pipe(inflate);
|
|
206
|
+
let decompressed = 0;
|
|
207
|
+
for await (const current of inflate) {
|
|
208
|
+
decompressed += current.length;
|
|
209
|
+
if (decompressed > maximumDecompressedBytes) {
|
|
210
|
+
inflate.destroy();
|
|
211
|
+
throw new Error("event_v3_support_decompression_bound_exceeded");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (10 + inflate.bytesWritten + 8 !== payloadBytes) {
|
|
215
|
+
throw new Error("event_v3_support_gzip_trailing_data");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function openStableRegularFile(path, containmentRoot, kind) {
|
|
219
|
+
const before = await lstat(path);
|
|
220
|
+
if (!before.isFile() || before.isSymbolicLink()) {
|
|
221
|
+
throw new Error(`event_v3_support_${kind}_not_regular`);
|
|
222
|
+
}
|
|
223
|
+
const beforeReal = await realpath(path);
|
|
224
|
+
if (containmentRoot)
|
|
225
|
+
assertContained(containmentRoot, beforeReal);
|
|
226
|
+
const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
227
|
+
try {
|
|
228
|
+
const opened = await handle.stat();
|
|
229
|
+
const after = await lstat(path);
|
|
230
|
+
const afterReal = await realpath(path);
|
|
231
|
+
if (!opened.isFile() ||
|
|
232
|
+
!after.isFile() ||
|
|
233
|
+
after.isSymbolicLink() ||
|
|
234
|
+
opened.dev !== before.dev ||
|
|
235
|
+
opened.ino !== before.ino ||
|
|
236
|
+
opened.dev !== after.dev ||
|
|
237
|
+
opened.ino !== after.ino ||
|
|
238
|
+
beforeReal !== afterReal) {
|
|
239
|
+
throw new Error(`event_v3_support_${kind}_changed_during_open`);
|
|
240
|
+
}
|
|
241
|
+
if (containmentRoot)
|
|
242
|
+
assertContained(containmentRoot, afterReal);
|
|
243
|
+
return handle;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
await handle.close();
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function assertContained(root, candidate) {
|
|
251
|
+
const path = relative(root, candidate);
|
|
252
|
+
if (path === "" ||
|
|
253
|
+
(path !== ".." &&
|
|
254
|
+
!path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) &&
|
|
255
|
+
!isAbsolute(path)))
|
|
256
|
+
return;
|
|
257
|
+
throw new Error("event_v3_support_payload_outside_pack");
|
|
258
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type EventV3SupportFamily, type EventV3SupportPackManifest, type EventV3SupportVerificationMode } from "./pack-contract.js";
|
|
2
|
+
export interface EventV3SupportPackSource {
|
|
3
|
+
relative_path: string;
|
|
4
|
+
family: EventV3SupportFamily;
|
|
5
|
+
recorded_at?: string;
|
|
6
|
+
diagnostic_category?: string;
|
|
7
|
+
diagnostic_reason?: string;
|
|
8
|
+
expected_bytes?: number;
|
|
9
|
+
expected_digest?: `sha256:${string}`;
|
|
10
|
+
}
|
|
11
|
+
export interface WriteEventV3SupportPackInput {
|
|
12
|
+
authority_root: string;
|
|
13
|
+
output_directory: string;
|
|
14
|
+
root_id: string;
|
|
15
|
+
genesis_id: string;
|
|
16
|
+
verification_mode: EventV3SupportVerificationMode;
|
|
17
|
+
source_authority_digest?: `sha256:${string}`;
|
|
18
|
+
sources: EventV3SupportPackSource[];
|
|
19
|
+
minimum_harnery_version: string;
|
|
20
|
+
created_at: string;
|
|
21
|
+
fault?: (boundary: "after_source_identity_before_open", path: string) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface WrittenEventV3SupportPack {
|
|
24
|
+
manifest: EventV3SupportPackManifest;
|
|
25
|
+
manifest_path: string;
|
|
26
|
+
payload_path: string;
|
|
27
|
+
}
|
|
28
|
+
/** Write a deterministic gzip-NDJSON support pack without buffering source files or the pack. */
|
|
29
|
+
export declare function writeEventV3SupportPack(input: WriteEventV3SupportPackInput): Promise<WrittenEventV3SupportPack>;
|
|
30
|
+
//# sourceMappingURL=pack-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-writer.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/support-storage/pack-writer.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EAIpC,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,UAAU,MAAM,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,8BAA8B,CAAC;IAClD,uBAAuB,CAAC,EAAE,UAAU,MAAM,EAAE,CAAC;IAC7C,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,mCAAmC,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/E;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD,iGAAiG;AACjG,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CA2GpC"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { constants, createReadStream, createWriteStream } from "node:fs";
|
|
4
|
+
import { chmod, lstat, mkdir, open, realpath, rename, rm } from "node:fs/promises";
|
|
5
|
+
import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
7
|
+
import { createGzip } from "node:zlib";
|
|
8
|
+
import { canonicalJsonV3 } from "../canonical.js";
|
|
9
|
+
import { EVENT_V3_SUPPORT_FAMILIES, logicalEntriesDigestV3, normalizeEventV3SupportPath, validateEventV3SupportPackManifest, } from "./pack-contract.js";
|
|
10
|
+
/** Write a deterministic gzip-NDJSON support pack without buffering source files or the pack. */
|
|
11
|
+
export async function writeEventV3SupportPack(input) {
|
|
12
|
+
if (input.sources.length === 0)
|
|
13
|
+
throw new Error("event_v3_support_pack_empty");
|
|
14
|
+
const authorityRoot = resolve(input.authority_root);
|
|
15
|
+
const authorityReal = await realDirectory(authorityRoot, "event_v3_support_authority_invalid");
|
|
16
|
+
const inspected = [];
|
|
17
|
+
for (const source of [...input.sources].sort((left, right) => left.relative_path.localeCompare(right.relative_path))) {
|
|
18
|
+
const relativePath = normalizeEventV3SupportPath(source.relative_path);
|
|
19
|
+
if (inspected.at(-1)?.path === relativePath)
|
|
20
|
+
throw new Error("event_v3_support_duplicate_path");
|
|
21
|
+
const absolutePath = resolve(authorityRoot, ...relativePath.split("/"));
|
|
22
|
+
const details = await inspectRegularFile(absolutePath, authorityReal, input.fault);
|
|
23
|
+
if ((source.expected_bytes !== undefined && source.expected_bytes !== details.bytes) ||
|
|
24
|
+
(source.expected_digest !== undefined && source.expected_digest !== details.digest)) {
|
|
25
|
+
throw new Error("event_v3_support_source_planned_mismatch");
|
|
26
|
+
}
|
|
27
|
+
inspected.push({
|
|
28
|
+
...source,
|
|
29
|
+
relative_path: relativePath,
|
|
30
|
+
path: relativePath,
|
|
31
|
+
absolute_path: absolutePath,
|
|
32
|
+
...details,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const logicalEntries = inspected.map(({ path, bytes, digest }) => ({ path, bytes, digest }));
|
|
36
|
+
const logicalDigest = logicalEntriesDigestV3(logicalEntries);
|
|
37
|
+
const packId = `vsp_${createHash("sha256")
|
|
38
|
+
.update(canonicalJsonV3({
|
|
39
|
+
root_id: input.root_id,
|
|
40
|
+
genesis_id: input.genesis_id,
|
|
41
|
+
verification_mode: input.verification_mode,
|
|
42
|
+
entries: logicalEntries,
|
|
43
|
+
}))
|
|
44
|
+
.digest("hex")
|
|
45
|
+
.slice(0, 32)}`;
|
|
46
|
+
const outputDirectory = resolve(input.output_directory);
|
|
47
|
+
await mkdir(outputDirectory, { recursive: true, mode: 0o700 });
|
|
48
|
+
await chmod(outputDirectory, 0o700);
|
|
49
|
+
const payloadName = `${packId}.ndjson.gz`;
|
|
50
|
+
const payloadPath = join(outputDirectory, payloadName);
|
|
51
|
+
const manifestPath = join(outputDirectory, `${packId}.manifest.json`);
|
|
52
|
+
const payloadPartial = `${payloadPath}.partial`;
|
|
53
|
+
const manifestPartial = `${manifestPath}.partial`;
|
|
54
|
+
await rejectExisting([payloadPath, manifestPath, payloadPartial, manifestPartial]);
|
|
55
|
+
try {
|
|
56
|
+
await streamPayload(inspected, payloadPartial, authorityReal);
|
|
57
|
+
await chmod(payloadPartial, 0o600);
|
|
58
|
+
await rename(payloadPartial, payloadPath);
|
|
59
|
+
const payload = await inspectRegularFile(payloadPath);
|
|
60
|
+
const manifest = validateEventV3SupportPackManifest({
|
|
61
|
+
format: "harnery-event-v3-support-pack",
|
|
62
|
+
format_version: 1,
|
|
63
|
+
pack_id: packId,
|
|
64
|
+
authority: {
|
|
65
|
+
root_id: input.root_id,
|
|
66
|
+
genesis_id: input.genesis_id,
|
|
67
|
+
verification_mode: input.verification_mode,
|
|
68
|
+
...(input.source_authority_digest
|
|
69
|
+
? { source_authority_digest: input.source_authority_digest }
|
|
70
|
+
: {}),
|
|
71
|
+
source_files_digest: logicalDigest,
|
|
72
|
+
},
|
|
73
|
+
scope: scopeFor(inspected),
|
|
74
|
+
entries: {
|
|
75
|
+
count: inspected.length,
|
|
76
|
+
uncompressed_bytes: inspected.reduce((sum, entry) => sum + entry.bytes, 0),
|
|
77
|
+
logical_entries_digest: logicalDigest,
|
|
78
|
+
by_family: rollupFamilies(inspected),
|
|
79
|
+
by_diagnostic_category: rollupStrings(inspected, "diagnostic_category"),
|
|
80
|
+
by_diagnostic_reason: rollupStrings(inspected, "diagnostic_reason"),
|
|
81
|
+
},
|
|
82
|
+
payload: {
|
|
83
|
+
algorithm: "gzip",
|
|
84
|
+
path: payloadName,
|
|
85
|
+
bytes: payload.bytes,
|
|
86
|
+
digest: payload.digest,
|
|
87
|
+
},
|
|
88
|
+
minimum_harnery_version: input.minimum_harnery_version,
|
|
89
|
+
created_at: input.created_at,
|
|
90
|
+
});
|
|
91
|
+
const handle = await open(manifestPartial, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600);
|
|
92
|
+
try {
|
|
93
|
+
await handle.writeFile(`${canonicalJsonV3(manifest)}\n`, "utf8");
|
|
94
|
+
await handle.sync();
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
await handle.close();
|
|
98
|
+
}
|
|
99
|
+
await rename(manifestPartial, manifestPath);
|
|
100
|
+
return { manifest, manifest_path: manifestPath, payload_path: payloadPath };
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
await rm(payloadPartial, { force: true });
|
|
104
|
+
await rm(manifestPartial, { force: true });
|
|
105
|
+
await rm(payloadPath, { force: true });
|
|
106
|
+
await rm(manifestPath, { force: true });
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function streamPayload(entries, destination, authorityReal) {
|
|
111
|
+
const gzip = createGzip({ level: 9 });
|
|
112
|
+
const output = createWriteStream(destination, { flags: "wx", mode: 0o600 });
|
|
113
|
+
const completed = pipeline(gzip, output);
|
|
114
|
+
try {
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
await writeChunk(gzip, `{"path":${JSON.stringify(entry.path)},"bytes":${entry.bytes},"digest":${JSON.stringify(entry.digest)},"content_base64":"`);
|
|
117
|
+
const handle = await openStableRegularFile(entry.absolute_path, authorityReal);
|
|
118
|
+
try {
|
|
119
|
+
const hash = createHash("sha256");
|
|
120
|
+
let bytes = 0;
|
|
121
|
+
let carry = Buffer.alloc(0);
|
|
122
|
+
const stream = createReadStream(entry.absolute_path, {
|
|
123
|
+
fd: handle.fd,
|
|
124
|
+
autoClose: false,
|
|
125
|
+
start: 0,
|
|
126
|
+
highWaterMark: 64 * 1024,
|
|
127
|
+
});
|
|
128
|
+
for await (const current of stream) {
|
|
129
|
+
const chunk = current;
|
|
130
|
+
bytes += chunk.length;
|
|
131
|
+
hash.update(chunk);
|
|
132
|
+
const combined = carry.length === 0 ? chunk : Buffer.concat([carry, chunk]);
|
|
133
|
+
const complete = combined.length - (combined.length % 3);
|
|
134
|
+
if (complete > 0)
|
|
135
|
+
await writeChunk(gzip, combined.subarray(0, complete).toString("base64"));
|
|
136
|
+
carry = combined.subarray(complete);
|
|
137
|
+
}
|
|
138
|
+
if (carry.length > 0)
|
|
139
|
+
await writeChunk(gzip, carry.toString("base64"));
|
|
140
|
+
const digest = `sha256:${hash.digest("hex")}`;
|
|
141
|
+
if (bytes !== entry.bytes || digest !== entry.digest) {
|
|
142
|
+
throw new Error("event_v3_support_source_changed_during_pack");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
await handle.close();
|
|
147
|
+
}
|
|
148
|
+
await writeChunk(gzip, `"}\n`);
|
|
149
|
+
}
|
|
150
|
+
gzip.end();
|
|
151
|
+
await completed;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
gzip.destroy(error);
|
|
155
|
+
await completed.catch(() => undefined);
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function inspectRegularFile(path, containmentRoot, fault) {
|
|
160
|
+
const handle = await openStableRegularFile(path, containmentRoot, fault);
|
|
161
|
+
try {
|
|
162
|
+
const hash = createHash("sha256");
|
|
163
|
+
let bytes = 0;
|
|
164
|
+
const stream = createReadStream(path, { fd: handle.fd, autoClose: false, start: 0 });
|
|
165
|
+
for await (const current of stream) {
|
|
166
|
+
const chunk = current;
|
|
167
|
+
bytes += chunk.length;
|
|
168
|
+
hash.update(chunk);
|
|
169
|
+
}
|
|
170
|
+
return { bytes, digest: `sha256:${hash.digest("hex")}` };
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
await handle.close();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function openStableRegularFile(path, containmentRoot, fault) {
|
|
177
|
+
const before = await lstat(path);
|
|
178
|
+
if (!before.isFile() || before.isSymbolicLink()) {
|
|
179
|
+
throw new Error("event_v3_support_source_not_regular");
|
|
180
|
+
}
|
|
181
|
+
const beforeReal = await realpath(path);
|
|
182
|
+
if (containmentRoot)
|
|
183
|
+
assertContained(containmentRoot, beforeReal);
|
|
184
|
+
fault?.("after_source_identity_before_open", path);
|
|
185
|
+
const handle = await open(path, constants.O_RDONLY | noFollow());
|
|
186
|
+
try {
|
|
187
|
+
const opened = await handle.stat();
|
|
188
|
+
const after = await lstat(path);
|
|
189
|
+
const afterReal = await realpath(path);
|
|
190
|
+
if (!opened.isFile() ||
|
|
191
|
+
!after.isFile() ||
|
|
192
|
+
after.isSymbolicLink() ||
|
|
193
|
+
!sameIdentity(before, opened) ||
|
|
194
|
+
!sameIdentity(opened, after) ||
|
|
195
|
+
beforeReal !== afterReal) {
|
|
196
|
+
throw new Error("event_v3_support_source_changed_during_open");
|
|
197
|
+
}
|
|
198
|
+
if (containmentRoot)
|
|
199
|
+
assertContained(containmentRoot, afterReal);
|
|
200
|
+
return handle;
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
await handle.close();
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function sameIdentity(left, right) {
|
|
208
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
209
|
+
}
|
|
210
|
+
async function realDirectory(path, code) {
|
|
211
|
+
const stat = await lstat(path);
|
|
212
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
213
|
+
throw new Error(code);
|
|
214
|
+
return realpath(path);
|
|
215
|
+
}
|
|
216
|
+
function assertContained(root, candidate) {
|
|
217
|
+
const path = relative(root, candidate);
|
|
218
|
+
if (path === "" ||
|
|
219
|
+
(path !== ".." &&
|
|
220
|
+
!path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) &&
|
|
221
|
+
!isAbsolute(path)))
|
|
222
|
+
return;
|
|
223
|
+
throw new Error("event_v3_support_source_outside_authority");
|
|
224
|
+
}
|
|
225
|
+
function noFollow() {
|
|
226
|
+
return constants.O_NOFOLLOW ?? 0;
|
|
227
|
+
}
|
|
228
|
+
async function rejectExisting(paths) {
|
|
229
|
+
for (const path of paths) {
|
|
230
|
+
try {
|
|
231
|
+
await lstat(path);
|
|
232
|
+
throw new Error(`event_v3_support_output_exists:${basename(path)}`);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (error.code !== "ENOENT")
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async function writeChunk(stream, value) {
|
|
241
|
+
if (!stream.write(value, "utf8"))
|
|
242
|
+
await once(stream, "drain");
|
|
243
|
+
}
|
|
244
|
+
function scopeFor(entries) {
|
|
245
|
+
const timestamps = entries
|
|
246
|
+
.flatMap((entry) => (entry.recorded_at ? [entry.recorded_at] : []))
|
|
247
|
+
.sort();
|
|
248
|
+
return {
|
|
249
|
+
families: [...new Set(entries.map(({ family }) => family))].sort(),
|
|
250
|
+
minimum_recorded_at: timestamps[0] ?? null,
|
|
251
|
+
maximum_recorded_at: timestamps.at(-1) ?? null,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function rollupFamilies(entries) {
|
|
255
|
+
const result = Object.fromEntries(EVENT_V3_SUPPORT_FAMILIES.map((family) => [family, 0]));
|
|
256
|
+
for (const entry of entries)
|
|
257
|
+
result[entry.family] += 1;
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
function rollupStrings(entries, key) {
|
|
261
|
+
const result = {};
|
|
262
|
+
for (const entry of entries) {
|
|
263
|
+
const value = entry[key];
|
|
264
|
+
if (value)
|
|
265
|
+
result[value] = (result[value] ?? 0) + 1;
|
|
266
|
+
}
|
|
267
|
+
return Object.fromEntries(Object.entries(result).sort(([left], [right]) => left.localeCompare(right)));
|
|
268
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface VerifyEventV3RecoveryBoundArchiveInput {
|
|
2
|
+
authority_root: string;
|
|
3
|
+
expected_authority_digest: `sha256:${string}`;
|
|
4
|
+
expected_archive_directory?: string;
|
|
5
|
+
archive_directory?: string;
|
|
6
|
+
recovery_receipt_id: string;
|
|
7
|
+
}
|
|
8
|
+
/** Fail closed unless a recovery receipt still binds one complete logical authority. */
|
|
9
|
+
export declare function verifyEventV3RecoveryBoundArchive(input: VerifyEventV3RecoveryBoundArchiveInput): Promise<{
|
|
10
|
+
recovery_receipt_id: string;
|
|
11
|
+
authority_digest: `sha256:${string}`;
|
|
12
|
+
logical_files: number;
|
|
13
|
+
packed_entries: number;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/support-storage/recovery.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sCAAsC;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,yBAAyB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,wFAAwF;AACxF,wBAAsB,iCAAiC,CACrD,KAAK,EAAE,sCAAsC,GAC5C,OAAO,CAAC;IACT,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAqBD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { digestEventV3LogicalAuthority, iterateEventV3LogicalAuthority, } from "./logical-authority.js";
|
|
2
|
+
/** Fail closed unless a recovery receipt still binds one complete logical authority. */
|
|
3
|
+
export async function verifyEventV3RecoveryBoundArchive(input) {
|
|
4
|
+
if (input.expected_archive_directory !== undefined &&
|
|
5
|
+
input.archive_directory !== input.expected_archive_directory) {
|
|
6
|
+
throw new Error("event_v3_support_recovery_archive_binding_mismatch");
|
|
7
|
+
}
|
|
8
|
+
const view = await iterateEventV3LogicalAuthority(input.authority_root);
|
|
9
|
+
if (view.quarantined_packs.length > 0) {
|
|
10
|
+
throw new Error("event_v3_support_recovery_pack_quarantined");
|
|
11
|
+
}
|
|
12
|
+
const digest = await digestEventV3LogicalAuthority(input.authority_root);
|
|
13
|
+
if (digest !== input.expected_authority_digest) {
|
|
14
|
+
throw new Error("event_v3_support_recovery_authority_digest_mismatch");
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
recovery_receipt_id: input.recovery_receipt_id,
|
|
18
|
+
authority_digest: digest,
|
|
19
|
+
logical_files: view.entries.length,
|
|
20
|
+
packed_entries: view.packed_entries,
|
|
21
|
+
};
|
|
22
|
+
}
|