## Summary - add a request-scoped derived-state store with deterministic keying and freshness controls - adopt the shared contract in ArtifactTruthPresenter, OperationUxPresenter, and RelatedNavigationResolver plus the covered Filament consumers - add spec, plan, contracts, guardrails, and focused memoization and freshness test coverage for spec 167 ## Verification - vendor/bin/sail artisan test --compact tests/Feature/078/RelatedLinksOnDetailTest.php - vendor/bin/sail artisan test --compact tests/Feature/078/ tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/Verification/VerificationAuthorizationTest.php tests/Feature/Verification/VerificationReportViewerDbOnlyTest.php tests/Feature/Verification/VerificationReportRedactionTest.php tests/Feature/Verification/VerificationReportMissingOrMalformedTest.php tests/Feature/OpsUx/FailureSanitizationTest.php tests/Feature/OpsUx/CanonicalViewRunLinksTest.php - vendor/bin/sail bin pint --dirty --format agent ## Notes - Livewire v4.0+ compliance preserved - provider registration remains in bootstrap/providers.php - no Filament assets or panel registration changes - no global-search behavior changes - no destructive action behavior changes in this PR Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #198
53 lines
5.4 KiB
Markdown
53 lines
5.4 KiB
Markdown
# Quickstart: Request-Scoped Derived State and Resolver Memoization
|
|
|
|
Implement Spec 167 by adding one explicit request-scoped derived-state store beneath the existing presenter and resolver families, then adopt it on representative list, detail, and canonical surfaces without changing operator-visible semantics.
|
|
|
|
## Implementation Steps
|
|
|
|
1. Add the narrow request-scoped derived-state support types under the existing support layer and bind the store in `app/Providers/AppServiceProvider.php` with request-local lifecycle semantics.
|
|
2. Define the deterministic key contract for family, record identity, variant, and scope-sensitive context, plus an explicit invalidation path for mutation-sensitive derivations.
|
|
3. Route `ArtifactTruthPresenter::forBaselineSnapshot()`, `forEvidenceSnapshot()`, `forTenantReview()`, `forReviewPack()`, and `forOperationRun()` through the shared store.
|
|
4. Refactor repeated consumer seams on `ReviewRegister`, `EvidenceOverview`, `BaselineSnapshotResource`, `BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php`, `EvidenceSnapshotResource`, `TenantReviewResource`, `ReviewPackResource`, and `OperationRunResource` so the first-slice badge, description, next-step, and helper consumers share one per-record derivation.
|
|
5. Route covered `OperationUxPresenter` guidance/explanation and `RelatedNavigationResolver` primary/detail/header entry paths through the same store.
|
|
6. Converge the existing finding-specific related-entry cache and other repeated navigation consumers toward the shared contract instead of leaving multiple local cache patterns in place.
|
|
7. Add focused unit and feature tests for derivation counts, negative-result reuse, mutation freshness, and cross-scope safety, including `tests/Feature/Filament/DerivedStateMutationFreshnessTest.php` as the dedicated freshness suite.
|
|
8. Add `tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php` so CI fails with actionable output if covered families reintroduce ad hoc local caches or adopt the shared store without explicit consumer declaration metadata.
|
|
|
|
## Future Family Adoption
|
|
|
|
1. Confirm the candidate family is deterministic for the proposed access path and that adopting the shared store does not introduce a second semantic layer.
|
|
2. Declare the full consumer metadata set under the top-level `x-derived-state-consumers` extension in `contracts/request-scoped-derived-state.logical.openapi.yaml` before adding the consumer: `surface`, `family`, `variant`, `accessPattern`, `scopeInputs`, `freshnessPolicy`, and `guardScope`. Add `requiredMarkers` and `maxOccurrences` guard metadata so the adoption guard can point to the intended helper seam and reject bypasses or resurrected local caches. Advisory hints such as `mutationSensitive` or `capabilitySensitive` may be added when they help review, but they do not replace the required declaration fields.
|
|
3. Choose one supported `accessPattern` per surface: `row_safe`, `page_safe`, or `direct_once`; do not introduce a new page-local static cache for a covered family.
|
|
4. Add or update the focused Pest coverage that proves repeated reads collapse to one derivation, scope boundaries remain intact, and any mutation-sensitive path is fresh after state changes.
|
|
5. If a family cannot satisfy deterministic keying or freshness rules, use the explicit no-reuse path instead of weakening the shared contract.
|
|
6. Run `tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php` after adding or widening adoption so undeclared scope inputs, freshness gaps, missing guard scope, and ad hoc local caches fail before merge.
|
|
|
|
## Verification
|
|
|
|
### Automated
|
|
|
|
```bash
|
|
vendor/bin/sail up -d
|
|
vendor/bin/sail artisan test --compact tests/Unit/Support/Ui/DerivedState/RequestScopedDerivedStateStoreTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Filament/ReviewRegisterDerivedStateMemoizationTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Filament/EvidenceOverviewDerivedStateMemoizationTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Filament/OperationRunDerivedStateMemoizationTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Filament/DerivedStateMutationFreshnessTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Navigation/RelatedNavigationResolverMemoizationTest.php
|
|
vendor/bin/sail artisan test --compact tests/Feature/Guards/DerivedStateConsumerAdoptionGuardTest.php
|
|
vendor/bin/sail bin pint --dirty --format agent
|
|
```
|
|
|
|
### Manual
|
|
|
|
1. Open the review register and verify artifact-truth label, publication state, and next-step text remain unchanged while repeated presenter calls are eliminated.
|
|
2. Open the evidence overview and verify one active snapshot row per tenant still renders the same truth and freshness messaging, then confirm one canonical authorization regression still behaves correctly: non-member or wrong-scope access remains deny-as-not-found and an in-scope user lacking capability remains forbidden.
|
|
3. Open the tenantless operation-run viewer and verify related context, guidance, and artifact-truth details remain consistent.
|
|
4. Exercise one covered mutating flow and verify any post-action truth or related navigation shown in the same request reflects the updated business state.
|
|
|
|
## Expected Outcome
|
|
|
|
- Covered presenter and resolver families resolve deterministic results once per request for the same key.
|
|
- Covered surfaces retain the same operator-visible semantics and navigation destinations.
|
|
- No persistent caches, no new semantic state families, and no cross-tenant or cross-workspace reuse leakage are introduced.
|