diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index b3fa54543..943679504 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -57,22 +57,3 @@ jobs: ${{ env.CLOUD_IMAGE }}:deploy-prod cache-from: type=gha,scope=cloud-core-prod cache-to: type=gha,mode=max,scope=cloud-core-prod - - name: Configure SSH - env: - SSH_KEY: ${{ secrets.JP09_SSH_KEY }} - KNOWN_HOSTS: ${{ secrets.JP09_KNOWN_HOSTS }} - run: | - install -m 700 -d ~/.ssh - install -m 600 /dev/null ~/.ssh/id_ed25519 - printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519 - printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts - - name: Upload release manifest and deploy - env: - HOST: ${{ secrets.JP09_HOST }} - USER: ${{ secrets.JP09_USER }} - PORT: ${{ secrets.JP09_PORT }} - run: | - remote="$USER@$HOST" - ssh -p "$PORT" "$remote" 'install -d -m 700 /opt/langbot-cloud-prod' - scp -P "$PORT" deploy/prod/docker-compose.yml deploy/prod/deploy.sh "$remote:/opt/langbot-cloud-prod/" - ssh -p "$PORT" "$remote" "chmod 700 /opt/langbot-cloud-prod/deploy.sh && /opt/langbot-cloud-prod/deploy.sh prod-${GITHUB_SHA}" diff --git a/src/langbot/pkg/cloud/bootstrap.py b/src/langbot/pkg/cloud/bootstrap.py index 8e9ee1886..c8341e56c 100644 --- a/src/langbot/pkg/cloud/bootstrap.py +++ b/src/langbot/pkg/cloud/bootstrap.py @@ -138,8 +138,14 @@ class VerifiedCloudDeployment: if plugin_worker.get('require_hard_limits') is not True: raise CloudBootstrapError('Cloud Runtime requires plugin.worker.require_hard_limits=true') box_config = config.get('box', {}) - if box_config.get('enabled') is not True: - raise CloudBootstrapError('Cloud runtime requires box.enabled=true') + box_enabled = box_config.get('enabled') + if box_enabled is False: + # Explicitly disabling Box removes the sandbox surface entirely and + # therefore does not weaken tenant isolation. Validate the strict + # runtime/admission contract only when the surface is enabled. + return + if box_enabled is not True: + raise CloudBootstrapError('Cloud runtime requires box.enabled to be an explicit boolean') if box_config.get('backend') != 'nsjail': raise CloudBootstrapError('Cloud runtime requires box.backend=nsjail') runtime_endpoint = str(box_config.get('runtime', {}).get('endpoint', '') or '').strip() diff --git a/tests/unit_tests/cloud/test_bootstrap.py b/tests/unit_tests/cloud/test_bootstrap.py index 77ccefa5d..e27367d8d 100644 --- a/tests/unit_tests/cloud/test_bootstrap.py +++ b/tests/unit_tests/cloud/test_bootstrap.py @@ -228,10 +228,23 @@ async def test_cloud_pgvector_contract_is_fail_closed(pgvector_config, message): ) +async def test_cloud_runtime_allows_explicitly_disabled_box(): + config = _cloud_config() + config['box']['enabled'] = False + + deployment = await resolve_deployment( + instance_uuid='instance-a', + instance_config=config, + entry_points=lambda: _EntryPoints([_EntryPoint(_Provider())]), + now=1_000, + ) + + assert isinstance(deployment, VerifiedCloudDeployment) + + @pytest.mark.parametrize( ('mutate', 'message'), [ - (lambda config: config['box'].update(enabled=False), 'box.enabled=true'), (lambda config: config['box'].update(backend='docker'), 'box.backend=nsjail'), (lambda config: config['box']['runtime'].update(endpoint=''), 'box.runtime.endpoint'), (