@timurproko/a1 0.2.7-dev.1249 → 0.2.7-dev.1252
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 +11 -36
- package/bin/cli.js +2 -17
- package/bin/ui.js +7 -48
- package/dist/app/session-shell/exit-notice.d.ts +2 -2
- package/dist/app/session-shell/exit-notice.js +10 -10
- package/dist/app/session-shell/prompt-submission.d.ts +2 -4
- package/dist/app/session-shell/prompt-submission.js +3 -23
- package/dist/app/session-shell/response-copy-transport.js +1 -2
- package/dist/app/session-shell/session-lifecycle.d.ts +1 -2
- package/dist/app/session-shell/session-lifecycle.js +2 -4
- package/dist/app/session-shell/session-shell-root.d.ts +0 -31
- package/dist/app/session-shell/session-shell-root.js +3 -4
- package/dist/app/session-shell/session-shell.js +6 -47
- package/dist/app/session-shell/session-viewport-controller.js +3 -6
- package/dist/app/session-shell/shell-host.js +2 -18
- package/dist/app/session-shell/transcript-document.d.ts +1 -2
- package/dist/app/session-shell/transcript-document.js +3 -28
- package/dist/app/session-shell/workflow-output.js +1 -1
- package/dist/app/session-shell/workflow-router.d.ts +1 -3
- package/dist/app/session-shell/workflow-router.js +1 -4
- package/dist/cli/dispatch.d.ts +1 -11
- package/dist/cli/dispatch.js +5 -92
- package/dist/cli/session-context.js +5 -7
- package/dist/cli/uninstall.d.ts +1 -5
- package/dist/cli/uninstall.js +6 -35
- package/dist/cli/version-stats.js +4 -7
- package/dist/composition/owned-settings.d.ts +0 -1
- package/dist/composition/owned-settings.js +0 -1
- package/dist/composition/owned-ui.d.ts +2 -24
- package/dist/composition/owned-ui.js +11 -87
- package/dist/composition/release-update-observation.d.ts +4 -4
- package/dist/composition/release-update-observation.js +17 -47
- package/dist/composition/session-backend.d.ts +0 -1
- package/dist/composition/session-runtime-registry.d.ts +3 -3
- package/dist/composition/settings-route-host.d.ts +0 -7
- package/dist/composition/settings-route-host.js +4 -10
- package/dist/composition/startup-route.d.ts +0 -1
- package/dist/composition/startup-route.js +0 -1
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/model.d.ts +0 -3
- package/dist/contracts/owned-ui/session-workflows.d.ts +1 -4
- package/dist/features/launch/development-launch.js +0 -1
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/intent.d.ts +1 -3
- package/dist/features/launch/intent.js +2 -4
- package/dist/features/launch/session-context.d.ts +2 -2
- package/dist/features/owned-ui/reference-screen-app.d.ts +0 -2
- package/dist/features/owned-ui/reference-screen-app.js +2 -9
- package/dist/features/owned-ui/settings-app.d.ts +0 -6
- package/dist/features/owned-ui/settings-app.js +5 -36
- package/dist/foundation/launch-context/index.d.ts +0 -12
- package/dist/foundation/launch-context/index.js +0 -26
- package/dist/foundation/lifecycle/claim-gate.d.ts +8 -0
- package/dist/foundation/lifecycle/claim-gate.js +37 -0
- package/dist/foundation/lifecycle/index.d.ts +5 -9
- package/dist/foundation/lifecycle/index.js +3 -4
- package/dist/foundation/lifecycle/model.d.ts +2 -59
- package/dist/foundation/lifecycle/model.js +0 -35
- package/dist/foundation/lifecycle/paths.d.ts +0 -24
- package/dist/foundation/lifecycle/paths.js +0 -40
- package/dist/foundation/lifecycle/process-liveness.d.ts +8 -0
- package/dist/foundation/lifecycle/process-liveness.js +18 -0
- package/dist/foundation/lifecycle/session-claim-lock.d.ts +1 -1
- package/dist/foundation/lifecycle/session-claim-lock.js +2 -2
- package/dist/foundation/lifecycle/session-repository-context.d.ts +6 -6
- package/dist/foundation/lifecycle/session-repository-context.js +2 -3
- package/dist/foundation/release/automatic-update.d.ts +1 -3
- package/dist/foundation/release/automatic-update.js +9 -30
- package/dist/foundation/release/bootstrap.d.ts +2 -25
- package/dist/foundation/release/bootstrap.js +33 -344
- package/dist/foundation/release/cohort-state.d.ts +21 -46
- package/dist/foundation/release/cohort-state.js +30 -62
- package/dist/foundation/release/dependency-certification.d.ts +1 -1
- package/dist/foundation/release/index.d.ts +10 -17
- package/dist/foundation/release/index.js +7 -11
- package/dist/foundation/release/latest-release.d.ts +1 -2
- package/dist/foundation/release/latest-release.js +1 -2
- package/dist/foundation/release/process-liveness.d.ts +2 -0
- package/dist/foundation/release/process-liveness.js +12 -0
- package/dist/foundation/release/release-gc.d.ts +12 -9
- package/dist/foundation/release/release-gc.js +34 -98
- package/dist/foundation/release/release-store.d.ts +2 -2
- package/dist/foundation/release/release-store.js +2 -2
- package/dist/foundation/release/restart-certification.js +1 -1
- package/dist/foundation/release/update-activation.d.ts +2 -9
- package/dist/foundation/release/update-activation.js +28 -43
- package/dist/foundation/release/update-execution-lease.js +1 -1
- package/dist/foundation/release/update-launch.d.ts +0 -2
- package/dist/foundation/release/update-launch.js +0 -7
- package/dist/foundation/release/update-recovery.js +1 -1
- package/dist/foundation/release/update-transaction.d.ts +1 -1
- package/dist/foundation/release/update-transaction.js +5 -2
- package/dist/foundation/release/update.d.ts +2 -10
- package/dist/foundation/release/update.js +23 -200
- package/dist/foundation/session-writer-lock/index.d.ts +14 -6
- package/dist/foundation/session-writer-lock/index.js +48 -103
- package/dist/foundation/startup/startup-runtime.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/exit-notice.d.ts +6 -0
- package/dist/foundation/terminal-cleanup/exit-notice.js +36 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +2 -1
- package/dist/foundation/terminal-cleanup/index.js +2 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +0 -5
- package/dist/foundation/terminal-cleanup/terminal-reset.js +0 -5
- package/dist/integrations/pi/components/index.d.ts +1 -1
- package/dist/integrations/pi/components/index.js +1 -1
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -4
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +2 -2
- package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +2 -5
- package/dist/integrations/pi/components/shell-presenters-info.js +4 -18
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +1 -1
- package/dist/integrations/pi/components/shell-presenters-transcript.js +1 -1
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +0 -2
- package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +2 -5
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -16
- package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +1 -2
- package/dist/integrations/pi/components/upstream/components/session-footer.js +6 -8
- package/dist/integrations/pi/engine/adapter.d.ts +0 -1
- package/dist/integrations/pi/engine/adapter.js +1 -16
- package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -1
- package/dist/integrations/pi/engine/diagnostics-state.js +0 -14
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +0 -1
- package/dist/integrations/pi/engine/prompt-suggestions.js +0 -40
- package/dist/integrations/pi/engine/session-runtime.js +0 -2
- package/dist/integrations/pi/engine/workflow-runner.js +1 -1
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -2
- package/dist/integrations/pi/tui-runtime/adapter.js +2 -2
- package/dist/product-identity.d.ts +4 -6
- package/dist/product-identity.js +6 -11
- package/dist/product-identity.json +1 -40
- package/dist/runtime-payload-inventory.json +0 -3
- package/dist/ui/components/index.d.ts +2 -2
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/submitted-prompt.d.ts +3 -13
- package/dist/ui/components/submitted-prompt.js +8 -41
- package/dist/ui/components/transcript-viewport.d.ts +1 -3
- package/dist/ui/components/transcript-viewport.js +1 -4
- package/dist/ui/settings/declarations.d.ts +3 -97
- package/dist/ui/settings/declarations.js +3 -78
- package/dist/ui/settings/migrations.js +18 -2
- package/docs/architecture/boundaries.md +22 -39
- package/docs/architecture/code-documentation.md +2 -2
- package/docs/architecture/internal-naming.md +9 -17
- package/docs/architecture/project-structure.md +9 -14
- package/docs/architecture/resource-and-data-policy.md +16 -31
- package/docs/architecture/toolchain.md +14 -19
- package/docs/architecture/ui-reference-provenance.md +2 -2
- package/docs/ci-release-runbook.md +5 -5
- package/docs/features/launch-profiles.md +11 -17
- package/docs/features/prompt-history.md +10 -11
- package/docs/local-worktree-cleanup.md +28 -1
- package/docs/manual-owned-ui-checkpoint.md +0 -1
- package/docs/validation.md +5 -11
- package/docs/worktree-link-recovery.md +6 -6
- package/package.json +7 -19
- package/bin/guardian.js +0 -42
- package/bin/supervisor.js +0 -7
- package/bin/tab-launch-context.d.ts +0 -27
- package/bin/tab-launch-context.js +0 -94
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +0 -38
- package/dist/app/session-shell/resident-tab-coordinator.js +0 -77
- package/dist/cli/tabs-request.d.ts +0 -7
- package/dist/cli/tabs-request.js +0 -1
- package/dist/cli/tabs.d.ts +0 -14
- package/dist/cli/tabs.js +0 -151
- package/dist/composition/resident-tab-bridge.d.ts +0 -41
- package/dist/composition/resident-tab-bridge.js +0 -209
- package/dist/composition/utility-tab.d.ts +0 -28
- package/dist/composition/utility-tab.js +0 -244
- package/dist/features/owned-ui/plus-menu-dialog.d.ts +0 -28
- package/dist/features/owned-ui/plus-menu-dialog.js +0 -89
- package/dist/features/resident-tab/auto-name.d.ts +0 -11
- package/dist/features/resident-tab/auto-name.js +0 -44
- package/dist/features/resident-tab/index.d.ts +0 -5
- package/dist/features/resident-tab/index.js +0 -7
- package/dist/features/resident-tab/shortcut-bindings-file.d.ts +0 -8
- package/dist/features/resident-tab/shortcut-bindings-file.js +0 -40
- package/dist/features/resident-tab/shortcut-declarations.d.ts +0 -13
- package/dist/features/resident-tab/shortcut-declarations.js +0 -26
- package/dist/features/resident-tab/shortcut-projection.d.ts +0 -29
- package/dist/features/resident-tab/shortcut-projection.js +0 -64
- package/dist/features/resident-tab/status-deriver.d.ts +0 -10
- package/dist/features/resident-tab/status-deriver.js +0 -12
- package/dist/foundation/launch-guardian/exit-watcher.d.ts +0 -14
- package/dist/foundation/launch-guardian/exit-watcher.js +0 -103
- package/dist/foundation/launch-guardian/index.d.ts +0 -2
- package/dist/foundation/launch-guardian/index.js +0 -1
- package/dist/foundation/launch-guardian/main.d.ts +0 -39
- package/dist/foundation/launch-guardian/main.js +0 -232
- package/dist/foundation/lifecycle/commands.d.ts +0 -40
- package/dist/foundation/lifecycle/commands.js +0 -1
- package/dist/foundation/lifecycle/launch-instance.d.ts +0 -46
- package/dist/foundation/lifecycle/launch-instance.js +0 -134
- package/dist/foundation/lifecycle/native-claim-gate.d.ts +0 -5
- package/dist/foundation/lifecycle/native-claim-gate.js +0 -41
- package/dist/foundation/lifecycle/supervisor-startup.d.ts +0 -30
- package/dist/foundation/lifecycle/supervisor-startup.js +0 -106
- package/dist/foundation/process-containment/addon-containment.d.ts +0 -20
- package/dist/foundation/process-containment/addon-containment.js +0 -139
- package/dist/foundation/process-containment/addon-process-inspector.d.ts +0 -11
- package/dist/foundation/process-containment/addon-process-inspector.js +0 -36
- package/dist/foundation/process-containment/addon.d.ts +0 -47
- package/dist/foundation/process-containment/addon.js +0 -57
- package/dist/foundation/process-containment/artifact.d.ts +0 -1
- package/dist/foundation/process-containment/artifact.js +0 -35
- package/dist/foundation/process-containment/contracts.d.ts +0 -33
- package/dist/foundation/process-containment/contracts.js +0 -35
- package/dist/foundation/process-containment/index.d.ts +0 -9
- package/dist/foundation/process-containment/index.js +0 -7
- package/dist/foundation/process-containment/linux-process-inspector.d.ts +0 -7
- package/dist/foundation/process-containment/linux-process-inspector.js +0 -27
- package/dist/foundation/process-containment/native-process-inspector.d.ts +0 -4
- package/dist/foundation/process-containment/native-process-inspector.js +0 -21
- package/dist/foundation/protocol/client.d.ts +0 -18
- package/dist/foundation/protocol/client.js +0 -130
- package/dist/foundation/protocol/index.d.ts +0 -3
- package/dist/foundation/protocol/index.js +0 -2
- package/dist/foundation/protocol/messages.d.ts +0 -90
- package/dist/foundation/protocol/messages.js +0 -100
- package/dist/foundation/release/cohort-selection.d.ts +0 -33
- package/dist/foundation/release/cohort-selection.js +0 -67
- package/dist/foundation/release/endpoint-lock.d.ts +0 -2
- package/dist/foundation/release/endpoint-lock.js +0 -37
- package/dist/foundation/release/endpoint-recovery.d.ts +0 -10
- package/dist/foundation/release/endpoint-recovery.js +0 -45
- package/dist/foundation/release/endpoints.d.ts +0 -32
- package/dist/foundation/release/endpoints.js +0 -152
- package/dist/foundation/release/prepared-update-activation.d.ts +0 -3
- package/dist/foundation/release/prepared-update-activation.js +0 -27
- package/dist/foundation/release/process-cleanup.d.ts +0 -14
- package/dist/foundation/release/process-cleanup.js +0 -76
- package/dist/foundation/release/supervisor-identity.d.ts +0 -15
- package/dist/foundation/release/supervisor-identity.js +0 -63
- package/dist/foundation/resident-tabs/boot-identity.d.ts +0 -6
- package/dist/foundation/resident-tabs/boot-identity.js +0 -16
- package/dist/foundation/resident-tabs/bounded-host-command.d.ts +0 -20
- package/dist/foundation/resident-tabs/bounded-host-command.js +0 -62
- package/dist/foundation/resident-tabs/bridge-client.d.ts +0 -73
- package/dist/foundation/resident-tabs/bridge-client.js +0 -327
- package/dist/foundation/resident-tabs/continuity.d.ts +0 -12
- package/dist/foundation/resident-tabs/continuity.js +0 -63
- package/dist/foundation/resident-tabs/doctor.d.ts +0 -28
- package/dist/foundation/resident-tabs/doctor.js +0 -166
- package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +0 -27
- package/dist/foundation/resident-tabs/draft-checkpoint.js +0 -145
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +0 -36
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +0 -151
- package/dist/foundation/resident-tabs/fault-injection.d.ts +0 -8
- package/dist/foundation/resident-tabs/fault-injection.js +0 -26
- package/dist/foundation/resident-tabs/fixture-control.d.ts +0 -7
- package/dist/foundation/resident-tabs/fixture-control.js +0 -35
- package/dist/foundation/resident-tabs/host-entry.d.ts +0 -1
- package/dist/foundation/resident-tabs/host-entry.js +0 -17
- package/dist/foundation/resident-tabs/index.d.ts +0 -15
- package/dist/foundation/resident-tabs/index.js +0 -10
- package/dist/foundation/resident-tabs/maintenance.d.ts +0 -39
- package/dist/foundation/resident-tabs/maintenance.js +0 -75
- package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +0 -34
- package/dist/foundation/resident-tabs/progress-observation-schema.js +0 -1
- package/dist/foundation/resident-tabs/progress-observation.d.ts +0 -4
- package/dist/foundation/resident-tabs/progress-observation.js +0 -150
- package/dist/foundation/resident-tabs/prompt-journal.d.ts +0 -63
- package/dist/foundation/resident-tabs/prompt-journal.js +0 -213
- package/dist/foundation/resident-tabs/protocol.d.ts +0 -12
- package/dist/foundation/resident-tabs/protocol.js +0 -195
- package/dist/foundation/resident-tabs/recovery.d.ts +0 -26
- package/dist/foundation/resident-tabs/recovery.js +0 -205
- package/dist/foundation/resident-tabs/release-holds.d.ts +0 -28
- package/dist/foundation/resident-tabs/release-holds.js +0 -78
- package/dist/foundation/resident-tabs/routes.d.ts +0 -5
- package/dist/foundation/resident-tabs/routes.js +0 -5
- package/dist/foundation/resident-tabs/routing.d.ts +0 -11
- package/dist/foundation/resident-tabs/routing.js +0 -10
- package/dist/foundation/resident-tabs/runtime-control.d.ts +0 -38
- package/dist/foundation/resident-tabs/runtime-control.js +0 -74
- package/dist/foundation/resident-tabs/session-sync.d.ts +0 -14
- package/dist/foundation/resident-tabs/session-sync.js +0 -37
- package/dist/foundation/resident-tabs/settings.d.ts +0 -16
- package/dist/foundation/resident-tabs/settings.js +0 -60
- package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +0 -14
- package/dist/foundation/resident-tabs/terminal-host-artifact.js +0 -78
- package/dist/foundation/resident-tabs/zip-archive.d.ts +0 -9
- package/dist/foundation/resident-tabs/zip-archive.js +0 -56
- package/dist/foundation/storage/control-store.d.ts +0 -20
- package/dist/foundation/storage/control-store.js +0 -331
- package/dist/foundation/storage/index.d.ts +0 -1
- package/dist/foundation/storage/index.js +0 -1
- package/dist/foundation/supervision/index.d.ts +0 -3
- package/dist/foundation/supervision/index.js +0 -3
- package/dist/foundation/supervision/main.d.ts +0 -1
- package/dist/foundation/supervision/main.js +0 -86
- package/dist/foundation/supervision/paths.d.ts +0 -1
- package/dist/foundation/supervision/paths.js +0 -1
- package/dist/foundation/supervision/server.d.ts +0 -46
- package/dist/foundation/supervision/server.js +0 -611
- package/dist/integrations/pi/engine/offline-settings-port.d.ts +0 -23
- package/dist/integrations/pi/engine/offline-settings-port.js +0 -54
- package/dist/native/darwin-arm64/manifest.json +0 -23
- package/dist/native/darwin-arm64/process-guardian.node +0 -0
- package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10500
- package/dist/native/darwin-arm64/terminal-host.manifest.json +0 -46
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +0 -23
- package/dist/native/darwin-x64/process-guardian.node +0 -0
- package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10737
- package/dist/native/darwin-x64/terminal-host.manifest.json +0 -46
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +0 -23
- package/dist/native/linux-x64/process-guardian.node +0 -0
- package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -11226
- package/dist/native/linux-x64/terminal-host.manifest.json +0 -46
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +0 -23
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +0 -10757
- package/dist/native/win32-x64/terminal-host.manifest.json +0 -46
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/docs/architecture/evidence/resident-tabs/linux-x64.md +0 -37
- package/docs/architecture/evidence/resident-tabs/macos-arm64.md +0 -36
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +0 -35
- package/docs/architecture/evidence/resident-tabs/windows-x64.md +0 -36
- package/docs/architecture/evidence/terminal-host-spike/manual-one-pane-terminal-host.md +0 -70
- package/docs/architecture/evidence/terminal-host-spike/manual-two-by-two-basic-terminal-host.md +0 -32
- package/docs/architecture/evidence/terminal-host-spike/milestone-baseline.json +0 -115
- package/docs/architecture/evidence/terminal-host-spike/owned-ui-foundation-prerequisite.json +0 -48
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-provenance.json +0 -125
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-1.json +0 -56
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-3.json +0 -174
- package/docs/architecture/evidence/terminal-host-spike/terminal-spike-acceptance-record.json +0 -18
- package/docs/architecture/native-fixture-isolation.md +0 -23
- package/docs/architecture/process-guardian-provenance.md +0 -36
- package/docs/architecture/resident-tabs-requirements.md +0 -18
- package/docs/architecture/resident-tabs.md +0 -668
- package/docs/architecture/terminal-host-proof-gate.md +0 -34
- package/docs/architecture/terminal-host-provenance.md +0 -81
- package/docs/architecture/terminal-host-spike-evidence.md +0 -39
- package/docs/launch-recovery.md +0 -23
- package/docs/manual-launch-instance-acceptance.md +0 -43
- package/docs/manual-resident-tabs-acceptance.md +0 -51
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { resolve } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
6
|
-
let backend;
|
|
7
|
-
/** No PID-file fallback: only the platform descriptor can prove upgraded-writer exclusion. */
|
|
8
|
-
export function tryAcquireClaimGate(path) {
|
|
9
|
-
if (backend === undefined) {
|
|
10
|
-
const require = createRequire(import.meta.url);
|
|
11
|
-
// Security: resolve only this release's addon, never a binary supplied by tool cwd.
|
|
12
|
-
const own = resolve(fileURLToPath(new URL("../../../", import.meta.url)), "dist", "native", `${process.platform}-${process.arch}`, `${PRODUCT_IDENTITY.artifacts.terminalHostAddon}.node`);
|
|
13
|
-
const override = process.env[PRODUCT_IDENTITY.environment.developmentInstanceId]
|
|
14
|
-
? process.env[PRODUCT_IDENTITY.environment.terminalHostPath] : undefined;
|
|
15
|
-
for (const candidate of override ? [override, own] : [own]) {
|
|
16
|
-
if (!existsSync(candidate))
|
|
17
|
-
continue;
|
|
18
|
-
try {
|
|
19
|
-
const loaded = require(candidate);
|
|
20
|
-
if (typeof loaded.SessionLock?.tryAcquireGate === "function") {
|
|
21
|
-
backend = loaded.SessionLock;
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
catch { /* Compatibility: an unusable addon is unavailable, not contended. */ }
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (backend === undefined)
|
|
29
|
-
throw Object.assign(new Error("native worktree coordination is unavailable; repair or update this A1 installation and retry"), {
|
|
30
|
-
code: "worktree-coordination-unavailable",
|
|
31
|
-
});
|
|
32
|
-
try {
|
|
33
|
-
const handle = backend.tryAcquireGate(path);
|
|
34
|
-
return handle.acquired ? handle : null;
|
|
35
|
-
}
|
|
36
|
-
catch (cause) {
|
|
37
|
-
throw Object.assign(new Error("cannot access the worktree mutation gate; check A1 data-directory permissions and filesystem availability", { cause }), {
|
|
38
|
-
code: "worktree-coordination-io",
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
declare const STARTUP_SCHEMA = "a1-supervisor-startup-v1";
|
|
2
|
-
export interface SupervisorStartupAttemptIdentity {
|
|
3
|
-
readonly attemptId: string;
|
|
4
|
-
readonly releaseId: string;
|
|
5
|
-
readonly resultPath: string;
|
|
6
|
-
}
|
|
7
|
-
export type SupervisorStartupResult = {
|
|
8
|
-
readonly schema: typeof STARTUP_SCHEMA;
|
|
9
|
-
readonly attemptId: string;
|
|
10
|
-
readonly releaseId: string;
|
|
11
|
-
readonly outcome: "ready";
|
|
12
|
-
readonly pid: number;
|
|
13
|
-
} | {
|
|
14
|
-
readonly schema: typeof STARTUP_SCHEMA;
|
|
15
|
-
readonly attemptId: string;
|
|
16
|
-
readonly releaseId: string;
|
|
17
|
-
readonly outcome: "failure";
|
|
18
|
-
readonly stage: string;
|
|
19
|
-
readonly code: string | null;
|
|
20
|
-
readonly message: string;
|
|
21
|
-
};
|
|
22
|
-
/** Create one unguessable startup result authority under the protected runtime root. */
|
|
23
|
-
export declare function createSupervisorStartupAttempt(runtimeDir: string, releaseId: string): Promise<SupervisorStartupAttemptIdentity>;
|
|
24
|
-
export declare function supervisorStartupResultPath(runtimeDir: string, attemptId: string): string;
|
|
25
|
-
/** Atomically publish the bounded result for one detached supervisor startup attempt. */
|
|
26
|
-
export declare function publishSupervisorStartupResult(path: string, result: SupervisorStartupResult): Promise<void>;
|
|
27
|
-
export declare function readSupervisorStartupResult(path: string, attemptId: string, releaseId: string): Promise<SupervisorStartupResult | null>;
|
|
28
|
-
export declare function supervisorStartupFailure(error: unknown, attemptId: string, releaseId: string, stage: string): SupervisorStartupResult;
|
|
29
|
-
export declare function supervisorStartupReady(attemptId: string, releaseId: string): SupervisorStartupResult;
|
|
30
|
-
export {};
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import { resolve } from "node:path";
|
|
4
|
-
const STARTUP_SCHEMA = "a1-supervisor-startup-v1";
|
|
5
|
-
const MAX_RESULT_BYTES = 8 * 1024;
|
|
6
|
-
const MAX_MESSAGE_LENGTH = 1_024;
|
|
7
|
-
const MAX_RETAINED_RESULTS = 16;
|
|
8
|
-
const MAX_RESULT_AGE_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
9
|
-
const ATTEMPT_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/;
|
|
10
|
-
/** Create one unguessable startup result authority under the protected runtime root. */
|
|
11
|
-
export async function createSupervisorStartupAttempt(runtimeDir, releaseId) {
|
|
12
|
-
const attemptId = randomUUID();
|
|
13
|
-
const directory = resolve(runtimeDir, "supervisor-startup");
|
|
14
|
-
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
15
|
-
await pruneSupervisorStartupResults(directory);
|
|
16
|
-
return { attemptId, releaseId, resultPath: supervisorStartupResultPath(runtimeDir, attemptId) };
|
|
17
|
-
}
|
|
18
|
-
export function supervisorStartupResultPath(runtimeDir, attemptId) {
|
|
19
|
-
if (!ATTEMPT_PATTERN.test(attemptId))
|
|
20
|
-
throw new TypeError("supervisor startup attempt identity is invalid");
|
|
21
|
-
return resolve(runtimeDir, "supervisor-startup", `${attemptId}.json`);
|
|
22
|
-
}
|
|
23
|
-
/** Atomically publish the bounded result for one detached supervisor startup attempt. */
|
|
24
|
-
export async function publishSupervisorStartupResult(path, result) {
|
|
25
|
-
validateSupervisorStartupResult(result, result.attemptId, result.releaseId);
|
|
26
|
-
const body = `${JSON.stringify(result)}\n`;
|
|
27
|
-
if (Buffer.byteLength(body) > MAX_RESULT_BYTES)
|
|
28
|
-
throw new Error("supervisor startup result exceeds its size bound");
|
|
29
|
-
const temporary = `${path}.${process.pid}.tmp`;
|
|
30
|
-
await writeFile(temporary, body, { encoding: "utf8", mode: 0o600 });
|
|
31
|
-
await rename(temporary, path);
|
|
32
|
-
}
|
|
33
|
-
export async function readSupervisorStartupResult(path, attemptId, releaseId) {
|
|
34
|
-
let metadata;
|
|
35
|
-
try {
|
|
36
|
-
metadata = await stat(path);
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
if (isNodeError(error, "ENOENT"))
|
|
40
|
-
return null;
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
if (!metadata.isFile() || metadata.size > MAX_RESULT_BYTES)
|
|
44
|
-
throw new Error("supervisor startup result is invalid or oversized");
|
|
45
|
-
const value = JSON.parse(await readFile(path, "utf8"));
|
|
46
|
-
return validateSupervisorStartupResult(value, attemptId, releaseId);
|
|
47
|
-
}
|
|
48
|
-
export function supervisorStartupFailure(error, attemptId, releaseId, stage) {
|
|
49
|
-
const source = error instanceof Error ? error : new Error(String(error));
|
|
50
|
-
return {
|
|
51
|
-
schema: STARTUP_SCHEMA,
|
|
52
|
-
attemptId,
|
|
53
|
-
releaseId,
|
|
54
|
-
outcome: "failure",
|
|
55
|
-
stage: boundedToken(stage, "unknown"),
|
|
56
|
-
code: "code" in source && typeof source.code === "string" ? boundedToken(source.code, "UNKNOWN") : null,
|
|
57
|
-
message: sanitizeMessage(source.message),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
export function supervisorStartupReady(attemptId, releaseId) {
|
|
61
|
-
return { schema: STARTUP_SCHEMA, attemptId, releaseId, outcome: "ready", pid: process.pid };
|
|
62
|
-
}
|
|
63
|
-
async function pruneSupervisorStartupResults(directory) {
|
|
64
|
-
const now = Date.now();
|
|
65
|
-
const entries = await readdir(directory, { withFileTypes: true });
|
|
66
|
-
const files = (await Promise.all(entries.filter(entry => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => {
|
|
67
|
-
const path = resolve(directory, entry.name);
|
|
68
|
-
const metadata = await stat(path).catch(() => null);
|
|
69
|
-
return metadata ? { path, modified: metadata.mtimeMs } : null;
|
|
70
|
-
}))).filter((file) => file !== null);
|
|
71
|
-
files.sort((left, right) => right.modified - left.modified);
|
|
72
|
-
await Promise.all(files.flatMap((file, index) => index >= MAX_RETAINED_RESULTS - 1 || now - file.modified > MAX_RESULT_AGE_MS
|
|
73
|
-
? [rm(file.path, { force: true })]
|
|
74
|
-
: []));
|
|
75
|
-
}
|
|
76
|
-
function validateSupervisorStartupResult(value, attemptId, releaseId) {
|
|
77
|
-
if (!value || typeof value !== "object")
|
|
78
|
-
throw new Error("supervisor startup result is malformed");
|
|
79
|
-
const result = value;
|
|
80
|
-
if (result.schema !== STARTUP_SCHEMA || result.attemptId !== attemptId || result.releaseId !== releaseId) {
|
|
81
|
-
throw new Error("supervisor startup result does not match the selected attempt and release");
|
|
82
|
-
}
|
|
83
|
-
if (result.outcome === "ready" && Number.isSafeInteger(result.pid) && Number(result.pid) > 0)
|
|
84
|
-
return result;
|
|
85
|
-
if (result.outcome === "failure" && typeof result.stage === "string" && result.stage.length > 0 && result.stage.length <= 128
|
|
86
|
-
&& (result.code === null || typeof result.code === "string") && typeof result.message === "string" && result.message.length <= MAX_MESSAGE_LENGTH) {
|
|
87
|
-
return result;
|
|
88
|
-
}
|
|
89
|
-
throw new Error("supervisor startup result is malformed");
|
|
90
|
-
}
|
|
91
|
-
function sanitizeMessage(message) {
|
|
92
|
-
let value = message.replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/:\/\/[^\s/@:]+:[^\s/@]+@/g, "://<redacted>@");
|
|
93
|
-
for (const [name, secret] of Object.entries(process.env)) {
|
|
94
|
-
if (!secret || secret.length < 4 || !/(?:TOKEN|SECRET|PASSWORD|COOKIE|CREDENTIAL|AUTH)/i.test(name))
|
|
95
|
-
continue;
|
|
96
|
-
value = value.split(secret).join("<redacted>");
|
|
97
|
-
}
|
|
98
|
-
return value.trim().slice(0, MAX_MESSAGE_LENGTH) || "supervisor startup failed";
|
|
99
|
-
}
|
|
100
|
-
function boundedToken(value, fallback) {
|
|
101
|
-
const normalized = value.replace(/[^A-Za-z0-9_.:-]/g, "-").slice(0, 128);
|
|
102
|
-
return normalized || fallback;
|
|
103
|
-
}
|
|
104
|
-
function isNodeError(error, code) {
|
|
105
|
-
return error instanceof Error && "code" in error && error.code === code;
|
|
106
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { NativeProcessIdentity, ProcessContainmentIdentity } from "../lifecycle/index.js";
|
|
2
|
-
import { type ProcessGuardianAddon } from "./addon.js";
|
|
3
|
-
import type { ContainedProcessHandle, ContainedSpawnOptions, ProcessContainment } from "./contracts.js";
|
|
4
|
-
/** Owns one native containment object in the launch guardian's Node process. */
|
|
5
|
-
export declare class AddonContainment implements ProcessContainment {
|
|
6
|
-
#private;
|
|
7
|
-
readonly instanceId: string;
|
|
8
|
-
readonly addonPath: string;
|
|
9
|
-
readonly exitNoticePath: string | null;
|
|
10
|
-
readonly addon: ProcessGuardianAddon;
|
|
11
|
-
private readonly platform;
|
|
12
|
-
constructor(instanceId: string, addonPath: string, exitNoticePath?: string | null, addon?: ProcessGuardianAddon, platform?: NodeJS.Platform);
|
|
13
|
-
get identity(): ProcessContainmentIdentity;
|
|
14
|
-
spawn(executable: string, arguments_: readonly string[], options: ContainedSpawnOptions): Promise<ContainedProcessHandle>;
|
|
15
|
-
contains(identity: NativeProcessIdentity): Promise<boolean>;
|
|
16
|
-
stop(force: boolean): Promise<void>;
|
|
17
|
-
waitForEmpty(timeoutMs: number): Promise<boolean>;
|
|
18
|
-
close(): Promise<void>;
|
|
19
|
-
}
|
|
20
|
-
export declare function resolveProcessGuardianPath(releaseRoot: string, environment?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, architecture?: string): string;
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { constants } from "node:os";
|
|
2
|
-
import { mkdir, rm } from "node:fs/promises";
|
|
3
|
-
import { dirname, resolve } from "node:path";
|
|
4
|
-
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
|
-
import { loadProcessGuardianAddon } from "./addon.js";
|
|
6
|
-
/** Owns one native containment object in the launch guardian's Node process. */
|
|
7
|
-
export class AddonContainment {
|
|
8
|
-
#identity;
|
|
9
|
-
#rootIdentity = null;
|
|
10
|
-
#runtime = null;
|
|
11
|
-
#outcome = null;
|
|
12
|
-
#settled = false;
|
|
13
|
-
instanceId;
|
|
14
|
-
addonPath;
|
|
15
|
-
exitNoticePath;
|
|
16
|
-
addon;
|
|
17
|
-
platform;
|
|
18
|
-
constructor(instanceId, addonPath, exitNoticePath = null, addon = loadProcessGuardianAddon(addonPath), platform = process.platform) {
|
|
19
|
-
this.instanceId = instanceId;
|
|
20
|
-
this.addonPath = addonPath;
|
|
21
|
-
this.exitNoticePath = exitNoticePath;
|
|
22
|
-
this.addon = addon;
|
|
23
|
-
this.platform = platform;
|
|
24
|
-
this.#identity = { provider: "native-addon-pending", token: instanceId };
|
|
25
|
-
}
|
|
26
|
-
get identity() {
|
|
27
|
-
return this.#identity;
|
|
28
|
-
}
|
|
29
|
-
async spawn(executable, arguments_, options) {
|
|
30
|
-
if (this.#runtime)
|
|
31
|
-
throw new Error("process containment already has a root runtime");
|
|
32
|
-
if (this.exitNoticePath) {
|
|
33
|
-
await mkdir(dirname(this.exitNoticePath), { recursive: true, mode: 0o700 });
|
|
34
|
-
await rm(this.exitNoticePath, { force: true });
|
|
35
|
-
}
|
|
36
|
-
const runtime = this.addon.spawnContained({
|
|
37
|
-
executable,
|
|
38
|
-
arguments: [...arguments_],
|
|
39
|
-
cwd: options.cwd,
|
|
40
|
-
environment: {
|
|
41
|
-
...options.environment,
|
|
42
|
-
...(options.terminalType ? { TERM: options.terminalType } : {}),
|
|
43
|
-
...(this.exitNoticePath ? { [PRODUCT_IDENTITY.environment.exitNoticePath]: this.exitNoticePath } : {}),
|
|
44
|
-
},
|
|
45
|
-
instanceId: this.instanceId,
|
|
46
|
-
});
|
|
47
|
-
assertRuntime(runtime);
|
|
48
|
-
this.#runtime = runtime;
|
|
49
|
-
this.#rootIdentity = { pid: runtime.pid, startIdentity: runtime.startIdentity };
|
|
50
|
-
this.#identity = { provider: runtime.containmentProvider, token: runtime.containmentToken };
|
|
51
|
-
const outcome = runtime.wait().then(exitCode => outcomeFromExitCode(exitCode, this.platform), error => ({
|
|
52
|
-
kind: "guardian-error",
|
|
53
|
-
message: errorMessage(error),
|
|
54
|
-
code: errorCode(error),
|
|
55
|
-
})).finally(() => { this.#settled = true; });
|
|
56
|
-
this.#outcome = outcome;
|
|
57
|
-
return {
|
|
58
|
-
identity: this.#rootIdentity,
|
|
59
|
-
outcome,
|
|
60
|
-
...(runtime.processGroup === null ? {} : { processGroup: runtime.processGroup }),
|
|
61
|
-
...(runtime.foregroundGroup === null ? {} : { foregroundGroup: runtime.foregroundGroup }),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
async contains(identity) {
|
|
65
|
-
return this.#rootIdentity !== null
|
|
66
|
-
&& identity.pid === this.#rootIdentity.pid
|
|
67
|
-
&& identity.startIdentity === this.#rootIdentity.startIdentity;
|
|
68
|
-
}
|
|
69
|
-
async stop(force) {
|
|
70
|
-
const runtime = this.#runtime;
|
|
71
|
-
if (!runtime || this.#settled)
|
|
72
|
-
return;
|
|
73
|
-
try {
|
|
74
|
-
if (force)
|
|
75
|
-
runtime.terminate(137);
|
|
76
|
-
else if (this.platform === "win32")
|
|
77
|
-
process.kill(runtime.pid, "SIGTERM");
|
|
78
|
-
else
|
|
79
|
-
runtime.stop();
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
if (errorCode(error) !== "ESRCH")
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async waitForEmpty(timeoutMs) {
|
|
87
|
-
if (this.#settled || !this.#outcome)
|
|
88
|
-
return true;
|
|
89
|
-
return await Promise.race([
|
|
90
|
-
this.#outcome.then(() => true),
|
|
91
|
-
new Promise(resolvePromise => {
|
|
92
|
-
const timer = setTimeout(() => resolvePromise(false), timeoutMs);
|
|
93
|
-
timer.unref();
|
|
94
|
-
}),
|
|
95
|
-
]);
|
|
96
|
-
}
|
|
97
|
-
async close() {
|
|
98
|
-
const runtime = this.#runtime;
|
|
99
|
-
if (!runtime)
|
|
100
|
-
return;
|
|
101
|
-
runtime.close();
|
|
102
|
-
await this.waitForEmpty(1_500);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
export function resolveProcessGuardianPath(releaseRoot, environment = process.env, platform = process.platform, architecture = process.arch) {
|
|
106
|
-
const override = environment[PRODUCT_IDENTITY.environment.processGuardianPath]?.trim();
|
|
107
|
-
if (override)
|
|
108
|
-
return resolve(override);
|
|
109
|
-
return resolve(releaseRoot, "dist", "native", `${platform}-${architecture}`, `${PRODUCT_IDENTITY.artifacts.processGuardianAddon}.node`);
|
|
110
|
-
}
|
|
111
|
-
function assertRuntime(runtime) {
|
|
112
|
-
if (!Number.isSafeInteger(runtime.pid) || runtime.pid <= 0
|
|
113
|
-
|| typeof runtime.startIdentity !== "string" || runtime.startIdentity.length === 0
|
|
114
|
-
|| typeof runtime.containmentProvider !== "string" || runtime.containmentProvider.length === 0
|
|
115
|
-
|| typeof runtime.containmentToken !== "string" || runtime.containmentToken.length === 0
|
|
116
|
-
|| (runtime.processGroup !== null && (!Number.isSafeInteger(runtime.processGroup) || runtime.processGroup <= 0))
|
|
117
|
-
|| (runtime.foregroundGroup !== null && (!Number.isSafeInteger(runtime.foregroundGroup) || runtime.foregroundGroup <= 0))) {
|
|
118
|
-
runtime.close();
|
|
119
|
-
throw Object.assign(new Error("process guardian addon returned invalid containment identity"), { code: "CONTAINMENT_ARTIFACT_INCOMPATIBLE" });
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function outcomeFromExitCode(exitCode, platform) {
|
|
123
|
-
if (!Number.isSafeInteger(exitCode) || exitCode < 0 || exitCode > 255) {
|
|
124
|
-
return { kind: "guardian-error", message: "process guardian addon returned an invalid exit code", code: "CONTAINMENT_OUTCOME_INVALID" };
|
|
125
|
-
}
|
|
126
|
-
if (platform !== "win32" && exitCode >= 128) {
|
|
127
|
-
const signalNumber = exitCode - 128;
|
|
128
|
-
const signal = Object.entries(constants.signals).find(([, value]) => value === signalNumber)?.[0];
|
|
129
|
-
if (signal)
|
|
130
|
-
return { kind: "signaled", signal };
|
|
131
|
-
}
|
|
132
|
-
return { kind: "exited", exitCode };
|
|
133
|
-
}
|
|
134
|
-
function errorCode(error) {
|
|
135
|
-
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : null;
|
|
136
|
-
}
|
|
137
|
-
function errorMessage(error) {
|
|
138
|
-
return error instanceof Error ? error.message : String(error);
|
|
139
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { NativeProcessIdentity } from "../lifecycle/index.js";
|
|
2
|
-
import type { ProcessGuardianAddon } from "./addon.js";
|
|
3
|
-
import type { NativeProcessInspector } from "./contracts.js";
|
|
4
|
-
/** Verifies native process identity through the process-guardian addon's bounded inspection call. */
|
|
5
|
-
export declare class AddonProcessInspector implements NativeProcessInspector {
|
|
6
|
-
readonly addon: Pick<ProcessGuardianAddon, "inspectProcessStart">;
|
|
7
|
-
readonly identityPrefix: string;
|
|
8
|
-
constructor(addon: Pick<ProcessGuardianAddon, "inspectProcessStart">, identityPrefix: string);
|
|
9
|
-
observe(pid: number): Promise<NativeProcessIdentity | null>;
|
|
10
|
-
matches(identity: NativeProcessIdentity): Promise<boolean>;
|
|
11
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/** Verifies native process identity through the process-guardian addon's bounded inspection call. */
|
|
2
|
-
export class AddonProcessInspector {
|
|
3
|
-
addon;
|
|
4
|
-
identityPrefix;
|
|
5
|
-
constructor(addon, identityPrefix) {
|
|
6
|
-
if (!identityPrefix || identityPrefix.includes("\0"))
|
|
7
|
-
throw new TypeError("process identity prefix is invalid");
|
|
8
|
-
this.addon = addon;
|
|
9
|
-
this.identityPrefix = identityPrefix;
|
|
10
|
-
}
|
|
11
|
-
async observe(pid) {
|
|
12
|
-
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
13
|
-
throw new TypeError("inspected PID must be a positive safe integer");
|
|
14
|
-
let startIdentity;
|
|
15
|
-
try {
|
|
16
|
-
startIdentity = this.addon.inspectProcessStart(pid);
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
throw Object.assign(new Error(`cannot inspect native process identity: ${errorMessage(error)}`), { code: "PROCESS_INSPECTION_FAILED" });
|
|
20
|
-
}
|
|
21
|
-
if (startIdentity === null)
|
|
22
|
-
return null;
|
|
23
|
-
if (typeof startIdentity !== "string" || startIdentity.length === 0 || startIdentity.length > 512
|
|
24
|
-
|| startIdentity.includes("\0") || !startIdentity.startsWith(this.identityPrefix)) {
|
|
25
|
-
throw Object.assign(new Error("process guardian returned mismatched identity data"), { code: "PROCESS_INSPECTION_INVALID" });
|
|
26
|
-
}
|
|
27
|
-
return { pid, startIdentity };
|
|
28
|
-
}
|
|
29
|
-
async matches(identity) {
|
|
30
|
-
const observed = await this.observe(identity.pid);
|
|
31
|
-
return observed !== null && observed.startIdentity === identity.startIdentity;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function errorMessage(error) {
|
|
35
|
-
return error instanceof Error ? error.message : String(error);
|
|
36
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export interface ProcessGuardianVersion {
|
|
2
|
-
readonly crateVersion: string;
|
|
3
|
-
readonly protocolVersion: 2;
|
|
4
|
-
readonly target: string;
|
|
5
|
-
}
|
|
6
|
-
export interface ProcessGuardianRuntime {
|
|
7
|
-
readonly pid: number;
|
|
8
|
-
readonly startIdentity: string;
|
|
9
|
-
readonly containmentProvider: string;
|
|
10
|
-
readonly containmentToken: string;
|
|
11
|
-
readonly processGroup: number | null;
|
|
12
|
-
readonly foregroundGroup: number | null;
|
|
13
|
-
wait(): Promise<number>;
|
|
14
|
-
terminate(code: number): void;
|
|
15
|
-
stop(): void;
|
|
16
|
-
close(): void;
|
|
17
|
-
}
|
|
18
|
-
export interface SpawnContainedOptions {
|
|
19
|
-
readonly executable: string;
|
|
20
|
-
readonly arguments: readonly string[];
|
|
21
|
-
readonly cwd: string;
|
|
22
|
-
readonly environment: Readonly<Record<string, string>>;
|
|
23
|
-
readonly instanceId: string;
|
|
24
|
-
}
|
|
25
|
-
export interface ProcessGuardianAddon {
|
|
26
|
-
version(): ProcessGuardianVersion;
|
|
27
|
-
inspectProcessStart(pid: number): string | null;
|
|
28
|
-
/** Additive capability; older retained addons remain usable for containment, not recovery gates. */
|
|
29
|
-
tryAcquireProcessGate?(path: string): {
|
|
30
|
-
readonly acquired: boolean;
|
|
31
|
-
release(): void;
|
|
32
|
-
};
|
|
33
|
-
captureTerminalModes(): string;
|
|
34
|
-
restoreTerminalModes(encoded: string): void;
|
|
35
|
-
deliverExitNotice(path: string, encodedModes: string): void;
|
|
36
|
-
spawnContained(options: SpawnContainedOptions): ProcessGuardianRuntime;
|
|
37
|
-
spawnWatcher(options: {
|
|
38
|
-
readonly executable: string;
|
|
39
|
-
readonly arguments: readonly string[];
|
|
40
|
-
}): number;
|
|
41
|
-
waitForProcessExit(pid: number): Promise<void>;
|
|
42
|
-
stopProcessGroup(processGroup: number): void;
|
|
43
|
-
restoreForegroundGroup(processGroup: number): void;
|
|
44
|
-
ignoreConsoleControl(): void;
|
|
45
|
-
}
|
|
46
|
-
/** Loads one verified Node-API guardian instance per exact addon path. */
|
|
47
|
-
export declare function loadProcessGuardianAddon(path: string): ProcessGuardianAddon;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
const require = createRequire(import.meta.url);
|
|
4
|
-
const cache = new Map();
|
|
5
|
-
/** Loads one verified Node-API guardian instance per exact addon path. */
|
|
6
|
-
export function loadProcessGuardianAddon(path) {
|
|
7
|
-
if (!path || path.includes("\0"))
|
|
8
|
-
throw new TypeError("process guardian addon path is invalid");
|
|
9
|
-
const exactPath = resolve(path);
|
|
10
|
-
const cached = cache.get(exactPath);
|
|
11
|
-
if (cached)
|
|
12
|
-
return cached;
|
|
13
|
-
let value;
|
|
14
|
-
try {
|
|
15
|
-
value = require(exactPath);
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
const code = errorCode(error) === "MODULE_NOT_FOUND" || errorCode(error) === "ENOENT"
|
|
19
|
-
? "CONTAINMENT_ARTIFACT_MISSING"
|
|
20
|
-
: "CONTAINMENT_ARTIFACT_INCOMPATIBLE";
|
|
21
|
-
throw diagnosticError(`process guardian addon could not be loaded: ${errorMessage(error)}`, code);
|
|
22
|
-
}
|
|
23
|
-
if (!isProcessGuardianAddon(value)) {
|
|
24
|
-
throw diagnosticError("process guardian addon exports are incompatible", "CONTAINMENT_ARTIFACT_INCOMPATIBLE");
|
|
25
|
-
}
|
|
26
|
-
let report;
|
|
27
|
-
try {
|
|
28
|
-
report = value.version();
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
throw diagnosticError(`process guardian addon identity failed: ${errorMessage(error)}`, "CONTAINMENT_ARTIFACT_INCOMPATIBLE");
|
|
32
|
-
}
|
|
33
|
-
if (report.protocolVersion !== 2 || typeof report.crateVersion !== "string" || report.crateVersion.length === 0 || typeof report.target !== "string") {
|
|
34
|
-
throw diagnosticError("process guardian addon protocol is incompatible", "CONTAINMENT_ARTIFACT_INCOMPATIBLE");
|
|
35
|
-
}
|
|
36
|
-
cache.set(exactPath, value);
|
|
37
|
-
return value;
|
|
38
|
-
}
|
|
39
|
-
function isProcessGuardianAddon(value) {
|
|
40
|
-
if (typeof value !== "object" || value === null)
|
|
41
|
-
return false;
|
|
42
|
-
const candidate = value;
|
|
43
|
-
return [
|
|
44
|
-
"version", "inspectProcessStart", "captureTerminalModes", "restoreTerminalModes",
|
|
45
|
-
"deliverExitNotice", "spawnContained", "spawnWatcher", "waitForProcessExit",
|
|
46
|
-
"stopProcessGroup", "restoreForegroundGroup", "ignoreConsoleControl",
|
|
47
|
-
].every(name => typeof candidate[name] === "function");
|
|
48
|
-
}
|
|
49
|
-
function diagnosticError(message, code) {
|
|
50
|
-
return Object.assign(new Error(message), { code });
|
|
51
|
-
}
|
|
52
|
-
function errorCode(error) {
|
|
53
|
-
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : null;
|
|
54
|
-
}
|
|
55
|
-
function errorMessage(error) {
|
|
56
|
-
return error instanceof Error ? error.message : String(error);
|
|
57
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function verifyProcessGuardianArtifact(addonPath: string, platform?: NodeJS.Platform, architecture?: string): Promise<void>;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { readFile, stat } from "node:fs/promises";
|
|
3
|
-
import { basename, dirname, resolve } from "node:path";
|
|
4
|
-
export async function verifyProcessGuardianArtifact(addonPath, platform = process.platform, architecture = process.arch) {
|
|
5
|
-
const manifestPath = resolve(dirname(addonPath), "manifest.json");
|
|
6
|
-
let manifest;
|
|
7
|
-
try {
|
|
8
|
-
manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
9
|
-
}
|
|
10
|
-
catch (error) {
|
|
11
|
-
throw artifactError(`process guardian manifest is missing or malformed: ${errorMessage(error)}`, "CONTAINMENT_ARTIFACT_MISSING");
|
|
12
|
-
}
|
|
13
|
-
if (manifest.schema !== "a1-process-guardian-artifact-v2" || manifest.kind !== "node-addon"
|
|
14
|
-
|| manifest.nodeApi !== 9 || manifest.protocolVersion !== 2
|
|
15
|
-
|| manifest.platform !== platform || manifest.architecture !== architecture
|
|
16
|
-
|| manifest.artifact?.filename !== basename(addonPath)) {
|
|
17
|
-
throw artifactError("process guardian manifest is incompatible with this platform or protocol", "CONTAINMENT_ARTIFACT_INCOMPATIBLE");
|
|
18
|
-
}
|
|
19
|
-
if (manifest.capability !== "supported") {
|
|
20
|
-
throw artifactError(`process containment is not certified for ${platform}-${architecture}`, "CONTAINMENT_UNSUPPORTED");
|
|
21
|
-
}
|
|
22
|
-
const [bytes, metadata] = await Promise.all([readFile(addonPath), stat(addonPath)]).catch(error => {
|
|
23
|
-
throw artifactError(`process guardian artifact is unavailable: ${errorMessage(error)}`, "CONTAINMENT_ARTIFACT_MISSING");
|
|
24
|
-
});
|
|
25
|
-
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
26
|
-
if (metadata.size !== manifest.artifact.size || digest !== manifest.artifact.sha256) {
|
|
27
|
-
throw artifactError("process guardian artifact integrity verification failed", "CONTAINMENT_ARTIFACT_TAMPERED");
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function artifactError(message, code) {
|
|
31
|
-
return Object.assign(new Error(message), { code });
|
|
32
|
-
}
|
|
33
|
-
function errorMessage(error) {
|
|
34
|
-
return error instanceof Error ? error.message : String(error);
|
|
35
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { LaunchInstanceOutcome, LaunchInstanceStopReason, NativeProcessIdentity, ProcessContainmentIdentity } from "../lifecycle/index.js";
|
|
2
|
-
export interface ContainedSpawnOptions {
|
|
3
|
-
readonly cwd: string;
|
|
4
|
-
readonly environment: Readonly<Record<string, string>>;
|
|
5
|
-
readonly terminalType?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface ContainedProcessHandle {
|
|
8
|
-
readonly identity: NativeProcessIdentity;
|
|
9
|
-
readonly outcome: Promise<LaunchInstanceOutcome>;
|
|
10
|
-
readonly processGroup?: number;
|
|
11
|
-
readonly foregroundGroup?: number;
|
|
12
|
-
}
|
|
13
|
-
export interface NativeProcessInspector {
|
|
14
|
-
observe(pid: number): Promise<NativeProcessIdentity | null>;
|
|
15
|
-
matches(identity: NativeProcessIdentity): Promise<boolean>;
|
|
16
|
-
}
|
|
17
|
-
export interface ProcessContainment {
|
|
18
|
-
readonly identity: ProcessContainmentIdentity;
|
|
19
|
-
spawn(executable: string, arguments_: readonly string[], options: ContainedSpawnOptions): Promise<ContainedProcessHandle>;
|
|
20
|
-
contains(identity: NativeProcessIdentity): Promise<boolean>;
|
|
21
|
-
stop(force: boolean): Promise<void>;
|
|
22
|
-
waitForEmpty(timeoutMs: number): Promise<boolean>;
|
|
23
|
-
close(): Promise<void>;
|
|
24
|
-
}
|
|
25
|
-
export interface ProcessContainmentFactory {
|
|
26
|
-
create(instanceId: string): Promise<ProcessContainment>;
|
|
27
|
-
}
|
|
28
|
-
export interface ContainmentCloseResult {
|
|
29
|
-
readonly outcome: LaunchInstanceOutcome;
|
|
30
|
-
readonly graceful: boolean;
|
|
31
|
-
readonly forced: boolean;
|
|
32
|
-
}
|
|
33
|
-
export declare function closeVerifiedContainment(containment: ProcessContainment, inspector: NativeProcessInspector, rootIdentity: NativeProcessIdentity, reason: LaunchInstanceStopReason, deadlineMs?: number): Promise<ContainmentCloseResult>;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export async function closeVerifiedContainment(containment, inspector, rootIdentity, reason, deadlineMs = 1_500) {
|
|
2
|
-
if (!await ownershipMatches(containment, inspector, rootIdentity)) {
|
|
3
|
-
return ownershipMismatch("refusing graceful cleanup because launch-instance ownership changed");
|
|
4
|
-
}
|
|
5
|
-
await containment.stop(false);
|
|
6
|
-
if (await containment.waitForEmpty(deadlineMs)) {
|
|
7
|
-
return { outcome: { kind: "stopped", reason }, graceful: true, forced: false };
|
|
8
|
-
}
|
|
9
|
-
if (!await ownershipMatches(containment, inspector, rootIdentity)) {
|
|
10
|
-
return ownershipMismatch("refusing forced cleanup because launch-instance ownership changed");
|
|
11
|
-
}
|
|
12
|
-
await containment.stop(true);
|
|
13
|
-
if (await containment.waitForEmpty(deadlineMs)) {
|
|
14
|
-
return { outcome: { kind: "stopped", reason }, graceful: false, forced: true };
|
|
15
|
-
}
|
|
16
|
-
return {
|
|
17
|
-
outcome: {
|
|
18
|
-
kind: "cleanup-error",
|
|
19
|
-
message: "launch-instance process tree did not exit within the bounded cleanup deadline",
|
|
20
|
-
code: "CONTAINMENT_CLEANUP_TIMEOUT",
|
|
21
|
-
},
|
|
22
|
-
graceful: false,
|
|
23
|
-
forced: true,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
async function ownershipMatches(containment, inspector, rootIdentity) {
|
|
27
|
-
return await inspector.matches(rootIdentity) && await containment.contains(rootIdentity);
|
|
28
|
-
}
|
|
29
|
-
function ownershipMismatch(message) {
|
|
30
|
-
return {
|
|
31
|
-
outcome: { kind: "cleanup-error", message, code: "PROCESS_IDENTITY_MISMATCH" },
|
|
32
|
-
graceful: false,
|
|
33
|
-
forced: false,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { loadProcessGuardianAddon } from "./addon.js";
|
|
2
|
-
export type { ProcessGuardianAddon, ProcessGuardianRuntime, ProcessGuardianVersion } from "./addon.js";
|
|
3
|
-
export { AddonContainment, resolveProcessGuardianPath } from "./addon-containment.js";
|
|
4
|
-
export { AddonProcessInspector } from "./addon-process-inspector.js";
|
|
5
|
-
export { verifyProcessGuardianArtifact } from "./artifact.js";
|
|
6
|
-
export { closeVerifiedContainment } from "./contracts.js";
|
|
7
|
-
export type { ContainedProcessHandle, ContainedSpawnOptions, ContainmentCloseResult, NativeProcessInspector, ProcessContainment, ProcessContainmentFactory, } from "./contracts.js";
|
|
8
|
-
export { LinuxNativeProcessInspector } from "./linux-process-inspector.js";
|
|
9
|
-
export { createNativeProcessInspector } from "./native-process-inspector.js";
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { loadProcessGuardianAddon } from "./addon.js";
|
|
2
|
-
export { AddonContainment, resolveProcessGuardianPath } from "./addon-containment.js";
|
|
3
|
-
export { AddonProcessInspector } from "./addon-process-inspector.js";
|
|
4
|
-
export { verifyProcessGuardianArtifact } from "./artifact.js";
|
|
5
|
-
export { closeVerifiedContainment } from "./contracts.js";
|
|
6
|
-
export { LinuxNativeProcessInspector } from "./linux-process-inspector.js";
|
|
7
|
-
export { createNativeProcessInspector } from "./native-process-inspector.js";
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { NativeProcessIdentity } from "../lifecycle/index.js";
|
|
2
|
-
import type { NativeProcessInspector } from "./contracts.js";
|
|
3
|
-
/** Verifies Linux process identity from the PID and kernel start-time field in procfs. */
|
|
4
|
-
export declare class LinuxNativeProcessInspector implements NativeProcessInspector {
|
|
5
|
-
observe(pid: number): Promise<NativeProcessIdentity | null>;
|
|
6
|
-
matches(identity: NativeProcessIdentity): Promise<boolean>;
|
|
7
|
-
}
|