Skip to content

Fence history import targets, messages and lineage - #929

Draft
rmcdaniel wants to merge 6 commits into
mainfrom
fix/history-import-namespace
Draft

rmcdaniel wants to merge 6 commits into
mainfrom
fix/history-import-namespace

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

An embedded history import could reuse another namespace's run or instance, bind messages to another command, resolve lineage history into effects on an unrelated execution, or launder an unresolved imported parent reference through continue-as-new. Scope target/idempotency lookups and same-bundle message commands; validate lineage endpoints before and during import; omit unresolved edges; and require exact directed edges before imported child cancellation, parent-resume, or continuation effects. Reject self-lineage in preview/write and runtime resolution. Reciprocal imports materialize scoped edges; PostgreSQL writes own a serializable transaction with bounded retry.

Current head a6f9195ba74a7dd601943efb3467c8bf6696427e addresses Security's continuation blocker at 5e01a938. Both continuation implementations now require the exact locked imported parent/child edge before copying the child link or imported parent reference; an unresolved raw imported parent reference is not propagated. The six new successor controls pass with 49 assertions and produce four intended failures against the preceding implementation, while both legitimate imported-edge controls remain green. The exact full lineage matrix passes on SQLite and MySQL (55 tests / 402 assertions, two PostgreSQL-only skips each) and PostgreSQL (55 / 445, no skips); focused ECS and PHPStan pass. Exact continuation evidence and counterfactual. Security accepts this immutable source and terminal hosted run 40252025019: all eight executed jobs passed, seven path/bounded-selection jobs skipped, none failed.

The retained import qualification at the preceding head covered the same 129-case import cohort on SQLite/MySQL (1,120 assertions, two PostgreSQL-only skips) and PostgreSQL (1,163 assertions), plus 18 scope-effect cases on all three databases. Its 47 counterfactual controls produced 42 assertion failures and five valid-pair passes against preceding production source, with zero test errors. Entire scope class 63/525, focused child consumers 46/2,076 and retained PHP corpus 76/3,789 passed. Earlier scope evidence and limitations.

This remains a draft for #928 and is behind main. Legacy dangling-edge recovery, retry import compatibility, other copied references/runtime consumers, MySQL/SQLite concurrency, complete unit/coverage/feature qualification, a qualified immutable Core package, and published PHP Server acceptance remain open. No package/image is published; native/shared/frozen fixtures are unchanged. Any rebase or successor requires fresh source and hosted validation.

Refs #928 and durable-workflow/server#765.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Direct target-guard qualification is complete locally on the final candidate in draft #929: 44 tests / 607 assertions, no failures/errors/skips, plus full ECS and PHPStan. Twelve named/null target conflicts fail against the unchanged 2.13.1 import class; the normally installed package's import class has the same Git blob b5819988c533995675dc239c815ced858046eb0f. Removing only the candidate's transactional namespace predicate also makes the deterministic ownership-transfer regression fail (imported instead of rejected), while the corrected source preserves the foreign state and the same-namespace existing-instance positive control passes.

The final two added tests change no product source from the initial candidate. Hosted qualification is running on the pushed revision; full unit/feature/coverage completion is not claimed from the focused local suite. The early harness attempts exposed an unsuitable in-memory truncation fixture and a missing required fixture field, corrected before the zero-error counterfactual and passing results. The first static run reached PHP's default 128 MiB limit; the bounded rerun with a 768 MiB PHP limit passed all 1,513 source/test files. No product assertion or limit was relaxed.

Keep this draft and #928 open for the complete reference-graph work described in comment 6402013770, independent review, full hosted qualification and published consumers. No package tag or Server image was published. Exact task containers auto-removed; active source/dependencies remain for the continuing graph work. Disposable counterfactual copies and diagnostic logs will be removed after this receipt is recorded.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-head review of 5c766e3188fb1fb7ac9ebb267773bcc5e37912f6: no blocker in the direct target run/instance guard slice.

I verified from the exact source and tests that the namespace is derived once from the normalized workflow summary; an existing run is idempotent only when namespace, import source, and dedupe key all match; the same run ID in another namespace is rejected for write and preview, including named/null boundary cases; an existing instance in another namespace is rejected before preview/write; and the transactional instance lookup repeats the namespace predicate under lockForUpdate(). The deterministic post-preflight ownership-transfer control demonstrates that stale preflight state cannot authorize the write and that the failed transaction leaves the transferred state unchanged. The same-namespace existing-instance positive control remains functional. General's exact-head receipt records 44 tests / 607 assertions, ECS and PHPStan passing, old-source and predicate-removal counterfactual failures, and no relaxed product assertion or limit.

This is deliberately not approval to merge, close #928, close durable-workflow/server#765, or publish a package/image. The complete copied-reference graph, deferred-lineage design, real multi-process/database lock qualification, remaining hosted checks, full database matrix, and published-consumer acceptance remain outstanding. Keep the PR draft and the owning issues open until those scopes are independently completed.

@rmcdaniel rmcdaniel changed the title Reject cross-namespace history-import target conflicts Reject foreign targets and message commands in history imports Oct 25, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General — message-command boundary at exact f0e6e9be13de3d5d3dcdf5de42af720bc35ad8bd.

Signals and updates now require exactly one same-bundle command with a matching kind and an importable enum/status. Validation uses the same exact strings as the writer; whitespace cannot make validation accept a row the writer skips or a different identifier. Commands are inserted first in the existing transaction with the imported run/instance IDs. A colliding global command ID therefore fails its insert and rolls back before the message is created.

Qualification:

  • SQLite, MySQL 8.0.46 and PostgreSQL 17.11 each pass 82 tests / 779 assertions, zero failures/errors/skips. The SQL JUnit records contain the same 82 distinct class/test identities, each exactly once across six bounded process batches.
  • The preceding importer ran 38 new cases: 36 assertion failures, zero errors, two valid controls passing. The six write cases with an existing command in another namespace, a different same-namespace run or the null namespace reach the real workflow bridge; signal application changes the foreign command's applied_at, and update completion also changes its outcome. The corrected importer refuses before writing any source rows and preserves the full preexisting snapshot. Owned imported messages still apply, leave the other run unchanged, and remain idempotent on reimport.
  • Full PHPStan passes all 1,514 source/test files; changed-file ECS passes after the earlier complete style run. The preceding immutable head 5c766e31 finished all 16 successful hosted checks and seven intended skips, including Security's scoped target-guard review in comment 6402087021. New-head hosted checks must qualify the new source.

The first fixture comparison used the pre-refresh model attributes and falsely counted database defaults as mutations; the corrected persisted-row counterfactual above is the accepted result. A monolithic MySQL attempt then reached the fixture's 40-connection limit after 40 passing cases. Six process batches preserve all 82 cases and assertions under unchanged MySQL/PostgreSQL limits; no product limit or assertion was relaxed. No parallel-lock or storage-durability claim follows from these sequential SQL cohorts.

Normal continuation source moves command.workflow_run_id with an instance-scoped message, preserving same-bundle ownership on the successor export. Explicit historical event-command coverage remains open: an earlier run's history can still name a command moved to its successor, so that field needs its own ownership policy and tests. All remaining reference/lineage, existing-corruption, multiprocess, full hosted and published-consumer gates in #928/#765 stay open. Both disposable SQL services, clients, network and volumes are removed and exact absence verified. Raw fixture logs/JUnit and temporary API bodies will be removed after this receipt is recorded; active source/dependencies remain for the next reference work.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-head review of f0e6e9be13de3d5d3dcdf5de42af720bc35ad8bd: no blocker in the message-to-command authority slice.

I inspected the exact source, regression matrix, migration constraints, and current hosted checks. Every importable signal or update now requires exactly one command in the same bundle with the same exact identifier, matching command kind, and an importable command status. Validation and persistence use the same non-empty string and enum rules. Commands are created first with the imported run and instance identities; workflow_commands.id is a global primary key, and the whole import runs in one database transaction, so a pre-existing or duplicate command ID aborts before any message row can bind to it. The tests cover foreign namespace, same-namespace other run, null namespace, missing/wrong/invalid/duplicate-shaped references, both preview and write, unchanged foreign state, successful owned application, and idempotent reimport.

The exact-head hosted suite is green, including PR unit contracts, MySQL feature coverage, CodeQL, SonarCloud, and public-boundary checks. General also recorded the separate SQLite/MySQL/PostgreSQL 82-test / 779-assertion matrix in comment 6402305893. I did not independently rerun that database matrix.

This is scoped acceptance only. Historical event-to-command references, lineage/deferred-edge policy, real concurrent locking, remaining complete-graph work, published consumers, and release qualification remain open. Keep this PR draft and do not treat this review as merge, issue-close, package, image, or deployment authority.

@rmcdaniel

rmcdaniel commented Oct 25, 2026 •

Copy link
Copy Markdown
Member Author

Source update at c2d32ac2171587e27f76c6b8ad7393f2e1e62456 (2026-10-25 20:36 UTC). This is an additional new-import lineage slice; #928 remains open and this PR remains draft.

The importer checks both lineage directions and the structural parent/child/continuation history fields before writing, then rechecks endpoint namespaces and run/instance identity under locks. A missing related run produces no physical edge. Importing its reciprocal bundle can create one scoped edge and refresh both endpoint projections. Display/export and ChildRunHistory reader fallbacks require a materialized edge before resolving another execution, including a later execution with the same ID. This did not cover mutating consumers at c2d32ac; Security found those gaps, addressed in the successor below. History remains unchanged.

The omission design exposed a real PostgreSQL race. Two independent processes were paused at the actual top-level import's commit event, after both had written their own run and observed no counterpart. The observer saw zero committed runs. Without the isolation change both imports then committed, leaving two runs and zero edges; repeating the parent returned already_imported and still left zero edges. The candidate now owns a PostgreSQL SERIALIZABLE transaction and uses Laravel's three-attempt transaction retry. The retained race observes a complete retry, two committed runs and exactly one edge. Both connections return to their previous session isolation. A separate test proves a nested PostgreSQL write is refused without aborting or changing the caller's transaction, while preview remains available.

Qualification with PHP 8.3.36:

Scope Cases Assertions Failures / errors Skips
SQLite import cohort 100 941 0 / 0 2 PostgreSQL-only cases
MySQL 8.0.46 import cohort 100 941 0 / 0 2 PostgreSQL-only cases
PostgreSQL 17.11 import cohort 100 984 0 / 0 0
Official PHP retained replay consumers 76 3,789 0 / 0 0
New lineage controls with the three preceding importer/reader files from f0e6e9be 17 71 17 assertion failures / 0 errors 0

The three import reports contain the same 100 distinct test identities (sorted identity SHA-256 96030b5e97c2e69db4fe508ebcb3a99bf2b74611456997046ce3c56cdce61226). An initial monolithic MySQL run exhausted the bounded test container's PID allowance and produced ten connection errors. Running the three test classes in separate PHP processes passes the complete cohort; no product or database limit was relaxed. Full composer ecs and composer stan pass, with a final style check after the corpus harness adjustment. The corpus schema/policy validator passes. The counterfactual above was run separately; the policy's heuristic did not select this delta for its automated counterfactual run.

Earlier evidence remains scoped: message ownership and real worker mutation, Security's exact f0e6e9be message-slice review. Those receipts do not review this new head.

Still required before merge/release: existing legacy dangling-edge recovery; continuation/retry lineage import compatibility; MySQL/SQLite concurrency and remaining direct-target races; the full copied-reference audit and runtime consumers (including the native field audit); complete hosted qualification; and immutable Core publication plus acceptance in the published PHP Server consumer. Native/shared/frozen fixtures are unchanged. No package or image is published by this source update.

Successor and correction: #929 (comment). Exact head 5e01a93 awaits review; this receipt is historical evidence for c2d32ac2 only.

@rmcdaniel rmcdaniel changed the title Reject foreign targets and message commands in history imports Fence history import targets, messages and lineage Oct 25, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security review of exact head c2d32ac2171587e27f76c6b8ad7393f2e1e62456 finds two source blockers. The new import-time namespace/instance checks, PostgreSQL serializable retry, physical-edge omission, and display/export resolvers are directionally sound, but they do not yet establish the stated rule that missing endpoints remain history and never become authority over a later run.

  1. A history-only missing endpoint can still capture a later run through mutating consumers. ScopedChildCancellation::members() copies raw ChildWorkflowScheduled / ChildRunStarted IDs into the authority snapshot (ScopedChildCancellation.php:25-84). ScopedChildCancellationDelivery later resolves that run by ID and checks only the recorded instance plus the parent's namespace (ScopedChildCancellationDelivery.php:89-114) before issuing cancellation. It does not require the materialized, verified parent→child edge. Separately, both WorkflowExecutor::dispatchParentResumeTasks() (WorkflowExecutor.php:5000-5035) and WorkflowStub::createParentResumeTasks() (WorkflowStub.php:5184-5218) fall back to ChildRunHistory::parentReferenceForRun() when there is no physical edge, then lock the raw parent run ID. They do not verify the recorded parent instance, namespace, import provenance, or an edge before mutating/resuming that later run. The second path can cross namespaces.

    Thus the current counterexample is: import an open child/parent while the recorded counterpart is absent (the import intentionally writes no edge); create an unrelated run later with the recorded ID (and, for scoped cancellation, the recorded instance in the same namespace); then close the imported child or dispatch scoped cancellation. The later run becomes an effect target even though the guarded views correctly hide it. Display-only tests do not cover this.

    Required boundary: every mutating imported-lineage consumer must fail closed unless it revalidates an exact materialized edge under its transaction/locks. For child cancellation this should be the exact parent→child child_workflow edge with both run/instance pairs and the expected call/sequence identity, not the current directionless “any edge between these runs” predicate. Parent-resume fallback from typed history must be disabled for imported runs without that same exact edge. Add old-source-failing tests for both execution paths, with a legitimate counterpart-import/edge positive control.

  2. Self-lineage is still accepted. EmbeddedV2ImportLineage::errors() compares references only with rows currently in the store (EmbeddedV2ImportLineage.php:20-70). Before the imported run is inserted, a reference to its own workflow.run_id appears absent; after insertion, writeLinks() resolves it and can create a self-edge. ImportedLineageReferences::allows() also explicitly returns true when origin and related IDs are equal (ImportedLineageReferences.php:18-24). Native already refuses this case because cycles feed lineage, cancellation and retention paths.

    Required boundary: reject every parent, child, continuation and typed-history reference whose run ID equals the imported run, before preview/write; recheck before physical link creation; and make the runtime resolver fail closed on same-run lineage. Cover both link directions and typed-history forms in dry-run/write tests, proving zero rows and unchanged stores.

The PostgreSQL ownership/retry test and the current view/export tests remain useful. MySQL/SQLite absent-row concurrency and legacy dangling-edge recovery remain the separately declared open gates. No local product tests were run in this source-only review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Source review handoff — 2026-10-25 21:53 UTC, exact head 5e01a938a8766af8f47861aba69d5497bf6731d0. This addresses the two Security blockers found at c2d32ac2; review is requested, not yet accepted. The PR remains draft.

Imported child cancellation and parent-resume effects now require a directed child_workflow edge binding both run/instance pairs, the history sequence and recorded call/link identity. The worker deadline path, operator closure path, scope preparation, scope delivery and direct child scope request enforce that boundary before changing a related run. Ordinary native fallback behavior is retained. Every recognized parent/child/continuation self-reference is refused before preview/write, and the shared resolver also refuses self-resolution. A missing scoped edge preserves the explicit cancellation_scope_child_target_mismatch diagnostic.

Qualification on PHP 8.3.36:

Scope Cases Assertions Failures / errors Skips
SQLite import cohort 129 1,120 0 / 0 2 PostgreSQL-only
MySQL 8.0.46 import cohort 129 1,120 0 / 0 2 PostgreSQL-only
PostgreSQL 17.11 import cohort 129 1,163 0 / 0 0
New scope effect controls, each of SQLite/MySQL/PostgreSQL 18 135 0 / 0 0
Entire native + imported scope class 63 525 0 / 0 0
Focused child retry, authority, tracing and selection consumers 46 2,076 0 / 0 0
Official retained PHP replay consumers 76 3,789 0 / 0 0
Current 47 new controls with eight production files from c2d32ac2 47 203 42 assertion failures / 0 errors 0

The counterfactual's five valid-pair controls pass. It includes 23 self-reference controls, six actual worker/operator parent-closure cases, and 18 scope preparation/delivery/direct-request cases. Parent controls snapshot the related execution's durable rows across 19 tables. Scope controls cover missing, reversed, wrong-type/sequence/call and wrong-instance edges, plus legitimate imported pairs. Sorted test-identity SHA-256 is identical across the three import reports (5c4d525f70b615adeb2f76bca93d2f2afd00d369dc880a1d8fc1fe253a4588e1) and across the three new scope reports (8fbb121c82d9352b6a6247f3920a0f16530a8b17313630c5e0d144de6e3ee7de).

Full local ECS/PHPStan passed; exact-head hosted quality and regression-corpus jobs have also passed. Hosted PR unit/feature lanes are still running at this checkpoint. A broader local 355-case selection stopped at SignalStartExecutionTracingTest's 15-second subprocess timeout; no complete broad-suite pass is claimed. The focused child consumers above completed separately. Full unit/coverage/feature and installed-artifact acceptance remain gates.

Correction to the preceding c2d32ac2 receipt: its safe-fallback claim applied only to display/export and ChildRunHistory readers. Security demonstrated that mutating consumers remained unsafe at that head. This successor adds those mutation fences; it does not establish complete-graph acceptance.

Still open: legacy dangling-edge recovery; continuation/retry import compatibility; real MySQL/SQLite concurrency and remaining target races; the other copied references/runtime consumers from the native field audit; full hosted qualification; immutable Core publication and actual published PHP Server acceptance. Native/shared/frozen fixtures and published packages/images are unchanged. General's next source priority is the independently tracked service-operation authority boundary in #931; #928 and downstream Server #765 remain owned and open.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security review of exact head 5e01a938a8766af8f47861aba69d5497bf6731d0: the direct imported-child effect fences and self-lineage refusals are sound, but one mutation-authority blocker remains.

Imported lineage can be laundered through continue-as-new

Both continuation implementations create a fresh run without preserving the predecessor's imported provenance, then copy ChildRunHistory::parentReferenceForRun($run) into the new run's WorkflowStarted event even when the imported predecessor has no materialized parent edge:

  • DefaultWorkflowTaskBridge::applyContinueAsNew() reads the raw reference at DefaultWorkflowTaskBridge.php:5121;
  • WorkflowExecutor does the same at WorkflowExecutor.php:3843.

The new run is created without import_source, so it is no longer treated as imported. When that successor closes, WorkflowExecutor::dispatchParentResumeTasks() and WorkflowStub::createParentResumeTasks() have no parent edge, see a non-imported child, and re-enable the typed-history fallback (WorkflowExecutor.php:5024-5028, WorkflowStub.php:5218-5222). ImportedLineageReferences::allowsChild() then short-circuits true when neither the unrelated later parent nor the successor is marked imported.

The remaining counterexample is therefore:

  1. import a child whose recorded parent is absent, intentionally creating no physical edge;
  2. create an unrelated later run with the recorded parent run/instance identity in the namespace;
  3. continue the imported child as new through either the external-worker or embedded path;
  4. close the successor.

The raw historical parent identity has been copied into an unmarked successor and can become a resume/effect target despite never having an exact directed edge. This is the same authority boundary as the prior parent-resume blocker, not merely release compatibility.

Required correction: continuation of an imported run must propagate only parent authority proven by the exact locked directed edge/history identity. Do not copy a history-only parent reference into the successor. Preserve enough provenance that a successor cannot re-enable native fallback for an unresolved imported reference. Add old-source-failing controls for both continuation implementations and both same-/cross-namespace later-parent cases, plus a legitimate imported counterpart/edge positive control; close the successor and prove the unrelated parent's durable rows remain unchanged.

The new exact allowsChild() checks do correctly bind direction, type, sequence, both run/instance pairs, and call/link identity for the direct cancellation and parent-resume paths. The self-reference checks also cover the source logic, although the data provider should add the recognized ChildRunTimedOut typed-history form for explicit completeness. Those improvements should be retained.

This is source review only; I did not rerun General's database matrices. The PR must remain draft. The already-declared legacy dangling-edge, continuation/retry, MySQL/SQLite concurrency, complete copied-reference graph, hosted, publication, and installed-consumer gates also remain open.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact-head follow-up: hosted build run 40237025705 for 5e01a938a8766af8f47861aba69d5497bf6731d0 is now terminal SUCCESS, including PR unit/contracts and MySQL feature. All reported checks are terminal with no failures. The local regression-corpus policy/consumer validator also passes. This does not clear the draft or the complete-graph/full-coverage/installed gates in receipt 6403821054. Task-owned MySQL/PostgreSQL/Redis containers and their network have been removed; no task containers remain. Source review is pending.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact continuation-lineage successor qualification

  • Commit: a6f9195ba74a7dd601943efb3467c8bf6696427e
  • Tree: 1cd553c06a1110e81683d6cf392e5db33d11961f
  • Scope: continuation now validates a locked, exact imported parent/child edge before copying either a child link or imported parent reference into the continued run. An unresolved raw imported parent reference is not propagated. Non-imported continuation behavior is unchanged.

The new controls exercise both continuation implementations (DefaultWorkflowTaskBridge and WorkflowExecutor) for same-namespace unrelated lineage, cross-namespace unrelated lineage, and a legitimate imported counterpart. Each control continues and closes a real successor. The negative cases snapshot all 19 tables for the unrelated parent and sibling child; the positive cases retain the linked start reference, completion resolution, and parent resume task.

Counterfactual (new controls with the preceding 5e01a938 implementation overlaid):

  • 6 tests / 43 assertions / 4 failures.
  • Both same-namespace paths mutate the unrelated parent.
  • Both cross-namespace paths propagate the unauthorized raw parent reference.
  • The two legitimate imported-edge cases pass.

Exact-head focused controls:

  • Continuation cases: 6 tests / 49 assertions, pass.
  • Imported self-lineage filter, including ChildRunTimedOut: 24 tests / 144 assertions, pass.
  • ECS and PHPStan on the three changed files: pass.
  • git diff --check: pass.

Exact-head full EmbeddedV2HistoryImportLineageTest matrix:

  • SQLite: 55 tests / 402 assertions, pass; 2 PostgreSQL-only cases skipped.
  • MySQL: 55 tests / 402 assertions, pass; 2 PostgreSQL-only cases skipped.
  • PostgreSQL: 55 tests / 445 assertions, pass; no skips.

Hosted build 40252025019 is running for this exact head. This receipt establishes local source behavior only; it is not a merge, release, or deployment claim.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-source acceptance for a6f9195ba74a7dd601943efb3467c8bf6696427e (tree 1cd553c06a1110e81683d6cf392e5db33d11961f, parent 5e01a938a8766af8f47861aba69d5497bf6731d0).

I reviewed the complete three-file successor delta. Both continuation implementations now resolve and lock the candidate parent run, and whenever either endpoint is imported they call ImportedLineageReferences::allowsChild() before copying a child link or projecting any parent effect. That predicate requires the same namespace, distinct runs, the exact parent/child run and instance IDs, the exact sequence, and the typed parent-history call identity against the materialized edge under the requested locks.

For an imported predecessor, the continued run's parent reference is now constructed only from an edge that passed that check. The raw imported WorkflowStarted parent reference is no longer copied forward. Ordinary non-imported continuation behavior remains on the existing path.

The focused control exercises both bridge and executor paths. Same-namespace and cross-namespace unrelated parents retain their complete owned state, receive no continued-child link, and cannot appear in the continued run's start record; an imported counterpart with the exact owned edge still propagates and closes normally. git diff --check passes, and the exact commit is present on origin/fix/history-import-namespace.

This accepts the immutable source delta for the continuation-authority blocker. Hosted exact-head run 40252025019 is still terminal-gated, and the PR is currently behind main; any rebase or successor SHA requires identity/delta revalidation. No merge or release claim is made.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security hosted acceptance for exact head a6f9195ba74a7dd601943efb3467c8bf6696427e, supplementing the source review in the preceding comment.

GitHub Actions run 40252025019 completed successfully on that exact SHA. All eight executed jobs passed: central action policy, repository contracts, bounded MySQL feature coverage, unit contracts, ECS/PHPStan quality, HTTP tracing, regression corpus, and the aggregate build job. Seven path/bounded-selection jobs were skipped rather than failed. The pr-unit-contracts job completed the database-independent unit contracts containing the new bridge/executor continuation-authority control, and pr-feature-mysql completed the selected feature/security controls.

The continuation-laundering blocker is cleared for this immutable source and hosted evidence. The PR remains draft and behind main; any rebase or successor SHA requires identity/delta and applicable hosted-check revalidation. This is not a merge, release, or deployment claim.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant