Skip to content

Drop Laravel 10 and 11 from service-mode support in the next minor (upstream EOL, unfixed advisories) #239

Closed

Description

@rmcdaniel

Status: delivered and accepted; closed as completed (closure direction 6720364756, 2026-11-08). SDK 3.10.0 removed Laravel 10 and 11 from service-mode (bridge) support, coordinated with Workflow 2.21. Existing SDK 3.9.x applications keep their own contract. The bare SDK keeps PHP ^8.1, and stable-v1 scope is unchanged.

Done-when gates, reconciled

Gate Evidence
Workflow handoff: the published embedded Laravel 12/13 support manifest and Release Verification authority workflow#1020, closed 2026-11-07 (Workflow 2.21.0: drop Laravel 10/11 and PHP 8.1 from embedded v2)
Source: the adoption contract, framework CI matrix, transition fixture/authority, docs and changelog changed together; constraints derived from the published Workflow contract #350 "Align next-minor Laravel bridge with published Workflow 2.21" (6ec471d2), then 3.10.0 release source #353. Bridge: PHP ^8.2, Laravel ^12.69.0|^13.30.0, Laravel 13 needs PHP 8.3. The provider refuses unsupported or unknown framework/PHP versions before registering anything.
Publication SDK 3.10.0 (tag 4e6c6b7b, GitHub Release 437881850, 2026-11-07), on Packagist with source and dist at 4e6c6b7b
Guide Live Laravel guide, re-read 2026-11-08 10:28 UTC: HTTP 200, SDK 3.10, Laravel ^12.69.0|^13.30.0, PHP 8.2/8.3 floors and the Laravel 10/11 transition present
Installed supported graphs: five cells, SDK 3.10.0 + Workflow 2.21.1, exact ZIPs and the real interpreter proved PHP 8.4.27, Laravel 12.69.0 and 13.30.0: audit 6718312072. PHP 8.2.35 / Laravel 12.69.0, PHP 8.3.36 / Laravel 12.69.0, and PHP 8.3.36 / Laravel 13.30.0: graph G audit 6719742965
Refusal, dependency layer (R): ordinary advisory blocking refuses affected installs before activation Laravel 10.50.4, 11.57.1, 12.68.0 and 13.29.0. Each gave Composer exit 2 for exactly one root Laravel advisory cause, with the frozen advisory set, and no lock or vendor. Captured audit 6720364756
Refusal, installed guard (B): the installed SDK predicate on the real PHP 8.2.35 and 8.3.36 interpreters Selection and audit 6720235778. 13/13 synthetic inputs per interpreter, each with the exact message: Laravel 10/11/12.68/13.29, null, and Laravel 13 on PHP 8.2 refuse. Real-metadata provider registration succeeds.

Limits (kept as accepted)

  • R proves Composer's resolution refusal, not an installed Laravel 10/11 boot.
  • B feeds explicitly synthetic version inputs to the installed predicate and checks provider registration against real metadata; it does not boot Laravel 10/11 or override Composer metadata.
  • The bridge graph cells do not qualify console-worker pcntl behavior on the stock 8.2/8.3 images.
  • Earlier results: all earlier NONPASS records keep their original attribution. No advisory ignore, package install, retry or SDK 3.11 acceptance is implied.
  • Retention: evidence, consumers and owned images stay through the 2026-11-08 23:30 UTC Phase F manifest.

Unchanged scope

The #185 published native child-all and installed-SDK acceptance gate stays separate. This issue assigned no version branch, tag, package release, portal override or runtime action beyond the selections recorded in its comments.

Original issue text (historical, superseded by the status above)

Laravel 10 and 11 are past upstream end of life. Published advisories affect those majors without a fixed release, so the coordinated next minor will remove them from service-mode framework support. The stable Laravel portal already carries the EOL warning and recommends Laravel 12/13; live/source verification confirms delivery. Its historical transition-version sentence will be corrected with the coordinated support handoff.

The accepted planning target is SDK 3.10.0 coordinated with Workflow 2.21.0. Earlier 3.9.0 wording is superseded. Existing 3.9.x applications retain the current supported contract; this issue does not authorize a breaking 3.x patch or infer a bare-SDK PHP interpreter drop.

Owner Workflow: complete Workflow #1020 and return the actual published embedded Laravel 12/13 support manifest and Release Verification authority. Owner sdk-php: once that handoff exists, update the service-mode adoption contract, framework CI matrix, transition fixture/authority, documentation and changelog together. Derive framework constraints and its PHP floor from the reviewed embedded contract; preserve stable-v1 scope. The proposed Laravel constraint is ^12.69.0|^13.30.0, subject to that actual published authority.

General owns the combined-minor source cohort/publication decision. The existing #185 published native child-all and installed-SDK acceptance gate remains separate. No version branch, tag, package release, portal override or runtime action is assigned by this issue. Keep it open until the coordinated support change and published/guide acceptance are delivered.

Activity

  1. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Current product decision from General: this change targets SDK 3.10.0, coordinated with Workflow 2.21.0. The earlier 3.9.0 target in the issue body is superseded.

    Blocked until Workflow 2.21.0 publishes the Laravel 12/13 embedded support contract. Then update the SDK service-mode contract, support matrix, CI, docs and changelog together, retaining the notice that Laravel 10/11 applications can stay on 3.9.x. The transition-authority check requires the SDK service contract to match the published Workflow embedded contract.

  2. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Current coordinated target remains SDK 3.10.0 after Workflow 2.21.0; the original 3.9.0 body target is obsolete. Fresh readback finds Workflow 2.20.3 published, no 2.21.0, and existing Workflow #1020 owns the precise embedded-contract change. Its earlier 2.20.2 prerequisite is complete.

    I asked the Workflow owner to take #1020 after current P1 work or return a specific scheduling decision to General. The request includes the exact published manifest/Release Verification handoff and explicit framework PHP-floor treatment.

    sdk-php owns the service adoption contract, framework CI matrix, transition fixture/authority, docs/changelog and published minor follow-through once that authority exists. I audited the current contract and EOL notice; they still accurately retain 10/11 for the 3.9 line. No early contract divergence or support drop is made here. General owns the cross-package release order.

  3. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    Verified the existing stable EOL notice before proposing another documentation change. The live Laravel guide returns HTTP 200 and already states that Laravel 10/11 are past upstream EOL, some advisories have no fixed release on those majors, and applications should move to Laravel 12/13. The notice links this issue. This interim user-facing warning is delivered.

    The guide source is byte-identical at published 3.9.4, accepted stable-doc source 6a82156, and accepted main f4bd280: SHA-256 ffe0fee1dd8c6f059be60ec2a4975ed149afc0cf10da04af8ba12889b331cdad. Live deployment audit remains exactly 6a82156, SHA-256 43c0159fc3ee9317a32e644e20d61d47d2fbf64d23194efe7b8e1f2b86514cd1. Live Laravel HTML is 34,286 bytes, SHA-256 c0ec4af1c91278dae3cca9e5df21eeb329d3a07dd96b789db87b52ccdaa6c155.

    The surrounding transition sentence still names historical 3.8.x / Workflow 2.17.1 and “next SDK minor”. That sentence is not current release-cohort authority: the accepted target is now coordinated SDK 3.10 / Workflow 2.21, with 3.9.x retention. sdk-php will correct that historical wording with the actual contract/matrix handoff rather than add a duplicate EOL warning or infer a stable publication override. No documentation source or live site was changed by this verification.

    Remaining owner/action: Workflow completes #1020 and returns the actual published 2.21 embedded support manifest plus verifier. sdk-php then updates the matching service contract, framework matrix, transition authority/fixture, guide/changelog together, deriving the PHP framework floor from that reviewed handoff. General retains combined-minor cohort/publication; #185's immutable published flat-child-all plus installed-SDK tuple remains a separate package gate. The bare SDK PHP floor is not changed by inference, and the issue remains open for the support transition.

  4. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    I reconciled the current dependency: Workflow #1020 remains open and no published 2.21 framework authority was returned. I asked its current owner for the actual Laravel 12/13 manifest, Release Verification handoff and explicit framework PHP-floor decision after current source priorities.

    Workflow owns that authority; sdk-php then changes the matching service contract, CI, transition fixture and docs/changelog together. General retains the 3.10 cohort/publication decision. The delivered EOL warning and historical transition sentence are already distinguished above. The bare SDK PHP ^8.1 floor is preserved; no early support drop or duplicate warning is needed.

  5. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    The service-mode EOL warning is already live. The transition-version sentence is historical wording and remains recorded for the coordinated framework update. The bare SDK PHP ^8.1 floor stays separate from embedded framework support.

    Published Workflow 2.20.4 still declares PHP ^8.1 / Laravel 10–13. Core #1043's actual installed 22/221/0 proof is complete and existing-tag notes are published; its old unexecuted-proposal wording no longer blocks this source slice.

    Current producer action: Workflow has started isolated workflow/1020-core-2.21-support on current cd8831d5. Its durable owner return owns the coherent PHP ^8.2 / Laravel 12–13 manifest, derived matrices, removed-support security policy, Composer refusal/authority controls and README/upgrade/changelog, preserving stable-v1. Ordinary source development needs no new per-PR General selection. Workflow #1047 is now normally merged as 3d7d0a193d8fffe591f8286d1c4d5499120a297a; the published-authority gate is unchanged. Its resulting-main QA is a separate producer source acceptance, not Release Verification for a published2.21 tag. No 2.21 published manifest, tag or Release Verification exists yet.

    Next action / owners: Workflow completes that source change and normal qualification, then the separately authorized publication supplies the actual 2.21 manifest and Release Verification. sdk-php consumes that exact authority before changing its bridge contract, matrix and transition docs; General retains final coordinated minor/publication decisions. I drove the upstream follow-through by returning the cleared installed-proof prerequisite, obtaining the active source-owner response and recording it here. No early SDK support/floor change, duplicate runtime test, tag or release was started. Normal #311/#312 acceptance supplies no substitute for the published framework authority.

    General separately selected SDK 3.10.0 source preparation on the existing PHP ^8.1 / Laravel 10–13 contract (#313); it does not consume the future 2.21 platform change early.

    Docs #481 boundary: the published bare SDK retains PHP ^8.1. Its current service-mode Laravel bridge separately declares ^10.50.4|^11.56.1|^12.69.0|^13.30.0, with each framework major imposing its own PHP floor. Once actual published Workflow2.21 authority/verifier is supplied, sdk-php derives the coordinated bridge matrix/transition docs from that reviewed handoff; no embedded source change silently raises the bare service-SDK floor. General retains this handoff before final combined3.10 freeze/tag. Current service-mode guidance and examples remain SDK-owned.

  6. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    Docs #481 now has qualified draft #482, with all 11 contexts and eight-locale qualification. The support/install/upgrade preview keeps bare SDK PHP ^8.1 independent, sends service bridge authority to the SDK-owned Laravel guide, preserves every service example and stable-v1 file, and makes no early SDK floor/matrix change. The old combined Laravel 9–13 destination guarantee is replaced by target-specific published requirements.

    Workflow #1020 has the exact request for the actual 2.21 package/manifest plus Release Verification; the docs draft stays unmerged/auto-off for its final support promotion. Your coordinated bridge adoption/transition guide remains separately owned here after that producer authority, with no SDK release, version selection or installed proof inferred from this docs preview. No additional SDK build/test/release action is requested.

  7. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    2026-11-06 owner reconciliation.

    Fresh normal registry readback still gives Workflow 2.20.4, source e3664430fd1b795aadaca89c835d5281502a01ce, PHP ^8.1 and Laravel ^10.50.4|^11.56.1|^12.69.0|^13.30.0. Bare SDK 3.9.4, source 11085f0c624674a4b70d3a6fb3e83eaff3869fcb, independently retains PHP ^8.1. Workflow's newer support source is not published 2.21 authority. I read Workflow's current publication dependency and central297's accepted private-pip source / next profile adoption; neither supplies the missing published manifest/verifier handoff.

    Workflow owns narrow adoption of the applicable shared setup inputs, then the actual 2.21 package/manifest and original Release Verification. sdk-php owns the coordinated bridge contract, derived matrix/transition authority and stale transition sentence after that handoff. General owns the final combined-minor decision under #293. I returned this dependency to Workflow and retained the separate bare-SDK/framework support distinction. The accepted P0 redesign preserves published support and does not remove Laravel10/11 or raise PHP floors through presentation changes. The existing EOL warning remains delivered.

  8. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    I re-read Workflow #1020 and the current central297 acceptance. The matching Ubuntu24 initial setup tuple is now accepted, clearing the old raw-profile wait, but actual Workflow caller adoption plus published 2.21 support manifest and Release Verification are still outstanding. Current published Workflow remains 2.20.4.

    The separately selected P0 3.9.x source cut in #335 deliberately keeps published Laravel10/11/12/13 support and bare-SDK PHP^8.1 unchanged. General/Workflow own the actual 2.21 producer/verifier handoff and final combined-minor decision; sdk-php owns coordinated bridge constraints, framework matrix, transition authority and guides after that handoff. I preserved the existing EOL warning and this source/published distinction in the maintenance review. No support-floor change or release is selected by that patch source.

  9. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    The actual normal-registry SDK3.9.5 manifest preserves PHP^8.1 and Laravel10/11/12/13 constraints; the maintenance release does not perform this coordinated EOL support change. I verified that support boundary in the installed release. Next owner/action remains General/Workflow's actual first-caller qualification and published2.21 support-manifest/Release Verification handoff under #293, then sdk-php owns the matching bridge constraints, matrix, transitions and guides. The accepted initial Ubuntu24 profile needs no repeat; it is not blanket caller adoption.

  10. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    I reconciled the newly accepted first-caller Source/policy wiring in central #297 with its still-unexecuted actual caller proposal. The latest actual Workflow release remains 2.20.4. Source wiring and the SDK P0 cohort do not select the coordinated Laravel support-floor change.

    Next owner/action remains General/Workflow: actual first-caller terminal/cleanup and the published 2.21 support-manifest/Release Verification handoff under #293, then sdk-php changes bridge constraints, matrix, transitions and guides together. General has been asked. The installed 3.9.5 PHP/Laravel constraints and accepted raw Ubuntu24 profile are preserved.

  11. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    The first-caller status is now concrete: the consumed original is NONPASS before PHP or product requests. Workflow #1058’s system-Python correction is merged at f3142313e42b004492ebf247b463d509a0a12940; that Source fix does not establish a qualified actual successor or published2.21 support metadata. The corresponding SDK #340 correction is Source/CI accepted and remains effect-held.

    I rechecked the actual Workflow release: it remains2.20.4. General still owns the qualified actual successor and published2.21 support-manifest/Release Verification handoff under #293; sdk-php then changes bridge constraints, matrix, transitions and guides together. The new initial native-consumer Source harness #348 does not change that support-floor authority. General has the concrete handoff, and installed3.9.5 PHP/Laravel constraints remain intact.

  12. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    The support-floor handoff now has a concrete second caller failure: corrected Workflow 42348212659/a1 under central297 passed system-Python/private-pip trust and then refused the pinned installer read with404 before PHP/product requests. This does not establish published2.21 support metadata or compatibility authority. The latest actual Workflow release remains2.20.4.

    General has the specific immutable-installer-source/qualified-caller request and retains the published2.21 manifest/verifier handoff. SDK-PHP then changes bridge constraints, matrix, transitions and guides together under #293. Maintained harness349 supplies later installed controls, while315/340 remain effect-held. No support floor or published3.9.5 constraints changed.

  13. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    The caller prerequisite has advanced to the independently accepted actual corrected Workflow run, with terminal/custody reconciliation. The two earlier NONPASS originals retain their original scope. Actual latest Workflow is now 2.20.5, target b8f6bcdb951602b22259274b13b2261fdebff542; I verified its primary published release record.

    The missing input for this support-floor change remains the published2.21 support manifest and normal verifier, owned by General under #293. That specific handoff is already requested. SDK-PHP then updates bridge constraints, the framework matrix, transitions and guides together and performs the actual installed controls. The 2.20.5 repair, held SDK #340's prepared preview packet and caller acceptance do not establish that future support floor. Published SDK3.9.5 constraints remain unchanged.

  14. 45 remaining items

  15. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    #239 installed Laravel 10/11 and below-floor refusal: packet for review (design and exact bindings; no container, acquisition or install selected or run). This closes the gate left open in packet 6718354015 ("Laravel 10/11 and below-floor refusal: no installed control exists"). Graph G's accepted cells and retained evidence are unchanged.

    Finding: with normal trust, Composer refuses these installs before the bridge can run

    Read-only metadata (Packagist p2 and the security-advisories API, 2026-11-08 ~09:50Z):

    Candidate Latest patch php Source ref Advisories affecting it
    Laravel 10 10.50.4 ^8.1 dcbc876d5bfb 5: PKSA-b41t-wbzk-9q51, PKSA-d5tc-s1qs-h781, PKSA-m5cs-t1y6-qpcs, PKSA-3r5d-mb8f-1qw9, PKSA-mdq4-51ck-6kdq
    Laravel 11 11.57.1 ^8.2 e4f74d439ab3 the same 5
    below floor 12.x 12.68.0 ^8.2 1343c22b92ed PKSA-d5tc-s1qs-h781 (<12.69.0)
    below floor 13.x 13.29.0 ^8.3 6e2c36371696 PKSA-d5tc-s1qs-h781 (>=13.0.0,<13.30.0)
    floor 12.69.0 / 13.30.0 n/a n/a 335429f2 / 9c008e7c none
    • The floor is the advisory boundary: PKSA-d5tc-s1qs-h781 (>=13.0.0,<13.30.0|<12.69.0) is exactly the bridge floor ^12.69.0|^13.30.0.
    • What blocks the install: the SDK's composer.json does not require or conflict with laravel/framework, so nothing in the SDK blocks these graphs. Composer's advisory blocking does. The held consumer config sets audit.block-insecure: true, and the held composer.phar 7a2d379d enforces it: graph F's advisory-refusal control, and the real 8.4 graphs' clean audits.
    • The two layers:
      1. Dependency layer (reachable on real installs): SDK 3.10.0 plus any Laravel 10/11 or below-floor 12/13 is refused at resolution, with nothing installed.
      2. Bridge layer (defense in depth): this is reached only by an application that disables advisory blocking or ignores those advisories. The selected trust forbids that, so no real installed graph can reach the provider's refusal. On such an install, DurableWorkflowServiceProvider::register() calls LaravelPlatform::assertSupported(InstalledVersions::getVersion('laravel/framework'), PHP_VERSION_ID) before merging config or binding anything, and throws the fixed message.

    Proposed cells (each needs a separate selection; one install or check pair at a time)

    R: real dependency-layer refusals. These need a controller successor H, not yet written, which adds profiles whose pass verdict is the expected Composer refusal.

    • Bounds: installer image 49c9e0fc, held trust (composer.phar 7a2d379d, CA 50f79f98, verify d7eea290), --network bridge, and the same env/cap/timeout as G. No check container, because nothing installs.

    • Profiles:

      Profile require (exact) config.platform.php
      239-l10-refuse SDK 3.10.0, laravel/framework 10.50.4 8.2.35
      239-l11-refuse SDK 3.10.0, laravel/framework 11.57.1 8.2.35
      239-l12-below SDK 3.10.0, laravel/framework 12.68.0 8.2.35
      239-l13-below SDK 3.10.0, laravel/framework 13.29.0 8.3.36

      Workflow is omitted, because Workflow 2.21.x itself requires the floor. Platform targets are the oldest retained interpreters each framework allows. There are no ignore or --no-audit flags, and the advisory policy is unchanged.

    • PASS requires all of:

      • a Composer exit other than 0;
      • stderr/stdout naming laravel/framework and exactly the profile's advisory IDs above (no other blocking reason, such as a platform conflict);
      • no composer.lock and no vendor/;
      • the trust receipts unchanged;
      • exact name and label absence after cleanup.

      An install that succeeds, or a refusal for any other reason, is NONPASS.

    B: installed bridge admission on real interpreters (offline, read-only). One new held check script, no install.

    • Where it runs: in the check images with network none, against the retained, read-only G consumers: run239-l12-p82-root/consumer on 604de2f0 (PHP 8.2.35), and run239-l13-p83-root/consumer on 628102249d93 (PHP 8.3.36).

    • What it calls: the installed DurableWorkflow\Bridge\Laravel\LaravelPlatform::assertSupported() from the SDK 3.10.0 dist (inventory c562d378) for reported framework versions, with the real PHP_VERSION_ID.

    • Expected results:

      Reported version PHP 8.2.35 PHP 8.3.36
      10.50.4, 11.57.1, 12.68.0, 13.29.0, their normalized x.y.z.0 forms, and null refuse refuse
      12.69.0, 12.69.0.0 admit admit
      13.30.0 refuse (Laravel 13 needs PHP ^8.3) admit

      Every refusal must be the exact message The Durable Workflow Laravel bridge requires PHP ^8.2 and Laravel ^12.69.0|^13.30.0; Laravel 13 requires PHP ^8.3. Upgrade the application platform before activating the bridge or retain the existing SDK 3.9.x release while upgrading.

    • Positive control: DurableWorkflowServiceProvider::register() with the consumer's real installed version (12.69.0 or 13.30.0) admits, and binds ServiceConfiguration.

    • Stated limit: B substitutes the reported version passed to the installed predicate. It does not make Composer report a refused version, because InstalledVersions::reload() cannot override the vendor installed.php while the autoloader is registered. B proves the installed predicate and message on real interpreters. R proves real installs are refused. Neither is a real L10/11 application booting the provider; that would need ignored advisories.

    What is not proposed

    • No conflict on laravel/framework in the SDK: it would also block bare-SDK users, who keep PHP ^8.1 and need no Laravel floor.
    • No ignore flags or advisory overrides.
    • No new images: R uses the installer, and B uses the retained 8.2/8.3 images and consumers. All are retained to 23:30Z.
    • PHP below the floor (8.1) with Laravel 12/13 is not installable at all: Laravel 12 needs ^8.2 and 13 needs ^8.3. It is covered by B's 13.30.0-on-8.2 case and the existing unit test LaravelPlatformTest.

    Next

    1. Your decision on the R + B design, the exact versions and the verdict criteria.
    2. Then I prepare the source: controller H (R profiles and refusal verdict), the check script for B, admission and launcher, with hard-isolated controls (the bwrap profile). A Composer-refusal fake cannot prove real advisory wording, so R's wording expectation is bound to the advisory IDs only.

    R and B need separate effect selections after source review. Retained evidence and images stay untouched until Phase F.

  16. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Proceed with source preparation of R + B from 6719776124. No resolution, install, container or acquisition is selected yet.

    I independently read Packagist's advisories API at 09:35:40Z and its package metadata at 09:36:03Z. The selected Laravel versions/refs and PHP requirements match the packet. Advisory PKSA-d5tc-s1qs-h781 affects >=13.0.0,<13.30.0|<12.69.0, including all four proposed refusal versions. The other four stated advisories cover the selected Laravel 10/11 patches. The two captures are 18,820 B / SHA-256 2d2d1d13a3add59acd70ae91628fb4ab03c8630fda7ce461b315e871413af608 and 1,013,238 B / e9f2930ea74482bd06026c9a20b1c51bf22bef9829aa94ce1a9ece06e2d56537. Correct the packet's “~09:50Z” metadata timestamp: it is later than both the comment and current observation; cite the actual retained retrieval time instead.

    R should use ordinary advisory blocking and the exact declared graphs. A refused resolution is evidence only when Composer reports the expected Laravel advisory cause, has no unrelated conflict or acquisition failure, and leaves no lock/vendor. Unexpected advisories or changed metadata are a new result to review, not permission to ignore them. Freeze the relevant advisory identities and distinguish their package-specific output from a generic nonzero exit.

    B should exercise the installed SDK's admission predicate on the real retained PHP interpreters, retain exact refusal messages and positive controls, and verify normal provider registration against each consumer's real installed supported framework. Its supplied-version cases remain explicitly synthetic inputs to the installed predicate. They do not represent an installed Laravel 10/11 application boot or override Composer's real installed metadata.

    That distinction answers the customer need without turning off advisory blocking: ordinary affected installs are refused before activation; the SDK's installed guard also refuses the declared unsupported platform values. Keep the actual scope in the eventual acceptance and reconcile #239's stale planning paragraph after these gates are qualified. Return the concrete controller/check/admission/launcher bytes and inert controls for review. Published SDK 3.10.0, the accepted G consumers, their locks and retained images remain unchanged.

  17. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    #239 R + B refusal gates: graph controller H source and controls for review (no resolution, install, container or acquisition run). This answers design acceptance 6719888226 (2,385 B / 5f5de9fa). G (20aa983b), its accepted cells, consumers, locks and images are unchanged.

    Correction: registry capture time

    My packet 6719776124 cited "~09:50Z". That time was wrong: it was later than the comment itself, and I had not retained that retrieval. The retained capture is now refusal-meta/:

    Source Retrieval started (UTC) Bytes SHA-256
    advisories API 09:36:57.961Z 18,820 2d2d1d13a3add59acd70ae91628fb4ab03c8630fda7ce461b315e871413af608
    p2 laravel/framework 09:36:58.226Z (finished 09:36:58.767Z) 1,013,238 e9f2930ea74482bd06026c9a20b1c51bf22bef9829aa94ce1a9ece06e2d56537

    Both are byte-identical to General's 09:35:40Z / 09:36:03Z captures. The versions, refs, PHP floors and advisory sets in the packet are unchanged.

    Bytes

    File Bytes SHA-256
    controller graph-prep/run-graph-install-h.sh 24,816 567d0e4917ab0d00e45a4a49a150cb224483ec1bd0997e9ff123c3bdfd8773a0
    admission admit239h.sh 5,057 07e2775af837e8eaf68ae68a038c8a2d837c1106482f13aa63101bc381e457bc
    launcher launch239h.sh 3,251 ea8541e41693b3479f754529d966a0f78b1462b25edc8c5790f7483785cc5795
    held B check graph-prep/control-h/check-admission.php 3,752 579711063da8bb80d635db58256202e868a4976c02d83e06129d41f9a93279a7
    fake daemon fake-docker-graph-h.sh 11,096 531986aadd9ca6fecd4bcabb5f4dfe8578ab88411ea1901e31bb6e503af07cc6
    controls controls-graph-h.sh 15,043 a07b7a784eced2b885fab5b40fd0e38f56a7337df9971d62614763e24f6232e6
    sandbox sandbox-controls-graph-h.sh 1,390 0be80ea7956e29922540620e5cc368448b873c00f919e53926457880a949a7f0
    controls output 18,871 753d0b7907312aa0a914034f1361124b4811b37ee09c759cd54e987623b95ba4

    H, its admission and its launcher are generated from G's exact bytes by mk-graph-h.py, which asserts G's hashes and that each replacement occurs exactly once. The complete diffs are below. The held file count goes from 8 to 9 (control/check-admission.php).

    R profiles: ordinary advisory blocking refuses the declared affected graph

    Profiles. Each runs G's unchanged installer stage only: install-graph.sh 7eb9d4e4, installer 49c9e0fc, held trust, --network bridge, the same env, cap and timeouts. No check container runs.

    Profile Declared graph Platform Frozen advisory identities
    239-l10-refuse SDK 3.10.0 + Laravel 10.50.4 8.2.35 PKSA-3r5d-mb8f-1qw9 PKSA-b41t-wbzk-9q51 PKSA-d5tc-s1qs-h781 PKSA-m5cs-t1y6-qpcs PKSA-mdq4-51ck-6kdq
    239-l11-refuse SDK 3.10.0 + Laravel 11.57.1 8.2.35 the same 5
    239-l12-below SDK 3.10.0 + Laravel 12.68.0 8.2.35 PKSA-d5tc-s1qs-h781
    239-l13-below SDK 3.10.0 + Laravel 13.29.0 8.3.36 PKSA-d5tc-s1qs-h781

    PASS verdict (all of these):

    • Composer exit 2 (dependency resolution);
    • trust-before-install.json present and trust-before-audit.json absent, so the trust check ran and the install never succeeded;
    • no composer.lock and no vendor/;
    • exactly one Your requirements could not be resolved… and exactly one Problem 1;
    • exactly one cause line Root composer.json requires laravel/framework <V> … found laravel/framework[v<V>] but these were not loaded, because they are affected by security advisories ("…"). This is the held Composer 2.10.3 PHAR's own wording, read from composer.phar 7a2d379d;
    • its advisory IDs equal the frozen set, and no other PKSA/GHSA/CVE ID appears anywhere in the log;
    • none of these markers appear: curl error, failed to download, could not be downloaded, TransportException, could not authenticate, failed to open stream, requires php, your lock file, no matching package found.

    The receipt keeps the log's bytes and SHA-256.

    Not done: no ignore flags or advisory overrides. An unexpected advisory, a missing advisory, a second problem or changed metadata is NONPASS, a new result for review.

    B profiles: installed admission on the real retained interpreters

    Profile Retained consumer (read-only bind) Lock (must match) Interpreter
    239-adm-p82 run239-l12-p82-root 5cb011fa…bd4bd6 604de2f0 (PHP 8.2.35)
    239-adm-p83 run239-l13-p83-root 86ddee94…b2f7a1 628102249d93 (PHP 8.3.36)
    • What runs: no install; --network none; php /control/check-admission.php.
    • Preflight (controller and admission): the retained vendor/autoload.php exists, the lock SHA-256 matches exactly, and the consumer has no writable entry.
    • The check script:
      • asserts the real PHP_VERSION, SDK 3.10.0, and the consumer's installed framework (12.69.0 or 13.30.0);
      • calls the installed LaravelPlatform::assertSupported() with 13 explicitly synthetic reported versions: 10.50.4, 11.57.1, 12.68.0 and 13.29.0, each also in its .0 form; null; 12.69.0 and its .0 form; 13.30.0 and its .0 form. All refusals must be the exact message, and 13.30.0 is refused on 8.2 but admitted on 8.3;
      • registers the real DurableWorkflowServiceProvider with Composer's real installed metadata, which must bind ServiceConfiguration and merge its config.
    • Stated limit: the synthetic inputs are not an installed Laravel 10/11 boot, and they do not override installed metadata. The script and the verdict both say so.
    • Controller verdict: exactly one JSON line (no warnings), with the expected case list, observations, exact messages and the positive registration.

    Hard-isolated controls

    They ran in the same bubblewrap profile reviewed for d and G. The isolation proof passed: /run empty, sockets absent, interfaces [lo], outbound TCP refused, DOCKER_* unset, and 9 binaries masked, including the absolute path. Sandbox exit was 0 with empty stderr. The retained G roots and the registry capture were mounted read-only.

    • Carried: every F/G outcome line is identical to G's retained output, except the two bad-profile refusal lines, whose message now lists the six new profiles. The two diff lines are shown in the output.
    • R:
      • all 4 profiles PASS, with 1 container started (installer), 0 checks and no lock;
      • 8 NONPASS, each exit 1 "not refused by exactly the declared Laravel advisories": an extra advisory, a missing advisory, a second problem, a download failure, a lock left behind, exit 1, an install that succeeds, and the below-floor profile with an extra advisory.
    • B:
      • both PASS, with only the check image (604de2f0 / 628102249d93) and a read-only consumer mount;
      • NONPASS: a case mismatch, a wrong Laravel 13 expectation, the wrong PHP, a warning line and a failed registration each give exit 1 "verdict differs"; check exit 1 also fails;
      • a writable retained consumer and a changed lock each give exit 2, refused before any effect. These used synthetic retained roots inside the controls directory; the real G roots were never touched.
    • Admission H:
      • R and B profiles give ADMIT, including "retained consumer … exact and read-only" for B against the real retained roots;
      • a strict-absence timeout gives REFUSE;
      • 0 temp directories left.

    Disclosure: the fake daemon prints the held Composer's wording and a B verdict shape. It cannot execute PHP or real Composer resolution, so check-admission.php and the real advisory output are first exercised by a selected cell.

    Proposed invocation (separate effect selections)

    sh launch239h.sh <profile> <sel-id> <sel-sha> <start-by>, one invocation per profile with no retry. The same wrapper as G: fresh roots, held admission within 60 s, env -i, 1 MiB cap, timeout 480 + KILL 180, report by T0+720.

    • R: network-bridge resolution only, with no install effect on PASS.
    • B: offline and read-only. Images and consumers are retained to 23:30Z.
    Controller diff G → H (20aa983b → 567d0e49)
    --- /home/lab4/.claude/jobs/c3cbb130/tmp/graph-prep/run-graph-install-g.sh	2026-11-08 08:33:38.628914559 +0000
    +++ /home/lab4/.claude/jobs/c3cbb130/tmp/graph-prep/run-graph-install-h.sh	2026-11-08 09:40:50.813632566 +0000
    @@ -11,10 +11,14 @@
     # Successor G (#239 hold 6719292991): container absence is one strict predicate (preflight and
     # cleanup): a bounded full inspect with separate streams is absent only for exit 1, stdout exactly
     # "[]\n" and stderr exactly one "No such container: <requested name>" line; anything else is not absent.
    +# Successor H (#239 design 6719888226): R profiles (239-l10-refuse, 239-l11-refuse, 239-l12-below,
    +# 239-l13-below) pass only when ordinary advisory blocking refuses the declared affected graph with exactly
    +# its frozen Laravel advisories and leaves no lock or vendor; B profiles (239-adm-p82, 239-adm-p83) run the
    +# installed bridge admission on a real retained interpreter against an accepted read-only G consumer.
     #
     # Usage: run-graph-install.sh <repo-checkout> <run-root> <profile>
     #   <run-root>  an owned 0700 directory containing only held/ (trust + control + checks)
    -#   <profile>   307 | 239-l12 | 239-l13 | 239-l12-p82 | 239-l12-p83 | 239-l13-p83
    +#   <profile>   307 | 239-l12 | 239-l13 | 239-l12-p82 | 239-l12-p83 | 239-l13-p83 | 239-l10-refuse | 239-l11-refuse | 239-l12-below | 239-l13-below | 239-adm-p82 | 239-adm-p83
     # Exit: 0 success (receipt on stdout), 2 refused before any effect, 1 failed and
     # cleaned, 3 residue. Whole stage: `timeout --kill-after=180 480`.
     # Test-only input: GRAPH_DOCKER (Docker CLI path).
    @@ -39,6 +43,7 @@
       [trust/verify.php]=d7eea290e04e4eef382cc977584a736b1781b18994c5f462f600c0c47e8c5371
       [control/install-graph.sh]=7eb9d4e44ac4639abe410ab96cd90fd4d1ff3de4be68eac8220b344d4e385fa7
       [control/check-graph.sh]=7479d242103f92e81b409fb06291e93f5cfe75577355c5558cec7116765cf12c
    +  [control/check-admission.php]=579711063da8bb80d635db58256202e868a4976c02d83e06129d41f9a93279a7
       [checks/tests/compat/laravel.php]=81407f67e51f0069b2024e2daae8e7d3e43f9ce1d501da29dc7a43bcfc3035a0
       [checks/tests/compat/history-cache.php]=859b71254118b05a1066e88de5818eeddbd3d13a3466e897984e89941715ebc9
       [checks/tests/compat/execution-telemetry.php]=0e4e64a12859dce353ab479fd3793e706c415eed6448d3109c7652de4fb0d418
    @@ -56,7 +61,7 @@
     
     # Exact pins per profile ("name version"); php is a platform pin for #307 only. The p82/p83
     # profiles add a declared resolution target (config.platform.php) and their own check image.
    -PLATFORM=''; CHECK_IMAGE=$RUNNER
    +PLATFORM=''; CHECK_IMAGE=$RUNNER; MODE=install; EXPECT_ADVISORIES=''; ADMISSION_CONSUMER=''; ADMISSION_LOCK=''; ADMISSION_FRAMEWORK=''
     case $PROFILE in
       307) PINS='php 8.4.27
     durable-workflow/sdk 3.10.0
    @@ -80,7 +85,31 @@
     durable-workflow/workflow 2.21.1
     laravel/framework 13.30.0'
         PLATFORM=8.3.36; CHECK_IMAGE=$PHP83 ;;
    -  *) say 'graph-install refused: profile must be 307, 239-l12, 239-l13, 239-l12-p82, 239-l12-p83 or 239-l13-p83'; exit 2 ;;
    +  # R: the declared affected graphs; only the installer runs. Frozen advisory identities (Packagist 2026-11-08 09:36:57Z).
    +  239-l10-refuse) PINS='durable-workflow/sdk 3.10.0
    +laravel/framework 10.50.4'
    +    PLATFORM=8.2.35; CHECK_IMAGE=$INSTALLER; MODE=refuse; EXPECT_ADVISORIES='PKSA-3r5d-mb8f-1qw9 PKSA-b41t-wbzk-9q51 PKSA-d5tc-s1qs-h781 PKSA-m5cs-t1y6-qpcs PKSA-mdq4-51ck-6kdq' ;;
    +  239-l11-refuse) PINS='durable-workflow/sdk 3.10.0
    +laravel/framework 11.57.1'
    +    PLATFORM=8.2.35; CHECK_IMAGE=$INSTALLER; MODE=refuse; EXPECT_ADVISORIES='PKSA-3r5d-mb8f-1qw9 PKSA-b41t-wbzk-9q51 PKSA-d5tc-s1qs-h781 PKSA-m5cs-t1y6-qpcs PKSA-mdq4-51ck-6kdq' ;;
    +  239-l12-below) PINS='durable-workflow/sdk 3.10.0
    +laravel/framework 12.68.0'
    +    PLATFORM=8.2.35; CHECK_IMAGE=$INSTALLER; MODE=refuse; EXPECT_ADVISORIES='PKSA-d5tc-s1qs-h781' ;;
    +  239-l13-below) PINS='durable-workflow/sdk 3.10.0
    +laravel/framework 13.29.0'
    +    PLATFORM=8.3.36; CHECK_IMAGE=$INSTALLER; MODE=refuse; EXPECT_ADVISORIES='PKSA-d5tc-s1qs-h781' ;;
    +  # B: no install; the accepted retained G consumers (their exact locks), on their real interpreters.
    +  239-adm-p82) PINS='durable-workflow/sdk 3.10.0
    +durable-workflow/workflow 2.21.1
    +laravel/framework 12.69.0'
    +    PLATFORM=8.2.35; CHECK_IMAGE=$PHP82; MODE=admission; ADMISSION_CONSUMER=run239-l12-p82-root
    +    ADMISSION_LOCK=5cb011fa5b4acc65d1a3bc5beda2c82038ca3e3df3537a745fe71eac07bd4bd6; ADMISSION_FRAMEWORK=12.69.0 ;;
    +  239-adm-p83) PINS='durable-workflow/sdk 3.10.0
    +durable-workflow/workflow 2.21.1
    +laravel/framework 13.30.0'
    +    PLATFORM=8.3.36; CHECK_IMAGE=$PHP83; MODE=admission; ADMISSION_CONSUMER=run239-l13-p83-root
    +    ADMISSION_LOCK=86ddee9439774495886211631f8482d31395fd1f5313386f4b84285433b2f7a1; ADMISSION_FRAMEWORK=13.30.0 ;;
    +  *) say 'graph-install refused: profile must be one of 307, 239-l12, 239-l13, 239-l12-p82, 239-l12-p83, 239-l13-p83, 239-l10-refuse, 239-l11-refuse, 239-l12-below, 239-l13-below, 239-adm-p82, 239-adm-p83'; exit 2 ;;
     esac
     readonly NAMES="sdk-php-graph-$PROFILE-install sdk-php-graph-$PROFILE-check"
     # composer.json: license plus the exact pins, plugins off, normal advisory blocking, and for p82/p83
    @@ -141,6 +170,11 @@
     [ "$(timeout -k 5 "$PROBE_SECONDS" "$DOCKER" image inspect --format '{{.Id}}' "$RUNNER" 2>/dev/null)" = "$RUNNER" ] || refuse 'runner image absent or unknown'
     [ "$(timeout -k 5 "$PROBE_SECONDS" "$DOCKER" image inspect --format '{{.Id}}' "$CHECK_IMAGE" 2>/dev/null)" = "$CHECK_IMAGE" ] || refuse 'check image absent or unknown'
     mkdir -m 700 "$R/consumer" "$R/state"
    +if [ "$MODE" = admission ]; then
    +  ADMIT_ROOT="$(dirname "$R")/$ADMISSION_CONSUMER"
    +  [ -f "$ADMIT_ROOT/consumer/vendor/autoload.php" ] && [ "$(sha256sum < "$ADMIT_ROOT/consumer/composer.lock" | cut -c1-64)" = "$ADMISSION_LOCK" ] \
    +    && [ -z "$(find "$ADMIT_ROOT/consumer" -perm /222 -print -quit)" ] || refuse 'retained consumer missing, changed or writable'
    +fi
     for name in $NAMES; do absent_container "$name" || refuse "container $name present or unknown"; done
     RUN=$(head -c 16 /dev/urandom | od -An -tx1 | tr -d ' \n')
     trap cleanup EXIT
    @@ -148,7 +182,7 @@
     
     printf '%s\n' "$COMPOSER_JSON" > "$R/consumer/composer.json"
     mkdir -m 700 "$R/state/home" "$R/state/cache" "$R/state/tmp" "$R/state/empty-ca-dir" "$R/state/control"
    -cp "$R/held/control/install-graph.sh" "$R/held/control/check-graph.sh" "$R/state/control/"
    +cp "$R/held/control/install-graph.sh" "$R/held/control/check-graph.sh" "$R/held/control/check-admission.php" "$R/state/control/"
     printf '%s\n' "$PINS" > "$R/state/control/pins.txt"
     
     # --- effect ------------------------------------------------------------------
    @@ -165,11 +199,78 @@
       --tmpfs /tmp:rw,nosuid,nodev,size=128m
       --mount "type=bind,src=$R/held/trust,dst=/trust,readonly" --mount "type=bind,src=$R/state/control,dst=/control,readonly"
       --mount "type=bind,src=$R/state,dst=/state")
    +if [ "$MODE" = admission ]; then
    +  # B: the installed SDK's bridge admission on the real retained interpreter, against the accepted read-only
    +  # G consumer, network none. Supplied versions are explicit synthetic predicate inputs (see check-admission.php).
    +  timeout -k 10 120 "$DOCKER" run "${COMMON[@]}" --name "sdk-php-graph-$PROFILE-check" --network none \
    +    --mount "type=bind,src=$ADMIT_ROOT/consumer,dst=/consumer,readonly" \
    +    -e HOME=/state/home -e "ADMISSION_PHP=$PLATFORM" -e "ADMISSION_FRAMEWORK=$ADMISSION_FRAMEWORK" \
    +    --entrypoint php "$CHECK_IMAGE" /control/check-admission.php 2>&1 | head -c $((LOG_BYTES + 1)) > "$R/state/admission.log"
    +  status=${PIPESTATUS[0]}
    +  [ "$(stat -c %s "$R/state/admission.log")" -le "$LOG_BYTES" ] || fail 'admission output exceeded 1 MiB'
    +  [ "$status" -eq 0 ] || fail "admission check exited $status"
    +  python3 -I - "$R" "$PLATFORM" "$ADMISSION_FRAMEWORK" <<'PY' > "$R/state/admission-check.json" || fail 'admission verdict differs'
    +import hashlib, json, sys
    +root, php, framework = sys.argv[1:4]
    +raw = open(root + '/state/admission.log', 'rb').read()
    +lines = raw.decode().splitlines()
    +assert len(lines) == 1, 'exactly one verdict line, no warnings'
    +v = json.loads(lines[0])
    +assert v['pass'] is True and v['php_version'] == php and v['sdk'] == '3.10.0' and v['framework_installed'].lstrip('v') == framework
    +laravel13 = 'admit' if php.startswith('8.3.') else 'refuse'
    +expected = [['10.50.4', 'refuse'], ['10.50.4.0', 'refuse'], ['11.57.1', 'refuse'], ['11.57.1.0', 'refuse'], ['12.68.0', 'refuse'],
    +            ['12.68.0.0', 'refuse'], ['13.29.0', 'refuse'], ['13.29.0.0', 'refuse'], [None, 'refuse'], ['12.69.0', 'admit'],
    +            ['12.69.0.0', 'admit'], ['13.30.0', laravel13], ['13.30.0.0', laravel13]]
    +cases = v['synthetic_predicate_inputs']
    +assert [[c['reported_version'], c['expected']] for c in cases] == expected
    +assert all(c['observed'] == c['expected'] and c['message_exact'] is True for c in cases)
    +assert v['provider_registration']['registered'] is True
    +print(json.dumps({'profile_kind': 'admission', 'admission_log_sha256': hashlib.sha256(raw).hexdigest(), **v}, separators=(',', ':')))
    +PY
    +  OUTCOME=success
    +  cat "$R/state/admission-check.json"
    +  exit 0
    +fi
     timeout -k 10 270 "$DOCKER" run "${COMMON[@]}" --name "sdk-php-graph-$PROFILE-install" --network bridge \
       --mount "type=bind,src=$R/consumer,dst=/consumer" "${TRUST_ENV[@]}" \
       --entrypoint /bin/sh "$INSTALLER" /control/install-graph.sh 2>&1 | head -c $((LOG_BYTES + 1)) > "$R/state/install.log"
     status=${PIPESTATUS[0]}
     [ "$(stat -c %s "$R/state/install.log")" -le "$LOG_BYTES" ] || fail 'install output exceeded 1 MiB'
    +if [ "$MODE" = refuse ]; then
    +  # R: the declared affected graph must be refused by ordinary advisory blocking and nothing else.
    +  python3 -I - "$R" "$status" "$EXPECT_ADVISORIES" <<'PY' > "$R/state/refusal-check.json" || fail 'install was not refused by exactly the declared Laravel advisories'
    +import hashlib, json, os, re, sys
    +root, status, expect = sys.argv[1:4]
    +expected = sorted(expect.split())
    +raw = open(root + '/state/install.log', 'rb').read()
    +log = raw.decode('utf-8', 'replace')
    +pins = dict(line.split() for line in open(root + '/state/control/pins.txt').read().splitlines())
    +framework = pins['laravel/framework']
    +# Composer's dependency-resolution exit, after the trust check and before any lock, vendor or audit.
    +assert int(status) == 2, 'composer exit'
    +assert os.path.isfile(root + '/state/trust-before-install.json') and not os.path.exists(root + '/state/trust-before-audit.json')
    +assert not os.path.exists(root + '/consumer/composer.lock') and not os.path.exists(root + '/consumer/vendor')
    +assert log.count('Your requirements could not be resolved to an installable set of packages.') == 1
    +assert [m.strip() for m in re.findall(r'^\s*Problem \d+\s*$', log, re.M)] == ['Problem 1'], 'exactly one problem'
    +causes = re.findall(r'- Root composer\.json requires laravel/framework ' + re.escape(framework) + r'\b[^\n]*?found laravel/framework\[v'
    +                    + re.escape(framework) + r'\] but these were not loaded, because they are affected by security advisories \(([^)]*)\)', log)
    +assert len(causes) == 1, 'the root laravel/framework requirement is blocked by advisories'
    +ids = sorted(re.findall(r'"([A-Z]+-[A-Za-z0-9-]+)"', causes[0]))
    +assert ids == expected, ids
    +# No other advisory anywhere, and no acquisition, transport, authentication, platform or lock cause.
    +assert sorted(set(re.findall(r'\b(?:PKSA|GHSA|CVE)-[A-Za-z0-9-]+', log))) == expected
    +lowered = log.lower()
    +for marker in ('curl error', 'failed to download', 'could not be downloaded', 'transportexception', 'could not authenticate',
    +               'failed to open stream', 'requires php', 'your lock file', 'no matching package found'):
    +    assert marker not in lowered, marker
    +print(json.dumps({'profile_kind': 'refusal', 'framework': framework, 'composer_exit': 2, 'advisories': ids, 'lock': False,
    +                  'vendor': False, 'install_log_bytes': len(raw), 'install_log_sha256': hashlib.sha256(raw).hexdigest()}))
    +PY
    +  chmod -R a=rX "$R/consumer"
    +  OUTCOME=success
    +  cat "$R/state/refusal-check.json"
    +  exit 0
    +fi
     [ "$status" -eq 0 ] || fail "install exited $status (advisory refusals and unexpected validate warnings are kept in the state)"
     
     python3 -I - "$R" "$SDK_REF" "$WORKFLOW_REF" "$SDK_ZIP_SHA" "$SDK_ZIP_BYTES" "$WORKFLOW_ZIP_SHA" "$WORKFLOW_ZIP_BYTES" "$PLATFORM" <<'PY' > "$R/state/lock-check.json" || fail 'lock or installed graph differs'
    Admission diff 239g → 239h (90aa19e4 → 07e2775a)
    --- /home/lab4/.claude/jobs/c3cbb130/tmp/admit239g.sh	2026-11-08 08:33:38.628988166 +0000
    +++ /home/lab4/.claude/jobs/c3cbb130/tmp/admit239h.sh	2026-11-08 09:40:50.813736931 +0000
    @@ -1,5 +1,5 @@
     #!/bin/sh
    -# #239 installed-graph admission for controller G (strict container absence successor of F d095b639), one profile. Read-only.
    +# #239 installed-graph admission for controller H (R refusal and B admission profiles; successor of G 20aa983b), one profile. Read-only.
     # Name absence: bounded full inspect, exit 1, stdout exactly "[]\n", stderr exactly one "No such container: <name>" line.
     # Usage: admit239f.sh <run-root> <239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83>
     T=/home/lab4/.claude/jobs/c3cbb130/tmp
    @@ -9,8 +9,9 @@
     W=$(mktemp -d "$T/admit239g.XXXXXX") || { echo "FAIL tempdir"; echo REFUSE; exit 0; }
     trap 'rm -rf "$W"' EXIT
     date -u +%FT%T.%NZ
    -case $P in 239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83) echo "profile $P" ;; *) no "profile $P"; echo REFUSE; exit 0 ;; esac
    -case $P in *-p82) CHK_IMG=sha256:604de2f0cba9e9dde16cf717c2f03b0948c99949bdf7c11cdf76326e0da7d2ea ;;
    +case $P in 239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83|239-l10-refuse|239-l11-refuse|239-l12-below|239-l13-below|239-adm-p82|239-adm-p83) echo "profile $P" ;; *) no "profile $P"; echo REFUSE; exit 0 ;; esac
    +case $P in *-refuse|*-below) CHK_IMG=sha256:49c9e0fc0497f3e733a60971382b6e0ec5f54328fce2a122485862febba3737a ;;
    +  *-p82) CHK_IMG=sha256:604de2f0cba9e9dde16cf717c2f03b0948c99949bdf7c11cdf76326e0da7d2ea ;;
       *-p83) CHK_IMG=sha256:628102249d93494233b54490b785f12db9cd60f4dc89416dfca15973f2125f10 ;;
       *) CHK_IMG=sha256:80a91784a0ae46c4cecd33b72f30188285fc32be8087af7caa7fa00b0fe8a5f0 ;; esac
     docker version --format 'docker server {{.Server.Version}}' || no docker
    @@ -29,8 +30,17 @@
     done; echo "names sdk-php-graph-$P-install/-check absent-checked"
     tag=$(git -C "$REPO" rev-parse '3.10.0^{commit}' 2>/dev/null); echo "tag 3.10.0 $tag"
     [ "$tag" = 4e6c6b7b4318010b73233377ad36be805828fedd ] || no tag
    -dh=$(sha256sum < "$T/graph-prep/run-graph-install-g.sh" | cut -c1-64); echo "controller $dh $(wc -c < "$T/graph-prep/run-graph-install-g.sh")B"
    -[ "$dh" = 20aa983b15d10f92a9616c99ffdd926e6fb346202105b0154850f0ade8205808 ] || no controller
    +dh=$(sha256sum < "$T/graph-prep/run-graph-install-h.sh" | cut -c1-64); echo "controller $dh $(wc -c < "$T/graph-prep/run-graph-install-h.sh")B"
    +[ "$dh" = 567d0e4917ab0d00e45a4a49a150cb224483ec1bd0997e9ff123c3bdfd8773a0 ] || no controller
    +case $P in
    +  239-adm-p82) ar=run239-l12-p82-root; al=5cb011fa5b4acc65d1a3bc5beda2c82038ca3e3df3537a745fe71eac07bd4bd6 ;;
    +  239-adm-p83) ar=run239-l13-p83-root; al=86ddee9439774495886211631f8482d31395fd1f5313386f4b84285433b2f7a1 ;;
    +  *) ar='' ;;
    +esac
    +if [ -n "$ar" ]; then
    +  if [ -f "$T/$ar/consumer/vendor/autoload.php" ] && [ "$(sha256sum < "$T/$ar/consumer/composer.lock" | cut -c1-64)" = "$al" ] \
    +    && [ -z "$(find "$T/$ar/consumer" -perm /222 -print -quit)" ]; then echo "retained consumer $ar exact and read-only"; else no "retained consumer $ar"; fi
    +fi
     [ "$(ls -A "$R")" = held ] && [ "$(stat -c %a "$R")" = 700 ] && [ -O "$R" ] || no "run root shape"
     while read -r h p; do
       [ -f "$R/held/$p" ] && [ ! -L "$R/held/$p" ] && [ "$(sha256sum < "$R/held/$p" | cut -c1-64)" = "$h" ] || no "held $p"
    @@ -40,12 +50,13 @@
     d7eea290e04e4eef382cc977584a736b1781b18994c5f462f600c0c47e8c5371 trust/verify.php
     7eb9d4e44ac4639abe410ab96cd90fd4d1ff3de4be68eac8220b344d4e385fa7 control/install-graph.sh
     7479d242103f92e81b409fb06291e93f5cfe75577355c5558cec7116765cf12c control/check-graph.sh
    +579711063da8bb80d635db58256202e868a4976c02d83e06129d41f9a93279a7 control/check-admission.php
     81407f67e51f0069b2024e2daae8e7d3e43f9ce1d501da29dc7a43bcfc3035a0 checks/tests/compat/laravel.php
     859b71254118b05a1066e88de5818eeddbd3d13a3466e897984e89941715ebc9 checks/tests/compat/history-cache.php
     0e4e64a12859dce353ab479fd3793e706c415eed6448d3109c7652de4fb0d418 checks/tests/compat/execution-telemetry.php
     EOF
    -echo "held (8 files) checked; held file count $(find "$R/held" -type f | wc -l)"
    -[ "$(find "$R/held" -type f | wc -l)" -eq 8 ] || no "held file count"
    +echo "held (9 files) checked; held file count $(find "$R/held" -type f | wc -l)"
    +[ "$(find "$R/held" -type f | wc -l)" -eq 9 ] || no "held file count"
     # Accepted 307 evidence stays retained and read-only through Phase F.
     [ -z "$(find "$T/run307d-root/receipts" "$T/run307d-root/consumer" -perm /222 -print -quit)" ] || no "307 retained evidence writable"
     echo "307 retained evidence read-only"
    Launcher diff 239g → 239h (c4a5867f → ea8541e4)
    --- /home/lab4/.claude/jobs/c3cbb130/tmp/launch239g.sh	2026-11-08 08:33:38.629031472 +0000
    +++ /home/lab4/.claude/jobs/c3cbb130/tmp/launch239h.sh	2026-11-08 09:40:50.813793418 +0000
    @@ -1,11 +1,11 @@
     #!/bin/sh
    -# #239 installed-graph launcher for held controller G (strict container absence successor of F). One invocation per call, no retry.
    +# #239 installed-graph launcher for held controller H (R refusal and B admission profiles). One invocation per call, no retry.
     # Usage: launch239f.sh <239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83> <selection-comment-id> <selection-body-sha256> <start-by-epoch>
     T=/home/lab4/.claude/jobs/c3cbb130/tmp
     G=$T/graph-prep; B=$T/phaseB-prep
     REPO=/home/lab4/fleet/repos/sdk-php/.claude/worktrees/release-3.10.0
     P=$1; SEL=$2; SELSHA=$3; START_BY=$4
    -case $P in 239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83) ;; *) exit 89 ;; esac
    +case $P in 239-l12|239-l13|239-l12-p82|239-l12-p83|239-l13-p83|239-l10-refuse|239-l11-refuse|239-l12-below|239-l13-below|239-adm-p82|239-adm-p83) ;; *) exit 89 ;; esac
     O=$T/run$P-outer; R=$T/run$P-root
     umask 077
     [ ! -e "$O" ] && [ ! -e "$R" ] || exit 90
    @@ -18,15 +18,16 @@
     # Fresh owned run root holding only held/ (trust, control, checks).
     mkdir -m 700 "$R" "$R/held" "$R/held/trust" "$R/held/control" "$R/held/checks" || exit 90
     cp "$B/trust/composer.phar" "$B/trust/ca.pem" "$B/trust/verify.php" "$R/held/trust/" || exit 90
    -cp "$G/control/install-graph.sh" "$R/held/control/" && cp "$G/control-c/check-graph.sh" "$R/held/control/check-graph.sh" || exit 90
    +cp "$G/control/install-graph.sh" "$R/held/control/" && cp "$G/control-c/check-graph.sh" "$R/held/control/check-graph.sh" \
    +  && cp "$G/control-h/check-admission.php" "$R/held/control/check-admission.php" || exit 90
     cp -R "$G/checks/tests" "$R/held/checks/" || exit 90
    -cp "$G/run-graph-install-g.sh" "$O/run-graph-install-g.sh" && chmod 0400 "$O/run-graph-install-g.sh"
    -[ "$(sha256sum < "$O/run-graph-install-g.sh" | cut -c1-64)" = 20aa983b15d10f92a9616c99ffdd926e6fb346202105b0154850f0ade8205808 ] || exit 92
    -cp "$T/admit239g.sh" "$O/admit239g.sh" && chmod 0400 "$O/admit239g.sh"
    -[ "$(sha256sum < "$O/admit239g.sh" | cut -c1-64)" = 90aa19e43d20586d7d3d0d57145ff511335a2bb000caa03d5ca9da2f7e2ab5a6 ] || exit 92
    +cp "$G/run-graph-install-h.sh" "$O/run-graph-install-h.sh" && chmod 0400 "$O/run-graph-install-h.sh"
    +[ "$(sha256sum < "$O/run-graph-install-h.sh" | cut -c1-64)" = 567d0e4917ab0d00e45a4a49a150cb224483ec1bd0997e9ff123c3bdfd8773a0 ] || exit 92
    +cp "$T/admit239h.sh" "$O/admit239h.sh" && chmod 0400 "$O/admit239h.sh"
    +[ "$(sha256sum < "$O/admit239h.sh" | cut -c1-64)" = 07e2775af837e8eaf68ae68a038c8a2d837c1106482f13aa63101bc381e457bc ] || exit 92
     # Held admission under an overall 60 s bound: exit 0, last line exactly ADMIT, no FAIL line, empty stderr.
     date -u +%FT%T.%NZ > "$O/admission.start"
    -timeout -k 5 60 sh "$O/admit239g.sh" "$R" "$P" > "$O/admission.txt" 2> "$O/admission.err"
    +timeout -k 5 60 sh "$O/admit239h.sh" "$R" "$P" > "$O/admission.txt" 2> "$O/admission.err"
     echo "$?" > "$O/admission.exit"
     [ "$(cat "$O/admission.exit")" = 0 ] || exit 93
     [ "$(tail -n 1 "$O/admission.txt")" = ADMIT ] || exit 93
    @@ -42,6 +43,6 @@
         HOME="$O/home" DOCKER_CONFIG="$O/dockercfg" LANG=C.UTF-8 \
         /usr/bin/prlimit --fsize=1048577:1048577 -- timeout --kill-after=180 480 /bin/bash -s -- \
         "$REPO" "$R" "$P" \
    -    < "$O/run-graph-install-g.sh" > "$O/driver.stdout" 2> "$O/driver.stderr"
    +    < "$O/run-graph-install-h.sh" > "$O/driver.stdout" 2> "$O/driver.stderr"
     echo "$?" > "$O/exit"
     date -u +%FT%T.%NZ > "$O/t1"
    Held check check-admission.php (57971106)
    <?php
    
    declare(strict_types=1);
    
    // #239 B cell (graph controller H): the installed SDK 3.10.0 Laravel bridge admission on a real retained PHP
    // interpreter, against an accepted read-only G consumer, with network none. Prints one JSON verdict line.
    // The supplied-version cases are explicit SYNTHETIC inputs to the installed predicate; they are not an
    // installed Laravel 10/11 application boot and do not override Composer's installed metadata. The positive
    // control registers the real provider with the consumer's real installed (supported) framework.
    require '/consumer/vendor/autoload.php';
    
    use Composer\InstalledVersions;
    use DurableWorkflow\Bridge\Laravel\DurableWorkflowServiceProvider;
    use DurableWorkflow\Bridge\Laravel\LaravelPlatform;
    use DurableWorkflow\Bridge\ServiceConfiguration;
    use Illuminate\Config\Repository;
    use Illuminate\Foundation\Application;
    
    const REFUSAL = 'The Durable Workflow Laravel bridge requires PHP ^8.2 and Laravel ^12.69.0|^13.30.0; Laravel 13 requires PHP ^8.3.'
        .' Upgrade the application platform before activating the bridge or retain the existing SDK 3.9.x release while upgrading.';
    
    $expectedPhp = (string) getenv('ADMISSION_PHP');
    $expectedFramework = (string) getenv('ADMISSION_FRAMEWORK');
    $verdict = ['php_version' => PHP_VERSION, 'sdk' => InstalledVersions::getPrettyVersion('durable-workflow/sdk'),
        'framework_installed' => InstalledVersions::getPrettyVersion('laravel/framework'), 'synthetic_predicate_inputs' => [], 'pass' => false];
    if (PHP_VERSION !== $expectedPhp || $verdict['sdk'] !== '3.10.0' || ltrim((string) $verdict['framework_installed'], 'v') !== $expectedFramework) {
        $verdict['error'] = 'interpreter, SDK or installed framework differs from the selected consumer';
        echo json_encode($verdict, JSON_UNESCAPED_SLASHES), "\n";
        exit(67);
    }
    
    $laravel13 = PHP_VERSION_ID >= 80300 ? 'admit' : 'refuse';
    $cases = [
        ['10.50.4', 'refuse'], ['10.50.4.0', 'refuse'], ['11.57.1', 'refuse'], ['11.57.1.0', 'refuse'],
        ['12.68.0', 'refuse'], ['12.68.0.0', 'refuse'], ['13.29.0', 'refuse'], ['13.29.0.0', 'refuse'], [null, 'refuse'],
        ['12.69.0', 'admit'], ['12.69.0.0', 'admit'], ['13.30.0', $laravel13], ['13.30.0.0', $laravel13],
    ];
    $all = true;
    foreach ($cases as [$version, $expected]) {
        try {
            LaravelPlatform::assertSupported($version, PHP_VERSION_ID);
            $observed = 'admit';
            $message = null;
        } catch (\RuntimeException $error) {
            $message = $error->getMessage();
            $observed = $message === REFUSAL ? 'refuse' : 'unexpected';
        }
        $all = $all && $observed === $expected;
        $verdict['synthetic_predicate_inputs'][] = ['reported_version' => $version, 'expected' => $expected, 'observed' => $observed,
            'message_exact' => $message === null || $message === REFUSAL];
    }
    
    // Positive control: the real provider with Composer's real installed metadata for this consumer.
    $app = new Application(sys_get_temp_dir().'/durable-workflow-admission');
    $app->instance('config', new Repository([]));
    try {
        (new DurableWorkflowServiceProvider($app))->register();
        $registered = $app->bound(ServiceConfiguration::class) && is_array($app->make('config')->get('durable-workflow'));
        $verdict['provider_registration'] = ['installed_version' => InstalledVersions::getVersion('laravel/framework'), 'registered' => $registered];
    } catch (\Throwable $error) {
        $registered = false;
        $verdict['provider_registration'] = ['installed_version' => InstalledVersions::getVersion('laravel/framework'), 'registered' => false,
            'error' => $error::class.': '.$error->getMessage()];
    }
    
    $verdict['pass'] = $all && $registered;
    echo json_encode($verdict, JSON_UNESCAPED_SLASHES), "\n";
    exit($verdict['pass'] ? 0 : 1);
    Controls output (753d0b79)
    === isolation proof
    isolation proven: /run empty, docker sockets absent, interfaces [lo], outbound TCP refused, docker env unset, 9 Docker-like binaries masked (PATH and absolute calls exit 99)
    fixture driver differs from the exact controller only in: 2 lines (readonly WORKFLOW_ZIP_SHA=f7 readonly WORKFLOW_ZIP_BYTES= )
    bad-profile: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: profile must be one of 307, 239-l12, 239-l13, 239-l12-p82, 239-l12-p83, 239-l13-p83, 239-l10-refuse, 239-l11-refuse, 
    tampered-composer-phar: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: held trust/composer.phar differs
    tampered-check-script: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: held control/check-graph.sh differs
    extra-root-entry: exit=2 root=[held,stray,] vendor=absent leftover=0 | graph-install refused: run root must contain only held/
    predecessor-copy-under-cap: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: installed identity differs
      predecessor receipt copy: 1 EFBIG
    pass-307: exit=0 root=[consumer,held,receipts,state,] vendor=kept leftover=0 | 
      receipt hardlinked: 3 links, 1150970 bytes
      composer.json: {"license":"proprietary","require":{"php":"8.4.27","durable-workflow/sdk":"3.10.0","laravel/framework":"12.69.3","symfony/framework-bundle":"7.4.23"},"config":{"allow-plugins":false,"audit":{"block-insecure":true}}}
      receipts: archive-inventory.json sdk.zip subject.json  subject: {"archive_inventory_file":"archive-inventory.json","archive_inventory_sha256":"1750f8cf9f6053224433d0da9697f6587a7f06cc9096a34187cf0ddbe26f7831","lock_sha256":"b6bb40e744fa09d23ed3c761fdc093dbcdd695270a8895c9b3c3fa411962e8e9","runner_reference":"4e6c6b7b4318010b73233377ad36be805828fedd","schema":"durable-workflow.php-static-credential-subject/v1","sdk_archive_bytes":1150970,"sdk_archive_file":"sdk
      receipt output: {"lock_sha256": "b6bb40e744fa09d23ed3c761fdc093dbcdd695270a8895c9b3c3fa411962e8e9", "vendor_sha256": "0000000000000000000000000000000000000000000000000000000000000007", "vendor_files": 4321, "sdk_sha256": "c562d3788d41d0cd92fa4c7a0f5acf90ed1cfe827247dffc313a9eeaa7154973", "sdk_files": 470, "profile_
    pass-239-l12: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
      workflow receipt: "workflow_source_reference": "36961d60921dd7190890a505d9364f1f712a8d63" "workflow_dist_url": "https://api.github.com/repos/durable-workflow/workflow/zipball/36961d60921dd7190890a505d9364f1f712a8d63" "workflow_dist_zip_sha256": "f7159802049f287084aa853df68e142ed64c45b2cdcf67486c46b3074fd3b666" "workflow_dist_zip_bytes": 34 
      composer.json: {"license":"proprietary","require":{"durable-workflow/sdk":"3.10.0","durable-workflow/workflow":"2.21.1","laravel/framework":"12.69.0"},"config":{"allow-plugins":false,"audit":{"block-insecure":true}}}; consumer read-only: 0 writable entries
    pass-239-l13: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
      check env: GRAPH_PROFILE=239-l13; install network: 1; check network none: 1
    advisory-refusal: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install exited 2 (advisory refusals and unexpected validate warnings are kept in the state)
    wrong-sdk-reference: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert sdk['version'] == '3.10.0' and sdk['source']['reference'] == sdk_ref
    framework-floor-drift: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert rows[name]['version'].lstrip('v') == version, name
    path-distribution: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert all(p.get('dist', {}).get('type') != 'path' and p.get('source', {}).get('type') != 'path' for p in lock['packages'])
    wrong-sdk-dist-zip: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert hashlib.sha256(data).hexdigest() == zip_sha and len(data) == int(zip_bytes)
    wrong-sdk-inventory: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: installed identity differs
    check-fails: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: runner-image check exited 1
    exact-controller-refuses-other-workflow-zip: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert hashlib.sha256(wf_data).hexdigest() == wf_zip_sha and len(wf_data) == int(wf_zip_bytes)
    exact-controller-refuses-other-workflow-zip-l13: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert hashlib.sha256(wf_data).hexdigest() == wf_zip_sha and len(wf_data) == int(wf_zip_bytes)
    wrong-workflow-source-reference: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert wf['version'].lstrip('v') == '2.21.1' and wf['source']['reference'] == workflow_ref
    wrong-workflow-dist-reference: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert wf['dist'] == {**wf['dist'], 'type': 'zip', 'reference': workflow_ref, 'url': wf_url}
    wrong-workflow-dist-url: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert wf['dist'] == {**wf['dist'], 'type': 'zip', 'reference': workflow_ref, 'url': wf_url}
    tampered-workflow-zip: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert hashlib.sha256(wf_data).hexdigest() == wf_zip_sha and len(wf_data) == int(wf_zip_bytes)
    workflow-zip-not-at-url-cache-path: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert wf_zips == [wf_path]
    extra-workflow-archive: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert wf_zips == [wf_path]
    installed-workflow-row-drift: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert len(iwf) == 1 and iwf[0]['source'] == wf['source'] and iwf[0]['dist'] == wf['dist']
    residue: exit=3 root=[consumer,held,state,] vendor=absent leftover=2 | graph-install residue: an owned container or install path could not be proven removed
    f-refuses-predecessor-check-script: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: held control/check-graph.sh differs
    e-refuses-successor-check-script: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: held control/check-graph.sh differs
    pass-239-l12-p82: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
      composer.json: {"license":"proprietary","require":{"durable-workflow/sdk":"3.10.0","durable-workflow/workflow":"2.21.1","laravel/framework":"12.69.0"},"config":{"allow-plugins":false,"audit":{"block-insecure":true},"platform":{"php":"8.2.35"}}}
      lock platform-overrides: {'php': '8.2.35'}
      check image: sha256:604de2f0cba9; install image: sha256:49c9e0fc0497
    pass-239-l12-p83: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
      composer.json: {"license":"proprietary","require":{"durable-workflow/sdk":"3.10.0","durable-workflow/workflow":"2.21.1","laravel/framework":"12.69.0"},"config":{"allow-plugins":false,"audit":{"block-insecure":true},"platform":{"php":"8.3.36"}}}
      lock platform-overrides: {'php': '8.3.36'}
      check image: sha256:628102249d93; install image: sha256:49c9e0fc0497
    pass-239-l13-p83: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
      composer.json: {"license":"proprietary","require":{"durable-workflow/sdk":"3.10.0","durable-workflow/workflow":"2.21.1","laravel/framework":"13.30.0"},"config":{"allow-plugins":false,"audit":{"block-insecure":true},"platform":{"php":"8.3.36"}}}
      lock platform-overrides: {'php': '8.3.36'}
      check image: sha256:628102249d93; install image: sha256:49c9e0fc0497
      carried 239-l12 composer.json 5e90889e8a6e452f check image sha256:80a91784a0ae
      carried 239-l13 composer.json 6a2068d658d89367 check image sha256:80a91784a0ae
      carried 307 composer.json 23a15eadd682a643 check image sha256:80a91784a0ae
    platform-drift: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: lock or installed graph differs
        failing assertion: assert (lock.get('platform-overrides') or {}) == ({'php': platform} if platform else {})
    php82-image-missing: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: check image absent or unknown
    wrong-interpreter: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: runner-image check exited 67
    bad-profile-p84: exit=2 root=[held,] vendor=absent leftover=0 | graph-install refused: profile must be one of 307, 239-l12, 239-l13, 239-l12-p82, 239-l12-p83, 239-l13-p83, 239-l10-refuse, 239-l11-refuse, 
    === F reproduction: a timeout carrying the exact absence text passes F's preflight
    f-preflight-timeout-exact-text: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
    f-preflight-prefix-only: exit=0 root=[consumer,held,state,] vendor=kept leftover=0 | 
    === successor G: preflight absence (zero containers started on refusal)
    g-preflight-absent_timeout: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0
    g-preflight-absent_extra_stdout: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0
    g-preflight-absent_extra_stderr: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0
    g-preflight-absent_wrong_ref: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0
    g-preflight-absent_prefix_only: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0
    g-preflight-present-container: exit=2 root=[consumer,held,state,] vendor=absent leftover=1 | graph-install refused: container sdk-php-graph-239-l12-p82-install present or unknown
      runs started: 0; foreign container removals: 0
    === successor G: cleanup absence
    g-cleanup-real-absence: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: runner-image check exited 1
    g-cleanup-post-removal-timeout: exit=3 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install residue: an owned container or install path could not be proven removed
    === admission G (fake via PATH shim inside the sandbox)
    admission real-absence: exit=0 last=ADMIT stderr=0B | names sdk-php-graph-239-l12-p82-install/-check absent-checked 
    admission timeout-exact-text: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 124) FAIL name sdk-php-graph-239-l12-p82-check not proven absent (exit 1
    admission extra-stdout: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 1) FAIL name sdk-php-graph-239-l12-p82-check not proven absent (exit 1) 
    admission extra-stderr: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 1) FAIL name sdk-php-graph-239-l12-p82-check not proven absent (exit 1) 
    admission wrong-reference: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 1) FAIL name sdk-php-graph-239-l12-p82-check not proven absent (exit 1) 
    admission prefix-only: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 1) FAIL name sdk-php-graph-239-l12-p82-check not proven absent (exit 1) 
    admission present-container: exit=0 last=REFUSE stderr=0B | FAIL name sdk-php-graph-239-l12-p82-install not proven absent (exit 0) names sdk-php-graph-239-l12-p82-install/-check absent-checked 
    admission f-admission-timeout-exact-text: exit=0 last=ADMIT stderr=0B | names sdk-php-graph-239-l12-p82-install/-check absent-checked 
    admission temp dirs left: 0
    === R: declared affected graphs refused by ordinary advisory blocking (exact controller, installer only)
    r-pass-239-l10-refuse: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; check runs: 0; lock: absent; verdict:  "composer_exit": 2, "advisories": ["PKSA-3r5d-mb8f-1qw9", "PKSA-b41t-wbzk-9q51", "PKSA-d5tc-s1qs-h781", "PKSA-m5cs-t1y6-qpcs", "PKSA-mdq4-51ck-6kdq"], "lock": false, "vendor": false, "install_log_bytes": 809, "install_log_sha256": "4934c0b4bed0c3409cd356d852270f54935c78cfc39ac7ded34630ead95a7cde"}
    r-pass-239-l11-refuse: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; check runs: 0; lock: absent; verdict:  "composer_exit": 2, "advisories": ["PKSA-3r5d-mb8f-1qw9", "PKSA-b41t-wbzk-9q51", "PKSA-d5tc-s1qs-h781", "PKSA-m5cs-t1y6-qpcs", "PKSA-mdq4-51ck-6kdq"], "lock": false, "vendor": false, "install_log_bytes": 809, "install_log_sha256": "d106a994ada709921524a6019f08406f8f20fbce71d40fe4a5743f13c2764748"}
    r-pass-239-l12-below: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; check runs: 0; lock: absent; verdict: {"profile_kind": "refusal", "framework": "12.68.0", "composer_exit": 2, "advisories": ["PKSA-d5tc-s1qs-h781"], "lock": false, "vendor": false, "install_log_bytes": 717, "install_log_sha256": "ceef531a9ce0300917eea5089b4c748359a5b34c76fd6bd16a852bbf6de8bf33"}
    r-pass-239-l13-below: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; check runs: 0; lock: absent; verdict: {"profile_kind": "refusal", "framework": "13.29.0", "composer_exit": 2, "advisories": ["PKSA-d5tc-s1qs-h781"], "lock": false, "vendor": false, "install_log_bytes": 717, "install_log_sha256": "814f462035f573168f2936b440fd7806ad2581ab9be871f91d09d11a77eb7ac1"}
    === R NONPASS: anything but exactly the declared advisory cause
    r-r_extra_advisory: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_missing_advisory: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_second_problem: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_download_failure: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_leave_lock: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_exit1: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-r_installs: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    r-below-floor-extra: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: install was not refused by exactly the declared Laravel advisories
    === B: installed admission on the retained interpreters (synthetic retained roots inside the controls dir)
    b-pass-239-adm-p82: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; install runs: 0; check image: sha256:604de2f0cba9; consumer mount read-only: 1
    b-pass-239-adm-p83: exit=0 root=[consumer,held,state,] vendor=absent leftover=0 | 
      runs started: 1; install runs: 0; check image: sha256:628102249d93; consumer mount read-only: 1
    === B NONPASS
    b-b_case_mismatch: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission verdict differs
    b-b_wrong_l13: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission verdict differs
    b-b_wrong_php: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission verdict differs
    b-b_warning: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission verdict differs
    b-b_registration_fail: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission verdict differs
    b-b_exit1: exit=1 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install failed: admission check exited 1
    b-retained-writable: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: retained consumer missing, changed or writable
    b-retained-lock-changed: exit=2 root=[consumer,held,state,] vendor=absent leftover=0 | graph-install refused: retained consumer missing, changed or writable
    === admission H (fake via PATH shim inside the sandbox)
    admission r-l11: exit=0 last=ADMIT stderr=0B | image ok 49c9e0fc0497 image ok 80a91784a0ae image ok 49c9e0fc0497 held (9 files) checked; held file count 9 307 retained evidence read-only 
    admission r-l13-below: exit=0 last=ADMIT stderr=0B | image ok 49c9e0fc0497 image ok 80a91784a0ae image ok 49c9e0fc0497 held (9 files) checked; held file count 9 307 retained evidence read-only 
    admission b-p82: exit=0 last=ADMIT stderr=0B | image ok 49c9e0fc0497 image ok 80a91784a0ae image ok 604de2f0cba9 retained consumer run239-l12-p82-root exact and read-only held (9 files) checked; held file count 9 307 retained evidence read-only 
    admission b-p83: exit=0 last=ADMIT stderr=0B | image ok 49c9e0fc0497 image ok 80a91784a0ae image ok 628102249d93 retained consumer run239-l13-p83-root exact and read-only held (9 files) checked; held file count 9 307 retained evidence read-only 
    admission r-absent-timeout: exit=0 last=REFUSE stderr=0B | image ok 49c9e0fc0497 image ok 80a91784a0ae image ok 49c9e0fc0497 FAIL name sdk-php-graph-239-l10-refuse-install not proven absent (exit 124) FAIL name sdk-php-graph-239-l10-refuse-check not proven absent (exit 124) held (9 files)
    admission temp dirs left: 0
    
  18. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    SOURCE and inert EFFECT review PASS for Graph H. One invocation for each of the two B admission profiles is selected, owned by sdk-php. R's Composer-resolution profiles are not selected by this decision.

    Bound packet 6719980562: 52,066 B / SHA-256 99643ee8f8aa1e72e1039d6ebb4b7c4193b196b23fdf8ba94e4ed14969d4743a.

    • Controller H: 24,816 B / 567d0e4917ab0d00e45a4a49a150cb224483ec1bd0997e9ff123c3bdfd8773a0.
    • Admission: 07e2775af837e8eaf68ae68a038c8a2d837c1106482f13aa63101bc381e457bc.
    • Launcher: ea8541e41693b3479f754529d966a0f78b1462b25edc8c5790f7483785cc5795.
    • Held check-admission.php: 3,752 B / 579711063da8bb80d635db58256202e868a4976c02d83e06129d41f9a93279a7.

    I read the new controller branches, admission, launcher and PHP check. I independently replayed the hard-isolated controls with all real Docker-like binaries masked and sockets/network unavailable: exit 0, empty stderr, output 18,871 B / 753d0b7907312aa0a914034f1361124b4811b37ee09c759cd54e987623b95ba4, byte-identical to the packet. Carried outcomes, R cause refusals, B verdict failures and B preflight refusals behave as declared. This fake replay supplies no actual PHP or Composer evidence.

    I also recomputed the retained G vendor/archive inventories and readonly state. The actual B inputs are:

    Order Profile / interpreter Read-only consumer Exact lock Vendor inventory
    1 239-adm-p82 / PHP 8.2.35, image 604de2f0 accepted 239-l12-p82, Laravel 12.69.0 5cb011fa5b4acc65d1a3bc5beda2c82038ca3e3df3537a745fe71eac07bd4bd6 9,581 files / 8527feb2e69c2086bcb296319a86356dad45c14d52295d19998bcd4e7c091235
    2 239-adm-p83 / PHP 8.3.36, image 628102249d93 accepted 239-l13-p83, Laravel 13.30.0 86ddee9439774495886211631f8482d31395fd1f5313386f4b84285433b2f7a1 9,814 files / 42f1022ce0803aa4ff2b08b65951b15d2d42db7fc327156907ef766752c2b2fa

    Both contain published SDK 3.10.0 at 4e6c6b7b, all 470 SDK files at inventory c562d378…, and the accepted Workflow 2.21.1 graph. Before each B effect, retain a fresh host-computed canonical vendor inventory matching the table, in addition to H's lock/permissions checks; any drift refuses. Recheck those inputs after the cell. No retained root may be modified.

    Re-read this raw decision and the packet. Use the held H launcher once per profile, fresh roots, exact nine held hashes, strict name absence, exact cached image IDs, 0 running/owned containers and no competing local slot. Admission must exit 0 within 60 seconds, end exactly ADMIT, contain no FAIL and have empty stderr. Start profile 1 by 10:25Z; profile 2 may start only after profile 1 PASS plus proven cleanup, by 10:37Z. No retry or fallback; a NONPASS stops the sequence. Authority ends 11:00Z and each terminal report is due by T0+720 seconds.

    Keep the launcher's env-i/private HOME/DOCKER_CONFIG, 1 MiB file-size cap and 480 + KILL 180 outer bound. Each B effect is one read-only, network-none check container using H's init, UID 1000, cap-drop ALL/no-new-privileges, 2 CPU / 2 GiB / 256 PIDs recipe. No install, pull or networked container. Require the actual interpreter, all 13 explicitly synthetic predicate inputs with exact messages/outcomes, real-metadata provider registration, controller exit 0 and no warning line. Preserve each verdict, streams, markers and executed bytes.

    Cleanup must prove both requested names absent, no run/owner residue and no running container before releasing the slot. Retain inputs/images and evidence through 23:30Z Phase F. No shared cleanup, release, portal, production or Server effect is authorized. B proves the installed predicate and supported provider registration; it does not boot a real Laravel 10/11 application or override Composer metadata. #239 remains open for the R evidence and final reconciliation.

  19. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H B cell 1/2 239-adm-p82: PASS under selection 6720197374 (3,916 B / afe934f4). T0 was 10:11:47.226Z and t1 was 10:11:48.421Z; controller exit 0, driver stderr empty, no retry.

    Before the cell (host-computed with CompletionPollSubject::inventory's exact canonical form, read-only), retained run239-l12-p82-root/consumer:

    • lock 5cb011fa…bd4bd6;
    • vendor 9,581 files / 8527feb2…c091235;
    • SDK 470 files / c562d378;
    • 0 writable entries.

    This matched the carry. I also re-read packet 6719980562 (52,066 B / 99643ee8), and the held hashes matched: controller 567d0e49, admission 07e2775a, launcher ea8541e4, check 57971106.

    Admission (started 10:11:46.556Z):

    • exit 0, ADMIT, no FAIL, empty stderr;
    • 0 running and 0 owned containers;
    • images 49c9e0fc, 80a91784 and 604de2f0 exact;
    • names strict-absent;
    • tag → 4e6c6b7b;
    • retained consumer exact and read-only;
    • 9 held files.

    Effect: one --network none read-only check on 604de2f0. Verdict (one line, no warnings; admission.log e4b687ad):

    • PHP 8.2.35, SDK 3.10.0, installed framework v12.69.0;
    • 13/13 synthetic predicate inputs as expected, all with the exact message:
      • 10.50.4, 11.57.1, 12.68.0 and 13.29.0 (each also in .0 form) and null refuse;
      • 12.69.0 and 12.69.0.0 admit;
      • 13.30.0 and 13.30.0.0 refuse on PHP 8.2;
    • the real provider registered with Composer's real installed 12.69.0.0 (ServiceConfiguration bound).

    After the cell:

    • the retained inventory recomputed byte-identical to the before-file;
    • sdk-php-graph-239-adm-p82-install/-check both strict-absent;
    • 0 containers in total, 0 running, 0 owned, 0 labelled.

    These synthetic inputs prove the installed predicate; they are not a Laravel 10/11 boot. Next: cell 2, 239-adm-p83, start-by 10:37Z.

  20. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H B cell 2/2 239-adm-p83: PASS. Run after cell 1's PASS and proven cleanup; T0 was 10:12:20.082Z and t1 was 10:12:21.256Z. Controller exit 0, driver stderr empty, no retry.

    Before the cell, retained run239-l13-p83-root/consumer:

    • lock 86ddee94…b2f7a1;
    • vendor 9,814 files / 42f1022c…52b2fa;
    • SDK 470 / c562d378;
    • 0 writable entries.

    This matched the carry.

    Admission (10:12:19.412Z): exit 0, ADMIT, empty stderr; image 628102249d93 exact; names strict-absent; retained consumer exact and read-only; 9 held files.

    Effect: one --network none read-only check on 628102249d93. Verdict (one line, no warnings; admission.log 66c56ac9):

    • PHP 8.3.36, SDK 3.10.0, v13.30.0;
    • 13/13 synthetic inputs as expected, all with the exact message: the same refusals as cell 1, and 12.69.0 / 12.69.0.0 admit, with 13.30.0 and 13.30.0.0 admitted on PHP 8.3;
    • the real provider registered with the installed 13.30.0.0.

    After the cell:

    • the retained inventory recomputed byte-identical; cell 1's retained consumer also re-verified unchanged at the end;
    • both names strict-absent; 0 containers, 0 running, 0 owned, 0 labelled.

    Graph H B selection: both cells PASS (239-adm-p82 on PHP 8.2.35, 239-adm-p83 on PHP 8.3.36). Each was an offline, read-only check against an unchanged accepted consumer, and each started well before its start-by.

    • What is now proven: the installed SDK 3.10.0 predicate refuses Laravel 10.50.4, 11.57.1, 12.68.0, 13.29.0 and null, and Laravel 13 on PHP 8.2, each with the exact message. Supported provider registration succeeds on the real installed frameworks.
    • What is not: this is not a real Laravel 10/11 application boot. R (real Composer advisory refusals) is still unselected, and Drop Laravel 10 and 11 from service-mode support in the next minor (upstream EOL, unfixed advisories) #239 stays open for R and final reconciliation.
    • Retained to 23:30Z: the evidence in run239-adm-p82-* and run239-adm-p83-*, and the binv/ before/after inventories.
    • Next: General's captured audit. The local slot can be released on confirmation.
  21. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    B captured audit PASS; both offline admission cells are accepted and their slot is released. I verified the selection/executed/controller/check hashes, admissions, exact one-line PHP verdicts and all 13 outcomes per interpreter, including exact-message flags and real provider registration. The PHP 8.2 cell ran 10:11:47.226–10:11:48.421Z; the PHP 8.3 cell 10:12:20.082–10:12:21.256Z. Both outer exits are 0 with empty stderr. Logs are e4b687ad1db09cc377f091949f87702f8c9949b05acb0886ff949dc7a18e27c3 and 66c56ac9ed50bf2101d8edcb3815bf9585c08066d7bd3b42a472a31c6df4c839. Audit record: 5,780 B / 247076bd1be35c6f6f585236e1c9672a30bd85816338b1e1029ccabdc6263651.

    I independently recomputed the retained G vendor/archive/SDK inventories after B: byte-identical to the pre-B audit, zero writable entries. Fresh daemon reads prove all four B names absent and zero containers in total. B proves the installed predicate with synthetic version inputs and supported provider registration; it does not boot Laravel 10/11.

    Now select one invocation per R profile, owned by sdk-php, in this order:

    Order Profile Declared framework / platform Expected Laravel advisory set
    1 239-l10-refuse 10.50.4 / PHP 8.2.35 target PKSA-3r5d-mb8f-1qw9, PKSA-b41t-wbzk-9q51, PKSA-d5tc-s1qs-h781, PKSA-m5cs-t1y6-qpcs, PKSA-mdq4-51ck-6kdq
    2 239-l11-refuse 11.57.1 / PHP 8.2.35 target same five
    3 239-l12-below 12.68.0 / PHP 8.2.35 target PKSA-d5tc-s1qs-h781
    4 239-l13-below 13.29.0 / PHP 8.3.36 target PKSA-d5tc-s1qs-h781

    Every graph also pins SDK 3.10.0. Workflow is omitted, as its own floor would create a separate conflict. These are resolution targets in composer.json, not claims of running the old frameworks.

    Bound H packet 6719980562, raw 52,066 B / 99643ee8f8aa1e72e1039d6ebb4b7c4193b196b23fdf8ba94e4ed14969d4743a. Controller 567d0e4917ab0d00e45a4a49a150cb224483ec1bd0997e9ff123c3bdfd8773a0; admission 07e2775af837e8eaf68ae68a038c8a2d837c1106482f13aa63101bc381e457bc; launcher ea8541e41693b3479f754529d966a0f78b1462b25edc8c5790f7483785cc5795; the same nine held files and trust bytes as reviewed. General's isolated H replay passed with exact output 753d0b79… and empty stderr.

    Before each effect, re-read this raw decision and packet; require fresh absent roots/names, exact cached installer/runner identities, nine held hashes and trust, 0 running/owned containers, and a fresh admission that exits 0 within 60 seconds, ends ADMIT, has no FAIL and empty stderr. Use H's held launcher, env-i/private HOME/DOCKER_CONFIG, 1 MiB file cap, outer 480 + KILL 180 and the unchanged read-only UID1000/cap-drop/NNP/2CPU/2GiB/256PID recipe. Each profile runs one installer container on the ordinary bridge network, with no check container. No egress allowlist is claimed.

    Start profile 1 by 10:30Z. Each later start requires the preceding profile PASS plus proven cleanup, with start-by times 10:42, 10:54 and 11:06Z respectively. Any NONPASS stops the sequence. No retry, fallback or source change. Authority ends 11:30Z; each report is due by T0+720.

    PASS requires Composer exit 2, the verified trust-before-install receipt and no audit-after-install receipt, no lock/vendor, exactly one resolution problem and the exact root Laravel advisory cause. The reported advisory identities must equal the frozen set, without any extra advisory or transport/platform/lock/acquisition cause. A successful install or any other failure is NONPASS. Do not ignore an advisory or weaken normal blocking. Retain the exact log, manifest, verdict, streams, markers and executed bytes.

    Require strict name absence and empty run/owner/running lists after each cell. Retain all roots/images/evidence through 23:30Z Phase F. No pull, shared cleanup, SDK release, portal or production effect is selected. #239 remains open for the captured R audit and acceptance reconciliation; prior NONPASSs remain attributed. Server's local stop remains in force.

  22. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H R cell 1/4 239-l10-refuse: PASS under selection 6720235778 (4,099 B / 53ae6fff). T0 was 10:15:19.074Z and t1 was 10:15:24.193Z; controller exit 0, driver stderr empty, no retry.

    Before the cell:

    • packet 6719980562 re-read (52,066 B / 99643ee8);
    • held controller 567d0e49, admission 07e2775a, launcher ea8541e4;
    • all R roots absent; 0 containers.

    Admission (10:15:18.458Z): exit 0, ADMIT, no FAIL, empty stderr.

    Effect: one installer container on the ordinary bridge network (49c9e0fc, held trust and Composer 2.10.3). The declared graph was SDK 3.10.0 + laravel/framework 10.50.4, target PHP 8.2.35.

    Verdict:

    • Composer exit 2;
    • trust-before-install.json present, no trust-before-audit.json;
    • no lock and no vendor: the consumer holds only composer.json, read-only;
    • exactly one Problem 1: Root composer.json requires laravel/framework 10.50.4 … found laravel/framework[v10.50.4] but these were not loaded, because they are affected by security advisories ("PKSA-b41t-wbzk-9q51", "PKSA-d5tc-s1qs-h781", "PKSA-m5cs-t1y6-qpcs", "PKSA-3r5d-mb8f-1qw9", "PKSA-mdq4-51ck-6kdq");
    • the advisory set equals the frozen five, with no other advisory and no transport, platform, lock or acquisition cause;
    • install.log 1,145 B / 1e160f892b2069f2dc3696aa7ce707bb13c54b84d82d2add7c85f9f5f06a5b7f.

    Real Composer also prints two informational lines that are not causes: "No composer.lock file present…" and "Running update with --no-dev…".

    Cleanup: both names strict-absent; 0 containers in total, 0 running, 0 owned, 0 run-labelled.

    Next: 239-l11-refuse, start-by 10:42Z.

  23. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H R cell 2/4 239-l11-refuse: PASS. Run after cell 1's PASS and cleanup. T0 was 10:15:46.318Z and t1 was 10:15:51.297Z; controller exit 0, stderr empty, no retry.

    Admission (10:15:45.683Z): exit 0, ADMIT, no FAIL, empty stderr.

    Effect: one bridge-network installer container. The declared graph was SDK 3.10.0 + laravel/framework 11.57.1, target PHP 8.2.35.

    Verdict:

    • Composer exit 2;
    • trust checked before install, no audit-after-install receipt;
    • no lock and no vendor;
    • exactly one problem: the root laravel/framework 11.57.1 requirement blocked by advisories exactly equal to the frozen five (PKSA-3r5d-mb8f-1qw9, PKSA-b41t-wbzk-9q51, PKSA-d5tc-s1qs-h781, PKSA-m5cs-t1y6-qpcs, PKSA-mdq4-51ck-6kdq), with no other cause;
    • install.log 1,145 B / 9ffcd4441c92ed5d211555054e1d2d537de6f538b700ee57367b7de36e6bc26a.

    Cleanup: both names strict-absent; 0 containers, owned or labelled.

    Next: 239-l12-below, start-by 10:54Z.

  24. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H R cell 3/4 239-l12-below: PASS. Run after cell 2's PASS and cleanup. T0 was 10:16:04.163Z and t1 was 10:16:08.994Z; controller exit 0, stderr empty, no retry.

    Admission (10:16:03.533Z): exit 0, ADMIT, no FAIL, empty stderr.

    Effect: one bridge-network installer container. The declared graph was SDK 3.10.0 + laravel/framework 12.68.0 (below the 12.69.0 floor), target PHP 8.2.35.

    Verdict:

    • Composer exit 2;
    • trust checked before install, no audit-after-install receipt;
    • no lock and no vendor;
    • exactly one problem: Root composer.json requires laravel/framework 12.68.0 … found laravel/framework[v12.68.0] but these were not loaded, because they are affected by security advisories ("PKSA-d5tc-s1qs-h781"). That is exactly the frozen floor advisory, with no other cause;
    • install.log 1,053 B / b860a13259a98550c4c954717a5431448fdc5d22ba207bf0066d2cc88ba74724.

    Cleanup: both names strict-absent; 0 containers, owned or labelled.

    Next: 239-l13-below, start-by 11:06Z.

  25. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Graph H R cell 4/4 239-l13-below: PASS. Run after cell 3's PASS and cleanup. T0 was 10:16:20.980Z and t1 was 10:16:25.852Z; controller exit 0, stderr empty, no retry.

    Admission (10:16:20.324Z): exit 0, ADMIT, no FAIL, empty stderr.

    Effect: one bridge-network installer container. The declared graph was SDK 3.10.0 + laravel/framework 13.29.0 (below the 13.30.0 floor), target PHP 8.3.36.

    Verdict:

    • Composer exit 2;
    • trust checked before install, no audit-after-install receipt;
    • no lock and no vendor;
    • exactly one problem: Root composer.json requires laravel/framework 13.29.0 … found laravel/framework[v13.29.0] but these were not loaded, because they are affected by security advisories ("PKSA-d5tc-s1qs-h781"). That is exactly the frozen floor advisory, with no other cause;
    • install.log 1,053 B / 438aca1eec9ea48c7a9cddce5765054e0f1ec3d002cbfaf92b8a48f78a2199b5.

    Cleanup: both names strict-absent; 0 containers, owned or labelled.


    Graph H R selection 6720235778: all four cells PASS, in order, each well before its start-by, each after the previous PASS plus proven cleanup:

    Profile Declared Laravel / platform Composer exit Advisory set (= frozen) install.log Duration
    239-l10-refuse 10.50.4 / 8.2.35 2 the 5 1e160f89 5.1 s
    239-l11-refuse 11.57.1 / 8.2.35 2 the 5 9ffcd444 5.0 s
    239-l12-below 12.68.0 / 8.2.35 2 PKSA-d5tc-s1qs-h781 b860a132 4.8 s
    239-l13-below 13.29.0 / 8.3.36 2 PKSA-d5tc-s1qs-h781 438aca1e 4.9 s
    • Executed bytes in every root: controller 567d0e49, admission 07e2775a; each selection re-read at 53ae6fff.
    • Not done: no advisory ignore, no weakened blocking, no pull, no check container, no install. Nothing was installed in any cell.
    • Retained through 23:30Z / Phase F: the logs, manifests (composer.json), verdicts (refusal-check.json), streams, markers and executed bytes in run239-l1*-refuse-* and run239-l1*-below-*.

    What #239 now has, together with B:

    • Real installs: with ordinary advisory blocking, real SDK 3.10.0 installs with Laravel 10.50.4, 11.57.1, 12.68.0 or 13.29.0 are refused by Composer before activation, for exactly their Laravel advisories.
    • Installed guard: the SDK's installed guard refuses those platform values, and Laravel 13 on PHP 8.2, on the real interpreters.
    • Not covered: neither boots a real Laravel 10/11 application.

    Next: General's captured audit, then #239 acceptance reconciliation. The local slot can be released on your confirmation.

  26. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Captured audit PASS: the four Graph H R Composer-refusal cells are accepted. The local slot is released.

    I checked the selection and executed controller identities, admissions, exact Composer logs and verdicts, trust verification before resolution, absent lock/vendor state, and cleanup. Each controller exited 0 with empty stderr; Composer exited 2 for exactly one root Laravel advisory cause. Laravel 10.50.4 and 11.57.1 reported the frozen five advisory IDs; 12.68.0 and 13.29.0 reported only PKSA-d5tc-s1qs-h781. The two informational Composer notes are not additional causes. All eight names were strictly absent and no containers remained.

    The captured audit is 3,235 B / 867d9a4a3bafee4961532275b6510d222ca8fa224e755f2886a51a278a79c093. The four receipts are L10, L11, L12 below floor, and L13 below floor.

    Together with the accepted five installed Laravel 12/13 graph cells and both offline admission cells, this completes the selected support-transition evidence. The live Laravel guide was re-read at 10:28 UTC: HTTP 200, SDK 3.10, Laravel ^12.69.0|^13.30.0, PHP 8.2/8.3 floors, and the Laravel 10/11 transition are present.

    Limits remain explicit: R proves Composer resolution refusal, not an installed Laravel 10/11 boot; B uses synthetic version inputs against the installed predicate and a real-metadata provider check; the bridge cells do not qualify console-worker pcntl behavior. All earlier NONPASSs retain their original attribution. No audit-ignore, package install, retry, pull, or SDK 3.11 acceptance is implied.

    Owner sdk-php: reconcile #239's current status and Done-when gates against the source, publication, guide and accepted installed/refusal receipts; preserve the historical record and these limits, then close as completed. Retain evidence, consumers and owned images through the existing 23:30 UTC Phase F manifest. No cleanup is selected here.

  27. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Reconciled and closing as completed per 6720364756.

    The issue body now records:

    • the delivered status;
    • each done-when gate, with its evidence: the Workflow handoff (workflow#1020), source (Align next-minor Laravel bridge with published Workflow 2.21 #350, Prepare SDK 3.10.0 release source #353), publication (SDK 3.10.0, tag 4e6c6b7b), the live guide re-read at 10:28 UTC, the five installed supported graph cells (PHP 8.4 / 8.2 / 8.3 audits), and R and B refusal (audits 6720364756 and 6720235778);
    • the accepted limits: R is not an L10/11 boot, B uses synthetic predicate inputs, and console-worker pcntl is not qualified.

    The original text is kept, collapsed as historical, and earlier NONPASS attributions are unchanged.

    Evidence, consumers and owned images are retained through the 23:30 UTC Phase F manifest. No cleanup or new effect.

  28. rmcdaniel commented on Nov 8, 2026

    @rmcdaniel
    MemberAuthor

    Phase F resource disposition is complete. The eight task-owned qualification images and 22 completed dependency/archive-cache copies were retired by exact identity. Their source and receipt inventories remain, along with the old SDK baseline and normal published 3.11 consumer needed for the remaining #269 checks. Two pre-existing/shared images and all WIP source were preserved. No global prune or registry cleanup ran.

    Earlier admission and partial NONPASS results remain attributed. This closes temporary-resource custody only and adds no installed-runtime qualification claim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions