TenantAtlas/specs/144-canonical-operation-viewer-context-decoupling/research.md

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.

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: OperateHubShell already 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 TenantlessOperationRunViewer and render it in tenantless-operation-run-viewer.blade.php above 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.
  • Decision: Keep OperationRunLinks::tenantlessView() and the admin.operations.view route 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.