TenantAtlas/specs/302-tenant-owned-surface-route-audit/spec.md
ahmido d072b0107b feat(specs/302): tenant owned surface route audit (#357)
Implements platform feature branch `302-tenant-owned-surface-route-audit`.

Target branch: `platform-dev`.

Follow-up integration path after merge:

`platform-dev` → `dev`.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #357
2026-05-14 21:14:59 +00:00

303 lines
28 KiB
Markdown

# Feature Specification: Tenant-Owned Surface Route Audit
**Feature Branch**: `302-tenant-owned-surface-route-audit`
**Created**: 2026-05-14
**Status**: Draft
**Input**: User description: "tenant-owned-surface-route-audit als 302"
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: The repo has moved toward workspace-first managed-environment routing, but the tenant-owned admin surface set is still understood through scattered code, tests, and candidate notes. Operators and implementers cannot tell which tenant-owned surfaces are fully migrated, intentionally hidden, partially cut over, blocked by product IA decisions, or dependent on retired tenant-panel behavior without reconstructing the answer manually.
- **Today's failure**: After Spec 301 restored Inventory navigation, adjacent surfaces such as Entra Groups, policies, backups, restore runs, findings, evidence, reports, diagnostics, and subordinate relation surfaces still need a repo-verified posture. Without an audit matrix, follow-up work risks either mass-enabling navigation too broadly or preserving stale hide-first assumptions as if they were product decisions.
- **User-visible improvement**: The next repair can be chosen from one clear, repo-verified inventory of tenant-owned admin surfaces, including route posture, navigation posture, context source, global-search posture, RBAC posture, existing proof, blocker, and recommended next action.
- **Smallest enterprise-capable version**: Produce one bounded audit artifact for admin-reachable tenant-owned surfaces and one sequenced repair-prep order. Do not enable routes, change navigation, migrate resources, delete dead code, or decide product IA for individual surfaces in this slice.
- **Explicit non-goals**: No mass navigation re-enablement, no broad runtime migration, no Entra Groups cutover decision, no navigation contract split, no tenant-panel dead-code deletion, no application code changes, no new persisted state, and no new framework for route auditing.
- **Permanent complexity imported**: One repo-local audit artifact in this spec package plus review tasks. No runtime models, tables, enums, services, registries, UI components, assets, jobs, or policies are introduced.
- **Why now**: `docs/product/spec-candidates.md` lists this as the second step after `admin-inventory-navigation-cutover`; Spec 301 is completed and explicitly deferred this generic route audit.
- **Why not local**: A local fix to one resource would hide the cross-surface drift. The current problem is incomplete shared understanding, so the narrowest correct step is a read-only repo audit and repair order.
- **Approval class**: Cleanup
- **Red flags triggered**: One lightweight document-only classification vocabulary is used for the audit matrix. It is not a runtime taxonomy or product state family.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 1 | Wiederverwendung: 1 | **Gesamt: 10/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: canonical-view
- **Primary Routes**:
- `/admin/workspaces/{workspace}`
- `/admin/workspaces/{workspace}/environments`
- `/admin/workspaces/{workspace}/environments/{environment}`
- `/admin/workspaces/{workspace}/environments/{environment}/...` tenant-owned resource/page routes generated by Filament
- retired or legacy tenant route families such as `/admin/t/{tenant}/...` and `/admin/tenants/{tenant}/...` as negative-control inputs only
- **Data Ownership**: The audit covers tenant-owned and managed-environment-owned runtime records that require workspace plus managed-environment entitlement at authorization time. No product data is created or changed.
- **RBAC**: The audit must record membership and capability expectations for each surface. Non-member workspace or tenant access remains deny-as-not-found. Member-without-capability remains 403 where capability checks apply. UI visibility remains non-authoritative.
For canonical-view specs, the spec MUST define:
- **Default filter behavior when tenant-context is active**: Environment-bound routes resolve their managed-environment context from the canonical workspace/environment route or current trusted context helpers. Workspace-level routes must not show tenant-owned surfaces unless a valid environment context is established.
- **Explicit entitlement checks preventing cross-tenant leakage**: The audit must verify whether each surface uses existing context/authorization paths such as `WorkspaceScopedTenantRoutes`, `NavigationScope`, `OperateHubShell`, `ScopesGlobalSearchToTenant`, `canAccess`, `canViewAny`, policy methods, and route middleware. Any missing or ambiguous check is documented as a repair blocker, not patched in this slice.
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
- **Cross-cutting feature?**: yes
- **Interaction class(es)**: navigation entry points, route generation, global search result destinations, tenant-owned detail/list surfaces, relation-manager entry points
- **Systems touched**:
- `apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php`
- `apps/platform/app/Support/Navigation/NavigationScope.php`
- `apps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.php`
- `apps/platform/app/Support/OperateHub/OperateHubShell.php`
- `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php`
- `apps/platform/app/Filament/Resources/*`
- `apps/platform/app/Filament/Pages/*`
- `apps/platform/routes/web.php`
- focused Filament feature tests under `apps/platform/tests/Feature/Filament/`
- **Existing pattern(s) to extend**: No runtime path is extended in this slice. The audit must measure surfaces against existing shared paths: workspace-scoped tenant routes, navigation scope, tenant-scoped global search, route middleware, and tenant-owned query helpers.
- **Shared contract / presenter / builder / renderer to reuse**: N/A for runtime. The audit should refer to the existing shared helpers above rather than defining a new route/navigation framework.
- **Why the existing shared path is sufficient or insufficient**: Sufficiency is the question being audited per surface. The output must state whether each surface already uses the shared path, legitimately deviates, or needs a follow-up repair.
- **Allowed deviation and why**: Document-only deviation. The audit may classify exceptions, but it must not create executable exception logic.
- **Consistency impact**: Future repair specs should use the audit to avoid parallel local navigation/search/routing behavior.
- **Review focus**: Reviewers must verify that the audit is repo-derived, that no runtime code was changed, and that follow-up recommendations are split into bounded candidates.
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
- **Touches OperationRun start/completion/link UX?**: no
- **Shared OperationRun UX contract/layer reused**: N/A
- **Delegated start/completion UX behaviors**: N/A
- **Local surface-owned behavior that remains**: The audit may mention tenant-owned surfaces that link to runs, but it does not change OperationRun start, completion, link, notification, or monitoring behavior.
- **Queued DB-notification policy**: N/A
- **Terminal notification path**: N/A
- **Exception required?**: none
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
- **Shared provider/platform boundary touched?**: no runtime boundary change
- **Boundary classification**: N/A for implementation. The audit may record provider-owned surfaces such as Entra Groups separately from platform-core route/context rules.
- **Seams affected**: Read-only review of route, navigation, global search, and authorization seams.
- **Neutral platform terms preserved or introduced**: Use `workspace`, `managed environment`, `tenant-owned surface`, `route posture`, `navigation posture`, and `repair blocker`.
- **Provider-specific semantics retained and why**: Provider-specific names such as Entra Groups remain only as audited surface names. They do not become platform-core vocabulary.
- **Why this does not deepen provider coupling accidentally**: The output is a bounded audit artifact and does not change shared contracts or runtime labels.
- **Follow-up path**: document-in-feature for the audit; follow-up-spec for any product-sensitive or runtime repair.
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | no runtime UI change | N/A | navigation, route, global search review only | none | no | `N/A - audit/prep artifact only` |
| Existing tenant-owned admin surfaces | no change in this slice | Native Filament surfaces are inspected, not changed | navigation, route, search | shell, page, route context as audited facts only | no runtime exception | The audit records current posture without re-rendering or enabling surfaces |
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Secondary Context | Product/engineering chooses the next bounded repair spec | Surface classification, blocker, recommended next action | Route names, resource/page classes, tests, search posture, RBAC notes | Not an operator runtime surface; it guides repair sequencing | Follows Admin Workspace Navigation & Tenant-owned Surface Repair candidate order | Prevents repeated manual reconstruction and broad repair bundling |
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | internal implementer/reviewer | Surface name, classification, blocker, next action | Source files, test files, route names, global-search notes | N/A | Promote the next bounded repair | Raw payloads and product data are out of scope | One matrix row per surface prevents duplicate scattered posture notes |
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Audit / Planning | Repo audit matrix | Choose next repair candidate | Read matrix row | N/A | N/A | N/A | `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` | N/A | Workspace/environment route posture fields | Tenant-owned surface | Migration state, blocker, next action | docs-only audit artifact |
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Product owner / implementer / reviewer | Decide which tenant-owned surface repair should be promoted next | Internal audit matrix | Which surfaces are already migrated, blocked, stale, or ready for a bounded repair? | Surface classification, blocker, next action, proof status | File/test/route evidence | route posture, navigation posture, search posture, RBAC posture, proof status | Docs-only; no TenantPilot or Microsoft tenant mutation | Promote next bounded spec | none |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no runtime source of truth. The audit artifact is repair-prep evidence, not product truth.
- **New persisted entity/table/artifact?**: no runtime persistence. One spec-package audit artifact is expected during implementation.
- **New abstraction?**: no
- **New enum/state/reason family?**: no runtime family. The audit uses document-only labels: migrated, partial cutover, stale panel logic, valid context gate, valid RBAC, ambiguous product IA, dead-code dependent.
- **New cross-domain UI framework/taxonomy?**: no runtime framework or taxonomy.
- **Current operator problem**: The team cannot safely choose the next tenant-owned route/navigation repair without a repo-verified surface inventory.
- **Existing structure is insufficient because**: Candidate notes, tests, resources, route helpers, and model-family metadata each hold part of the answer, but no single artifact records the cross-surface posture.
- **Narrowest correct implementation**: Create one audit matrix and repair order from current repo evidence.
- **Ownership cost**: The matrix must be maintained only when a follow-up repair changes the posture. No runtime code or framework cost is added.
- **Alternative intentionally rejected**: A broad migration or route/navigation framework split is rejected because the audit must first identify the actual drift and product-decision blockers.
- **Release truth**: Current-release repair preparation.
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Feature-validation review using existing Pest feature tests; no new runtime test family is required unless the audit discovers that the audit artifact itself needs a repo guard in a follow-up spec.
- **Validation lane(s)**: confidence for existing focused Filament tests; N/A for runtime because this slice does not change app behavior.
- **Why this classification and these lanes are sufficient**: The deliverable is a repo audit. Existing route, navigation, global-search, and admin-scope tests provide evidence; any missing proof is documented as an audit gap and follow-up blocker rather than patched here.
- **New or expanded test families**: none in this spec.
- **Fixture / helper cost impact**: none.
- **Heavy-family visibility / justification**: none.
- **Special surface test profile**: standard-native-filament for any referenced existing Filament surface; no browser proof is required because no UI changes are made.
- **Standard-native relief or required special coverage**: ordinary feature-test evidence and static route/resource review only.
- **Reviewer handoff**: Confirm no runtime code changed, every audit row links to repo evidence, test gaps are marked as gaps, and follow-up repairs are split.
- **Budget / baseline / trend impact**: none.
- **Escalation needed**: document-in-feature.
- **Active feature PR close-out entry**: Guardrail.
- **Planned validation commands**:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/PanelNavigationSegregationTest.php tests/Feature/Filament/AdminTenantSurfaceParityTest.php tests/Feature/Filament/AdminSharedSurfacePanelParityTest.php tests/Feature/Filament/TenantOwnedResourceScopeParityTest.php tests/Feature/Filament/EntraGroupAdminScopeTest.php tests/Feature/Filament/EntraGroupGlobalSearchScopeTest.php tests/Feature/Filament/PolicyResourceAdminSearchParityTest.php tests/Feature/Filament/PolicyVersionAdminSearchParityTest.php`
- `git diff --check`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Inventory the tenant-owned admin surface set (Priority: P1)
As an implementer preparing the next repair, I need a repo-verified matrix of tenant-owned admin surfaces so I can see which surfaces are migrated, hidden, blocked, or stale before changing behavior.
**Why this priority**: Without the matrix, every follow-up risks repeating the broad drift that Spec 301 intentionally avoided.
**Independent Test**: Review `surface-route-audit.md` and confirm each first-slice tenant-owned family from `TenantOwnedModelFamilies::firstSlice()` plus named residual exceptions has a row with route posture, navigation posture, context source, global-search posture, RBAC posture, proof status, blocker, and next action.
**Acceptance Scenarios**:
1. **Given** the current repo surface set, **When** the audit is completed, **Then** every tenant-owned first-slice model/resource family is represented exactly once.
2. **Given** a tenant-owned surface with no direct primary resource, **When** it is subordinate or indirect, **Then** the audit records the parent relation or indirect surface instead of inventing a primary route.
3. **Given** a surface with unclear product IA, **When** it is classified, **Then** the blocker is recorded as ambiguous product IA and the next action is a bounded follow-up decision.
---
### User Story 2 - Classify route, navigation, search, and RBAC posture (Priority: P2)
As a reviewer, I need each surface classified against the existing route/navigation/global-search/RBAC contracts so I can distinguish valid gates from stale panel logic.
**Why this priority**: The audit only helps if it separates legitimate denials from implementation drift.
**Independent Test**: Sample at least one surface in each classification group and verify the matrix cites concrete files, route families, or tests that support the classification.
**Acceptance Scenarios**:
1. **Given** a migrated surface, **When** it is classified, **Then** the matrix identifies the canonical workspace/environment route path or route-generation helper.
2. **Given** a stale hidden surface, **When** it is classified, **Then** the matrix names the hidden navigation or panel logic and marks it as a repair candidate, not a product decision.
3. **Given** a global-search capable resource, **When** it is classified, **Then** the matrix records whether it has an Edit or View page or whether global search is disabled.
4. **Given** an inaccessible tenant-owned surface, **When** RBAC posture is classified, **Then** non-member 404 and member-missing-capability 403 expectations are recorded separately where applicable.
---
### User Story 3 - Produce a sequenced repair order (Priority: P3)
As a product owner, I need a recommended follow-up order so adjacent repairs remain small and do not become a single umbrella migration.
**Why this priority**: The candidate group already names follow-ups, but the audit must make the next one defensible from repo evidence.
**Independent Test**: Confirm the audit includes one ordered follow-up list with blockers and explicitly keeps runtime fixes out of this spec.
**Acceptance Scenarios**:
1. **Given** surfaces classified as stale panel logic or partial cutover, **When** the audit proposes follow-up work, **Then** each recommendation is scoped as a bounded spec candidate.
2. **Given** surfaces blocked by product IA, **When** the audit proposes follow-up work, **Then** it calls out the decision needed before implementation.
3. **Given** tenant-panel dead-code dependencies, **When** the audit proposes follow-up work, **Then** it keeps deletion after route/navigation replacement decisions.
## Edge Cases
- A surface may be tenant-owned by data but intentionally workspace-canonical by route; the audit must record both facts.
- A surface may be tenant-owned but subordinate to a relation manager; the audit must not create an artificial top-level route recommendation.
- A surface may be tenant-bound but not globally searchable; the audit must distinguish disabled/not-applicable search from missing search coverage.
- A direct URL may be reachable while navigation is hidden; the audit must classify route access and navigation registration separately.
- A test may encode stale behavior; the audit must record that as a test-contract finding without changing tests in this slice.
- Legacy `/admin/t/{tenant}` and `/admin/tenants/{tenant}` behavior must be treated as negative-control evidence, not as a route family to revive.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-302-001**: The implementation MUST create `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` as the single audit matrix artifact.
- **FR-302-002**: The audit MUST cover every first-slice tenant-owned family listed by `TenantOwnedModelFamilies::firstSlice()`.
- **FR-302-003**: The audit MUST cover documented residual or exception surfaces from `TenantOwnedModelFamilies::residualRolloutInventory()` and `scopeExceptions()` when they have admin-reachable or admin-relevant surfaces.
- **FR-302-004**: Each audited row MUST include surface name, model/resource/page owner, route posture, navigation posture, context source, global-search posture, RBAC posture, existing proof, blocker, migration state, and recommended next action.
- **FR-302-005**: Migration state MUST be one of: migrated, partial cutover, stale panel logic, valid context gate, valid RBAC, ambiguous product IA, or dead-code dependent.
- **FR-302-006**: The audit MUST distinguish route reachability from navigation registration.
- **FR-302-007**: The audit MUST distinguish workspace-home cleanliness from environment-bound admin visibility.
- **FR-302-008**: The audit MUST verify global-search posture for resources using tenant-scoped search or search-disabled posture, including the Filament v5 requirement that globally searchable resources have an Edit or View page.
- **FR-302-009**: The audit MUST record existing high-signal tests that prove each posture or explicitly mark proof as missing.
- **FR-302-010**: The audit MUST produce a recommended repair order that keeps `admin-directory-groups-cutover`, `navigation-contract-split`, and `tenant-panel-dead-code-retirement` as separate follow-up candidates unless repo evidence justifies a different bounded order.
- **FR-302-011**: The implementation MUST NOT modify application runtime code, routes, migrations, models, services, jobs, Filament resources, Livewire components, policies, commands, views, assets, or tests.
- **FR-302-012**: Any discovered runtime defect MUST be documented as a follow-up blocker or candidate, not fixed in this spec.
### Non-Functional Requirements
- **NFR-302-001**: The audit must be repo-derived from current files and tests, not roadmap-aspirational.
- **NFR-302-002**: The audit must be concise enough to review in one PR and structured enough for later implementation agents to use directly.
- **NFR-302-003**: The feature must remain docs/spec-artifact only and must not change runtime behavior.
- **NFR-302-004**: Filament v5 and Livewire v4 compliance must be preserved by not introducing legacy APIs or new runtime code.
- **NFR-302-005**: No new assets are registered; deployment `filament:assets` requirements are unchanged.
### RBAC / Security Requirements
- **SEC-302-001**: The audit MUST record whether each surface's expected denial semantics are non-member 404 and member-without-capability 403, where applicable.
- **SEC-302-002**: The audit MUST treat UI visibility as non-authoritative and identify server-side authorization proof separately.
- **SEC-302-003**: The audit MUST flag any surface where route/context access appears to depend only on navigation hiding.
### Auditability / Observability Requirements
- **AUD-302-001**: This docs-only slice introduces no `AuditLog` event and no `OperationRun`.
- **AUD-302-002**: The audit artifact must provide evidence references sufficient for reviewers to trace each conclusion back to repo files or tests.
### Data / Truth-Source Requirements
- **DATA-302-001**: No product data or database schema is changed.
- **DATA-302-002**: Tenant-owned runtime truth remains in existing models/tables; the audit artifact is repair evidence only.
- **DATA-302-003**: The audit must not promote document classification labels into product state or persisted truth.
## Success Criteria *(mandatory)*
- **SC-302-001**: `surface-route-audit.md` exists and covers the expected tenant-owned surface inventory.
- **SC-302-002**: Every row has route, navigation, context, search, RBAC, proof, blocker, migration state, and next-action fields.
- **SC-302-003**: The audit identifies at least one ordered follow-up path and explains why close alternatives are deferred or blocked.
- **SC-302-004**: No application runtime files are changed.
- **SC-302-005**: Existing focused Filament validation commands either pass or any failures are documented as pre-existing/runtime follow-up blockers.
## Assumptions
- The user explicitly requested feature number `302`; `specs/302-tenant-owned-surface-route-audit` did not exist before this preparation.
- `301-admin-inventory-navigation-cutover` is completed context and must not be rewritten.
- The implementation deliverable is an audit artifact, not an application behavior change.
- `TenantOwnedModelFamilies` is the starting inventory, but the audit may add admin-relevant pages/resources discovered from Filament files and tests.
- The current Laravel/Filament stack is Laravel 12, Filament 5, Livewire 4, Pest 4, and PHP 8.4.
## Risks
- The audit could become too broad if it tries to solve every route or IA problem it finds.
- Document-only labels could be mistaken for runtime taxonomy if not clearly bounded.
- Some tests may assert stale behavior; those must be reported as findings rather than edited in this spec.
- A later implementation loop could accidentally patch runtime code unless the tasks keep the docs-only boundary explicit.
## Out of Scope
- Any application code change.
- Any migration, model, service, job, policy, command, view, route, Filament resource/page, Livewire component, or test edit.
- Broad runtime route migration.
- Mass navigation re-enablement.
- Entra Groups cutover implementation.
- Navigation contract split implementation.
- Tenant-panel dead-code deletion.
- New global-search enablement.
- New audit log or OperationRun behavior.
## Follow-up Spec Candidates
- `admin-directory-groups-cutover`
- `navigation-contract-split`, only if the audit shows shared contract drift remains after bounded surface repairs
- `tenant-panel-dead-code-retirement`
- surface-specific repair specs named by `surface-route-audit.md`
## Manual Promotion Notes
- **Selected candidate title**: `tenant-owned-surface-route-audit`
- **Source location**: `docs/product/spec-candidates.md`, Admin Workspace Navigation & Tenant-owned Surface Repair candidate group.
- **Why selected**: User explicitly promoted it as `302`; it is the recommended follow-up after `admin-inventory-navigation-cutover`.
- **Close alternatives deferred**: `admin-directory-groups-cutover` needs the audit/product IA evidence first; `navigation-contract-split` should happen only if drift remains after bounded repairs; `tenant-panel-dead-code-retirement` should wait until dependencies are known.
- **Roadmap relationship**: UI and Product Maturity Polish, parallel immediate repair lane for Admin Workspace Navigation & Tenant-owned Surface Repair.
- **Completed-spec guardrail result**: Spec 301 has completed task markers and is treated as historical/completed context only. Specs 279-301 are not modified by this preparation.
- **Smallest viable implementation slice**: Create the audit matrix and repair-prep order only; do not patch runtime.