machine-bridge-mcp 2.0.0 → 3.0.0-beta.102
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/CHANGELOG.md +1142 -0
- package/CONTRIBUTING.md +23 -25
- package/GOVERNANCE.md +2 -2
- package/README.md +58 -20
- package/SECURITY.md +161 -120
- package/SUPPORT.md +1 -1
- package/browser-extension/broker-auth.js +83 -0
- package/browser-extension/broker-liveness.js +35 -0
- package/browser-extension/browser-error-boundary.js +96 -0
- package/browser-extension/browser-operations.js +1456 -101
- package/browser-extension/devtools-input.js +195 -34
- package/browser-extension/devtools-observation.js +429 -0
- package/browser-extension/devtools-session.js +48 -0
- package/browser-extension/manifest.json +4 -3
- package/browser-extension/page-automation.js +578 -118
- package/browser-extension/pairing-bootstrap.js +42 -0
- package/browser-extension/pairing.js +28 -12
- package/browser-extension/service-worker.js +126 -106
- package/docs/AGENT_CONTEXT.md +13 -10
- package/docs/ARCHITECTURE.md +159 -67
- package/docs/AUDIT.md +1302 -4
- package/docs/CLIENTS.md +19 -6
- package/docs/COMPUTER_USE.md +297 -0
- package/docs/ENGINEERING.md +72 -13
- package/docs/GETTING_STARTED.md +18 -20
- package/docs/LOCAL_AUTHORIZATION.md +115 -72
- package/docs/LOCAL_AUTOMATION.md +27 -21
- package/docs/LOGGING.md +40 -19
- package/docs/MANAGED_JOBS.md +37 -34
- package/docs/MULTI_ACCOUNT.md +98 -37
- package/docs/OPERATIONS.md +145 -51
- package/docs/OVERVIEW.md +14 -11
- package/docs/POLICY_REFERENCE.md +71 -3
- package/docs/PRIVACY.md +41 -2
- package/docs/PROJECT_STANDARDS.md +29 -6
- package/docs/RELEASING.md +238 -64
- package/docs/TESTING.md +150 -39
- package/docs/THREAT_MODEL.md +164 -67
- package/docs/TOOL_REFERENCE.md +653 -60
- package/docs/UPGRADING.md +78 -18
- package/native/macos/MachineBridgeBackgroundInput.swift +1051 -0
- package/native/macos/MachineBridgeBackgroundInputSmokeFixture.swift +295 -0
- package/native/macos/MachineBridgeTrustBroker.swift +233 -0
- package/package.json +94 -16
- package/scripts/accepted-candidate-tarball.mjs +77 -0
- package/scripts/candidate-runtime-store.mjs +93 -0
- package/scripts/check-plan.mjs +73 -3
- package/scripts/check-runner.mjs +129 -17
- package/scripts/commit-message-check.mjs +5 -2
- package/scripts/consumer-package-security.mjs +293 -0
- package/scripts/coverage-check.mjs +251 -15
- package/scripts/coverage-generation.mjs +41 -0
- package/scripts/coverage-range-merge.mjs +41 -0
- package/scripts/foreground-daemon-recovery.mjs +88 -0
- package/scripts/generate-policy-reference.mjs +28 -5
- package/scripts/generate-tool-reference.mjs +1 -1
- package/scripts/generate-worker-types.mjs +21 -11
- package/scripts/github-backlog.mjs +11 -10
- package/scripts/github-push.mjs +62 -16
- package/scripts/github-release-asset.mjs +58 -0
- package/scripts/github-release.mjs +241 -132
- package/scripts/global-package-installation.mjs +68 -0
- package/scripts/hardened-npm-session.mjs +42 -0
- package/scripts/install-published-prerelease.mjs +198 -0
- package/scripts/local-release-acceptance.mjs +103 -45
- package/scripts/macos-background-input-smoke.mjs +515 -0
- package/scripts/network-retry.mjs +8 -1
- package/scripts/npm-global-prefix.mjs +27 -0
- package/scripts/npm-publication-policy.mjs +17 -0
- package/scripts/official-mcp-conformance.mjs +267 -0
- package/scripts/persistent-activation-process.mjs +101 -0
- package/scripts/prepare-pinned-npm.mjs +12 -69
- package/scripts/prerelease-activation.mjs +160 -0
- package/scripts/privacy-check.mjs +14 -6
- package/scripts/promotion-digest.mjs +128 -0
- package/scripts/publish-npm.mjs +260 -0
- package/scripts/published-release.mjs +132 -0
- package/scripts/release-acceptance.mjs +62 -54
- package/scripts/release-browser-extension-store.mjs +172 -0
- package/scripts/release-candidate-manifest.mjs +52 -0
- package/scripts/release-channel.mjs +106 -0
- package/scripts/release-diagnostic.mjs +41 -0
- package/scripts/release-impact-check.mjs +12 -22
- package/scripts/release-oauth-canary-core.mjs +325 -0
- package/scripts/release-oauth-canary-evidence.mjs +100 -0
- package/scripts/release-oauth-canary.mjs +127 -0
- package/scripts/release-publication-guard.mjs +67 -0
- package/scripts/release-soak.mjs +284 -0
- package/scripts/release-state.mjs +1 -1
- package/scripts/run-checks.mjs +44 -7
- package/scripts/run-worker-dry-run.mjs +21 -0
- package/scripts/sarif-security-gate.mjs +2 -1
- package/scripts/sbom-check.mjs +106 -0
- package/scripts/start-release-candidate.mjs +267 -44
- package/scripts/syntax-check.mjs +36 -14
- package/scripts/verification-generation-guard.mjs +15 -0
- package/scripts/verification-idle-sleep-guard.mjs +37 -0
- package/scripts/verification-state.mjs +108 -0
- package/scripts/wrangler-command-lifecycle.mjs +115 -0
- package/src/local/account-access.mjs +13 -1
- package/src/local/account-admin-response.mjs +92 -0
- package/src/local/account-admin.mjs +52 -19
- package/src/local/agent-context-projection.mjs +26 -7
- package/src/local/agent-context.mjs +88 -49
- package/src/local/agent-skill-discovery.mjs +16 -5
- package/src/local/app-automation-macos-jxa.mjs +350 -0
- package/src/local/app-automation.mjs +873 -163
- package/src/local/application-capability-projection.mjs +24 -0
- package/src/local/authority-context.mjs +106 -0
- package/src/local/autostart-log-maintenance.mjs +36 -0
- package/src/local/browser-bridge-http.mjs +5 -3
- package/src/local/browser-bridge.mjs +109 -31
- package/src/local/browser-broker-auth-http.mjs +67 -0
- package/src/local/browser-broker-auth.mjs +98 -0
- package/src/local/browser-broker-routes.mjs +63 -20
- package/src/local/browser-broker-server.mjs +17 -7
- package/src/local/browser-command.mjs +79 -30
- package/src/local/browser-computer-observation-service.mjs +266 -0
- package/src/local/browser-extension-identity.mjs +50 -0
- package/src/local/browser-extension-path.mjs +22 -0
- package/src/local/browser-extension-protocol.mjs +50 -11
- package/src/local/browser-operation-service.mjs +147 -117
- package/src/local/browser-pairing-grant.mjs +109 -0
- package/src/local/browser-pairing-http.mjs +36 -0
- package/src/local/browser-pairing-launch.mjs +58 -0
- package/src/local/browser-pairing-store.mjs +85 -48
- package/src/local/browser-request-registry.mjs +40 -14
- package/src/local/browser-request-settlement.mjs +78 -0
- package/src/local/browser-resource-input.mjs +74 -0
- package/src/local/browser-trusted-input-health.mjs +63 -0
- package/src/local/call-authority.mjs +21 -0
- package/src/local/call-capacity.mjs +45 -0
- package/src/local/call-registry-drain.mjs +54 -0
- package/src/local/call-registry.mjs +30 -15
- package/src/local/capability-observer.mjs +5 -0
- package/src/local/capability-ranking.mjs +3 -2
- package/src/local/child-process-settlement.mjs +132 -0
- package/src/local/cli-account-admin.mjs +40 -6
- package/src/local/cli-activate.mjs +162 -0
- package/src/local/cli-local-admin.mjs +20 -45
- package/src/local/cli-options.mjs +12 -13
- package/src/local/cli-ready-output.mjs +52 -0
- package/src/local/cli-service.mjs +91 -11
- package/src/local/cli.mjs +232 -150
- package/src/local/computer-use-application-observation.mjs +224 -0
- package/src/local/computer-use-arguments.mjs +270 -0
- package/src/local/computer-use-deadline.mjs +50 -0
- package/src/local/computer-use-dispatch-settlement.mjs +40 -0
- package/src/local/computer-use-expectation.mjs +171 -0
- package/src/local/computer-use-observation.mjs +769 -0
- package/src/local/computer-use-recovery.mjs +82 -0
- package/src/local/computer-use-result-budget.mjs +145 -0
- package/src/local/computer-use-snapshot-store.mjs +67 -0
- package/src/local/computer-use.mjs +2255 -0
- package/src/local/daemon-http-relay-auth.mjs +26 -0
- package/src/local/daemon-http-relay-connection.mjs +298 -0
- package/src/local/daemon-http-relay-request.mjs +64 -0
- package/src/local/daemon-http-relay-sequence.mjs +49 -0
- package/src/local/daemon-process.mjs +40 -7
- package/src/local/delegated-process-sandbox.mjs +148 -0
- package/src/local/device-identity.mjs +156 -49
- package/src/local/device-root-provider.mjs +81 -0
- package/src/local/directory-metadata.mjs +47 -0
- package/src/local/doctor-reporting.mjs +23 -0
- package/src/local/durable-process-spec.mjs +80 -0
- package/src/local/errors.mjs +25 -15
- package/src/local/exclusive-file.mjs +74 -26
- package/src/local/execution-limits.mjs +9 -0
- package/src/local/execution-routing.mjs +276 -0
- package/src/local/execution-surface.mjs +23 -0
- package/src/local/file-mutation-coordinator.mjs +47 -0
- package/src/local/file-snapshot-preservation.mjs +24 -0
- package/src/local/filesystem-identity.mjs +54 -0
- package/src/local/fixed-process-environment.mjs +21 -0
- package/src/local/full-access-test.mjs +31 -13
- package/src/local/git-commit.mjs +69 -0
- package/src/local/git-config-safety.mjs +55 -0
- package/src/local/git-log-parser.mjs +41 -0
- package/src/local/git-metadata-boundary.mjs +77 -0
- package/src/local/git-metadata-tree-safety.mjs +59 -0
- package/src/local/git-operation-state.mjs +19 -0
- package/src/local/git-service.mjs +165 -30
- package/src/local/hardened-npm-download-timeout.mjs +46 -0
- package/src/local/hardened-npm-download.mjs +109 -0
- package/src/local/hardened-npm-extract.mjs +20 -0
- package/src/local/hardened-npm-verification.mjs +104 -0
- package/src/local/hardened-npm.mjs +199 -0
- package/src/local/job-runner.mjs +244 -89
- package/src/local/lifecycle.mjs +6 -0
- package/src/local/log.mjs +19 -45
- package/src/local/macos-background-input.mjs +398 -0
- package/src/local/macos-idle-sleep-assertion.mjs +65 -0
- package/src/local/macos-trust-broker.mjs +404 -0
- package/src/local/managed-job-cancellation.mjs +42 -0
- package/src/local/managed-job-capacity.mjs +16 -0
- package/src/local/managed-job-directory-generation.mjs +60 -0
- package/src/local/managed-job-directory.mjs +75 -0
- package/src/local/managed-job-durable-process.mjs +49 -0
- package/src/local/managed-job-lock.mjs +46 -14
- package/src/local/managed-job-plan.mjs +38 -14
- package/src/local/managed-job-projection.mjs +23 -15
- package/src/local/managed-job-retention.mjs +128 -0
- package/src/local/managed-job-runner-claim.mjs +70 -0
- package/src/local/managed-job-runner.mjs +35 -10
- package/src/local/managed-job-storage.mjs +22 -6
- package/src/local/managed-job-terminal-maintenance.mjs +40 -0
- package/src/local/managed-job-terminal.mjs +150 -0
- package/src/local/managed-jobs.mjs +424 -287
- package/src/local/npm-cli.mjs +42 -0
- package/src/local/npm-environment.mjs +37 -0
- package/src/local/operation-authorization.mjs +68 -324
- package/src/local/operation-risk.mjs +51 -4
- package/src/local/owner-state-lock.mjs +118 -0
- package/src/local/package-identity.mjs +9 -0
- package/src/local/patch.mjs +20 -18
- package/src/local/path-inspection.mjs +23 -0
- package/src/local/policy.mjs +19 -0
- package/src/local/private-toolchain-integrity.mjs +54 -0
- package/src/local/process-execution.mjs +87 -75
- package/src/local/process-foreground-timeout.mjs +50 -0
- package/src/local/process-identity.mjs +41 -7
- package/src/local/process-nonreplayable-settlement.mjs +50 -0
- package/src/local/process-result-projection.mjs +22 -0
- package/src/local/process-session-events.mjs +47 -0
- package/src/local/process-session-remote-activity.mjs +10 -0
- package/src/local/process-session-termination.mjs +73 -0
- package/src/local/process-sessions.mjs +144 -112
- package/src/local/process-tracker.mjs +140 -13
- package/src/local/process-tree-ownership-types.d.ts +37 -0
- package/src/local/process-tree-ownership.mjs +57 -0
- package/src/local/process-tree-signal.mjs +34 -0
- package/src/local/process-tree-snapshot.mjs +77 -0
- package/src/local/process-tree-supervisor.mjs +69 -0
- package/src/local/process-tree.mjs +11 -53
- package/src/local/project-metadata.mjs +19 -6
- package/src/local/relay-call-recovery.mjs +58 -38
- package/src/local/relay-connection-classification.mjs +131 -0
- package/src/local/relay-connection-support.mjs +91 -0
- package/src/local/relay-connection.mjs +179 -272
- package/src/local/relay-diagnostics.mjs +91 -0
- package/src/local/relay-heartbeat.mjs +119 -0
- package/src/local/relay-liveness.mjs +109 -0
- package/src/local/relay-peer-diagnostics.mjs +29 -0
- package/src/local/release-runtime-lock.mjs +18 -0
- package/src/local/remote-activity-idle-sleep-guard.mjs +77 -0
- package/src/local/remote-configuration.mjs +48 -0
- package/src/local/resilient-relay-connection.mjs +178 -0
- package/src/local/resource-admission-diagnostics.mjs +52 -0
- package/src/local/resource-admission-policy.mjs +115 -0
- package/src/local/resource-admission.mjs +339 -0
- package/src/local/resource-build-root.mjs +83 -0
- package/src/local/resource-cargo-concurrency.mjs +38 -0
- package/src/local/resource-cmake-concurrency.mjs +42 -0
- package/src/local/resource-command-concurrency.mjs +37 -0
- package/src/local/resource-command-profile.mjs +176 -0
- package/src/local/resource-coordinator-accounting.mjs +21 -0
- package/src/local/resource-cpu-window.mjs +20 -0
- package/src/local/resource-disk-headroom.mjs +13 -0
- package/src/local/resource-elastic-memory.mjs +19 -0
- package/src/local/resource-elastic-request.mjs +36 -0
- package/src/local/resource-foreground-wait.mjs +29 -0
- package/src/local/resource-go-concurrency.mjs +43 -0
- package/src/local/resource-gradle-concurrency.mjs +57 -0
- package/src/local/resource-host-cache.mjs +39 -0
- package/src/local/resource-host-darwin.mjs +54 -0
- package/src/local/resource-host-linux.mjs +35 -0
- package/src/local/resource-host-sample-file.mjs +23 -0
- package/src/local/resource-host-snapshot.mjs +99 -0
- package/src/local/resource-lease-accounting.mjs +119 -0
- package/src/local/resource-light-command.mjs +6 -0
- package/src/local/resource-make-concurrency.mjs +42 -0
- package/src/local/resource-maven-concurrency.mjs +38 -0
- package/src/local/resource-ninja-command-concurrency.mjs +20 -0
- package/src/local/resource-ninja-concurrency.mjs +28 -0
- package/src/local/resource-operations.mjs +26 -10
- package/src/local/resource-pressure.mjs +67 -0
- package/src/local/resource-probe-command.mjs +35 -0
- package/src/local/resource-process-admission.mjs +59 -0
- package/src/local/resource-process-ancestry-cache.mjs +43 -0
- package/src/local/resource-process-ancestry.mjs +32 -0
- package/src/local/resource-process-priority.mjs +15 -0
- package/src/local/resource-project-key.mjs +53 -0
- package/src/local/resource-pytest-concurrency.mjs +33 -0
- package/src/local/resource-release-control-classification.mjs +14 -0
- package/src/local/resource-release-control-executable.mjs +70 -0
- package/src/local/resource-release-control-workspace.mjs +41 -0
- package/src/local/resource-request-contract.mjs +30 -0
- package/src/local/resource-script-classification.mjs +44 -0
- package/src/local/resource-shell-analysis.mjs +58 -0
- package/src/local/resource-staging-recovery.mjs +97 -0
- package/src/local/resource-swift-concurrency.mjs +31 -0
- package/src/local/resource-transaction-lock.mjs +189 -0
- package/src/local/resource-wait.mjs +48 -0
- package/src/local/resource-waiters.mjs +139 -0
- package/src/local/resource-xcode-command.mjs +7 -0
- package/src/local/resource-xcode-concurrency.mjs +34 -0
- package/src/local/resource-xcode-non-build.mjs +19 -0
- package/src/local/runtime-activation.mjs +700 -0
- package/src/local/runtime-activity-projection.mjs +48 -0
- package/src/local/runtime-capabilities.mjs +48 -15
- package/src/local/runtime-diagnostic-state.mjs +14 -0
- package/src/local/runtime-diagnostics.mjs +40 -13
- package/src/local/runtime-info-projection.mjs +60 -0
- package/src/local/runtime-info-relay-projection.mjs +21 -0
- package/src/local/runtime-paths.mjs +2 -1
- package/src/local/runtime-process-routing.mjs +33 -0
- package/src/local/runtime-relay-connection-options.mjs +44 -0
- package/src/local/runtime-relay-control.mjs +98 -0
- package/src/local/runtime-relay.mjs +26 -50
- package/src/local/runtime-reporting.mjs +37 -21
- package/src/local/runtime-resource-service.mjs +77 -0
- package/src/local/runtime-tool-handlers.mjs +13 -10
- package/src/local/runtime.mjs +244 -208
- package/src/local/secure-file.mjs +73 -20
- package/src/local/security-audit-dispatch.mjs +35 -0
- package/src/local/security-audit-log.mjs +215 -0
- package/src/local/security-audit-state.mjs +139 -0
- package/src/local/security-audit-storage.mjs +135 -0
- package/src/local/security-audit-warning.mjs +31 -0
- package/src/local/security-audit-worker.mjs +87 -0
- package/src/local/service-convergence.mjs +42 -1
- package/src/local/service-definition.mjs +24 -0
- package/src/local/service-environment.mjs +18 -10
- package/src/local/service-owner.mjs +146 -0
- package/src/local/service-ownership.mjs +17 -0
- package/src/local/service-restart-handoff.mjs +64 -0
- package/src/local/service-restart-scheduler.mjs +49 -0
- package/src/local/service-runtime-convergence.mjs +52 -0
- package/src/local/service-runtime.mjs +105 -0
- package/src/local/service-status.mjs +60 -0
- package/src/local/service.mjs +385 -92
- package/src/local/shell.mjs +39 -19
- package/src/local/ssh-key.mjs +158 -42
- package/src/local/state-inventory.mjs +50 -24
- package/src/local/state-owner-lock-inventory.mjs +23 -0
- package/src/local/state-root-owned-namespaces.mjs +83 -0
- package/src/local/state-root-retirement.mjs +89 -0
- package/src/local/state.mjs +386 -96
- package/src/local/stdio.mjs +96 -66
- package/src/local/support-state-projection.mjs +30 -0
- package/src/local/system-network-route.mjs +76 -0
- package/src/local/systemd-removal.mjs +20 -0
- package/src/local/tool-executor.mjs +85 -20
- package/src/local/tool-result-boundary.mjs +51 -0
- package/src/local/toolchain-operation-lock.mjs +41 -0
- package/src/local/tools.mjs +7 -5
- package/src/local/trusted-executable.mjs +53 -0
- package/src/local/trusted-git-executable.mjs +34 -0
- package/src/local/trusted-github-cli.mjs +24 -0
- package/src/local/windows-service-convergence.mjs +49 -0
- package/src/local/windows-service.mjs +52 -45
- package/src/local/worker-deployment-fingerprint.mjs +102 -0
- package/src/local/worker-deployment.mjs +48 -60
- package/src/local/worker-health.mjs +12 -4
- package/src/local/worker-secret-file.mjs +37 -17
- package/src/local/workspace-file-service.mjs +156 -239
- package/src/local/workspace-file-transaction.mjs +189 -0
- package/src/local/workspace-search.mjs +55 -0
- package/src/local/wrangler-toolchain/package-lock.json +1505 -0
- package/src/local/wrangler-toolchain/package.json +23 -0
- package/src/local/wrangler-toolchain-verification.mjs +135 -0
- package/src/local/wrangler-toolchain.mjs +188 -0
- package/src/shared/access-contract.json +7 -1
- package/src/shared/activation-recovery.mjs +49 -0
- package/src/shared/admin-auth.d.mts +2 -1
- package/src/shared/admin-auth.mjs +3 -3
- package/src/shared/authority-revocation.d.mts +9 -0
- package/src/shared/authority-revocation.mjs +28 -0
- package/src/shared/daemon-auth.d.mts +11 -0
- package/src/shared/daemon-auth.mjs +17 -0
- package/src/shared/device-session-auth.d.mts +20 -0
- package/src/shared/device-session-auth.mjs +51 -0
- package/src/shared/foreground-timeout.d.mts +15 -0
- package/src/shared/foreground-timeout.mjs +70 -0
- package/src/shared/log-redaction.d.mts +9 -0
- package/src/shared/log-redaction.mjs +51 -0
- package/src/shared/mcp-protocol.d.mts +27 -0
- package/src/shared/mcp-protocol.mjs +275 -0
- package/src/shared/project-overview-projection.d.mts +4 -0
- package/src/shared/project-overview-projection.mjs +96 -0
- package/src/shared/relay-contract.json +28 -0
- package/src/shared/result-projection.d.mts +2 -1
- package/src/shared/result-projection.mjs +13 -2
- package/src/shared/server-metadata.json +15 -9
- package/src/shared/tool-argument-validation.d.mts +17 -0
- package/src/shared/tool-argument-validation.mjs +325 -0
- package/src/shared/tool-call-capacity.d.mts +41 -0
- package/src/shared/tool-call-capacity.mjs +59 -0
- package/src/shared/tool-catalog.json +626 -57
- package/src/worker/access.ts +12 -0
- package/src/worker/account-admin.ts +55 -33
- package/src/worker/authority-revocations.ts +174 -0
- package/src/worker/authority.ts +52 -6
- package/src/worker/daemon-auth.ts +49 -68
- package/src/worker/daemon-channel.ts +36 -0
- package/src/worker/daemon-http-auth.ts +63 -0
- package/src/worker/daemon-http-channel.ts +120 -0
- package/src/worker/daemon-http-controller.ts +163 -0
- package/src/worker/daemon-http-protocol.ts +62 -0
- package/src/worker/daemon-http-registry.ts +82 -0
- package/src/worker/daemon-last-observation.ts +30 -0
- package/src/worker/daemon-liveness.ts +8 -6
- package/src/worker/daemon-ready-dispatch.ts +17 -0
- package/src/worker/daemon-ready-messages.ts +73 -0
- package/src/worker/daemon-ready-waiters.ts +79 -0
- package/src/worker/daemon-recovery-budget.ts +13 -0
- package/src/worker/daemon-registry.ts +58 -0
- package/src/worker/daemon-relay-diagnostics.ts +127 -0
- package/src/worker/daemon-socket-attachment.ts +55 -0
- package/src/worker/daemon-sockets.ts +72 -62
- package/src/worker/daemon-status.ts +38 -0
- package/src/worker/device-session-verifier.ts +129 -0
- package/src/worker/dpop.ts +157 -0
- package/src/worker/durable-process-timeout.ts +29 -0
- package/src/worker/errors.ts +57 -0
- package/src/worker/http.ts +112 -26
- package/src/worker/index.ts +446 -440
- package/src/worker/mcp-access.ts +57 -0
- package/src/worker/mcp-controller.ts +188 -0
- package/src/worker/mcp-http-accept.ts +11 -0
- package/src/worker/mcp-http-contract.ts +322 -0
- package/src/worker/mcp-initialization-compat.ts +141 -0
- package/src/worker/mcp-jsonrpc.ts +11 -29
- package/src/worker/mcp-removed-protocol.ts +17 -0
- package/src/worker/mcp-response-proxy.ts +135 -0
- package/src/worker/mcp-response-stream.ts +65 -0
- package/src/worker/mcp-stale-schema-compat.ts +57 -0
- package/src/worker/mcp-stream-proxy-contract.ts +48 -0
- package/src/worker/mcp-tool-call-input.ts +23 -0
- package/src/worker/nonce-store.ts +33 -35
- package/src/worker/oauth-authorization-page.ts +21 -1
- package/src/worker/oauth-client-admin.ts +52 -0
- package/src/worker/oauth-client-contract.ts +38 -0
- package/src/worker/oauth-controller.ts +107 -47
- package/src/worker/oauth-field-contract.ts +31 -0
- package/src/worker/oauth-record-contract.ts +7 -0
- package/src/worker/oauth-refresh-authority.ts +27 -0
- package/src/worker/oauth-refresh-exchange.ts +162 -0
- package/src/worker/oauth-refresh-families.ts +130 -27
- package/src/worker/oauth-refresh-persistence.ts +116 -0
- package/src/worker/oauth-state.ts +33 -18
- package/src/worker/oauth-store-validation.ts +131 -0
- package/src/worker/oauth-token-derivation.ts +33 -0
- package/src/worker/oauth-token-issuance.ts +119 -0
- package/src/worker/oauth-tokens.ts +56 -190
- package/src/worker/observability.ts +38 -5
- package/src/worker/pending-admission.ts +15 -0
- package/src/worker/pending-call-capacity.ts +108 -0
- package/src/worker/pending-call-contract.ts +42 -5
- package/src/worker/pending-call-deadlines.ts +75 -0
- package/src/worker/pending-calls.ts +131 -125
- package/src/worker/runtime-alarm-storage.ts +37 -0
- package/src/worker/runtime-alarm.ts +136 -0
- package/src/worker/server-info-activity.ts +36 -0
- package/src/worker/server-info-tool-delivery.ts +15 -0
- package/src/worker/server-info.ts +168 -0
- package/src/worker/tool-catalog.ts +47 -1
- package/src/worker/tool-timeout.ts +75 -14
- package/src/worker/websocket-protocol.ts +26 -2
- package/src/worker/worker-edge-guard.ts +90 -0
- package/src/worker/worker-edge-log.ts +65 -0
- package/src/worker/worker-entry.ts +52 -0
- package/src/worker/worker-mcp-config.ts +23 -0
- package/src/worker/worker-metadata.ts +48 -0
- package/src/worker/worker-rate-limit-key.ts +30 -0
- package/src/worker/worker-runtime-config.ts +20 -0
- package/src/worker/worker-static-routes.ts +54 -0
- package/src/worker/worker-task-lifetime.ts +18 -0
- package/tsconfig.local.json +17 -1
- package/wrangler.jsonc +13 -0
- package/src/local/cli-approval.mjs +0 -117
- package/src/local/operation-state-lock.mjs +0 -92
- package/src/worker/mcp-session.ts +0 -72
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join, resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { defaultStateRoot, expandHome } from "../src/local/state.mjs";
|
|
9
|
+
import { ACTIVATION_SCHEMA_VERSION, writePrereleaseActivation } from "./prerelease-activation.mjs";
|
|
10
|
+
import { computePromotionContentDigest } from "./promotion-digest.mjs";
|
|
11
|
+
import { readGithubPrerelease, readPublishedNpmPrerelease } from "./published-release.mjs";
|
|
12
|
+
import { verifyCurrentReleaseAcceptance } from "./release-acceptance.mjs";
|
|
13
|
+
import { assertSoakEligiblePrerelease } from "./release-channel.mjs";
|
|
14
|
+
import { persistentActivationSpawnOptions, validateActivationRecoveryPayload } from "./persistent-activation-process.mjs";
|
|
15
|
+
import { createHardenedNpmSession, settleHardenedNpmSession } from "./hardened-npm-session.mjs";
|
|
16
|
+
import { nestedNpmEnvironment } from "../src/local/npm-environment.mjs";
|
|
17
|
+
import { inspectGlobalPackageInstallation } from "./global-package-installation.mjs";
|
|
18
|
+
import { resolveNpmGlobalPrefix } from "./npm-global-prefix.mjs";
|
|
19
|
+
import { releaseCommandFailure, releaseDiagnostic, releaseDiagnosticEvent } from "./release-diagnostic.mjs";
|
|
20
|
+
import { withReleaseRuntimeLock } from "../src/local/release-runtime-lock.mjs";
|
|
21
|
+
|
|
22
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
23
|
+
const lifecycleNpmCli = process.env.npm_execpath;
|
|
24
|
+
let npmCli = "";
|
|
25
|
+
let npmSession = null;
|
|
26
|
+
let previousInstallation = null;
|
|
27
|
+
let globalInstallAttempted = false;
|
|
28
|
+
let globalInstallCompleted = false;
|
|
29
|
+
let installedPrerelease = "";
|
|
30
|
+
if (!lifecycleNpmCli) fail("published prerelease installation must run through npm");
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
if (!process.argv.includes("--allow-worker-deploy")) {
|
|
34
|
+
throw new Error("published prerelease activation updates the global package, same-name Worker, and login daemon; rerun with --allow-worker-deploy");
|
|
35
|
+
}
|
|
36
|
+
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
37
|
+
const requested = argumentValue("--version") || pkg.version;
|
|
38
|
+
const prerelease = assertSoakEligiblePrerelease(requested);
|
|
39
|
+
if (pkg.version !== prerelease.raw) {
|
|
40
|
+
throw new Error(`source checkout version ${pkg.version} does not match requested prerelease ${prerelease.raw}`);
|
|
41
|
+
}
|
|
42
|
+
const globalPrefix = resolveNpmGlobalPrefix(lifecycleNpmCli, { cwd: root, env: process.env });
|
|
43
|
+
const acceptance = verifyCurrentReleaseAcceptance(root, { npmCli: lifecycleNpmCli, env: process.env });
|
|
44
|
+
if (!acceptance.required || acceptance.metadata.package_version !== prerelease.raw) {
|
|
45
|
+
throw new Error("published prerelease installation requires the locally accepted exact prerelease source");
|
|
46
|
+
}
|
|
47
|
+
const promotionDigest = computePromotionContentDigest(root, { npmCli: lifecycleNpmCli });
|
|
48
|
+
if (acceptance.record.promotion_content_sha256 !== promotionDigest) {
|
|
49
|
+
throw new Error("current source promotion digest does not match local candidate acceptance");
|
|
50
|
+
}
|
|
51
|
+
readGithubPrerelease(prerelease.raw, { expectedArtifactSha256: acceptance.artifactSha256 });
|
|
52
|
+
npmSession = await createHardenedNpmSession();
|
|
53
|
+
npmCli = npmSession.cli;
|
|
54
|
+
const published = readPublishedNpmPrerelease(pkg.name, prerelease.raw, prerelease.npmTag, { npmCli, env: process.env });
|
|
55
|
+
if (published.integrity !== acceptance.metadata.integrity || published.shasum !== acceptance.metadata.shasum) {
|
|
56
|
+
throw new Error("npm prerelease bytes do not match the locally accepted candidate");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const stateRoot = resolve(expandHome(argumentValue("--state-dir") || defaultStateRoot()));
|
|
60
|
+
await withReleaseRuntimeLock(stateRoot, async () => {
|
|
61
|
+
previousInstallation = currentGlobalInstallation(pkg.name, globalPrefix);
|
|
62
|
+
globalInstallAttempted = true;
|
|
63
|
+
runNpm([
|
|
64
|
+
"install", "--dry-run=false", "--workspaces=false", "--ignore-scripts=false",
|
|
65
|
+
"--global", "--prefix", globalPrefix,
|
|
66
|
+
"--omit=optional", "--include=prod", "--package-lock-only=false",
|
|
67
|
+
"--allow-scripts=esbuild,workerd,sharp,fsevents",
|
|
68
|
+
`${pkg.name}@${prerelease.raw}`,
|
|
69
|
+
]);
|
|
70
|
+
globalInstallCompleted = true;
|
|
71
|
+
const installed = currentGlobalInstallation(pkg.name, globalPrefix);
|
|
72
|
+
if (!installed || installed.version !== prerelease.raw) {
|
|
73
|
+
throw new Error(`global prerelease installation did not converge on ${prerelease.raw}`);
|
|
74
|
+
}
|
|
75
|
+
installedPrerelease = prerelease.raw;
|
|
76
|
+
disposeNpmSession();
|
|
77
|
+
|
|
78
|
+
const forwarded = forwardedActivationArgs();
|
|
79
|
+
const activation = runActivation(installed.entry, ["activate", ...forwarded, "--state-dir", stateRoot, "--json"]);
|
|
80
|
+
if (activation.version !== prerelease.raw || activation.daemon?.version !== prerelease.raw || activation.worker?.health?.version !== prerelease.raw) {
|
|
81
|
+
throw new Error("published prerelease activation did not converge on the exact registry version");
|
|
82
|
+
}
|
|
83
|
+
const recovery = validateActivationRecoveryPayload(activation);
|
|
84
|
+
const recordPath = writePrereleaseActivation({
|
|
85
|
+
schema_version: ACTIVATION_SCHEMA_VERSION,
|
|
86
|
+
package_name: pkg.name,
|
|
87
|
+
package_version: prerelease.raw,
|
|
88
|
+
source: "npm-prerelease",
|
|
89
|
+
shasum: published.shasum,
|
|
90
|
+
integrity: published.integrity,
|
|
91
|
+
promotion_content_sha256: promotionDigest,
|
|
92
|
+
activated_at: new Date().toISOString(),
|
|
93
|
+
published_at: published.publishedAt,
|
|
94
|
+
npm_dist_tag: prerelease.npmTag,
|
|
95
|
+
workspace_hash: workspaceHash(activation.workspace),
|
|
96
|
+
runtime_entry: installed.entry,
|
|
97
|
+
...(recovery.recovered ? {
|
|
98
|
+
activation_recovered: true,
|
|
99
|
+
activation_recovery_reason: recovery.reason,
|
|
100
|
+
activation_recovery_detail: recovery.detail,
|
|
101
|
+
} : {}),
|
|
102
|
+
...(previousInstallation ? { global_package_rollback_baseline: previousInstallation } : {}),
|
|
103
|
+
}, stateRoot);
|
|
104
|
+
|
|
105
|
+
if (recovery.recovered) {
|
|
106
|
+
console.warn(`Published prerelease activation used verified candidate-service recovery (${recovery.reason}): ${recovery.detail}`);
|
|
107
|
+
}
|
|
108
|
+
console.log(`Published prerelease activated: ${prerelease.raw}`);
|
|
109
|
+
console.log(`Worker and login daemon version: ${activation.version}`);
|
|
110
|
+
console.log(`Soak activation record: ${recordPath}`);
|
|
111
|
+
console.log("Use this prerelease normally. Any blocking issue requires a new beta/rc version and restarts the soak clock.");
|
|
112
|
+
});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
const settled = settleNpmSession(error);
|
|
115
|
+
const message = releaseDiagnostic(settled?.message || settled, 1600);
|
|
116
|
+
if (installedPrerelease) {
|
|
117
|
+
const previousVersion = previousInstallation?.version || "unknown";
|
|
118
|
+
fail(`${message}. The global package is now ${installedPrerelease}, but Worker/service activation may not have converged. Previous global version: ${previousVersion}. Preserve state and logs; fix forward with the exact prerelease or restore package, Worker, service definition, browser extension, and state as one verified unit.`);
|
|
119
|
+
}
|
|
120
|
+
if (globalInstallAttempted) {
|
|
121
|
+
const previousVersion = previousInstallation?.version || "unknown";
|
|
122
|
+
const installState = globalInstallCompleted
|
|
123
|
+
? "The global installation command completed, but the exact installed package identity was not verified"
|
|
124
|
+
: "The global installation command was attempted and may have changed the installed package";
|
|
125
|
+
fail(`${message}. ${installState}. Previous global version: ${previousVersion}. Inspect the configured global prefix before retrying or activating any runtime.`);
|
|
126
|
+
}
|
|
127
|
+
fail(message);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function disposeNpmSession() {
|
|
131
|
+
const error = settleNpmSession();
|
|
132
|
+
if (error) throw error;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function settleNpmSession(primaryError = null) {
|
|
136
|
+
const session = npmSession;
|
|
137
|
+
npmSession = null;
|
|
138
|
+
return settleHardenedNpmSession(session, primaryError, "published prerelease failed and hardened npm temporary cleanup was incomplete");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function currentGlobalInstallation(packageName, globalPrefix) {
|
|
142
|
+
const globalRoot = runNpm(["root", "--json=false", "--parseable=false", "--workspaces=false", "--global", "--prefix", globalPrefix]).stdout.trim();
|
|
143
|
+
return inspectGlobalPackageInstallation(globalRoot, packageName);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function runActivation(entry, args) {
|
|
147
|
+
const result = spawnSync(
|
|
148
|
+
process.execPath,
|
|
149
|
+
[entry, ...args],
|
|
150
|
+
persistentActivationSpawnOptions({ cwd: root, env: nestedNpmEnvironment(process.env) }),
|
|
151
|
+
);
|
|
152
|
+
if (result.error || result.status !== 0) throw new Error(releaseCommandFailure("machine-mcp", ["activate"], result, { maxChars: 1600 }));
|
|
153
|
+
try { return JSON.parse(result.stdout); } catch { throw new Error("prerelease runtime activation did not return valid JSON"); }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function runNpm(args) {
|
|
157
|
+
const result = spawnSync(process.execPath, [npmCli, ...args], {
|
|
158
|
+
cwd: root,
|
|
159
|
+
env: nestedNpmEnvironment(process.env),
|
|
160
|
+
encoding: "utf8",
|
|
161
|
+
timeout: 300_000,
|
|
162
|
+
killSignal: "SIGKILL",
|
|
163
|
+
windowsHide: true,
|
|
164
|
+
});
|
|
165
|
+
if (result.error || result.status !== 0) throw new Error(releaseCommandFailure("npm", args, result, { maxChars: 1600 }));
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function forwardedActivationArgs() {
|
|
170
|
+
const out = [];
|
|
171
|
+
const skipWithValue = new Set(["--version", "--state-dir"]);
|
|
172
|
+
for (let index = 2; index < process.argv.length; index += 1) {
|
|
173
|
+
const value = process.argv[index];
|
|
174
|
+
if (value === "--allow-worker-deploy") continue;
|
|
175
|
+
if (skipWithValue.has(value)) { index += 1; continue; }
|
|
176
|
+
if (["--version=", "--state-dir="].some((prefix) => value.startsWith(prefix))) continue;
|
|
177
|
+
if (value === "--json" || value.startsWith("--json=")) continue;
|
|
178
|
+
out.push(value);
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function argumentValue(name) {
|
|
184
|
+
const exact = process.argv.find((value) => value.startsWith(`${name}=`));
|
|
185
|
+
if (exact) return exact.slice(name.length + 1);
|
|
186
|
+
const index = process.argv.indexOf(name);
|
|
187
|
+
return index >= 0 ? process.argv[index + 1] : "";
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function workspaceHash(workspace) {
|
|
191
|
+
const value = process.platform === "win32" ? String(workspace).toLowerCase() : String(workspace);
|
|
192
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 24);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function fail(message) {
|
|
196
|
+
console.error(JSON.stringify(releaseDiagnosticEvent("prerelease.install.failed", message, 1800)));
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
mkdtempSync,
|
|
6
6
|
readFileSync,
|
|
7
7
|
rmSync,
|
|
8
|
-
writeFileSync,
|
|
9
8
|
} from "node:fs";
|
|
10
9
|
import { spawnSync } from "node:child_process";
|
|
11
10
|
import { tmpdir } from "node:os";
|
|
@@ -16,74 +15,120 @@ import {
|
|
|
16
15
|
ACCEPTANCE_SCHEMA_VERSION,
|
|
17
16
|
acceptancePath,
|
|
18
17
|
packProject,
|
|
19
|
-
requiresLocalAcceptance,
|
|
20
18
|
verifyAcceptanceRecord,
|
|
21
19
|
verifyCurrentReleaseAcceptance,
|
|
22
20
|
verifyTarball,
|
|
23
21
|
} from "./release-acceptance.mjs";
|
|
22
|
+
import { computePromotionContentDigest } from "./promotion-digest.mjs";
|
|
23
|
+
import { parseReleaseVersion } from "./release-channel.mjs";
|
|
24
|
+
import { validateCandidateManifest } from "./release-candidate-manifest.mjs";
|
|
25
|
+
import { replaceFileAtomicallySync } from "../src/local/exclusive-file.mjs";
|
|
26
|
+
import { resolveTrustedGitExecutable } from "../src/local/trusted-git-executable.mjs";
|
|
27
|
+
import { nestedNpmEnvironment } from "../src/local/npm-environment.mjs";
|
|
28
|
+
import { releaseCommandFailure, releaseDiagnosticEvent } from "./release-diagnostic.mjs";
|
|
29
|
+
import { createHardenedNpmSession } from "./hardened-npm-session.mjs";
|
|
30
|
+
import { readReleaseOAuthCanaryEvidence } from "./release-oauth-canary-evidence.mjs";
|
|
31
|
+
import { assertFreshFullVerificationReceipt } from "./verification-state.mjs";
|
|
24
32
|
|
|
25
33
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
26
34
|
const candidateDirectory = join(root, ".release-candidate");
|
|
27
35
|
const candidateManifestPath = join(candidateDirectory, "manifest.json");
|
|
28
36
|
const mode = process.argv[2] || "--verify";
|
|
37
|
+
const git = resolveTrustedGitExecutable({ workspace: root });
|
|
29
38
|
|
|
30
39
|
try {
|
|
31
|
-
|
|
32
|
-
else if (mode === "--record") recordAcceptance();
|
|
33
|
-
else if (mode === "--verify") verifyAcceptance();
|
|
34
|
-
else fail("usage: node scripts/local-release-acceptance.mjs [--prepare|--record|--verify]");
|
|
40
|
+
await runWithHardenedNpm();
|
|
35
41
|
} catch (error) {
|
|
36
42
|
fail(error?.message || error);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
async function runWithHardenedNpm() {
|
|
46
|
+
let session = null;
|
|
47
|
+
let primaryError = null;
|
|
48
|
+
try {
|
|
49
|
+
session = await createHardenedNpmSession();
|
|
50
|
+
if (mode === "--prepare") prepareCandidate(session.cli);
|
|
51
|
+
else if (mode === "--record") recordAcceptance(session.cli);
|
|
52
|
+
else if (mode === "--verify") verifyAcceptance(session.cli);
|
|
53
|
+
else throw new Error("usage: node scripts/local-release-acceptance.mjs [--prepare|--record|--verify]");
|
|
54
|
+
} catch (error) {
|
|
55
|
+
primaryError = error;
|
|
56
|
+
}
|
|
57
|
+
let cleanupError = null;
|
|
58
|
+
try { session?.dispose(); } catch (error) { cleanupError = error; }
|
|
59
|
+
if (primaryError && cleanupError) {
|
|
60
|
+
throw new AggregateError([primaryError, cleanupError], "local release acceptance failed and hardened npm cleanup was incomplete");
|
|
43
61
|
}
|
|
44
|
-
|
|
62
|
+
if (primaryError) throw primaryError;
|
|
63
|
+
if (cleanupError) throw cleanupError;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function prepareCandidate(npmCli) {
|
|
67
|
+
const pkg = readPackage();
|
|
68
|
+
const fullVerification = assertFreshFullVerificationReceipt(root);
|
|
69
|
+
rmSync(candidateDirectory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
|
|
45
70
|
mkdirSync(candidateDirectory, { recursive: true });
|
|
46
|
-
const metadata = packProject(root, candidateDirectory);
|
|
71
|
+
const metadata = packProject(root, candidateDirectory, { npmCli, env: process.env });
|
|
47
72
|
const manifest = {
|
|
48
73
|
schema_version: ACCEPTANCE_SCHEMA_VERSION,
|
|
49
74
|
result: "pending",
|
|
50
75
|
...metadata,
|
|
76
|
+
promotion_content_sha256: computePromotionContentDigest(root, { npmCli }),
|
|
51
77
|
prepared_at: new Date().toISOString(),
|
|
52
78
|
};
|
|
53
|
-
|
|
79
|
+
replaceFileAtomicallySync(candidateManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
|
|
54
80
|
const phrase = confirmationPhrase(pkg.name, pkg.version);
|
|
55
81
|
console.log(`Release candidate created: ${join(candidateDirectory, metadata.filename)}`);
|
|
56
|
-
console.log(
|
|
57
|
-
|
|
58
|
-
console.log("
|
|
59
|
-
console.log("
|
|
82
|
+
console.log(`Reused exact-tree full verification from ${fullVerification.verified_at}.`);
|
|
83
|
+
parseReleaseVersion(pkg.version);
|
|
84
|
+
console.log("Before live activation, the coding agent must reverify current source identity, package modes, tarball integrity, and disposable installability with direct Node argv (not npm lifecycle):");
|
|
85
|
+
console.log("node scripts/start-release-candidate.mjs --install-only");
|
|
86
|
+
console.log("Only after that non-live preflight succeeds and the repository owner explicitly authorizes activation may the owner or authorized agent run this exact persistent command:");
|
|
87
|
+
console.log("npm run release:candidate:activate -- --allow-worker-deploy");
|
|
88
|
+
console.log("The guarded command installs the exact candidate in the private state root, updates the same-name Worker, verifies candidate relay readiness, replaces the login daemon, verifies the background handoff, and exits while the service remains active.");
|
|
89
|
+
console.log("After activation, the coding agent derives the activated package root from the activation record runtime_entry and runs its packaged canary as direct Node argv from this repository cwd:");
|
|
90
|
+
console.log("node <activated-runtime-package>/scripts/release-oauth-canary.mjs --allow-live-oauth-canary");
|
|
91
|
+
console.log("For prereleases, the workspace script and npm lifecycle forms are source/developer paths only: they receive ordinary accounting and fail runtime-provenance evidence because the executing package must match activation runtime_entry.");
|
|
92
|
+
console.log("Only after the canary and observed live verification succeed does the coding agent record acceptance with:");
|
|
60
93
|
console.log(`npm run release:accept -- --confirm \"${phrase}\"`);
|
|
61
94
|
console.log("Automated tests alone do not authorize acceptance or the first GitHub push.");
|
|
62
95
|
}
|
|
63
96
|
|
|
64
|
-
function recordAcceptance() {
|
|
97
|
+
function recordAcceptance(npmCli) {
|
|
65
98
|
const pkg = readPackage();
|
|
66
99
|
const supplied = argumentValue("--confirm");
|
|
67
100
|
const expected = confirmationPhrase(pkg.name, pkg.version);
|
|
68
101
|
if (supplied !== expected) {
|
|
69
|
-
throw new Error(`
|
|
70
|
-
}
|
|
71
|
-
const pending = readJson(candidateManifestPath, "release candidate manifest");
|
|
72
|
-
if (pending.result !== "pending" || pending.package_name !== pkg.name || pending.package_version !== pkg.version) {
|
|
73
|
-
throw new Error("release candidate manifest does not match the current package");
|
|
102
|
+
throw new Error(`candidate verification confirmation must exactly match: ${expected}`);
|
|
74
103
|
}
|
|
104
|
+
const pending = validateCandidateManifest(readJson(candidateManifestPath, "release candidate manifest"), {
|
|
105
|
+
packageName: pkg.name,
|
|
106
|
+
packageVersion: pkg.version,
|
|
107
|
+
});
|
|
75
108
|
verifyTarball(join(candidateDirectory, pending.filename), pending);
|
|
109
|
+
readReleaseOAuthCanaryEvidence(root, {
|
|
110
|
+
package_name: pending.package_name,
|
|
111
|
+
package_version: pending.package_version,
|
|
112
|
+
shasum: pending.shasum,
|
|
113
|
+
integrity: pending.integrity,
|
|
114
|
+
promotion_content_sha256: pending.promotion_content_sha256,
|
|
115
|
+
});
|
|
76
116
|
|
|
77
117
|
const verificationDirectory = join(candidateDirectory, "verification");
|
|
78
|
-
rmSync(verificationDirectory, { recursive: true, force: true });
|
|
118
|
+
rmSync(verificationDirectory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
|
|
79
119
|
mkdirSync(verificationDirectory, { recursive: true });
|
|
80
|
-
const current = packProject(root, verificationDirectory);
|
|
120
|
+
const current = packProject(root, verificationDirectory, { npmCli, env: process.env });
|
|
81
121
|
for (const key of ["package_name", "package_version", "filename", "shasum", "integrity"]) {
|
|
82
122
|
if (pending[key] !== current[key]) {
|
|
83
123
|
throw new Error(`source changed after candidate preparation: ${key} no longer matches`);
|
|
84
124
|
}
|
|
85
125
|
}
|
|
86
126
|
|
|
127
|
+
const promotionDigest = computePromotionContentDigest(root, { npmCli });
|
|
128
|
+
if (pending.promotion_content_sha256 !== promotionDigest) {
|
|
129
|
+
throw new Error("source changed after candidate preparation: promotion content digest no longer matches");
|
|
130
|
+
}
|
|
131
|
+
|
|
87
132
|
const record = {
|
|
88
133
|
schema_version: ACCEPTANCE_SCHEMA_VERSION,
|
|
89
134
|
result: "passed",
|
|
@@ -94,18 +139,19 @@ function recordAcceptance() {
|
|
|
94
139
|
shasum: current.shasum,
|
|
95
140
|
integrity: current.integrity,
|
|
96
141
|
accepted_at: new Date().toISOString(),
|
|
97
|
-
package_content_sha256: computePortablePackageDigest(),
|
|
142
|
+
package_content_sha256: computePortablePackageDigest(npmCli),
|
|
143
|
+
promotion_content_sha256: promotionDigest,
|
|
98
144
|
};
|
|
99
145
|
verifyAcceptanceRecord(record, current);
|
|
100
146
|
const path = acceptancePath(root, pkg.version);
|
|
101
147
|
mkdirSync(dirname(path), { recursive: true });
|
|
102
|
-
|
|
103
|
-
console.log(`
|
|
148
|
+
replaceFileAtomicallySync(path, `${JSON.stringify(record, null, 2)}\n`, { mode: 0o644 });
|
|
149
|
+
console.log(`Local candidate acceptance recorded: ${path}`);
|
|
104
150
|
console.log("Commit this record with the candidate. Any packaged-file change invalidates it.");
|
|
105
151
|
}
|
|
106
152
|
|
|
107
|
-
function verifyAcceptance() {
|
|
108
|
-
const result = verifyCurrentReleaseAcceptance(root);
|
|
153
|
+
function verifyAcceptance(npmCli) {
|
|
154
|
+
const result = verifyCurrentReleaseAcceptance(root, { npmCli, env: process.env });
|
|
109
155
|
if (!result.required) {
|
|
110
156
|
console.log(`Local release acceptance is not required for ${result.version}.`);
|
|
111
157
|
return;
|
|
@@ -113,18 +159,22 @@ function verifyAcceptance() {
|
|
|
113
159
|
console.log(`Local release acceptance matches ${result.metadata.filename} (${result.metadata.shasum}).`);
|
|
114
160
|
}
|
|
115
161
|
|
|
116
|
-
function computePortablePackageDigest() {
|
|
117
|
-
|
|
118
|
-
if (!npmCli) throw new Error("portable package digest requires npm_execpath");
|
|
162
|
+
function computePortablePackageDigest(npmCli) {
|
|
163
|
+
if (!npmCli) throw new Error("portable package digest requires a hardened npm CLI");
|
|
119
164
|
const temporary = mkdtempSync(join(tmpdir(), "mbm-release-index-"));
|
|
120
165
|
const indexPath = join(temporary, "index");
|
|
121
|
-
const env = { ...process.env, GIT_INDEX_FILE: indexPath };
|
|
166
|
+
const env = { ...nestedNpmEnvironment(process.env), GIT_INDEX_FILE: indexPath };
|
|
167
|
+
let digest = "";
|
|
168
|
+
let primaryError = null;
|
|
122
169
|
try {
|
|
123
|
-
runChecked(
|
|
124
|
-
runChecked(
|
|
170
|
+
runChecked(git, ["read-tree", "HEAD"], { env });
|
|
171
|
+
runChecked(git, ["add", "--all", "--", "."], { env });
|
|
125
172
|
const packed = runChecked(process.execPath, [
|
|
126
173
|
npmCli,
|
|
127
174
|
"pack",
|
|
175
|
+
"--workspaces=false",
|
|
176
|
+
"--global=false",
|
|
177
|
+
"--prefix", root,
|
|
128
178
|
"--ignore-scripts",
|
|
129
179
|
"--silent",
|
|
130
180
|
"--dry-run",
|
|
@@ -134,12 +184,20 @@ function computePortablePackageDigest() {
|
|
|
134
184
|
join(root, ".github", "scripts", "verify-release-acceptance.mjs"),
|
|
135
185
|
"--print-digest",
|
|
136
186
|
], { env, input: packed.stdout });
|
|
137
|
-
|
|
187
|
+
digest = verifier.stdout.trim();
|
|
138
188
|
if (!/^[0-9a-f]{64}$/.test(digest)) throw new Error("portable package digest output is invalid");
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
189
|
+
} catch (error) {
|
|
190
|
+
primaryError = error;
|
|
191
|
+
}
|
|
192
|
+
let cleanupError = null;
|
|
193
|
+
try { rmSync(temporary, { recursive: true, force: true }); }
|
|
194
|
+
catch (error) { cleanupError = error; }
|
|
195
|
+
if (primaryError && cleanupError) {
|
|
196
|
+
throw new AggregateError([primaryError, cleanupError], "portable package digest failed and temporary cleanup was incomplete");
|
|
142
197
|
}
|
|
198
|
+
if (primaryError) throw primaryError;
|
|
199
|
+
if (cleanupError) throw cleanupError;
|
|
200
|
+
return digest;
|
|
143
201
|
}
|
|
144
202
|
|
|
145
203
|
function runChecked(file, args, { env = process.env, input } = {}) {
|
|
@@ -148,12 +206,12 @@ function runChecked(file, args, { env = process.env, input } = {}) {
|
|
|
148
206
|
encoding: "utf8",
|
|
149
207
|
env,
|
|
150
208
|
input,
|
|
209
|
+
timeout: 5 * 60 * 1000,
|
|
210
|
+
killSignal: "SIGKILL",
|
|
211
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
151
212
|
windowsHide: true,
|
|
152
213
|
});
|
|
153
|
-
if (result.error) throw result
|
|
154
|
-
if (result.status !== 0) {
|
|
155
|
-
throw new Error(`${file} ${args[0] || ""} failed: ${String(result.stderr || result.stdout).trim()}`);
|
|
156
|
-
}
|
|
214
|
+
if (result.error || result.status !== 0) throw new Error(releaseCommandFailure(file, args, result));
|
|
157
215
|
return result;
|
|
158
216
|
}
|
|
159
217
|
|
|
@@ -181,6 +239,6 @@ function confirmationPhrase(name, version) {
|
|
|
181
239
|
}
|
|
182
240
|
|
|
183
241
|
function fail(message) {
|
|
184
|
-
console.error(
|
|
242
|
+
console.error(JSON.stringify(releaseDiagnosticEvent("release.acceptance.failed", message, 1200)));
|
|
185
243
|
process.exit(1);
|
|
186
244
|
}
|