## Summary - harden the canonical operation run viewer so mismatched, missing, archived, onboarding, and selector-excluded tenant context no longer invalidates authorized canonical run viewing - extend canonical route, header-context, deep-link, and presentation coverage for Spec 144 and add the full spec artifact set under `specs/144-canonical-operation-viewer-context-decoupling/` - harden onboarding draft provider-connection resume logic so stale persisted provider connections fall back to the connect-provider step instead of resuming invalid state - add architecture-audit follow-up candidate material and prompt assets for the next governance hardening wave ## Testing - `vendor/bin/sail bin pint --dirty --format agent` - `vendor/bin/sail artisan test --compact tests/Feature/144/CanonicalOperationViewerContextMismatchTest.php tests/Feature/144/CanonicalOperationViewerDeepLinkTrustTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/OpsUx/OperateHubShellTest.php tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/RunAuthorizationTenantIsolationTest.php tests/Feature/Filament/OperationRunEnterpriseDetailPageTest.php tests/Feature/Monitoring/HeaderContextBarTest.php tests/Feature/Monitoring/OperationRunResolvedReferencePresentationTest.php tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php` - `vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Unit/Onboarding/OnboardingDraftStageResolverTest.php tests/Unit/Onboarding/OnboardingLifecycleServiceTest.php` ## Notes - branch: `144-canonical-operation-viewer-context-decoupling` - base: `dev` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #173
4.8 KiB
4.8 KiB
Research: Canonical Operation Viewer Context Decoupling
R-001: Authorization must remain run-first and direct-entitlement based
- Decision: Keep
OperationRunPolicy::view()as the canonical authorization boundary for/admin/operations/{run}and keep its logic based on the run's workspace membership, direct tenant entitlement, and capability resolution by run type. - Rationale: The existing policy already encodes the correct 404 versus 403 semantics: workspace non-members and users lacking entitlement to the run's tenant receive deny-as-not-found, while in-scope users missing a resolved capability receive forbidden. This matches Spec 143 and Spec 144 directly and avoids scattering authorization across header-context helpers.
- Alternatives considered:
- Move authorization into
TenantlessOperationRunViewer::mount(): rejected because it would duplicate policy logic and increase the chance of 404 versus 403 drift. - Authorize from selected tenant context instead of the run's tenant: rejected because that is the failure mode the spec is explicitly correcting.
- Move authorization into
R-002: OperateHubShell should remain a display and navigation helper only
- Decision: Treat
OperateHubShell::activeEntitledTenant()as the source for header labels, return affordances, and optional banner context, but not as a precondition for canonical viewer legitimacy. - Rationale:
OperateHubShellalready resolves the current admin-plane tenant context in a way that respects route tenant, Filament tenant, and remembered tenant fallbacks. That makes it useful for describing the operator's current context, but using it as an authorization or route-validity gate would reintroduce the same hidden coupling Spec 144 is removing. - Alternatives considered:
- Ignore active tenant context completely on the viewer: rejected because the spec explicitly requires non-blocking transparency when current header context differs from the run tenant.
- Force the viewer to switch the remembered tenant to the run's tenant: rejected because it would turn a read action into an implicit context mutation and violate the spec's convenience-only rule for remembered context.
R-003: Context mismatch UX belongs in the viewer wrapper, not in policy or infolist definitions
- Decision: Add canonical-context messaging in
TenantlessOperationRunViewerand render it intenantless-operation-run-viewer.blade.phpabove the reused infolist. - Rationale: The current viewer wrapper already renders the redaction-integrity note before the infolist and owns polling and page-level concerns. Adding a second informational banner there is low-risk and preserves reuse of
OperationRunResource::infolist()without injecting presentation logic into policy code or shared resource schema builders. - Alternatives considered:
- Inject banner rows directly into
OperationRunResource::infolist(): rejected because the infolist is shared and the banner is specific to the canonical workspace viewer semantics. - Encode mismatch state in policy responses: rejected because authorization responses should stay limited to allow, 404, and 403 semantics.
- Inject banner rows directly into
R-004: Preserve the existing canonical deep-link helper contract
- Decision: Keep
OperationRunLinks::tenantlessView()and theadmin.operations.viewroute as the only canonical run-view target for this feature. - Rationale: Existing tests and notification surfaces already rely on this helper, and
OperationRunLinks::view()already normalizes tenant-aware callers onto the tenantless canonical route. The problem is not URL shape; it is trust in the viewer after the URL is opened. - Alternatives considered:
- Introduce a new source-aware deep-link helper: rejected because it would fragment the canonical route contract.
- Reintroduce tenant-bound operation detail URLs: rejected because Spec 078 already consolidated operations onto the canonical tenantless route family.
R-005: Extend focused existing tests and add a small spec-specific pack
- Decision: Extend the strongest existing viewer, shell, authorization, and canonical-link tests, and add a small
tests/Feature/144/pack for mismatch and deep-link trust scenarios. - Rationale: The repo already has substantial coverage around
TenantlessOperationRunViewer,OperateHubShell, operations canonical URLs, and tenant isolation. Reusing those anchors reduces new-test duplication while still giving Spec 144 a clear regression pack that maps directly to the acceptance criteria. - Alternatives considered:
- Put all coverage in one large existing test file: rejected because the matrix of mismatch, lifecycle, and deep-link cases becomes harder to scan and maintain.
- Add only spec-specific tests with no existing-test updates: rejected because that would miss the places where current semantics are already encoded and likely to regress.