# Route Contracts: Operations Tenantless Canonical Migration **Feature**: 078-operations-tenantless-canonical **Date**: 2026-02-06 --- ## Canonical Routes (Retained — No Changes) ### GET /admin/operations | Property | Value | |----------|-------| | **Route name** | `admin.operations.index` | | **Handler** | `App\Filament\Pages\Monitoring\Operations` | | **Middleware** | `web`, `panel:admin`, `ensure-correct-guard:web`, `DenyNonMemberTenantAccess`, Filament middleware, `ensure-workspace-selected`, `ensure-filament-tenant-selected` | | **Auth** | Requires authentication + workspace membership | | **Scope** | Workspace-level (shows all runs in workspace) | | **Response** | 200 HTML (Livewire page) | ### GET /admin/operations/{run} | Property | Value | |----------|-------| | **Route name** | `admin.operations.view` | | **Handler** | `App\Filament\Pages\Operations\TenantlessOperationRunViewer` | | **Middleware** | `web`, `panel:admin`, `ensure-correct-guard:web`, `DenyNonMemberTenantAccess`, Filament middleware | | **Auth** | Requires authentication + workspace membership for `$run->workspace_id` | | **Model binding** | `{run}` resolves to `OperationRun` by ID | | **Non-member** | 404 (deny-as-not-found) | | **Not found** | 404 (Laravel model binding) | | **Response** | 200 HTML (Livewire page with infolist) | --- ## Decommissioned Routes (Resource-Generated Routes Removed After Migration) ### GET /admin/t/{tenant}/operations/r/{record} | Property | Value | |----------|-------| | **Route name** | `filament.admin.resources.operations.view` | | **Status** | ❌ **REMOVED** — route no longer registered | | **After migration** | Natural 404 | | **Previously** | `ViewOperationRun` (Filament ViewRecord page) | ### GET /admin/t/{tenant}/operations | Property | Value | |----------|-------| | **Route name** | `filament.admin.resources.operations.index` | | **Status** | ❌ **REMOVED** — route no longer registered | | **After migration** | Replaced by explicit convenience route `admin.operations.legacy-index` that redirects 302 → `/admin/operations` | | **Previously** | `ListOperationRuns` (Filament ListRecords page) | --- ## Link Generation Contracts ### OperationRunLinks::view($run, $tenant) | Property | Value | |----------|-------| | **Returns** | `route('admin.operations.view', ['run' => $run])` | | **Delegates to** | `OperationRunLinks::tenantlessView($run)` | | **Tenant parameter** | Ignored (no-op) | | **Change** | None — already canonical | ### OperationRunLinks::tenantlessView($run) | Property | Value | |----------|-------| | **Returns** | `route('admin.operations.view', ['run' => $run])` | | **Change** | None | ### OperationRunLinks::index() | Property | Value | |----------|-------| | **Returns** | `route('admin.operations.index')` | | **Change** | None | ### OperationRunLinks::related($run, $tenant) | Property | Value | |----------|-------| | **Returns** | Array of up to 11 contextual link arrays | | **Change** | None — consumed by `TenantlessOperationRunViewer` header actions | --- ## Test Route Assertions ### Positive (must work) | Test | Route | Expected | |------|-------|----------| | T-078-001 | `GET /admin/operations/{run}` | 200 (member) | | T-078-001 | `GET /admin/operations/{run}` | 200 (run with `tenant_id = null`) | | T-078-009 | `GET /admin/t/{tenant}/operations` | 302 redirect to `/admin/operations` | ### Negative (must 404) | Test | Route | Expected | |------|-------|----------| | T-078-001 | `GET /admin/operations/{run}` | 404 (non-member) | | T-078-002 | `GET /admin/t/{tenant}/operations/r/{record}` | 404 (any user) | | T-078-004 | Route name `filament.admin.resources.operations.view` | Not registered | | T-078-004 | Route name `filament.admin.resources.operations.index` | Not registered |