@timurproko/a1 0.1.8-dev.3b54f21 → 0.1.8-dev.407
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -65
- package/bin/cli.js +28 -10
- package/bin/guardian.js +12 -6
- package/bin/module-identity.js +69 -35
- package/bin/pi-tui.d.ts +6 -0
- package/bin/pi-tui.js +28 -0
- package/bin/release-cleanup.js +8 -0
- package/bin/supervisor.js +2 -2
- package/bin/sync-pi-tui-proxy.js +97 -0
- package/bin/ui.js +62 -21
- package/bin/update-recovery.js +274 -0
- package/bin/warmup.js +27 -0
- package/dist/cli/capabilities.d.ts +6 -0
- package/dist/{src/cli → cli}/capabilities.js +1 -1
- package/dist/{src/cli → cli}/dispatch.d.ts +15 -1
- package/dist/cli/dispatch.js +261 -0
- package/dist/cli/package-messages.d.ts +26 -0
- package/dist/cli/package-messages.js +71 -0
- package/dist/{src/cli → cli}/packages.d.ts +11 -2
- package/dist/{src/cli → cli}/packages.js +24 -27
- package/dist/{src/cli → cli}/version-stats.d.ts +6 -0
- package/dist/cli/version-stats.js +112 -0
- package/dist/composition/agent-engine-bridge.d.ts +3 -0
- package/dist/composition/agent-engine-bridge.js +108 -0
- package/dist/composition/index.d.ts +3 -0
- package/dist/composition/index.js +3 -0
- package/dist/composition/owned-ui.d.ts +35 -0
- package/dist/composition/owned-ui.js +118 -0
- package/dist/composition/process.d.ts +16 -0
- package/dist/composition/process.js +45 -0
- package/dist/composition/settings-route-host.d.ts +8 -0
- package/dist/composition/settings-route-host.js +75 -0
- package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/capability-ports.d.ts +2 -2
- package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain-validation.js +22 -4
- package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain.d.ts +17 -0
- package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/package-ports.d.ts +6 -0
- package/dist/contracts/owned-ui/image-attachments.d.ts +36 -0
- package/dist/contracts/owned-ui/image-attachments.js +67 -0
- package/dist/contracts/owned-ui/index.d.ts +8 -0
- package/dist/contracts/owned-ui/index.js +8 -0
- package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/model.d.ts +123 -0
- package/dist/contracts/owned-ui/prompt-history.d.ts +55 -0
- package/dist/contracts/owned-ui/prompt-history.js +23 -0
- package/dist/contracts/owned-ui/prompt-suggestions.d.ts +3 -0
- package/dist/contracts/owned-ui/prompt-suggestions.js +44 -0
- package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +22 -0
- package/dist/contracts/owned-ui/suggestion-diagnostics.js +9 -0
- package/dist/contracts/owned-ui/transcript-lifecycle.d.ts +5 -0
- package/dist/contracts/owned-ui/transcript-lifecycle.js +33 -0
- package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/validation.d.ts +5 -1
- package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/validation.js +129 -4
- package/dist/{src/foundation/presentation-contracts → contracts/presentation}/index.d.ts +8 -0
- package/dist/{src/features → features}/launch/development-launch.js +11 -3
- package/dist/{src/features → features}/launch/index.d.ts +0 -1
- package/dist/{src/features → features}/launch/index.js +0 -1
- package/dist/features/launch/intent.d.ts +10 -0
- package/dist/features/launch/intent.js +8 -0
- package/dist/{src/features → features}/launch/prepare-launch.d.ts +0 -2
- package/dist/{src/features → features}/launch/prepare-launch.js +2 -9
- package/dist/{src/features → features}/launch/profile-paths.d.ts +3 -2
- package/dist/{src/features → features}/launch/profile-paths.js +13 -8
- package/dist/{src/features → features}/launch/runtime-selection.d.ts +2 -5
- package/dist/{src/features → features}/owned-ui/customization.d.ts +3 -1
- package/dist/{src/features → features}/owned-ui/customization.js +3 -1
- package/dist/{src/features → features}/owned-ui/diagnostics.d.ts +2 -1
- package/dist/{src/features → features}/owned-ui/diagnostics.js +1 -0
- package/dist/{src/features → features}/owned-ui/index.d.ts +2 -0
- package/dist/{src/features → features}/owned-ui/index.js +2 -0
- package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
- package/dist/features/owned-ui/project-trust-prompt.js +149 -0
- package/dist/{src/features → features}/owned-ui/run.d.ts +2 -2
- package/dist/features/owned-ui/run.js +32 -0
- package/dist/features/owned-ui/session-fork-prompt.d.ts +8 -0
- package/dist/features/owned-ui/session-fork-prompt.js +34 -0
- package/dist/{src/features → features}/owned-ui/settings-app.d.ts +3 -3
- package/dist/{src/features → features}/owned-ui/settings-app.js +105 -56
- package/dist/features/prompt-history/image-sidecar.d.ts +32 -0
- package/dist/features/prompt-history/image-sidecar.js +130 -0
- package/dist/features/prompt-history/index.d.ts +4 -0
- package/dist/features/prompt-history/index.js +3 -0
- package/dist/features/prompt-history/paths.d.ts +5 -0
- package/dist/features/prompt-history/paths.js +17 -0
- package/dist/features/prompt-history/service.d.ts +54 -0
- package/dist/features/prompt-history/service.js +425 -0
- package/dist/features/prompt-history/store.d.ts +16 -0
- package/dist/features/prompt-history/store.js +223 -0
- package/dist/features/prompt-history/worker.d.ts +9 -0
- package/dist/features/prompt-history/worker.js +45 -0
- package/dist/features/prompt-suggestions/diagnostics.d.ts +18 -0
- package/dist/features/prompt-suggestions/diagnostics.js +82 -0
- package/dist/features/prompt-suggestions/index.d.ts +1 -0
- package/dist/features/prompt-suggestions/index.js +1 -0
- package/dist/{src/features → features}/workspace/capabilities.d.ts +1 -1
- package/dist/{src/features → features}/workspace/reducer.d.ts +2 -1
- package/dist/{src/features → features}/workspace/reducer.js +2 -1
- package/dist/{src/features → features}/workspace/router.d.ts +2 -1
- package/dist/{src/features → features}/workspace/router.js +1 -0
- package/dist/{src/features → features}/workspace/store.d.ts +2 -1
- package/dist/{src/features → features}/workspace/store.js +1 -0
- package/dist/foundation/launch-context/index.d.ts +59 -0
- package/dist/foundation/launch-context/index.js +136 -0
- package/dist/{src/foundation → foundation}/launch-guardian/main.d.ts +2 -0
- package/dist/{src/foundation → foundation}/launch-guardian/main.js +23 -8
- package/dist/{src/foundation → foundation}/lifecycle/index.d.ts +2 -0
- package/dist/{src/foundation → foundation}/lifecycle/index.js +2 -0
- package/dist/{src/foundation → foundation}/lifecycle/model.d.ts +1 -1
- package/dist/{src/foundation → foundation}/lifecycle/model.js +1 -1
- package/dist/foundation/lifecycle/paths.d.ts +30 -0
- package/dist/{src/foundation → foundation}/lifecycle/paths.js +29 -1
- package/dist/foundation/lifecycle/session-selection.d.ts +9 -0
- package/dist/foundation/lifecycle/session-selection.js +39 -0
- package/dist/foundation/lifecycle/supervisor-startup.d.ts +30 -0
- package/dist/foundation/lifecycle/supervisor-startup.js +106 -0
- package/dist/{src/foundation → foundation}/native-host-protocol/codec.d.ts +2 -0
- package/dist/{src/foundation → foundation}/native-host-protocol/codec.js +2 -0
- package/dist/{src/foundation → foundation}/native-host-protocol/messages.d.ts +1 -1
- package/dist/{src/foundation → foundation}/native-host-protocol/messages.js +1 -1
- package/dist/foundation/process-containment/darwin-process-inspector.d.ts +5 -0
- package/dist/foundation/process-containment/darwin-process-inspector.js +7 -0
- package/dist/{src/foundation → foundation}/process-containment/index.d.ts +1 -0
- package/dist/{src/foundation → foundation}/process-containment/index.js +1 -0
- package/dist/{src/foundation → foundation}/process-containment/linux-process-inspector.d.ts +1 -0
- package/dist/{src/foundation → foundation}/process-containment/linux-process-inspector.js +1 -0
- package/dist/{src/foundation → foundation}/process-containment/native-guardian-containment.d.ts +1 -0
- package/dist/{src/foundation → foundation}/process-containment/native-guardian-containment.js +1 -0
- package/dist/{src/foundation → foundation}/process-containment/windows-process-inspector.d.ts +3 -1
- package/dist/{src/foundation → foundation}/process-containment/windows-process-inspector.js +5 -2
- package/dist/{src/foundation → foundation}/protocol/client.d.ts +1 -0
- package/dist/{src/foundation → foundation}/protocol/client.js +1 -0
- package/dist/{src/foundation → foundation}/protocol/messages.d.ts +1 -0
- package/dist/{src/foundation → foundation}/protocol/messages.js +1 -0
- package/dist/foundation/release/bootstrap.d.ts +55 -0
- package/dist/{src/foundation → foundation}/release/bootstrap.js +219 -46
- package/dist/foundation/release/cohort-state.d.ts +157 -0
- package/dist/foundation/release/cohort-state.js +472 -0
- package/dist/foundation/release/dependency-certification-retention.d.ts +7 -0
- package/dist/foundation/release/dependency-certification-retention.js +88 -0
- package/dist/foundation/release/dependency-certification.d.ts +24 -0
- package/dist/foundation/release/dependency-certification.js +266 -0
- package/dist/foundation/release/dependency-layer.d.ts +81 -0
- package/dist/foundation/release/dependency-layer.js +466 -0
- package/dist/foundation/release/endpoints.d.ts +20 -0
- package/dist/foundation/release/endpoints.js +50 -0
- package/dist/foundation/release/immutable-platform.d.ts +6 -0
- package/dist/foundation/release/immutable-platform.js +13 -0
- package/dist/{src/foundation → foundation}/release/index.d.ts +6 -0
- package/dist/{src/foundation → foundation}/release/index.js +6 -0
- package/dist/foundation/release/release-gc.d.ts +71 -0
- package/dist/foundation/release/release-gc.js +764 -0
- package/dist/{src/foundation → foundation}/release/release-store.d.ts +9 -3
- package/dist/{src/foundation → foundation}/release/release-store.js +74 -14
- package/dist/{src/foundation → foundation}/release/release.d.ts +6 -1
- package/dist/{src/foundation → foundation}/release/release.js +15 -4
- package/dist/foundation/release/restart-certification.d.ts +68 -0
- package/dist/foundation/release/restart-certification.js +227 -0
- package/dist/foundation/release/update-launch.d.ts +6 -0
- package/dist/foundation/release/update-launch.js +17 -0
- package/dist/foundation/release/update-recovery.d.ts +76 -0
- package/dist/foundation/release/update-recovery.js +356 -0
- package/dist/{src/foundation → foundation}/release/update-transaction.d.ts +11 -0
- package/dist/{src/foundation → foundation}/release/update-transaction.js +13 -1
- package/dist/{src/foundation → foundation}/release/update.d.ts +40 -4
- package/dist/{src/foundation → foundation}/release/update.js +196 -78
- package/dist/foundation/release/warmup.d.ts +3 -0
- package/dist/foundation/release/warmup.js +47 -0
- package/dist/foundation/startup/index.d.ts +1 -0
- package/dist/foundation/startup/index.js +1 -0
- package/dist/foundation/startup/startup-runtime.d.ts +36 -0
- package/dist/foundation/startup/startup-runtime.js +142 -0
- package/dist/{src/foundation → foundation}/storage/control-store.d.ts +2 -1
- package/dist/{src/foundation → foundation}/storage/control-store.js +39 -4
- package/dist/{src/foundation → foundation}/structured-agent-runtime/backpressure.d.ts +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/backpressure.js +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/commands.d.ts +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/commands.js +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/handshake.d.ts +1 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/handshake.js +1 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/reconnection.d.ts +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/reconnection.js +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/state.d.ts +2 -1
- package/dist/{src/foundation → foundation}/structured-agent-runtime/state.js +2 -1
- package/dist/foundation/supervision/index.d.ts +3 -0
- package/dist/foundation/supervision/index.js +3 -0
- package/dist/foundation/supervision/main.d.ts +1 -0
- package/dist/foundation/supervision/main.js +84 -0
- package/dist/foundation/supervision/paths.d.ts +1 -0
- package/dist/foundation/supervision/paths.js +1 -0
- package/dist/foundation/supervision/server.d.ts +51 -0
- package/dist/{src/foundation → foundation}/supervision/server.js +142 -20
- package/dist/foundation/terminal-cleanup/fatal-exit.d.ts +12 -0
- package/dist/foundation/terminal-cleanup/fatal-exit.js +85 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +2 -0
- package/dist/foundation/terminal-cleanup/index.js +2 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +4 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +40 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/components.d.ts +1 -1
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/conformance.d.ts +1 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/conformance.js +3 -2
- package/dist/integrations/pi/components/editor-interaction.d.ts +38 -0
- package/dist/integrations/pi/components/history-editor-loader.d.ts +5 -0
- package/dist/integrations/pi/components/history-editor-loader.js +5 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/index.d.ts +2 -1
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/index.js +2 -1
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +74 -0
- package/dist/integrations/pi/components/owned-editor-ux.js +1093 -0
- package/dist/integrations/pi/components/path-word-ranges.d.ts +2 -0
- package/dist/integrations/pi/components/path-word-ranges.js +37 -0
- package/dist/integrations/pi/components/prompt-input-port.d.ts +18 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-components.d.ts +1 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-components.js +1 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +297 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-extension-ui.d.ts +1 -1
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-footer-status.d.ts +4 -4
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-footer-status.js +58 -23
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +43 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +114 -0
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +29 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-presenters-transcript.js +174 -170
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-selectors-dialogs.d.ts +8 -4
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-selectors-dialogs.js +10 -6
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +213 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-shared-facade.js +5 -2
- package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +15 -0
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +43 -0
- package/dist/integrations/pi/components/tool-image-presentation.d.ts +21 -0
- package/dist/integrations/pi/components/tool-image-presentation.js +86 -0
- package/dist/integrations/pi/components/tool-result-adapter.d.ts +6 -0
- package/dist/integrations/pi/components/tool-result-adapter.js +27 -0
- package/dist/integrations/pi/components/transcript-image-resolver.d.ts +7 -0
- package/dist/integrations/pi/components/transcript-image-resolver.js +19 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/adjacent/core/keybindings.d.ts +11 -2
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/adjacent/core/keybindings.js +41 -3
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +12 -0
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +42 -0
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +40 -0
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +166 -0
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/scoped-models-selector.js +3 -1
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-footer.d.ts +3 -2
- package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-footer.js +12 -7
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +61 -0
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +344 -0
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +280 -0
- package/dist/integrations/pi/components/upstream/history/editor-core.js +2062 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +32 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +48 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.d.ts +1 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.js +40 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.d.ts +14 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +28 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +22 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +36 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.d.ts +24 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +100 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/adapter.d.ts +74 -6
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/adapter.js +1340 -228
- package/dist/integrations/pi/engine/changelog.d.ts +2 -0
- package/dist/integrations/pi/engine/changelog.js +63 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/conformance.d.ts +4 -2
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/conformance.js +15 -5
- package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
- package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/index.d.ts +4 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/index.js +4 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/model-auth-integration.d.ts +2 -1
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/model-auth-integration.js +1 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/package-integration.d.ts +1 -1
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/package-integration.js +32 -26
- package/dist/integrations/pi/engine/pending-delivery.d.ts +30 -0
- package/dist/integrations/pi/engine/pending-delivery.js +158 -0
- package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
- package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/resource-extension-integration.d.ts +2 -1
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/resource-extension-integration.js +1 -0
- package/dist/integrations/pi/engine/resources/changelog.json +12 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/runtime-integration.d.ts +19 -1
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/runtime-integration.js +56 -5
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/session-integration.d.ts +4 -2
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/session-integration.js +19 -4
- package/dist/integrations/pi/engine/session-selection.d.ts +28 -0
- package/dist/integrations/pi/engine/session-selection.js +90 -0
- package/dist/integrations/pi/engine/settings-effects.d.ts +66 -0
- package/dist/integrations/pi/engine/settings-effects.js +249 -0
- package/dist/integrations/pi/engine/settings-integration.d.ts +43 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/settings-integration.js +102 -108
- package/dist/integrations/pi/engine/tool-rendering.d.ts +13 -0
- package/dist/integrations/pi/engine/tool-rendering.js +145 -0
- package/dist/integrations/pi/engine/transcript-image-assets.d.ts +11 -0
- package/dist/integrations/pi/engine/transcript-image-assets.js +86 -0
- package/dist/integrations/pi/engine/windows-filesystem-hygiene.d.ts +21 -0
- package/dist/integrations/pi/engine/windows-filesystem-hygiene.js +55 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflow-controllers.d.ts +3 -2
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflow-controllers.js +1 -0
- package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflows.d.ts +19 -2
- package/dist/integrations/pi/session-ui/clipboard-diagnostics.d.ts +16 -0
- package/dist/integrations/pi/session-ui/clipboard-diagnostics.js +65 -0
- package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
- package/dist/integrations/pi/session-ui/clipboard-image.js +38 -0
- package/dist/integrations/pi/session-ui/editor-hyperlink-budget.d.ts +9 -0
- package/dist/integrations/pi/session-ui/editor-hyperlink-budget.js +23 -0
- package/dist/integrations/pi/session-ui/image-preparation-client.d.ts +20 -0
- package/dist/integrations/pi/session-ui/image-preparation-client.js +145 -0
- package/dist/integrations/pi/session-ui/image-preparation.d.ts +18 -0
- package/dist/integrations/pi/session-ui/image-preparation.js +126 -0
- package/dist/integrations/pi/session-ui/image-source.d.ts +13 -0
- package/dist/integrations/pi/session-ui/image-source.js +171 -0
- package/dist/integrations/pi/session-ui/image-worker.d.ts +17 -0
- package/dist/integrations/pi/session-ui/image-worker.js +23 -0
- package/dist/integrations/pi/session-ui/index.d.ts +5 -0
- package/dist/integrations/pi/session-ui/index.js +5 -0
- package/dist/integrations/pi/session-ui/paste-executor.d.ts +10 -0
- package/dist/integrations/pi/session-ui/paste-executor.js +232 -0
- package/dist/integrations/pi/session-ui/paste-helper.d.ts +1 -0
- package/dist/integrations/pi/session-ui/paste-helper.js +173 -0
- package/dist/integrations/pi/session-ui/paste-preparation-client.d.ts +16 -0
- package/dist/integrations/pi/session-ui/paste-preparation-client.js +159 -0
- package/dist/integrations/pi/session-ui/paste-protocol.d.ts +78 -0
- package/dist/integrations/pi/session-ui/paste-protocol.js +18 -0
- package/dist/integrations/pi/session-ui/paste-text-preparation.d.ts +20 -0
- package/dist/integrations/pi/session-ui/paste-text-preparation.js +134 -0
- package/dist/integrations/pi/session-ui/paste-text-worker.d.ts +1 -0
- package/dist/integrations/pi/session-ui/paste-text-worker.js +12 -0
- package/dist/integrations/pi/session-ui/path-chip-presentation.d.ts +7 -0
- package/dist/integrations/pi/session-ui/path-chip-presentation.js +24 -0
- package/dist/integrations/pi/session-ui/prompt-chips.d.ts +72 -0
- package/dist/integrations/pi/session-ui/prompt-chips.js +503 -0
- package/dist/integrations/pi/session-ui/prompt-history-controller.d.ts +36 -0
- package/dist/integrations/pi/session-ui/prompt-history-controller.js +170 -0
- package/dist/integrations/pi/session-ui/prompt-suggestion-controller.d.ts +35 -0
- package/dist/integrations/pi/session-ui/prompt-suggestion-controller.js +207 -0
- package/dist/integrations/pi/session-ui/response-copy-coordinator.d.ts +27 -0
- package/dist/integrations/pi/session-ui/response-copy-coordinator.js +189 -0
- package/dist/integrations/pi/session-ui/response-copy-helper.d.ts +1 -0
- package/dist/integrations/pi/session-ui/response-copy-helper.js +122 -0
- package/dist/integrations/pi/session-ui/response-copy-protocol.d.ts +56 -0
- package/dist/integrations/pi/session-ui/response-copy-protocol.js +5 -0
- package/dist/integrations/pi/session-ui/response-copy-transport.d.ts +31 -0
- package/dist/integrations/pi/session-ui/response-copy-transport.js +187 -0
- package/dist/integrations/pi/session-ui/route-host.d.ts +5 -0
- package/dist/integrations/pi/session-ui/route-host.js +1 -0
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +221 -0
- package/dist/integrations/pi/session-ui/session-shell-root.js +1305 -0
- package/dist/integrations/pi/session-ui/session-shell.d.ts +55 -0
- package/dist/integrations/pi/session-ui/session-shell.js +1792 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +56 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +569 -0
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.d.ts +29 -0
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.js +79 -0
- package/dist/integrations/pi/session-ui/system-clipboard.d.ts +20 -0
- package/dist/integrations/pi/session-ui/system-clipboard.js +156 -0
- package/dist/integrations/pi/session-ui/text-paste.d.ts +5 -0
- package/dist/integrations/pi/session-ui/text-paste.js +16 -0
- package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/adapter.d.ts +10 -1
- package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/adapter.js +255 -11
- package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/contracts.d.ts +32 -6
- package/dist/integrations/pi/tui-runtime/contracts.js +1 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +81 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +424 -0
- package/dist/integrations/pi/tui-runtime/index.d.ts +7 -0
- package/dist/integrations/pi/tui-runtime/index.js +7 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
- package/dist/integrations/pi/tui-runtime/mouse-report-input.d.ts +13 -0
- package/dist/integrations/pi/tui-runtime/mouse-report-input.js +59 -0
- package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +32 -0
- package/dist/integrations/pi/tui-runtime/overlay-geometry.js +159 -0
- package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/presentation-adapter.d.ts +1 -1
- package/dist/native/darwin-arm64/manifest.json +4 -4
- package/dist/native/darwin-arm64/process-guardian +0 -0
- package/dist/native/linux-x64/manifest.json +3 -3
- package/dist/native/linux-x64/process-guardian +0 -0
- package/dist/native/win32-x64/manifest.json +3 -3
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/{src/product-identity.d.ts → product-identity.d.ts} +4 -4
- package/dist/{src/product-identity.js → product-identity.js} +7 -38
- package/dist/{src/product-identity.json → product-identity.json} +13 -27
- package/dist/runtime-payload-inventory.json +122333 -0
- package/dist/{src/foundation/ui-apps → ui/apps}/contracts.d.ts +23 -1
- package/dist/{src/foundation/ui-apps → ui/apps}/host.d.ts +1 -1
- package/dist/{src/foundation/ui-apps → ui/apps}/host.js +14 -10
- package/dist/{src/foundation/ui-apps → ui/apps}/registry.d.ts +1 -0
- package/dist/{src/foundation/ui-apps → ui/apps}/registry.js +1 -0
- package/dist/{src/foundation/ui-components → ui/components}/dialog-panel.js +5 -3
- package/dist/{src/foundation/ui-components → ui/components}/frame.d.ts +1 -0
- package/dist/{src/foundation/ui-components → ui/components}/frame.js +1 -0
- package/dist/{src/foundation/ui-components → ui/components}/index.d.ts +7 -0
- package/dist/{src/foundation/ui-components → ui/components}/index.js +7 -0
- package/dist/{src/foundation/ui-components → ui/components}/line-input.d.ts +2 -8
- package/dist/{src/foundation/ui-components → ui/components}/line-input.js +7 -28
- package/dist/{src/foundation/ui-components → ui/components}/list-view.d.ts +0 -6
- package/dist/{src/foundation/ui-components → ui/components}/list-view.js +14 -7
- package/dist/{src/foundation/ui-components → ui/components}/mouse.d.ts +10 -0
- package/dist/{src/foundation/ui-components → ui/components}/mouse.js +24 -0
- package/dist/ui/components/progress-status.d.ts +2 -0
- package/dist/ui/components/progress-status.js +4 -0
- package/dist/ui/components/prompt-input.d.ts +32 -0
- package/dist/ui/components/prompt-input.js +54 -0
- package/dist/ui/components/prompt-row.d.ts +14 -0
- package/dist/ui/components/prompt-row.js +20 -0
- package/dist/{src/foundation/ui-components → ui/components}/scrollbar.d.ts +26 -0
- package/dist/{src/foundation/ui-components → ui/components}/scrollbar.js +35 -0
- package/dist/ui/components/selection-copy.d.ts +24 -0
- package/dist/ui/components/selection-copy.js +39 -0
- package/dist/{src/foundation/ui-components → ui/components}/shortcuts.d.ts +1 -0
- package/dist/{src/foundation/ui-components → ui/components}/shortcuts.js +1 -0
- package/dist/ui/components/spans.d.ts +28 -0
- package/dist/ui/components/spans.js +266 -0
- package/dist/ui/components/submitted-prompt.d.ts +23 -0
- package/dist/ui/components/submitted-prompt.js +50 -0
- package/dist/{src/foundation/ui-components → ui/components}/surface.d.ts +0 -5
- package/dist/{src/foundation/ui-components → ui/components}/surface.js +1 -5
- package/dist/ui/components/text-selection.d.ts +62 -0
- package/dist/ui/components/text-selection.js +210 -0
- package/dist/{src/foundation/ui-components → ui/components}/text.d.ts +14 -0
- package/dist/{src/foundation/ui-components → ui/components}/text.js +67 -5
- package/dist/ui/components/transcript-viewport.d.ts +173 -0
- package/dist/ui/components/transcript-viewport.js +753 -0
- package/dist/ui/components/visible-hyperlinks.d.ts +26 -0
- package/dist/ui/components/visible-hyperlinks.js +97 -0
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/declarations.d.ts +8 -1
- package/dist/ui/settings/declarations.js +94 -0
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/migrations.d.ts +1 -1
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/migrations.js +28 -2
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/sections.d.ts +6 -19
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/sections.js +41 -22
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/session.d.ts +9 -17
- package/dist/ui/settings/session.js +164 -0
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/store.d.ts +1 -0
- package/dist/{src/foundation/owned-ui-settings → ui/settings}/store.js +2 -1
- package/docs/architecture/boundaries.md +14 -10
- package/docs/architecture/code-documentation.md +77 -0
- package/docs/architecture/history-editor-provenance.md +100 -0
- package/docs/architecture/internal-naming.md +91 -0
- package/docs/architecture/process-guardian-provenance.md +3 -1
- package/docs/architecture/project-structure.md +69 -30
- package/docs/architecture/prompt-suggestions.md +68 -0
- package/docs/architecture/resource-and-data-policy.md +28 -2
- package/docs/architecture/response-copy-delivery.md +83 -0
- package/docs/architecture/tool-image-presentation.md +62 -0
- package/docs/architecture/toolchain.md +24 -10
- package/docs/architecture/ui-reference-provenance.md +59 -5
- package/docs/ci-release-runbook.md +236 -79
- package/docs/features/launch-profiles.md +24 -17
- package/docs/features/modal-content-interaction.md +37 -0
- package/docs/features/prompt-history.md +149 -0
- package/docs/local-worktree-cleanup.md +128 -0
- package/docs/manual-code-streaming-cleanup.md +88 -0
- package/docs/manual-ghost-link-baseline.md +89 -0
- package/docs/manual-launch-instance-acceptance.md +12 -35
- package/docs/manual-owned-ui-checkpoint.md +78 -0
- package/docs/manual-pi-boundary-candidate.md +4 -5
- package/docs/manual-terminal-colour-check.md +4 -3
- package/docs/openspec-archive-automation.md +128 -0
- package/docs/repository-governance-live-acceptance.md +77 -0
- package/package.json +45 -28
- package/dist/src/cli/capabilities.d.ts +0 -15
- package/dist/src/cli/dispatch.js +0 -142
- package/dist/src/cli/version-stats.js +0 -72
- package/dist/src/composition/index.d.ts +0 -48
- package/dist/src/composition/index.js +0 -258
- package/dist/src/features/launch/intent.d.ts +0 -7
- package/dist/src/features/launch/intent.js +0 -4
- package/dist/src/features/launch/profiles.d.ts +0 -12
- package/dist/src/features/launch/profiles.js +0 -26
- package/dist/src/features/owned-ui/run.js +0 -15
- package/dist/src/foundation/lifecycle/paths.d.ts +0 -10
- package/dist/src/foundation/owned-ui-contracts/index.d.ts +0 -3
- package/dist/src/foundation/owned-ui-contracts/index.js +0 -3
- package/dist/src/foundation/owned-ui-settings/declarations.js +0 -39
- package/dist/src/foundation/owned-ui-settings/session.js +0 -145
- package/dist/src/foundation/pi-component-adapter/shell-editor-autocomplete.js +0 -162
- package/dist/src/foundation/pi-component-adapter/shell-presenters-transcript.d.ts +0 -57
- package/dist/src/foundation/pi-component-adapter/shell-shared-facade.d.ts +0 -116
- package/dist/src/foundation/pi-component-adapter/upstream/components/earendil-announcement.js +0 -19
- package/dist/src/foundation/pi-component-adapter/upstream/components/owned-editor.d.ts +0 -18
- package/dist/src/foundation/pi-component-adapter/upstream/components/owned-editor.js +0 -55
- package/dist/src/foundation/pi-engine-adapter/settings-integration.d.ts +0 -55
- package/dist/src/foundation/pi-owned-ui-integration/index.d.ts +0 -2
- package/dist/src/foundation/pi-owned-ui-integration/index.js +0 -2
- package/dist/src/foundation/pi-owned-ui-integration/route-host.d.ts +0 -29
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.d.ts +0 -106
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.js +0 -1518
- package/dist/src/foundation/pi-tui-runtime-adapter/index.d.ts +0 -4
- package/dist/src/foundation/pi-tui-runtime-adapter/index.js +0 -4
- package/dist/src/foundation/release/bootstrap.d.ts +0 -29
- package/dist/src/foundation/release/cohort-state.d.ts +0 -70
- package/dist/src/foundation/release/cohort-state.js +0 -202
- package/dist/src/foundation/release/release-gc.d.ts +0 -5
- package/dist/src/foundation/release/release-gc.js +0 -16
- package/dist/src/foundation/supervision/index.d.ts +0 -3
- package/dist/src/foundation/supervision/index.js +0 -3
- package/dist/src/foundation/supervision/main.d.ts +0 -1
- package/dist/src/foundation/supervision/main.js +0 -41
- package/dist/src/foundation/supervision/paths.d.ts +0 -1
- package/dist/src/foundation/supervision/paths.js +0 -1
- package/dist/src/foundation/supervision/server.d.ts +0 -22
- package/dist/src/foundation/ui-components/spans.d.ts +0 -7
- package/dist/src/foundation/ui-components/spans.js +0 -59
- package/docs/manual-transparent-checkpoint.md +0 -53
- /package/dist/{src/cli → cli}/index.d.ts +0 -0
- /package/dist/{src/cli → cli}/index.js +0 -0
- /package/dist/{src/cli → cli}/version.d.ts +0 -0
- /package/dist/{src/cli → cli}/version.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/capability-ports.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain-validation.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/index.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/index.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/package-ports.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/ports.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/ports.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.js +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.d.ts +0 -0
- /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.js +0 -0
- /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/extension-ui.d.ts +0 -0
- /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/extension-ui.js +0 -0
- /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/model.js +0 -0
- /package/dist/{src/foundation/presentation-contracts → contracts/presentation}/index.js +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/index.d.ts +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/index.js +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/model.d.ts +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/model.js +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/validation.d.ts +0 -0
- /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/validation.js +0 -0
- /package/dist/{src/features → features}/launch/development-launch.d.ts +0 -0
- /package/dist/{src/features → features}/launch/initialize-profile.d.ts +0 -0
- /package/dist/{src/features → features}/launch/initialize-profile.js +0 -0
- /package/dist/{src/features → features}/launch/runtime-selection.js +0 -0
- /package/dist/{src/features → features}/workspace/capabilities.js +0 -0
- /package/dist/{src/features → features}/workspace/index.d.ts +0 -0
- /package/dist/{src/features → features}/workspace/index.js +0 -0
- /package/dist/{src/features → features}/workspace/presentation.d.ts +0 -0
- /package/dist/{src/features → features}/workspace/presentation.js +0 -0
- /package/dist/{src/features → features}/workspace/reconciliation.d.ts +0 -0
- /package/dist/{src/features → features}/workspace/reconciliation.js +0 -0
- /package/dist/{src/foundation → foundation}/launch-guardian/index.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/launch-guardian/index.js +0 -0
- /package/dist/{src/foundation → foundation}/lifecycle/commands.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/lifecycle/commands.js +0 -0
- /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.js +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/evidence.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/evidence.js +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/index.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/index.js +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/proof-gate.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/native-host-protocol/proof-gate.js +0 -0
- /package/dist/{src/foundation → foundation}/process-containment/artifact.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/process-containment/artifact.js +0 -0
- /package/dist/{src/foundation → foundation}/process-containment/contracts.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/process-containment/contracts.js +0 -0
- /package/dist/{src/foundation → foundation}/protocol/index.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/protocol/index.js +0 -0
- /package/dist/{src/foundation → foundation}/release/cohort-selection.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/release/cohort-selection.js +0 -0
- /package/dist/{src/foundation → foundation}/release/concurrency.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/release/concurrency.js +0 -0
- /package/dist/{src/foundation → foundation}/release/process-cleanup.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/release/process-cleanup.js +0 -0
- /package/dist/{src/foundation → foundation}/release/stable-release.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/release/stable-release.js +0 -0
- /package/dist/{src/foundation → foundation}/storage/index.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/storage/index.js +0 -0
- /package/dist/{src/foundation → foundation}/structured-agent-runtime/index.d.ts +0 -0
- /package/dist/{src/foundation → foundation}/structured-agent-runtime/index.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/components.js +0 -0
- /package/dist/{src/foundation/pi-owned-ui-integration/route-host.js → integrations/pi/components/editor-interaction.js} +0 -0
- /package/dist/{src/foundation/pi-tui-runtime-adapter/contracts.js → integrations/pi/components/prompt-input-port.js} +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/resources/builtin-themes.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/resources/builtin-themes.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-editor-autocomplete.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-extension-ui.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/theme.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/theme.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/countdown-timer.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/countdown-timer.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/custom-entry.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/custom-entry.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/daxnuts.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/daxnuts.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/earendil-announcement.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/extension-editor.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/extension-editor.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/first-time-setup.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/first-time-setup.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/markdown-transform.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/markdown-transform.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/mermaid.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/mermaid.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector-search.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector-search.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/skill-invocation-message.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/skill-invocation-message.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/status-indicator.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/status-indicator.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/tree-selector.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/tree-selector.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/trust-selector.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/trust-selector.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/external-editor.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/external-editor.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/model-search.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/model-search.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme-controller.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme-controller.js +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme.d.ts +0 -0
- /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme.js +0 -0
- /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/pi-settings-metadata.json +0 -0
- /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.d.ts +0 -0
- /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.js +0 -0
- /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflows.js +0 -0
- /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/conformance.d.ts +0 -0
- /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/conformance.js +0 -0
- /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/presentation-adapter.js +0 -0
- /package/dist/{src/foundation/ui-apps → ui/apps}/contracts.js +0 -0
- /package/dist/{src/foundation/ui-apps → ui/apps}/index.d.ts +0 -0
- /package/dist/{src/foundation/ui-apps → ui/apps}/index.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/dialog-panel.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/label.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/label.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/list-block.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/list-block.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/pane.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/pane.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/revision.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/revision.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/status-line.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/status-line.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/stepper.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/stepper.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/theme.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/theme.js +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/value-menu.d.ts +0 -0
- /package/dist/{src/foundation/ui-components → ui/components}/value-menu.js +0 -0
- /package/dist/{src/foundation/owned-ui-settings → ui/settings}/index.d.ts +0 -0
- /package/dist/{src/foundation/owned-ui-settings → ui/settings}/index.js +0 -0
- /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.d.ts +0 -0
- /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.js +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type ReleaseIdentity } from "./release.js";
|
|
2
|
+
import { type ReadCertifiedDependencyLayerOptions, type RuntimePayloadInventory } from "./dependency-layer.js";
|
|
2
3
|
export declare const RELEASE_MANIFEST_FILENAME: string;
|
|
3
4
|
export interface MaterializedRelease extends ReleaseIdentity {
|
|
4
5
|
readonly releaseRoot: string;
|
|
5
6
|
}
|
|
6
|
-
export type ReleaseContentOperation = "source-read" | "candidate-write" | "verification-read";
|
|
7
|
+
export type ReleaseContentOperation = "source-read" | "candidate-write" | "layer-write" | "layer-reuse" | "verification-read";
|
|
7
8
|
export interface ReleaseContentOperationEvent {
|
|
8
9
|
readonly operation: ReleaseContentOperation;
|
|
9
10
|
readonly path: string;
|
|
@@ -15,6 +16,7 @@ export interface MaterializeReleaseOptions {
|
|
|
15
16
|
readonly fileCount: number;
|
|
16
17
|
}) => void;
|
|
17
18
|
readonly onOperation?: (event: ReleaseContentOperationEvent) => void;
|
|
19
|
+
readonly onRuntimeInventory?: (inventory: RuntimePayloadInventory) => void;
|
|
18
20
|
/** Test seam for deterministic write-failure coverage. */
|
|
19
21
|
readonly writeCandidateFile?: (path: string, bytes: Uint8Array, mode: number) => Promise<void>;
|
|
20
22
|
}
|
|
@@ -26,18 +28,22 @@ export interface CertifiedReleaseRecord {
|
|
|
26
28
|
readonly releaseRoot: string;
|
|
27
29
|
readonly packageVersion?: string;
|
|
28
30
|
readonly contentDigest: string;
|
|
31
|
+
/** Absent on records written before releases declared a handoff contract. */
|
|
32
|
+
readonly launchContract?: string;
|
|
29
33
|
}
|
|
34
|
+
/** Process-authority compatibility controls for metadata-only release loading. */
|
|
35
|
+
export type ReadCertifiedReleaseManifestOptions = ReadCertifiedDependencyLayerOptions;
|
|
30
36
|
export declare function materializeRelease(packageRoot: string, dataDir: string, options?: MaterializeReleaseOptions): Promise<MaterializedRelease>;
|
|
31
37
|
/** Consume proof that this exact object was freshly materialized or fully verified in this process. */
|
|
32
38
|
export declare function consumeMaterializationProof(release: MaterializedRelease): boolean;
|
|
33
|
-
export declare function readMaterializedRelease(releaseRoot: string): Promise<MaterializedRelease>;
|
|
39
|
+
export declare function readMaterializedRelease(releaseRoot: string, selectedStoreRoot?: string): Promise<MaterializedRelease>;
|
|
34
40
|
/**
|
|
35
41
|
* Load metadata for a release whose bytes were already certified by the
|
|
36
42
|
* current parent process or an authenticated live supervisor. Callers must
|
|
37
43
|
* establish one of those preconditions; untrusted releases require full
|
|
38
44
|
* verification.
|
|
39
45
|
*/
|
|
40
|
-
export declare function readCertifiedReleaseManifest(record: CertifiedReleaseRecord, selectedStoreRoot: string): Promise<MaterializedRelease>;
|
|
46
|
+
export declare function readCertifiedReleaseManifest(record: CertifiedReleaseRecord, selectedStoreRoot: string, options?: ReadCertifiedReleaseManifestOptions): Promise<MaterializedRelease>;
|
|
41
47
|
export declare function verifyMaterializedRelease(releaseRoot: string, expected?: ReleaseIdentity, selectedStoreRoot?: string, options?: VerifyMaterializedReleaseOptions): Promise<MaterializedRelease>;
|
|
42
48
|
export declare function assertImmutableExecutionRoot(release: MaterializedRelease, dataDir: string): Promise<void>;
|
|
43
49
|
export declare function resolveReleaseEntryPoint(release: MaterializedRelease, entryPoint: string): Promise<string>;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { chmod, lstat, mkdir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { chmod, lstat, mkdir, readFile, realpath, rename, rm, symlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { PRODUCT_PACKAGE_NAME, createReleaseIdentity,
|
|
4
|
+
import { PRODUCT_PACKAGE_NAME, createReleaseIdentity, discoverReleasePayload, releaseFileIdentity, resolveWithin, } from "./release.js";
|
|
5
5
|
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
6
|
+
import { assertCurrentLaunchContract, isCurrentLaunchContract, readLaunchContext } from "../launch-context/index.js";
|
|
6
7
|
import { mapWithConcurrency } from "./concurrency.js";
|
|
8
|
+
import { assertImmutableFileMode } from "./immutable-platform.js";
|
|
9
|
+
import { dependencyReference, materializeDependencyLayer, readCertifiedDependencyLayer, selectPublishedDependencyRuntimePayload, verifyDependencyLayer, } from "./dependency-layer.js";
|
|
7
10
|
const RELEASE_FILE_IO_CONCURRENCY = 32;
|
|
8
11
|
const certificationReady = new WeakSet();
|
|
9
12
|
export const RELEASE_MANIFEST_FILENAME = PRODUCT_IDENTITY.manifest.releaseFilename;
|
|
@@ -11,17 +14,35 @@ export async function materializeRelease(packageRoot, dataDir, options = {}) {
|
|
|
11
14
|
const payload = await discoverReleasePayload(packageRoot, {
|
|
12
15
|
onSourceRead: (path, bytes) => options.onOperation?.({ operation: "source-read", path, bytes }),
|
|
13
16
|
});
|
|
17
|
+
assertCurrentLaunchContract(payload);
|
|
14
18
|
const storeRoot = resolve(dataDir, "releases");
|
|
15
19
|
await mkdir(storeRoot, { recursive: true, mode: 0o700 });
|
|
16
|
-
|
|
20
|
+
const dependencyPaths = payload.paths.filter(path => path.startsWith("node_modules/"));
|
|
21
|
+
const productPaths = payload.paths.filter(path => !path.startsWith("node_modules/"));
|
|
22
|
+
const selectedDependencies = await selectPublishedDependencyRuntimePayload(payload.packageRoot, dependencyPaths);
|
|
23
|
+
options.onRuntimeInventory?.(selectedDependencies.inventory);
|
|
24
|
+
const layerOperations = [];
|
|
25
|
+
const layer = await materializeDependencyLayer(payload.packageRoot, dataDir, selectedDependencies.paths, {
|
|
26
|
+
inventory: selectedDependencies.inventory,
|
|
27
|
+
cachedFiles: payload.cachedFiles,
|
|
28
|
+
onOperation: event => layerOperations.push(event),
|
|
29
|
+
...(options.writeCandidateFile === undefined ? {} : { writeCandidateFile: options.writeCandidateFile }),
|
|
30
|
+
});
|
|
31
|
+
const layerReferences = layer === null ? [] : [dependencyReference(layer)];
|
|
32
|
+
options.onProgress?.({
|
|
33
|
+
phase: "copying",
|
|
34
|
+
fileCount: productPaths.length + (layer?.reused === false ? layer.files.length : 0),
|
|
35
|
+
});
|
|
36
|
+
for (const event of layerOperations)
|
|
37
|
+
options.onOperation?.(event);
|
|
17
38
|
const candidate = resolveWithin(storeRoot, `.candidate-${randomUUID()}`);
|
|
18
39
|
await mkdir(candidate, { recursive: false, mode: 0o700 });
|
|
19
40
|
try {
|
|
20
|
-
const directories = [...new Set(
|
|
41
|
+
const directories = [...new Set(productPaths.map(path => dirname(resolveWithin(candidate, path))))];
|
|
21
42
|
await mapWithConcurrency(directories, RELEASE_FILE_IO_CONCURRENCY, async (directory) => {
|
|
22
43
|
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
23
44
|
});
|
|
24
|
-
const files = await mapWithConcurrency(
|
|
45
|
+
const files = await mapWithConcurrency(productPaths, RELEASE_FILE_IO_CONCURRENCY, async (path) => {
|
|
25
46
|
const source = resolveWithin(payload.packageRoot, path);
|
|
26
47
|
const destination = resolveWithin(candidate, path);
|
|
27
48
|
const metadata = await lstat(source);
|
|
@@ -41,7 +62,12 @@ export async function materializeRelease(packageRoot, dataDir, options = {}) {
|
|
|
41
62
|
options.onOperation?.({ operation: "candidate-write", path, bytes: bytes.length });
|
|
42
63
|
return releaseFileIdentity(path, bytes, (metadata.mode & 0o111) !== 0);
|
|
43
64
|
});
|
|
44
|
-
const identity = createReleaseIdentity(payload.packageRoot, payload.packageVersion, files);
|
|
65
|
+
const identity = createReleaseIdentity(payload.packageRoot, payload.packageVersion, files, layerReferences, payload.launchContract);
|
|
66
|
+
if (layer !== null) {
|
|
67
|
+
const binding = resolveWithin(candidate, "node_modules");
|
|
68
|
+
const target = resolveWithin(layer.layerRoot, "node_modules");
|
|
69
|
+
await symlink(target, binding, process.platform === "win32" ? "junction" : "dir");
|
|
70
|
+
}
|
|
45
71
|
const releaseRoot = resolveWithin(storeRoot, identity.releaseId);
|
|
46
72
|
if (await lstat(releaseRoot).catch(() => null)) {
|
|
47
73
|
await rm(candidate, { recursive: true, force: true });
|
|
@@ -71,10 +97,10 @@ export function consumeMaterializationProof(release) {
|
|
|
71
97
|
certificationReady.delete(release);
|
|
72
98
|
return true;
|
|
73
99
|
}
|
|
74
|
-
export async function readMaterializedRelease(releaseRoot) {
|
|
100
|
+
export async function readMaterializedRelease(releaseRoot, selectedStoreRoot) {
|
|
75
101
|
const canonical = await realpath(releaseRoot);
|
|
76
102
|
const manifest = JSON.parse(await readFile(resolve(canonical, RELEASE_MANIFEST_FILENAME), "utf8"));
|
|
77
|
-
return await verifyMaterializedRelease(canonical, manifest);
|
|
103
|
+
return certificationReadyRelease(await verifyMaterializedRelease(canonical, manifest, selectedStoreRoot));
|
|
78
104
|
}
|
|
79
105
|
/**
|
|
80
106
|
* Load metadata for a release whose bytes were already certified by the
|
|
@@ -82,9 +108,10 @@ export async function readMaterializedRelease(releaseRoot) {
|
|
|
82
108
|
* establish one of those preconditions; untrusted releases require full
|
|
83
109
|
* verification.
|
|
84
110
|
*/
|
|
85
|
-
export async function readCertifiedReleaseManifest(record, selectedStoreRoot) {
|
|
111
|
+
export async function readCertifiedReleaseManifest(record, selectedStoreRoot, options = {}) {
|
|
86
112
|
const canonical = await realpath(record.releaseRoot);
|
|
87
|
-
|
|
113
|
+
const canonicalStoreRoot = await realpath(selectedStoreRoot);
|
|
114
|
+
assertContained(canonicalStoreRoot, canonical, "release root is outside the selected release store");
|
|
88
115
|
const manifest = JSON.parse(await readFile(resolveWithin(canonical, RELEASE_MANIFEST_FILENAME), "utf8"));
|
|
89
116
|
validateManifest(manifest);
|
|
90
117
|
if (manifest.releaseId !== record.releaseId || manifest.contentDigest !== record.contentDigest
|
|
@@ -93,12 +120,13 @@ export async function readCertifiedReleaseManifest(record, selectedStoreRoot) {
|
|
|
93
120
|
}
|
|
94
121
|
if (canonical.split(sep).at(-1) !== manifest.releaseId)
|
|
95
122
|
throw new Error(`release directory does not match identity ${manifest.releaseId}`);
|
|
123
|
+
await verifyReleaseDependencies(canonical, canonicalStoreRoot, manifest.dependencyLayers ?? [], false, {}, options);
|
|
96
124
|
return { ...manifest, releaseRoot: canonical };
|
|
97
125
|
}
|
|
98
126
|
export async function verifyMaterializedRelease(releaseRoot, expected, selectedStoreRoot, options = {}) {
|
|
99
127
|
const canonical = await realpath(releaseRoot);
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
const canonicalStoreRoot = selectedStoreRoot ? await realpath(selectedStoreRoot) : await realpath(dirname(canonical));
|
|
129
|
+
assertContained(canonicalStoreRoot, canonical, "release root is outside the selected release store");
|
|
102
130
|
const manifestPath = resolveWithin(canonical, RELEASE_MANIFEST_FILENAME);
|
|
103
131
|
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
104
132
|
validateManifest(manifest);
|
|
@@ -111,15 +139,16 @@ export async function verifyMaterializedRelease(releaseRoot, expected, selectedS
|
|
|
111
139
|
await mapWithConcurrency(manifest.files, RELEASE_FILE_IO_CONCURRENCY, async (file) => {
|
|
112
140
|
await verifyFile(canonical, file, options);
|
|
113
141
|
});
|
|
114
|
-
const recomputed =
|
|
142
|
+
const recomputed = createReleaseIdentity(manifest.packageRoot, manifest.packageVersion, manifest.files, manifest.dependencyLayers ?? [], manifest.launchContract).contentDigest;
|
|
115
143
|
if (recomputed !== manifest.contentDigest)
|
|
116
144
|
throw new Error(`release content digest mismatch for ${manifest.releaseId}`);
|
|
145
|
+
await verifyReleaseDependencies(canonical, canonicalStoreRoot, manifest.dependencyLayers ?? [], true, options);
|
|
117
146
|
return { ...manifest, releaseRoot: canonical };
|
|
118
147
|
}
|
|
119
148
|
export async function assertImmutableExecutionRoot(release, dataDir) {
|
|
120
149
|
const storeRoot = await realpath(resolve(dataDir, "releases"));
|
|
121
150
|
assertContained(storeRoot, release.releaseRoot, "release root is outside the selected release store");
|
|
122
|
-
const selectedRoot = process.env
|
|
151
|
+
const selectedRoot = readLaunchContext(process.env, "release").releaseRoot;
|
|
123
152
|
if (!selectedRoot)
|
|
124
153
|
throw new Error(PRODUCT_TEXT.diagnostic("persistent process has no immutable release root"));
|
|
125
154
|
const selected = await realpath(selectedRoot);
|
|
@@ -135,6 +164,25 @@ export async function resolveReleaseEntryPoint(release, entryPoint) {
|
|
|
135
164
|
assertContained(release.releaseRoot, canonical, "entry point resolves outside the selected release root");
|
|
136
165
|
return canonical;
|
|
137
166
|
}
|
|
167
|
+
async function verifyReleaseDependencies(releaseRoot, storeRoot, references, fullVerification, options = {}, certificationOptions = {}) {
|
|
168
|
+
if (references.length === 0)
|
|
169
|
+
return;
|
|
170
|
+
if (references.length !== 1)
|
|
171
|
+
throw new Error("release currently supports exactly one dependency layer");
|
|
172
|
+
const dataDir = dirname(storeRoot);
|
|
173
|
+
const reference = references[0];
|
|
174
|
+
const layer = fullVerification
|
|
175
|
+
? await verifyDependencyLayer(dataDir, reference, event => options.onOperation?.({ operation: event.operation, path: event.path, bytes: event.bytes }))
|
|
176
|
+
: await readCertifiedDependencyLayer(dataDir, reference.layerId, reference, certificationOptions);
|
|
177
|
+
const binding = resolveWithin(releaseRoot, reference.binding);
|
|
178
|
+
const metadata = await lstat(binding);
|
|
179
|
+
if (!metadata.isSymbolicLink())
|
|
180
|
+
throw new Error(`release dependency binding is not managed: ${binding}`);
|
|
181
|
+
const target = await realpath(binding);
|
|
182
|
+
const expected = await realpath(resolveWithin(layer.layerRoot, "node_modules"));
|
|
183
|
+
if (target !== expected)
|
|
184
|
+
throw new Error(`release dependency binding targets unexpected content: ${target}`);
|
|
185
|
+
}
|
|
138
186
|
async function verifyFile(root, file, options) {
|
|
139
187
|
const path = resolveWithin(root, file.path);
|
|
140
188
|
const metadata = await lstat(path).catch(() => null);
|
|
@@ -142,6 +190,7 @@ async function verifyFile(root, file, options) {
|
|
|
142
190
|
throw new Error(`release candidate is incomplete: ${file.path}`);
|
|
143
191
|
if (metadata.size !== file.bytes)
|
|
144
192
|
throw new Error(`release file size mismatch: ${file.path}`);
|
|
193
|
+
assertImmutableFileMode(metadata, path);
|
|
145
194
|
const bytes = await readFile(path);
|
|
146
195
|
options.onOperation?.({ operation: "verification-read", path: file.path, bytes: bytes.length });
|
|
147
196
|
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
@@ -153,12 +202,20 @@ function certificationReadyRelease(release) {
|
|
|
153
202
|
return release;
|
|
154
203
|
}
|
|
155
204
|
function validateManifest(value) {
|
|
205
|
+
if (value.launchContract !== undefined && !isCurrentLaunchContract(value)) {
|
|
206
|
+
throw new Error(PRODUCT_TEXT.diagnostic(`release manifest declares an unsupported launch contract: ${String(value.launchContract)}`));
|
|
207
|
+
}
|
|
156
208
|
if (value.packageName !== PRODUCT_PACKAGE_NAME || typeof value.packageVersion !== "string")
|
|
157
209
|
throw new Error(PRODUCT_TEXT.diagnostic("release manifest metadata is invalid"));
|
|
158
210
|
if (!/^[a-f0-9]{64}$/.test(value.contentDigest) || !/^[0-9A-Za-z.+_-]+-[a-f0-9]{20}$/.test(value.releaseId))
|
|
159
211
|
throw new Error(PRODUCT_TEXT.diagnostic("release identity is invalid"));
|
|
160
212
|
if (!Array.isArray(value.files) || value.files.length === 0)
|
|
161
213
|
throw new Error("release manifest contains no files");
|
|
214
|
+
if (value.dependencyLayers !== undefined && (!Array.isArray(value.dependencyLayers) || value.dependencyLayers.length === 0
|
|
215
|
+
|| value.dependencyLayers.some(layer => !/^dependencies-[a-f0-9]{32}$/.test(layer.layerId)
|
|
216
|
+
|| !/^[a-f0-9]{64}$/.test(layer.contentDigest) || layer.binding !== "node_modules"))) {
|
|
217
|
+
throw new Error("release dependency-layer references are invalid");
|
|
218
|
+
}
|
|
162
219
|
for (const file of value.files) {
|
|
163
220
|
if (typeof file.path !== "string" || file.path.length === 0 || file.path.includes("\\") || file.path.startsWith("/") || file.path.split("/").includes("..")) {
|
|
164
221
|
throw new Error(`invalid release manifest path: ${String(file.path)}`);
|
|
@@ -166,6 +223,9 @@ function validateManifest(value) {
|
|
|
166
223
|
if (!Number.isSafeInteger(file.bytes) || file.bytes < 0 || !/^[a-f0-9]{64}$/.test(file.sha256))
|
|
167
224
|
throw new Error(`invalid release manifest file identity: ${file.path}`);
|
|
168
225
|
}
|
|
226
|
+
const expected = createReleaseIdentity(value.packageRoot, value.packageVersion, value.files, value.dependencyLayers ?? [], value.launchContract);
|
|
227
|
+
if (expected.contentDigest !== value.contentDigest)
|
|
228
|
+
throw new Error("release manifest content/contract digest mismatch");
|
|
169
229
|
}
|
|
170
230
|
function assertContained(parent, child, message) {
|
|
171
231
|
const fromParent = relative(parent, child);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DependencyLayerReference } from "./dependency-layer.js";
|
|
1
2
|
export declare const PRODUCT_PACKAGE_NAME: string;
|
|
2
3
|
export interface ReleaseFileIdentity {
|
|
3
4
|
readonly path: string;
|
|
@@ -11,12 +12,16 @@ export interface ReleaseIdentity {
|
|
|
11
12
|
readonly contentDigest: string;
|
|
12
13
|
readonly releaseId: string;
|
|
13
14
|
readonly packageRoot: string;
|
|
15
|
+
readonly launchContract?: string;
|
|
14
16
|
readonly files: readonly ReleaseFileIdentity[];
|
|
17
|
+
/** Absent for legacy full-copy releases. */
|
|
18
|
+
readonly dependencyLayers?: readonly DependencyLayerReference[];
|
|
15
19
|
}
|
|
16
20
|
export interface DiscoveredReleasePayload {
|
|
17
21
|
readonly packageRoot: string;
|
|
18
22
|
readonly packageVersion: string;
|
|
19
23
|
readonly paths: readonly string[];
|
|
24
|
+
readonly launchContract?: string;
|
|
20
25
|
/** Package manifests already read to discover the dependency closure. */
|
|
21
26
|
readonly cachedFiles: ReadonlyMap<string, Buffer>;
|
|
22
27
|
}
|
|
@@ -31,7 +36,7 @@ export declare function discoverReleasePayload(packageRoot: string, options?: Di
|
|
|
31
36
|
* content.
|
|
32
37
|
*/
|
|
33
38
|
export declare function deriveReleaseIdentity(packageRoot: string): Promise<ReleaseIdentity>;
|
|
34
|
-
export declare function createReleaseIdentity(packageRoot: string, packageVersion: string, files: readonly ReleaseFileIdentity[]): ReleaseIdentity;
|
|
39
|
+
export declare function createReleaseIdentity(packageRoot: string, packageVersion: string, files: readonly ReleaseFileIdentity[], dependencyLayers?: readonly DependencyLayerReference[], launchContract?: string): ReleaseIdentity;
|
|
35
40
|
export declare function releaseFileIdentity(path: string, bytes: Uint8Array, executable: boolean): ReleaseFileIdentity;
|
|
36
41
|
export declare function digestManifestFiles(files: readonly ReleaseFileIdentity[]): string;
|
|
37
42
|
export declare function resolveWithin(root: string, candidate: string): string;
|
|
@@ -31,6 +31,7 @@ export async function discoverReleasePayload(packageRoot, options = {}) {
|
|
|
31
31
|
packageRoot: canonicalRoot,
|
|
32
32
|
packageVersion: manifest.version,
|
|
33
33
|
paths: [...paths].sort(),
|
|
34
|
+
...(typeof manifest.privateLaunchContract === "string" ? { launchContract: manifest.privateLaunchContract } : {}),
|
|
34
35
|
cachedFiles,
|
|
35
36
|
};
|
|
36
37
|
}
|
|
@@ -49,17 +50,27 @@ export async function deriveReleaseIdentity(packageRoot) {
|
|
|
49
50
|
const bytes = payload.cachedFiles.get(path) ?? await readFile(absolute);
|
|
50
51
|
return releaseFileIdentity(path, bytes, (metadata.mode & 0o111) !== 0);
|
|
51
52
|
});
|
|
52
|
-
return createReleaseIdentity(payload.packageRoot, payload.packageVersion, files);
|
|
53
|
+
return createReleaseIdentity(payload.packageRoot, payload.packageVersion, files, [], payload.launchContract);
|
|
53
54
|
}
|
|
54
|
-
export function createReleaseIdentity(packageRoot, packageVersion, files) {
|
|
55
|
-
const
|
|
55
|
+
export function createReleaseIdentity(packageRoot, packageVersion, files, dependencyLayers = [], launchContract) {
|
|
56
|
+
const fileDigest = digestManifestFiles(files);
|
|
57
|
+
const productDigest = launchContract === undefined ? fileDigest
|
|
58
|
+
: createHash("sha256").update(`launch-contract\0${launchContract}\0${fileDigest}`).digest("hex");
|
|
59
|
+
const contentDigest = dependencyLayers.length === 0
|
|
60
|
+
? productDigest
|
|
61
|
+
: createHash("sha256")
|
|
62
|
+
.update(`product\0${productDigest}\n`)
|
|
63
|
+
.update(dependencyLayers.map(layer => `${layer.layerId}\0${layer.contentDigest}\0${layer.binding}\n`).join(""))
|
|
64
|
+
.digest("hex");
|
|
56
65
|
return {
|
|
57
66
|
packageName: PRODUCT_PACKAGE_NAME,
|
|
58
67
|
packageVersion,
|
|
59
68
|
contentDigest,
|
|
60
69
|
releaseId: `${packageVersion}-${contentDigest.slice(0, 20)}`,
|
|
61
70
|
packageRoot,
|
|
71
|
+
...(launchContract === undefined ? {} : { launchContract }),
|
|
62
72
|
files: [...files].sort(compareReleaseFiles),
|
|
73
|
+
...(dependencyLayers.length === 0 ? {} : { dependencyLayers: [...dependencyLayers] }),
|
|
63
74
|
};
|
|
64
75
|
}
|
|
65
76
|
export function releaseFileIdentity(path, bytes, executable) {
|
|
@@ -143,7 +154,7 @@ async function findInstalledDependency(root, requesterRoot, name) {
|
|
|
143
154
|
const metadata = await lstat(candidate).catch(() => null);
|
|
144
155
|
if (metadata?.isDirectory() && !metadata.isSymbolicLink())
|
|
145
156
|
return candidate;
|
|
146
|
-
//
|
|
157
|
+
// Invariant: a linked dependency directory is how this installation unifies a module
|
|
147
158
|
// that would otherwise be present twice, and the link is made by A1 itself
|
|
148
159
|
// at install and at every launch. Follow it to the directory it names and
|
|
149
160
|
// collect from there, so the payload still reads only real files — but
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
2
|
+
import { type DependencyLayerReference } from "./dependency-layer.js";
|
|
3
|
+
import { type ImmutablePlatformPolicy } from "./immutable-platform.js";
|
|
4
|
+
import { type ReleaseFileIdentity } from "./release.js";
|
|
5
|
+
import { type CertifiedReleaseRecord, type MaterializedRelease } from "./release-store.js";
|
|
6
|
+
declare const RESTART_SEAL_VERSION = 1;
|
|
7
|
+
type EvidenceKind = "directory" | "file" | "binding";
|
|
8
|
+
interface PathEvidence {
|
|
9
|
+
readonly path: string;
|
|
10
|
+
readonly kind: EvidenceKind;
|
|
11
|
+
readonly device: string;
|
|
12
|
+
readonly inode: string;
|
|
13
|
+
readonly mode: number;
|
|
14
|
+
readonly size: string;
|
|
15
|
+
readonly modifiedNs: string;
|
|
16
|
+
readonly changedNs: string;
|
|
17
|
+
readonly bornNs: string;
|
|
18
|
+
}
|
|
19
|
+
interface LayerRestartEvidence extends DependencyLayerReference {
|
|
20
|
+
readonly layerRoot: PathEvidence;
|
|
21
|
+
readonly manifest: PathEvidence;
|
|
22
|
+
readonly certification: PathEvidence;
|
|
23
|
+
readonly bindingEvidence: PathEvidence;
|
|
24
|
+
readonly bindingTarget: string;
|
|
25
|
+
}
|
|
26
|
+
interface RestartSealCore {
|
|
27
|
+
readonly version: typeof RESTART_SEAL_VERSION;
|
|
28
|
+
readonly launchContract: string;
|
|
29
|
+
readonly platform: NodeJS.Platform;
|
|
30
|
+
readonly platformPolicy: ImmutablePlatformPolicy;
|
|
31
|
+
readonly releaseId: string;
|
|
32
|
+
readonly packageVersion: string;
|
|
33
|
+
readonly contentDigest: string;
|
|
34
|
+
readonly packageRoot: string;
|
|
35
|
+
readonly releaseRoot: PathEvidence;
|
|
36
|
+
readonly manifest: PathEvidence;
|
|
37
|
+
readonly launchEntries: readonly ReleaseFileIdentity[];
|
|
38
|
+
readonly launchEntryEvidence: readonly PathEvidence[];
|
|
39
|
+
readonly dependencyLayers: readonly LayerRestartEvidence[];
|
|
40
|
+
readonly certifiedAt: string;
|
|
41
|
+
}
|
|
42
|
+
export interface RestartSeal extends RestartSealCore {
|
|
43
|
+
readonly sealDigest: string;
|
|
44
|
+
}
|
|
45
|
+
interface ReleaseCertificationDocument {
|
|
46
|
+
readonly schema: typeof PRODUCT_IDENTITY.evidence.releaseCertificationSchema;
|
|
47
|
+
readonly releaseId: string;
|
|
48
|
+
readonly contentDigest: string;
|
|
49
|
+
readonly verifiedAt: string;
|
|
50
|
+
readonly checks: readonly {
|
|
51
|
+
readonly id: string;
|
|
52
|
+
readonly passed: boolean;
|
|
53
|
+
}[];
|
|
54
|
+
readonly restartSeal: RestartSeal | null;
|
|
55
|
+
}
|
|
56
|
+
export interface RestartValidationEvent {
|
|
57
|
+
readonly operation: "restart-evidence-read";
|
|
58
|
+
readonly path: string;
|
|
59
|
+
}
|
|
60
|
+
/** Build compact restart authority after complete content verification established read-only payload files. */
|
|
61
|
+
export declare function createRestartSeal(release: MaterializedRelease, dataDir: string): Promise<RestartSeal | null>;
|
|
62
|
+
/** Recover an approved release from durable bounded evidence without traversing its payload. */
|
|
63
|
+
export declare function readRestartCertifiedRelease(record: CertifiedReleaseRecord & {
|
|
64
|
+
readonly diagnosticsPath?: string | null;
|
|
65
|
+
}, dataDir: string, onEvent?: (event: RestartValidationEvent) => void): Promise<MaterializedRelease>;
|
|
66
|
+
export declare function releaseCertificationDocument(release: MaterializedRelease, restartSeal: RestartSeal | null, verifiedAt?: string): ReleaseCertificationDocument;
|
|
67
|
+
export declare function restartSealDigest(core: RestartSealCore): string;
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat, readFile, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import { basename, isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
|
+
import { PRIVATE_LAUNCH_CONTRACT, launchContractTarget } from "../launch-context/index.js";
|
|
6
|
+
import { DEPENDENCY_LAYER_MANIFEST, dependencyLayerCertificationPath, legacyDependencyLayerCertificationPath, readCertifiedDependencyLayer } from "./dependency-layer.js";
|
|
7
|
+
import { managedDependencyCertificationPath } from "./dependency-certification.js";
|
|
8
|
+
import { immutablePlatformPolicy } from "./immutable-platform.js";
|
|
9
|
+
import { PRODUCT_PACKAGE_NAME } from "./release.js";
|
|
10
|
+
import { RELEASE_MANIFEST_FILENAME } from "./release-store.js";
|
|
11
|
+
import { UpdateTransactionStore } from "./update-transaction.js";
|
|
12
|
+
const RESTART_SEAL_VERSION = 1;
|
|
13
|
+
const REQUIRED_LAUNCH_ENTRIES = ["bin/supervisor.js", "bin/guardian.js"];
|
|
14
|
+
/** Build compact restart authority after complete content verification established read-only payload files. */
|
|
15
|
+
export async function createRestartSeal(release, dataDir) {
|
|
16
|
+
const policy = immutablePlatformPolicy();
|
|
17
|
+
if (policy === null)
|
|
18
|
+
return null;
|
|
19
|
+
const canonicalData = await realpath(dataDir);
|
|
20
|
+
const releasesRoot = await realpath(resolve(canonicalData, "releases"));
|
|
21
|
+
const releaseRoot = await realpath(release.releaseRoot);
|
|
22
|
+
assertDirectChild(releasesRoot, releaseRoot, release.releaseId, "release");
|
|
23
|
+
const manifestPath = resolve(releaseRoot, RELEASE_MANIFEST_FILENAME);
|
|
24
|
+
const launchEntries = REQUIRED_LAUNCH_ENTRIES.map(path => release.files.find(candidate => candidate.path === path));
|
|
25
|
+
if (launchEntries.some(file => file === undefined))
|
|
26
|
+
return null;
|
|
27
|
+
const certifiedLaunchEntries = launchEntries;
|
|
28
|
+
const layersRoot = release.dependencyLayers?.length ? await realpath(resolve(canonicalData, "dependency-layers")) : null;
|
|
29
|
+
const dependencyLayers = await Promise.all((release.dependencyLayers ?? []).map(async (reference) => {
|
|
30
|
+
if (layersRoot === null)
|
|
31
|
+
throw new Error("restart certification has no dependency-layer root");
|
|
32
|
+
await readCertifiedDependencyLayer(canonicalData, reference.layerId, reference);
|
|
33
|
+
const layerRoot = await realpath(resolve(layersRoot, reference.layerId));
|
|
34
|
+
assertDirectChild(layersRoot, layerRoot, reference.layerId, "dependency layer");
|
|
35
|
+
const bindingPath = resolve(releaseRoot, reference.binding);
|
|
36
|
+
const bindingTarget = await realpath(bindingPath);
|
|
37
|
+
const expectedTarget = await realpath(resolve(layerRoot, "node_modules"));
|
|
38
|
+
if (bindingTarget !== expectedTarget)
|
|
39
|
+
throw new Error(`restart certification dependency binding targets unexpected content: ${bindingPath}`);
|
|
40
|
+
return {
|
|
41
|
+
...reference,
|
|
42
|
+
layerRoot: await pathEvidence(layerRoot, "directory"),
|
|
43
|
+
manifest: await pathEvidence(resolve(layerRoot, DEPENDENCY_LAYER_MANIFEST), "file"),
|
|
44
|
+
certification: await pathEvidence(dependencyLayerCertificationPath(canonicalData, reference.layerId), "file"),
|
|
45
|
+
bindingEvidence: await pathEvidence(bindingPath, "binding", true),
|
|
46
|
+
bindingTarget,
|
|
47
|
+
};
|
|
48
|
+
}));
|
|
49
|
+
const core = {
|
|
50
|
+
version: RESTART_SEAL_VERSION,
|
|
51
|
+
launchContract: launchContractTarget(release),
|
|
52
|
+
platform: process.platform,
|
|
53
|
+
platformPolicy: policy,
|
|
54
|
+
releaseId: release.releaseId,
|
|
55
|
+
packageVersion: release.packageVersion,
|
|
56
|
+
contentDigest: release.contentDigest,
|
|
57
|
+
packageRoot: release.packageRoot,
|
|
58
|
+
releaseRoot: await pathEvidence(releaseRoot, "directory"),
|
|
59
|
+
manifest: await pathEvidence(manifestPath, "file"),
|
|
60
|
+
launchEntries: certifiedLaunchEntries,
|
|
61
|
+
launchEntryEvidence: await Promise.all(certifiedLaunchEntries.map(file => pathEvidence(resolve(releaseRoot, file.path), "file"))),
|
|
62
|
+
dependencyLayers,
|
|
63
|
+
certifiedAt: new Date().toISOString(),
|
|
64
|
+
};
|
|
65
|
+
return { ...core, sealDigest: restartSealDigest(core) };
|
|
66
|
+
}
|
|
67
|
+
/** Recover an approved release from durable bounded evidence without traversing its payload. */
|
|
68
|
+
export async function readRestartCertifiedRelease(record, dataDir, onEvent) {
|
|
69
|
+
const transaction = await new UpdateTransactionStore(dataDir).read();
|
|
70
|
+
if (transaction?.status === "active")
|
|
71
|
+
throw new Error("restart certification is unavailable during an active update transaction");
|
|
72
|
+
const certificationPath = resolve(dataDir, `certification-${record.releaseId}.json`);
|
|
73
|
+
if (record.diagnosticsPath !== undefined && record.diagnosticsPath !== certificationPath) {
|
|
74
|
+
throw new Error("restart certification path differs from the approved release record");
|
|
75
|
+
}
|
|
76
|
+
const certificationMetadata = await lstat(certificationPath);
|
|
77
|
+
onEvent?.({ operation: "restart-evidence-read", path: certificationPath });
|
|
78
|
+
if (!certificationMetadata.isFile() || certificationMetadata.isSymbolicLink() || (certificationMetadata.mode & 0o222) !== 0) {
|
|
79
|
+
throw new Error("restart certification is not an immutable regular file");
|
|
80
|
+
}
|
|
81
|
+
const certification = await readJson(certificationPath, onEvent);
|
|
82
|
+
if (certification.schema !== PRODUCT_IDENTITY.evidence.releaseCertificationSchema
|
|
83
|
+
|| certification.releaseId !== record.releaseId || certification.contentDigest !== record.contentDigest
|
|
84
|
+
|| !certification.checks.some(check => check.id === "immutable-content" && check.passed)) {
|
|
85
|
+
throw new Error("restart certification differs from the approved release record");
|
|
86
|
+
}
|
|
87
|
+
const seal = normalizeRestartSeal(certification.restartSeal);
|
|
88
|
+
// Invariant: a seal is restart authority only for a handoff this build can still
|
|
89
|
+
// perform, which is the contract it emits or the pre-cutover one it retains.
|
|
90
|
+
if (seal.launchContract !== PRIVATE_LAUNCH_CONTRACT && seal.launchContract !== "superseded") {
|
|
91
|
+
throw new Error(`restart seal declares an unsupported launch contract: ${String(seal.launchContract)}`);
|
|
92
|
+
}
|
|
93
|
+
if (seal.platform !== process.platform || seal.platformPolicy !== immutablePlatformPolicy()) {
|
|
94
|
+
throw new Error("restart certification platform immutability evidence is unsupported");
|
|
95
|
+
}
|
|
96
|
+
if (seal.releaseId !== record.releaseId || seal.contentDigest !== record.contentDigest
|
|
97
|
+
|| resolve(seal.releaseRoot.path) !== resolve(record.releaseRoot)
|
|
98
|
+
|| (record.packageVersion !== undefined && seal.packageVersion !== record.packageVersion)) {
|
|
99
|
+
throw new Error("restart seal differs from the approved release identity");
|
|
100
|
+
}
|
|
101
|
+
const { sealDigest, ...core } = seal;
|
|
102
|
+
if (restartSealDigest(core) !== sealDigest)
|
|
103
|
+
throw new Error("restart seal digest is invalid");
|
|
104
|
+
const canonicalData = await observedRealpath(dataDir, onEvent);
|
|
105
|
+
const releasesRoot = await observedRealpath(resolve(canonicalData, "releases"), onEvent);
|
|
106
|
+
const releaseRoot = await observedRealpath(seal.releaseRoot.path, onEvent);
|
|
107
|
+
assertDirectChild(releasesRoot, releaseRoot, seal.releaseId, "release");
|
|
108
|
+
await assertPathEvidence(seal.releaseRoot, onEvent);
|
|
109
|
+
await assertPathEvidence(seal.manifest, onEvent);
|
|
110
|
+
for (let index = 0; index < seal.launchEntries.length; index += 1) {
|
|
111
|
+
const file = seal.launchEntries[index];
|
|
112
|
+
if (!REQUIRED_LAUNCH_ENTRIES.includes(file.path)) {
|
|
113
|
+
throw new Error(`restart seal contains an unexpected launch entry: ${file.path}`);
|
|
114
|
+
}
|
|
115
|
+
const evidence = seal.launchEntryEvidence[index];
|
|
116
|
+
if (!evidence || evidence.path !== resolve(releaseRoot, file.path) || file.bytes !== Number(evidence.size)) {
|
|
117
|
+
throw new Error(`restart launch entry evidence differs: ${file.path}`);
|
|
118
|
+
}
|
|
119
|
+
await assertPathEvidence(evidence, onEvent);
|
|
120
|
+
}
|
|
121
|
+
if (seal.launchEntries.length !== REQUIRED_LAUNCH_ENTRIES.length)
|
|
122
|
+
throw new Error("restart seal launch entries are incomplete");
|
|
123
|
+
const layersRoot = seal.dependencyLayers.length ? await observedRealpath(resolve(canonicalData, "dependency-layers"), onEvent) : null;
|
|
124
|
+
for (const layer of seal.dependencyLayers) {
|
|
125
|
+
if (layersRoot === null)
|
|
126
|
+
throw new Error("restart seal has no dependency-layer root");
|
|
127
|
+
const layerRoot = await observedRealpath(layer.layerRoot.path, onEvent);
|
|
128
|
+
assertDirectChild(layersRoot, layerRoot, layer.layerId, "dependency layer");
|
|
129
|
+
await assertPathEvidence(layer.layerRoot, onEvent);
|
|
130
|
+
await assertPathEvidence(layer.manifest, onEvent);
|
|
131
|
+
const legacyPath = legacyDependencyLayerCertificationPath(canonicalData, layer.layerId);
|
|
132
|
+
const canonicalPath = dependencyLayerCertificationPath(canonicalData, layer.layerId);
|
|
133
|
+
if (layer.certification.path !== legacyPath && layer.certification.path !== canonicalPath) {
|
|
134
|
+
throw new Error("restart dependency certification path is outside managed storage");
|
|
135
|
+
}
|
|
136
|
+
await managedDependencyCertificationPath(canonicalData, layer.layerId, layer.certification.path === legacyPath);
|
|
137
|
+
await assertPathEvidence(layer.certification, onEvent);
|
|
138
|
+
await assertPathEvidence(layer.bindingEvidence, onEvent, true);
|
|
139
|
+
const bindingTarget = await observedRealpath(layer.bindingEvidence.path, onEvent);
|
|
140
|
+
const expectedTarget = await observedRealpath(resolve(layerRoot, "node_modules"), onEvent);
|
|
141
|
+
if (bindingTarget !== layer.bindingTarget || bindingTarget !== expectedTarget) {
|
|
142
|
+
throw new Error(`restart dependency binding targets unexpected content: ${layer.bindingEvidence.path}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
packageName: PRODUCT_PACKAGE_NAME,
|
|
147
|
+
launchContract: seal.launchContract,
|
|
148
|
+
packageVersion: seal.packageVersion,
|
|
149
|
+
contentDigest: seal.contentDigest,
|
|
150
|
+
releaseId: seal.releaseId,
|
|
151
|
+
packageRoot: seal.packageRoot,
|
|
152
|
+
files: seal.launchEntries,
|
|
153
|
+
...(seal.dependencyLayers.length === 0 ? {} : {
|
|
154
|
+
dependencyLayers: seal.dependencyLayers.map(({ layerId, contentDigest, binding }) => ({ layerId, contentDigest, binding })),
|
|
155
|
+
}),
|
|
156
|
+
releaseRoot,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export function releaseCertificationDocument(release, restartSeal, verifiedAt = new Date().toISOString()) {
|
|
160
|
+
return {
|
|
161
|
+
schema: PRODUCT_IDENTITY.evidence.releaseCertificationSchema,
|
|
162
|
+
releaseId: release.releaseId,
|
|
163
|
+
contentDigest: release.contentDigest,
|
|
164
|
+
verifiedAt,
|
|
165
|
+
checks: [{ id: "immutable-content", passed: true }],
|
|
166
|
+
restartSeal,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export function restartSealDigest(core) {
|
|
170
|
+
return createHash("sha256").update(JSON.stringify(core)).digest("hex");
|
|
171
|
+
}
|
|
172
|
+
async function assertPathEvidence(evidence, onEvent, symbolic = false) {
|
|
173
|
+
const actual = await pathEvidence(evidence.path, evidence.kind, symbolic, onEvent);
|
|
174
|
+
if (JSON.stringify(actual) !== JSON.stringify(evidence))
|
|
175
|
+
throw new Error(`restart path evidence changed: ${evidence.path}`);
|
|
176
|
+
}
|
|
177
|
+
async function pathEvidence(path, kind, symbolic = false, onEvent) {
|
|
178
|
+
onEvent?.({ operation: "restart-evidence-read", path });
|
|
179
|
+
const metadata = symbolic ? await lstat(path, { bigint: true }) : await stat(path, { bigint: true });
|
|
180
|
+
if ((kind === "directory") !== metadata.isDirectory())
|
|
181
|
+
throw new Error(`restart evidence kind changed: ${path}`);
|
|
182
|
+
if (kind === "file" && !metadata.isFile())
|
|
183
|
+
throw new Error(`restart evidence file changed: ${path}`);
|
|
184
|
+
if (kind === "binding" && !metadata.isSymbolicLink())
|
|
185
|
+
throw new Error(`restart evidence binding changed: ${path}`);
|
|
186
|
+
if (kind === "file" && (metadata.mode & 146n) !== 0n)
|
|
187
|
+
throw new Error(`restart evidence file is writable: ${path}`);
|
|
188
|
+
return {
|
|
189
|
+
path: resolve(path),
|
|
190
|
+
kind,
|
|
191
|
+
device: metadata.dev.toString(),
|
|
192
|
+
inode: metadata.ino.toString(),
|
|
193
|
+
mode: Number(metadata.mode),
|
|
194
|
+
size: metadata.size.toString(),
|
|
195
|
+
modifiedNs: metadata.mtimeNs.toString(),
|
|
196
|
+
changedNs: metadata.ctimeNs.toString(),
|
|
197
|
+
bornNs: metadata.birthtimeNs.toString(),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function normalizeRestartSeal(value) {
|
|
201
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
202
|
+
throw new Error("release certification has no durable restart seal");
|
|
203
|
+
const seal = value;
|
|
204
|
+
if (seal.version !== RESTART_SEAL_VERSION || typeof seal.platform !== "string" || typeof seal.platformPolicy !== "string"
|
|
205
|
+
|| typeof seal.releaseId !== "string" || typeof seal.packageVersion !== "string" || typeof seal.contentDigest !== "string"
|
|
206
|
+
|| typeof seal.packageRoot !== "string" || typeof seal.certifiedAt !== "string" || typeof seal.sealDigest !== "string"
|
|
207
|
+
|| !seal.releaseRoot || !seal.manifest || !Array.isArray(seal.launchEntries) || !Array.isArray(seal.launchEntryEvidence)
|
|
208
|
+
|| !Array.isArray(seal.dependencyLayers)) {
|
|
209
|
+
throw new Error("durable restart seal is invalid");
|
|
210
|
+
}
|
|
211
|
+
return seal;
|
|
212
|
+
}
|
|
213
|
+
async function readJson(path, onEvent) {
|
|
214
|
+
onEvent?.({ operation: "restart-evidence-read", path });
|
|
215
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
216
|
+
}
|
|
217
|
+
async function observedRealpath(path, onEvent) {
|
|
218
|
+
onEvent?.({ operation: "restart-evidence-read", path });
|
|
219
|
+
return await realpath(path);
|
|
220
|
+
}
|
|
221
|
+
function assertDirectChild(parent, child, expectedName, kind) {
|
|
222
|
+
const fromParent = relative(parent, child);
|
|
223
|
+
if (isAbsolute(fromParent) || fromParent === ".." || fromParent.startsWith(`..${sep}`) || fromParent.includes(sep)
|
|
224
|
+
|| basename(child) !== expectedName) {
|
|
225
|
+
throw new Error(`restart ${kind} is outside its managed store: ${child}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CohortState, ReleaseRecord } from "./cohort-state.js";
|
|
2
|
+
import type { UpdateTransaction } from "./update-transaction.js";
|
|
3
|
+
/** Keep interactive launches on the last successful release until the update commits success. */
|
|
4
|
+
export declare function selectUpdateLaunchRelease(state: CohortState, transaction: UpdateTransaction | null): ReleaseRecord | null;
|
|
5
|
+
/** Pause cohort retirement during preparation; afterward only the successful launch release admits new sessions. */
|
|
6
|
+
export declare function selectSupervisorLaunchReleaseId(state: CohortState, transaction: UpdateTransaction | null): string | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Keep interactive launches on the last successful release until the update commits success. */
|
|
2
|
+
export function selectUpdateLaunchRelease(state, transaction) {
|
|
3
|
+
if (transaction === null || transaction.status === "completed")
|
|
4
|
+
return null;
|
|
5
|
+
const prior = transaction.priorActiveReleaseId === null ? undefined : state.releases[transaction.priorActiveReleaseId];
|
|
6
|
+
if (!prior || prior.approval !== "approved") {
|
|
7
|
+
throw new Error("unfinished update has no verified previous release available for launch; resume the update");
|
|
8
|
+
}
|
|
9
|
+
return prior;
|
|
10
|
+
}
|
|
11
|
+
/** Pause cohort retirement during preparation; afterward only the successful launch release admits new sessions. */
|
|
12
|
+
export function selectSupervisorLaunchReleaseId(state, transaction) {
|
|
13
|
+
// Concurrency: both the previous cohort and the warming candidate must remain available until cutover.
|
|
14
|
+
if (transaction?.status === "active")
|
|
15
|
+
return null;
|
|
16
|
+
return selectUpdateLaunchRelease(state, transaction)?.releaseId ?? state.references.active;
|
|
17
|
+
}
|