feat: EnforceAuditSnapshotOnRetryRule (ADR-0001 §Snapshot-on-Retry Safety)#2
Open
Goosterhof wants to merge 2 commits intomainfrom
Open
feat: EnforceAuditSnapshotOnRetryRule (ADR-0001 §Snapshot-on-Retry Safety)#2Goosterhof wants to merge 2 commits intomainfrom
Goosterhof wants to merge 2 commits intomainfrom
Conversation
…y Safety) Promotes the cross-territory AST harness from a Pest arch test to a canonical PHPStan rule. Type-based receiver detection (ConnectionInterface) replaces territory-specific property-name matching. Discovery filter scopes to App\Actions\* classes injecting entity audit loggers. Three compliant first-statement shapes (refresh, fresh-fetch, new-or-newInstance) plus if-block escape hatch and @audit-snapshot-retry-safety opt-out marker. Origin: emmie PR #187, entreezuil PR #139, ublgenie PR #166, kendo PR #1029. Doctrine: ADR-0001 §Snapshot-on-Retry Safety. Phase 2 of phpstan-warroom-rules per ADR-0021.
The package's Pint config (mb_str_functions: true) normalizes ltrim/trim to mb_ltrim/mb_trim, which are PHP 8.4+ functions. The new rule introduced the first mb_ltrim/mb_trim callsites; the composer.json constraint should match what the formatter actually produces. All consuming territories already run PHP 8.4 — no real-world impact. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promotes the cross-territory audit-snapshot-on-retry-safety AST harness — currently shipped as a Pest arch test in emmie, entreezuil, ublgenie, and kendo — to a canonical PHPStan rule in this package. Phase 2 promotion per ADR-0021.
What lands
EnforceAuditSnapshotOnRetryRule(Rule<MethodCall>) — flagsApp\Actions\*classes whose constructor injects an entity audit logger and whose$connection->transaction(...)calls do not begin with an in-memory state reset$model->refresh()or$this->prop->refresh()— updates$model = $this->prop->newQuery()->find*/first*or*->fresh()— deletes / fresh reads$model = new SomeClass(...)or$this->prop->newInstance()— createsif-block escape hatch (mirrors emmie'sSoftDeleteDocumentActionshape)// @audit-snapshot-retry-safety: <rationale>preceding the transaction callenforceAuditSnapshotOnRetry.firstStatementMustResetStateDesign choices vs the original Pest harness
ObjectType::isSuperTypeOf(ConnectionInterface)instead of property-name matching ($this->dbvs$this->connection). Removes territory variance as a class.phpstan.neon ignoreErrors(e.g., ublgenie'sBranchCredentialAuditLoggerfixed-action-writer exemption migrates from arch-test allowlist to consumer config).MethodCallnodes (verified empirically). Falls back toScope::getFile()upward-line scan, mirroring the kendo arch test verbatim.Tests
26/26 PHPUnit tests pass. 14 fixtures cover: three compliant shapes, three failure shapes, marker exemption, if-block escape hatch, channel-logger exclusion, non-Action class, non-
ConnectionInterfacereceiver gate.Parity gate (cross-territory verification)
Ran the rule against three of four consuming territories at their
origin/developmenttips:ublgenie:
app/Actions/SaveBranchCredentials.php:36and:59— both attributable to ublgenie's arch test hardcodingBranchCredentialAuditLoggeras a fixed-action-writer exemption (see ublgenietests/Arch/AuditTest.php:516-524). The post-cascade migration is mechanical: hardcoded entry → consumerphpstan.neon ignoreErrors. A separate Sapper recon mission has been filed to verify the exemption is doctrinally sound (the null-coalesce$branch->credentials ?? new BranchCredentialsshape may indicate a real retry-corruption path, not a true fixed-action writer).Versioning
Per ADR-0021 SemVer: this is documented expected behavior (consumer-side
ignoreErrorsfor territory-specific false positives). Targeting minor bump (v0.2.0) at the release-cut PR, which moves[Unreleased]to a versioned heading. This PR does not tag.PHP constraint
Bumped
composer.jsonphp: ^8.3→^8.4. The package's Pint config (mb_str_functions: true) normalizesltrim/trimtomb_ltrim/mb_trim(PHP 8.4+ functions). The new rule introduced the first such callsites. All consuming territories run 8.4 — no real-world impact.Test plan
ObjectType::isSuperTypeOf(ConnectionInterface)is the appropriate type-based receiver detection idiomReferences
campaigns/war-room/2026-05-01-audit-snapshot-on-retry-safety-cross-territory.md🤖 Generated with Claude Code