# Feature Specification: Managed Environment Cutover Final Seal & Regression Guard Pack

**Feature Branch**: `299-managed-environment-cutover-final-seal`  
**Created**: 2026-05-13  
**Status**: Ready  
**Input**: User-provided Spec 299 prompt: final hardening, regression guards, and cutover closure for the workspace-first managed-environment migration after Specs 297 and 298.

## Spec Candidate Check *(mandatory - SPEC-GATE-001)*

- **Problem**: The managed-environment cutover is close to done, but the repo still lacks one final seal package that proves the runtime core stays off retired tenant routes, that workspace surfaces remain workspace-scoped even with stale environment context, and that remaining `Tenant` terms are either removed from active product UI or explicitly allowlisted.
- **Today's failure**: Contributors can still see broad legacy test and copy surfaces, including technical `TenantResource::getUrl(...)` / `TenantDashboard::getUrl(...)` usages in tests, workspace overview copy such as `Accessible tenants`, and route-scope-sensitive navigation that must stay sealed against remembered environment context. Without a final proof pack, future work can accidentally revive retired product truths even if the app tree currently looks clean.
- **User-visible improvement**: Operators get one final, credible cutover state: workspace-first navigation on workspace pages, explicit environment drill-down on canonical environment routes, no revived `/admin/t...` or `/admin/tenants...` runtime paths, and environment-first copy on the touched active surfaces.
- **Smallest enterprise-capable version**: Refresh a final cutover audit, prove the runtime app tree remains clean, seal any last workspace-vs-environment navigation or intended-URL seam, bound active product copy, classify remaining technical/provider/historical `Tenant` references, and add the final focused regression guard pack.
- **Explicit non-goals**: No database/model/table rename from `Tenant` to `ManagedEnvironment`, no compatibility routes, no dual-read or dual-write, no new product workflow, no new RBAC model, no provider-model rewrite, no package execution, no guided operations, no AI workflow, no generic historical-doc cleanup, and no raw full-suite requirement by default.
- **Permanent complexity imported**: One spec-local `final-cutover-audit.md` artifact, a final focused guard/validation pack, and at most narrow adjustments to existing navigation or link owners if a concrete remaining seam is found. No new application persistence, status family, framework, or broad UI layer is introduced.
- **Why now**: Specs 297 and 298 already did the cutover and terminology cleanup work. The next safe move is to close the topic with one final seal package before unrelated features reintroduce tenant-first runtime or workspace/environment drift.
- **Why not local**: The remaining risk spans canonical links, intended URL handling, navigation registration, workspace overview copy, guard tests, browser smokes, and explicit allowlists. A one-file cleanup would not make the cutover traceable or durable.
- **Approval class**: Cleanup
- **Red flags triggered**: cross-cutting final hardening across routes, navigation, tests, and copy. Defense: the scope is intentionally closure-only, tied to already prepared Specs 297 and 298, and explicitly forbids reopening broader rename or architecture work.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12**
- **Decision**: approve

## Start Condition

- Spec 299 implementation may start only after Spec 298 changes are either committed/merged into the implementation base or explicitly isolated in a separate clean worktree/session branch.
- Do not begin 299 implementation on a dirty intermediate 298 state.
- Before runtime edits, run `git status --short --branch` and `git diff --stat`, then document any pre-existing changes that are intentionally carried into the 299 implementation branch.

## Summary

Spec 299 is the final seal package for the managed-environment cutover. It does not open a new product lane. It proves and, only if necessary, finishes the current product truth:

- no active `/admin/t/...` or `/admin/tenants/...` runtime paths
- no active runtime link generators back to retired tenant surfaces
- no workspace-level environment navigation leak from stale session or `Filament::getTenant()` state
- no callable retired `setTenantPanelContext()` helper
- no product-facing tenant-first wording on the touched active cutover surfaces
- an explicit allowlist for remaining technical, provider-specific, guard-only, or historical `Tenant` references
- a final proof pack that keeps the cutover sealed

## Spec Scope Fields *(mandatory)*

- **Scope**: canonical-view
- **Primary Routes**:
  - Retired and forbidden as active product truth: `/admin/t/...`, `/admin/tenants/...`
  - Canonical workspace home: `/admin/workspaces/{workspace}`
  - Canonical managed-environment list/detail: `/admin/workspaces/{workspace}/environments`, `/admin/workspaces/{workspace}/environments/{environment}`
  - Canonical environment child routes: `/admin/workspaces/{workspace}/environments/{environment}/required-permissions`, `/diagnostics`, `/access-scopes`, and other repo-real child routes
  - Canonical workspace operations: `/admin/workspaces/{workspace}/operations` and `/admin/workspaces/{workspace}/operations/{run}`
- **Data Ownership**:
  - No persistence change.
  - Workspace remains the primary SaaS context.
  - Managed environment remains the secondary managed target context.
  - Internal `Tenant` model/class/table naming may remain technical implementation truth where a structural rename is out of scope.
- **RBAC**:
  - Workspace membership remains the primary access boundary.
  - Managed-environment access scope remains narrowing-only and must not become role authority.
  - Non-member or out-of-scope access remains 404.
  - Established member missing capability remains 403.

For canonical-view specs:

- **Default filter behavior when tenant-context is active**: remembered environment context may survive as a secondary drill-down hint, but route scope decides navigation, intended URL acceptance, and which surface is primary. Workspace surfaces remain workspace-scoped even if an environment is remembered.
- **Explicit entitlement checks preventing cross-tenant leakage**: `WorkspaceIntendedUrl` and `WorkspaceRedirectResolver` must reject retired tenant paths, `ManagedEnvironmentLinks` must derive canonical URLs from explicit workspace/environment scope, and any canonical environment or operations route must keep existing workspace and managed-environment entitlement checks.

## Goals

### G1 - Final active legacy scan is clean

The final route/source scans must show no active runtime hits for `/admin/t/...`, `/admin/tenants/...`, `TenantPanelProvider`, retired tenant panel IDs, retired runtime URL generators, or `setTenantPanelContext()` in the runtime app tree.

### G2 - Workspace/environment navigation is sealed

Workspace surfaces may expose workspace-owned navigation only. Environment-owned primary navigation must appear only on canonical environment routes.

### G3 - Canonical managed-environment link ownership is enforced

Runtime links must stay owned by `ManagedEnvironmentLinks`, `RequiredPermissionsLinks`, `OperationRunLinks`, or the current canonical route owner. Retired tenant route generators must not become active product truth again.

### G4 - Intended URL handling cannot revive retired paths

Stored intended URLs must reject retired tenant paths and only normalize safe canonical workspace operations routes.

### G5 - Product-facing tenant terminology is bounded

Touched active product surfaces should use environment-first wording where the subject is a managed environment. Provider-specific Microsoft/Entra tenant wording remains allowed only when the external provider is the subject.

### G6 - Guard pack prevents regression

The final proof pack must make it difficult to reintroduce retired tenant routes, tenant-panel helper semantics, or workspace/environment navigation leaks.

## Required Artifact

Create or update:

```text
specs/299-managed-environment-cutover-final-seal/final-cutover-audit.md
```

This audit must track:

- active runtime legacy findings
- test legacy findings
- copy findings
- allowed references
- final route/source scan results
- final validation commands and outcomes

## 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 registration, canonical environment links, intended URL handling, workspace overview summary metrics and copy, guard tests, browser smokes, and allowlist auditing.
- **Systems touched**:
  - `apps/platform/app/Support/ManagedEnvironmentLinks.php`
  - `apps/platform/app/Support/Workspaces/WorkspaceIntendedUrl.php`
  - `apps/platform/app/Support/Workspaces/WorkspaceRedirectResolver.php`
  - `apps/platform/app/Providers/Filament/AdminPanelProvider.php`
  - resource/page `shouldRegisterNavigation()` owners under `apps/platform/app/Filament/**`
  - `apps/platform/app/Support/Workspaces/WorkspaceOverviewBuilder.php`
  - `apps/platform/resources/views/filament/pages/workspace-overview.blade.php`
  - `apps/platform/tests/Pest.php`
  - `apps/platform/tests/Feature/Filament/PanelNavigationSegregationTest.php`
  - focused guard/browser tests that still mention retired tenant routes or technical `Tenant*` owners
- **Existing pattern(s) to extend**: `ManagedEnvironmentLinks`, `WorkspaceIntendedUrl`, `WorkspaceRedirectResolver`, `OperationRunLinks`, `TenantPageCategory`, existing navigation registration closures, `setAdminEnvironmentContext()`, and the current guard-test pattern.
- **Shared contract / presenter / builder / renderer to reuse**: the existing canonical route helpers and route-scope navigation owners named above; no new shared framework is justified.
- **Why the existing shared path is sufficient or insufficient**: the runtime app tree is already mostly aligned to the canonical owners. The missing closure is one final proof/audit layer, plus narrow fixes only if the final baseline still exposes a live seam.
- **Allowed deviation and why**: technical `Tenant` class/model/table names, provider-specific Microsoft/Entra tenant language, and guard-regex strings may remain when explicitly classified in `final-cutover-audit.md`.
- **Consistency impact**: runtime links, workspace/environment navigation, intended URL handling, workspace overview copy, and the focused proof pack must all agree on the same workspace-first / environment-drilldown product truth.
- **Review focus**: reviewers must verify that `299` does not reopen broader rename work, does not preserve compatibility routes, and does not leave any unclassified product-facing tenant-first seams.

## 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?**: yes, link and redirect ownership only.
- **Shared OperationRun UX contract/layer reused**: `OperationRunLinks` plus `ManagedEnvironmentLinks::operationsUrl(...)` for workspace-scoped operations entry points.
- **Delegated start/completion UX behaviors**: no new toast, status, or notification behavior. The only required proof is that legacy intended URLs do not restore retired tenant-scoped operation paths and that workspace operations remain canonical.
- **Local surface-owned behavior that remains**: workspace overview and environment detail surfaces keep their current local labels and calls to the shared link owners.
- **Queued DB-notification policy**: N/A.
- **Terminal notification path**: unchanged.
- **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?**: yes
- **Boundary classification**: mixed
- **Seams affected**: operator vocabulary, provider connection scope language, required-permissions wording, workspace/environment route labels, and allowed technical `Tenant` references.
- **Neutral platform terms preserved or introduced**: workspace, managed environment, environment, provider connection, required permissions, diagnostics, access scope, operation, finding, evidence, review.
- **Provider-specific semantics retained and why**: Microsoft tenant ID, Entra tenant ID, and provider target-tenant wording remain allowed only where the external provider is the subject.
- **Why this does not deepen provider coupling accidentally**: the spec narrows `tenant` wording to provider-owned or technical-only seams while keeping platform-core navigation and operator UI environment-first.
- **Follow-up path**: document-in-feature for allowed technical/provider references; follow-up-spec only for future structural DB/model rename.

## 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 |
|---|---|---|---|---|---|---|
| Workspace overview and sidebar scope | yes | Native Filament + shared builders | navigation, summary metrics, context copy | shell, page | no | closure-only; no redesign |
| Canonical environment detail/readiness surfaces | yes | Native Filament + shared route helpers | environment navigation, page/back links, detail copy | page, detail | no | prove the current environment drill-down remains canonical |
| Final cutover audit and guard pack | no direct operator surface | N/A | guard tests, scans, audit evidence | docs, tests | no | repo-proof only |

## 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 |
|---|---|---|---|---|---|---|---|
| Workspace overview and sidebar scope | Primary Decision Surface | Operator chooses whether to stay at workspace scope or drill into one environment | workspace summary, allowed workspace navigation, explicit environment drill-down affordance | environment details, diagnostics, and evidence remain on child surfaces | Primary because the workspace home is the first scope decision after the cutover | Workspace first, environment second | prevents stale environment context from hijacking workspace navigation |
| Canonical environment detail/readiness surfaces | Secondary Context Surface | Operator follows one selected environment into detail, permissions, or diagnostics | selected environment identity and current environment-owned navigation | diagnostics, provider detail, raw support content | Secondary because the environment route supports a decision already made at workspace scope | explicit drill-down from workspace to environment | avoids mixed workspace/environment affordances on the same page |

## 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 |
|---|---|---|---|---|---|---|---|
| Workspace overview and sidebar scope | operator-MSP, support-platform | workspace summary metrics, calmness/attention framing, workspace-owned navigation | environment-specific follow-up only through explicit drill-down | none beyond existing support tools | choose environment or view workspace operations | environment-owned navigation on workspace surfaces | one scope truth per route |
| Canonical environment detail/readiness surfaces | operator-MSP, support-platform | selected environment context, current readiness or workload state | provider readiness, diagnostics, evidence | provider/raw support detail only where already allowed | continue environment workflow on the current canonical route | workspace-only actions remain secondary or absent | current environment route owns the environment story |

## 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Workspace overview and sidebar scope | Dashboard / Navigation | Workspace-first overview | choose environment or review operations | direct page load on workspace home | N/A | current summary drill-downs and navigation items | unchanged; existing destructive actions stay elsewhere | `/admin/workspaces/{workspace}` | N/A | workspace only | Workspace / Environment | workspace-first scope and allowed nav | none |
| Canonical environment detail/readiness surfaces | Detail / Readiness | Environment-scoped detail | open the current environment area or remediate readiness | canonical environment route | N/A | existing detail/header actions | unchanged and still confirmation-gated where destructive | `/admin/workspaces/{workspace}/environments` | `/admin/workspaces/{workspace}/environments/{environment}` | workspace + environment | Environment / Managed environment | selected environment and current child navigation | none |

## 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 |
|---|---|---|---|---|---|---|---|---|---|---|
| Workspace overview and sidebar scope | Workspace operator | Decide whether to stay at workspace scope or drill into one environment | overview | What needs attention in this workspace before I narrow scope? | workspace summary metrics, allowed navigation, scope framing | none beyond existing linked surfaces | calmness, attention, activity | none | Choose environment, View operations | none added |
| Canonical environment detail/readiness surfaces | Workspace operator | Continue environment-specific investigation or remediation | environment detail/readiness | What needs action in this environment? | environment identity, environment navigation, current readiness/action context | provider detail, diagnostics, support/raw detail | readiness, governance result, activity | existing environment-owned actions only | existing page-owned actions | existing destructive actions only |

## Proportionality Review *(mandatory when structural complexity is introduced)*

- **New source of truth?**: no
- **New persisted entity/table/artifact?**: yes, one spec-local audit artifact only
- **New abstraction?**: no application abstraction by default; the implementation may only extend existing route-scope helpers if a live seam is confirmed
- **New enum/state/reason family?**: no
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: without one final proof package, the cutover can quietly drift back toward retired tenant routes or mixed workspace/environment truth.
- **Existing structure is insufficient because**: Specs 297 and 298 prepared and cleaned the main seams, but the remaining test, copy, and regression burden is spread across multiple owners and lacks one final acceptance artifact.
- **Narrowest correct implementation**: one closure spec that proves the app tree stays clean, fixes only confirmed remaining seams, and classifies everything else.
- **Ownership cost**: one audit file plus focused guard maintenance.
- **Alternative intentionally rejected**: a broad rename or another foundational cutover spec. That would reopen work already intentionally kept out of scope.
- **Release truth**: current-release closure in a pre-production environment.

### Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility routes, legacy helper aliases, migration shims, historical fixture preservation for runtime behavior, and compatibility-specific runtime tests are out of scope unless they already exist as explicit negative regression guards.

Canonical replacement or explicit rejection is preferred over preservation.

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Retired Tenant Runtime Stays Sealed (Priority: P1)

As a maintainer, I need the final cutover proof to show that no active runtime route or link generator revives `/admin/t/...` or `/admin/tenants/...` behavior.

**Why this priority**: This is the core cutover promise. If it regresses, the product truth is no longer workspace-first.

**Independent Test**: Run the focused route/source/guard proof pack and verify representative retired paths return 404 while canonical environment and workspace operations links remain valid.

**Acceptance Scenarios**:

1. **Given** an authenticated workspace member, **When** they request a representative retired tenant path such as `/admin/t/{id}` or `/admin/tenants/{id}`, **Then** the response is 404.
2. **Given** the runtime app tree, **When** the final legacy scan runs, **Then** no active retired route/helper pattern remains under `apps/platform/app`, `apps/platform/resources`, or `apps/platform/routes`.

---

### User Story 2 - Workspace Navigation Wins Over Stale Environment Context (Priority: P1)

As an operator, I need workspace pages to stay workspace-scoped even when the session remembers an environment or `Filament::getTenant()` still holds one.

**Why this priority**: Mixed workspace/environment navigation makes the cutover feel unfinished and can mislead operators about scope.

**Independent Test**: Exercise workspace overview and canonical environment routes with remembered environment context and verify the sidebar changes by route scope, not by stale environment state.

**Acceptance Scenarios**:

1. **Given** a remembered environment and a workspace overview request, **When** the page renders, **Then** only workspace-owned navigation is visible.
2. **Given** the canonical environment detail route, **When** the page renders, **Then** environment-owned navigation appears again.

---

### User Story 3 - Remaining Tenant References Are Honest And Bounded (Priority: P2)

As a reviewer, I need every remaining `Tenant` reference to be either fixed or explicitly classified so future work can tell the difference between product drift and allowed technical/provider/historical wording.

**Why this priority**: The remaining legacy footprint is broadest in tests and copy. Unclassified references create noisy audits and invite accidental regressions.

**Independent Test**: Refresh the final audit, run the copy/test scans, and verify every remaining hit is marked `fixed`, `allowed-provider-term`, `allowed-internal-model`, `allowed-historical`, or `allowed-regression-guard`.

**Acceptance Scenarios**:

1. **Given** an active product-facing workspace or environment surface, **When** the cutover copy scan runs, **Then** remaining tenant-first wording is either removed or intentionally allowed because it is provider-specific.
2. **Given** a technical test or guard, **When** it still mentions `TenantResource`, `TenantDashboard`, `/admin/t`, or `setTenantPanelContext`, **Then** the final audit states why that reference remains safe.

## Edge Cases

- What happens when a remembered environment belongs to the current workspace but the current route is workspace-only? The page must stay workspace-scoped and suppress environment-owned navigation.
- What happens when an intended URL points to `/admin/operations` with query data? It may normalize only to the canonical workspace operations route, not to any retired tenant-scoped operations path.
- What happens when a string contains `tenant` but the subject is Microsoft/Entra provider identity? The wording may remain only when the external provider is the actual subject.

## Functional Requirements

- **FR-001 No active retired tenant routes**: `route:list` and focused request tests must prove that `/admin/t/...` and `/admin/tenants/...` are not active product routes.
- **FR-002 Tenant runtime owners stay technical-only or retired**: if `TenantResource`, `TenantDashboard`, or `TenantRequiredPermissions` remain in code, they must not restore primary admin navigation, global search entries, or retired route families.
- **FR-003 Canonical managed-environment link ownership is preserved**: runtime environment links remain owned by `ManagedEnvironmentLinks`, `RequiredPermissionsLinks`, `OperationRunLinks`, or the current canonical route owner.
- **FR-004 Workspace intended URL rejection is final**: `WorkspaceIntendedUrl` and `WorkspaceRedirectResolver` must reject retired tenant paths and only normalize safe workspace operations routes.
- **FR-005 Route-scope-first navigation is final**: workspace routes render workspace-only navigation, canonical environment routes render environment-owned navigation, and stale remembered environment context does not override route scope.
- **FR-006 Retired tenant-panel helper remains retired**: no callable `setTenantPanelContext()` alias may exist; remaining string hits may survive only inside explicit forbidden-pattern guards.
- **FR-007 Product-facing tenant terminology is bounded**: touched active UI surfaces use environment-first wording where the subject is a managed environment.
- **FR-008 Remaining tenant references are explicitly allowlisted**: the final audit must classify every remaining `Tenant` reference that survives the final scans.
- **FR-009 No broad refactors**: the implementation must not reopen DB/model rename, provider refactor, package execution, guided operations, or generic historical-doc cleanup.
- **FR-010 Final cutover audit is maintained**: `final-cutover-audit.md` must capture baseline findings, final findings, validation commands, and the final decision string.

## Non-Functional Requirements

- The validation mix must stay focused to guard/feature/browser anchors relevant to the cutover; no raw full suite is required unless explicitly requested.
- Filament v5 / Livewire v4 compliance remains explicit, and provider registration stays in `apps/platform/bootstrap/providers.php`.
- The package must stay implementation-bounded: fix only confirmed remaining seams and document everything else.
- Final proof commands must be explicit, reproducible, and small enough for a bounded implementation loop.

## Out Of Scope

- Database, model, namespace, or table rename from `Tenant` to `ManagedEnvironment`
- Migration or historical data rewrite
- Reintroducing compatibility routes or compatibility aliases
- New product features, new operations workflows, or new navigation families
- Broad localization project or historical docs/spec rewrite
- Provider architecture refactor or new RBAC model
- Raw full-suite enforcement without explicit user instruction

## Acceptance Criteria

- **AC-001**: `route:list` does not expose `/admin/t` or `/admin/tenants` as active routes.
- **AC-002**: no active runtime route/helper pattern for retired tenant surfaces remains under `apps/platform/app`, `apps/platform/resources`, or `apps/platform/routes`.
- **AC-003**: `ManagedEnvironmentLinks`, `WorkspaceIntendedUrl`, and `WorkspaceRedirectResolver` remain the canonical owners for environment detail, intended URLs, and workspace operations redirects.
- **AC-004**: workspace overview does not show environment-owned navigation, even with remembered environment session data or `Filament::getTenant()` state.
- **AC-005**: canonical environment routes still show the intended environment-owned navigation entries.
- **AC-006**: no callable `setTenantPanelContext()` helper remains.
- **AC-007**: touched active product-facing copy no longer uses tenant-first wording when the subject is a managed environment.
- **AC-008**: every remaining `Tenant` reference that survives final scans is documented as allowed technical, provider-specific, historical, or regression-guard only.
- **AC-009**: the focused proof pack, feature lanes, browser anchors, final route/source scans, Pint, and `git diff --check` all pass or the failure is explicitly recorded as a blocker.
- **AC-010**: the final report ends with one explicit decision string for the cutover seal.

## Success Criteria

- Reviewers can answer "is the managed-environment cutover sealed?" from one spec package without reopening 297 or 298.
- The final audit distinguishes active product drift from allowed technical/provider/historical references.
- The implementation loop can stop with a clear decision instead of vague residual cleanup.

## Risks

- Spec 298 runtime changes may not yet be landed in the exact implementation base, so 299 could otherwise mix closure work with unfinished navigation/copy cleanup.
- The remaining test surface is broad and uses technical `Tenant*` owners heavily; without disciplined classification, the audit can become noisy or overreach.
- Workspace overview copy and navigation are easy to drift because they mix workspace summary, environment drill-down, and operations entry points.

## Assumptions

- Specs 297 and 298 remain authoritative context and must not be rewritten back into preparation-only state.
- The runtime app tree already follows the canonical route owners unless the final baseline uncovers a concrete exception.
- Internal `Tenant` model/class naming is still allowed as technical implementation detail for this release.

## Open Questions

- None blocking. The only prerequisite boundary is implementation timing: Spec 298 changes must be committed or cleanly isolated before 299 runtime work begins.

## Definition Of Done

Spec 299 is done when:

1. The baseline audit is recorded in `final-cutover-audit.md`.
2. Any confirmed active runtime legacy seam is fixed without restoring compatibility paths.
3. Workspace/environment navigation segregation is re-proven.
4. Intended URL rejection is re-proven.
5. Touched active product copy is environment-first.
6. Remaining `Tenant` references are classified in the allowlist.
7. The focused proof pack, lanes, browser anchors, scans, Pint, and diff check are recorded.
8. The final decision string is explicit.

## Final Output Required

At implementation close-out, report:

1. Commands run and outcomes.
2. Runtime legacy closure findings.
3. Workspace vs environment navigation classification.
4. Remaining allowed `Tenant` references and why they remain.
5. Test results.
6. One final decision string:
   - `merge-ready; managed environment cutover sealed`
   - `merge-ready with documented allowed internal Tenant references`
   - `blocked by active legacy runtime finding`
   - `blocked by navigation context leak`
