From 6c7dff94e1bd8cf067b71b82f90136855332b344 Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Fri, 13 Nov 2026 17:28:12 +0000 Subject: [PATCH] Bind the final SDK PHP 8.2 transition runtime to its caller --- qualification/composer-container-trust.json | 78 +++++++++++++++++++ tests/fixtures/sdk-php-transition-runtime.yml | 52 +++++++++++++ tests/test_composer_trust_contract.py | 26 +++++++ 3 files changed, 156 insertions(+) create mode 100644 tests/fixtures/sdk-php-transition-runtime.yml diff --git a/qualification/composer-container-trust.json b/qualification/composer-container-trust.json index ebb76c7..7c61713 100644 --- a/qualification/composer-container-trust.json +++ b/qualification/composer-container-trust.json @@ -608,6 +608,84 @@ "mode": 420 } } + }, + "sdk-php-transition82-ci": { + "target": "sdk-php", + "workflows": { + "ci.yml": [ + "laravel-transition-compat" + ] + }, + "commands": [ + "bash \"$GITHUB_WORKSPACE/scripts/ci/setup-php-container.sh\" \"8.2\"" + ], + "environment": [ + "SDK_PHP_CI_IMAGE", + "SDK_PHP_CI_ROOT", + "SDK_PHP_CI_STATE" + ], + "absent_files": [ + "docker/php-ci/Dockerfile.dockerignore", + "docker/php-ci/Dockerfile.81.dockerignore" + ], + "files": { + ".dockerignore": { + "sha256": "77afbcb7937677f268f626472f8cf3fef5c8a7384e743df09e081d38279383e1", + "mode": 420 + }, + "docker/php-ci/Dockerfile": { + "sha256": "81d23fbbee7e4ee97ca14df9d17982aa664335b94499c5019662259fe0387eaa", + "mode": 420 + }, + "docker/php-ci/Dockerfile.81": { + "sha256": "c16c2c06252b1b179ccab41876ce76a30febf8a6fd5d92234a2bbed54d7be222", + "mode": 420 + }, + "docker/php-ci/ci-defaults.ini": { + "sha256": "656a644d0a5392488dd843614c40c763a950294e4af6eee124c919930a21a72f", + "mode": 420 + }, + "docker/php-ci/verify-php-trust.php": { + "sha256": "529c282e7422202bf25565431a6391de388f86dfe5bfd6c75cf21daa56ffa75e", + "mode": 420 + }, + "scripts/ci/php-container-images.json": { + "sha256": "389247efc6e551b553314bfe64f66aaef3a96c0bf659e6f78322b84b0dc9860b", + "mode": 420 + }, + "scripts/ci/setup-php-container.sh": { + "sha256": "ae216b71a15ab40098e4341e6ab2ebe4f2a3cecc497cbb9eb412bfd19c446cf9", + "mode": 493 + }, + "scripts/ci/run-php-container.sh": { + "sha256": "025b2def722eed3a3e534698333478bd82d6c735dca14cf8c2dbb8c3bb0392e3", + "mode": 493 + }, + "tests/ci/test_php_container_tls.py": { + "sha256": "d73a2a3c494bd31bd4f8b5215070aa7ff4807c3e4cb75e8b3eb51d2fe057c0ae", + "mode": 420 + }, + "docker/brotli/install-vendor.sh": { + "sha256": "d7eb8b2a3e0af1c3072a56bcb81632b22f061f211d8fe5e57ee901c8bf94c92f", + "mode": 420 + }, + "docker/brotli/verify-runtime.php": { + "sha256": "580cc465e349f3872eca592355294e7320fe7f1a4560ff5d4c83d5900921c00e", + "mode": 420 + }, + "docker/brotli/verify-system-brotli.c": { + "sha256": "3353927d206aaf5e63157e46be715c6cbee46bac777e29f8f9e25c4c1f656667", + "mode": 420 + }, + "docker/brotli/version": { + "sha256": "e064953e075ddb99fb7b48ad29e215f2dfa075812c127eb1d6ab680e9920fba2", + "mode": 420 + }, + "tests/ci/test_php_container_isolation.py": { + "sha256": "209b1382e473f674dad3f6a1fbc447557dba647df2d23b70c8af1db2dab97697", + "mode": 420 + } + } } } } diff --git a/tests/fixtures/sdk-php-transition-runtime.yml b/tests/fixtures/sdk-php-transition-runtime.yml new file mode 100644 index 0000000..8a9eff8 --- /dev/null +++ b/tests/fixtures/sdk-php-transition-runtime.yml @@ -0,0 +1,52 @@ +# Proposed SDK source 094eb50771d8e5a42297b85c51aba1021888d031. +jobs: + laravel-transition-compat: + name: Laravel ${{ matrix.source }} to service mode + runs-on: ubuntu-24.04 + timeout-minutes: 20 + needs: action-policy + strategy: + fail-fast: false + matrix: + include: + - source: embedded-v1 + source_mode: embedded_v1 + php: '8.2' + laravel: ^12.0 + workflow: ^1.0 + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 + with: + persist-credentials: false + - name: Check out the fixed APT prerequisite + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 + with: + repository: durable-workflow/.github + ref: 18783be6bef737cc778e4c7282a8797e39daa61a + path: .central-apt-source + persist-credentials: false + - name: Select Ubuntu's Python 3.12 + run: '/usr/bin/python3 -I -S -c ''import sys; assert sys.version_info[:2] == + (3, 12)'' + + echo /usr/bin >> "$GITHUB_PATH" + + ' + - name: Select authenticated dependency trust + uses: durable-workflow/.github/.github/actions/bootstrap-patched-pip@242c2a7fb23459db2e1ada5f84dbee6d61d9b1e5 + with: + clients: pip,python,composer,curl,git + - name: Disable APT download retries (CVE-2026-109518) + run: echo 'Acquire::Retries "0";' | sudo tee /etc/apt/apt.conf.d/99-no-retries + >/dev/null + - name: Prepare the reviewed PHP container runtime + run: bash "$GITHUB_WORKSPACE/scripts/ci/setup-php-container.sh" "8.2" + - name: Verify Composer trust before requests + uses: durable-workflow/.github/.github/actions/verify-composer-trust@242c2a7fb23459db2e1ada5f84dbee6d61d9b1e5 + - name: Exercise the established Laravel application transition + env: + LARAVEL_REQUIREMENT: ${{ matrix.laravel }} + SDK_PATH: ${{ github.workspace }} + SOURCE_MODE: ${{ matrix.source_mode }} + WORKFLOW_REQUIREMENT: ${{ matrix.workflow }} + run: scripts/ci/laravel-service-transition-smoke.sh diff --git a/tests/test_composer_trust_contract.py b/tests/test_composer_trust_contract.py index 00b22c2..0847b6a 100644 --- a/tests/test_composer_trust_contract.py +++ b/tests/test_composer_trust_contract.py @@ -689,6 +689,32 @@ def validate(candidate): with self.assertRaises(PolicyError): validate(changed) + def test_sdk_transition_job_requires_its_own_fixed_minor_runtime(self): + repository = Path(__file__).resolve().parents[1] + catalog = json.loads((repository / "qualification/composer-container-trust.json").read_text()) + catalog["requests"] = {} + document = yaml.safe_load((repository / "tests/fixtures/sdk-php-transition-runtime.yml").read_text()) + policy = json.loads((repository / "qualification/policy.json").read_text()) + # Expand the actual driver path into its first request sink. The SDK's + # full transition qualification owns execution of the complete script. + driver = self.root / "scripts/ci/laravel-service-transition-smoke.sh" + driver.parent.mkdir(parents=True, exist_ok=True) + driver.write_text('composer create-project "laravel/laravel:${laravel_requirement}" "$application"\n') + + def validate(candidate): + with (mock.patch("scripts.qualification_policy._composer_container_catalog", return_value=catalog), + mock.patch("scripts.qualification_policy._require_composer_runtime_sources")): + return verify_composer_network_sinks(policy, "sdk-php", {"ci.yml": yaml.safe_dump(candidate)}, self.root) + + self.assertTrue(validate(document)) + for recipe in ("sdk-php-unit-ci", "sdk-php-carbon-ci", "sdk-php-framework-81-ci", "sdk-php-framework-84-ci"): + changed = deepcopy(document) + setup = next(step for step in changed["jobs"]["laravel-transition-compat"]["steps"] + if "setup-php-container.sh" in step.get("run", "")) + setup["run"] = catalog["runtime_setups"][recipe]["commands"][0] + with self.subTest(recipe=recipe), self.assertRaises(PolicyError): + validate(changed) + def test_a_symlinked_build_input_directory_refuses_even_when_bytes_match(self): original = self.root / "docker/php" moved = self.root / "actual-build-input"