diff --git a/Dockerfile b/Dockerfile index b51a2cfa97..00fe86304d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -250,7 +250,25 @@ RUN set -eu; \ test -n "$specifiers" || { echo "ERROR: CLOUD_BUNDLED_SERVER_DEPS names no package" >&2; exit 1; }; \ pnpm add --ignore-workspace --no-lockfile $specifiers +# Use the same qualified interpreter as the Daytona provider-pack build. +# The controller owns this pack and its manifest; remote OpenCode/ACPX launches +# verify sandbox bytes against it, or stage this complete pack when needed. +# Keep it Cloud-only so ordinary local execution and the production target do +# not acquire remote-provider configuration. +FROM node:24-bookworm@sha256:9137a20e25879e0b557227b57e3ee4e9af4bde29eb3db66134cd1723e84f830b AS cloud-provider-pack +RUN corepack enable +WORKDIR /app +COPY --from=build /app /app +ARG PAPERCLIP_BUILD_COMMIT +RUN test -n "${PAPERCLIP_BUILD_COMMIT}" \ + && PAPERCLIP_RUNNER_SOURCE_REVISION="${PAPERCLIP_BUILD_COMMIT}" \ + node packages/paperclip-runner/scripts/build-provider-pack.mjs /provider-pack \ + && node packages/paperclip-runner/scripts/verify-pi-provider-launch.mjs /provider-pack \ + && chmod -R a+rX /provider-pack + FROM production AS cloud +COPY --from=cloud-provider-pack /provider-pack /opt/paperclip-runner/provider-pack +ENV PAPERCLIP_RUNNER_REMOTE_PROVIDER_PACK_PATH=/opt/paperclip-runner/provider-pack COPY --chown=node:node --from=cloud-plugins /app/packages/plugins/sandbox-providers /app/packages/plugins/sandbox-providers # Land the isolated install inside the server's own `node_modules`, the # directory Node's module resolution walks up to from `/app/server` for diff --git a/doc/sandbox-work-folders.md b/doc/sandbox-work-folders.md index a2f57f035f..cdce71a5dc 100644 --- a/doc/sandbox-work-folders.md +++ b/doc/sandbox-work-folders.md @@ -151,6 +151,16 @@ All routes start at ## Acceptance gate +The Cloud app image includes a build-owned remote provider pack at +`/opt/paperclip-runner/provider-pack` and configures +`PAPERCLIP_RUNNER_REMOTE_PROVIDER_PACK_PATH` to that directory. Native OpenCode +and ACPX runs verify the sandbox's installed pack against this manifest; if it +differs, the host stages its complete pack before launch. The pack is built +from the app revision, includes the production lockfile and artifact hashes, +and must pass its provider-launch checks during the image build. It belongs to +the app image, not the workspace volume or a scoped file collection. Ordinary +local execution is unchanged. + Automated tests do not qualify a deployed runner image. Before merging, use a new pinned staging stack with the branch's Cloud image and matching migrator. The deployed harness must target that tenant URL without launching a local