# Data Model: Quality Gates / No-Legacy Enforcement ## Overview `288` introduces no new persisted entity, table, lifecycle state, or runtime DTO. The "data model" for this package is a bounded enforcement inventory that defines which route/path families, helper patterns, provider-core seams, role-authority invariants, browser gates, and baseline-classification rules must remain true after Spec `287`. ## Canonical Enforcement Categories | Enforcement Key | Meaning | Primary Targets | Canonical Enforcement | |---|---|---|---| | `legacy_route_path_contract` | exact retired management route/path families must stay forbidden | guard scans, legacy redirect tests, route emission assertions | targeted no-legacy route/path guard plus supporting runtime regression tests | | `route_emission_contract` | cutover-owned builders and launch points emit canonical admin/workspace routes only | runtime launch-point tests and emitted URL assertions | emitted URLs use canonical admin/workspace managed-environment shapes | | `tenant_panel_helper_contract` | retired tenant-panel bootstrapping must not re-enter shared test support or other owned seams | `tests/Pest.php` and owned test/support seams | explicit helper/panel-bootstrapping guard inventory | | `provider_core_boundary_contract` | platform-core provider seams stay provider-neutral | provider-boundary guards and shared provider catalogs | shared identity/operation seams reject provider-specific request shaping or binding truth | | `environment_scope_role_authority_contract` | workspace membership stays role-bearing and environment scope stays narrowing-only | policy tests, managed-environment scope tests, role-string guard | current wrong-scope `404`, in-scope `403`, and direct role-edit rejection semantics remain true | | `browser_smoke_gate_contract` | the visible canonical provider and RBAC environment flows stay honest | Spec `281` and Spec `285` browser smokes | targeted browser proof only | | `baseline_classification_contract` | broader baseline fallout is classified without becoming repair scope | lane manifest, report contract, README guidance | classification-only wording via existing report seams | ## Pinned Forbidden Families and Replacements | Enforcement Key | Retired Pattern / Drift | Canonical Replacement | |---|---|---| | `legacy_route_path_contract` | `/admin/tenants/{tenant:slug}/provider-connections...` | `/admin/provider-connections...` | | `legacy_route_path_contract` | `/admin/t/{tenant}/provider-connections`, `/admin/t/{tenant}/required-permissions`, `/admin/t/{tenant}/memberships` | canonical admin/workspace managed-environment routes and launch points | | `legacy_route_path_contract` | duplicate `/admin/t/t/{tenant}/...` emission | one canonical managed-environment route prefix only | | `tenant_panel_helper_contract` | `setTenantPanelContext()` or direct `tenant` panel bootstrapping on owned seams | admin/workspace context setup or an explicit file-scoped exception | | `provider_core_boundary_contract` | `graphOptions`, `client_request_id`, or provider binding keys in platform-core seams | provider-neutral shared seams with provider-owned nested detail only | | `environment_scope_role_authority_contract` | managed-environment scope acting like a second role-bearing matrix | workspace membership role truth plus narrowing-only scope rows | | `baseline_classification_contract` | broader baseline fallout silently becoming repair scope | explicit classification-only documentation and report labeling | ## Pinned Historical / Immutable Exclusions | Exclusion Class | Meaning | Representative Paths | |---|---|---| | `immutable_history` | files that intentionally preserve removed vocabulary or route families as historical truth | `database/migrations/**`, `references/**` | | `spec_history` | spec and planning artifacts that must be able to mention retired patterns explicitly | `specs/**`, `spechistory/**`, `docs/**` | | `generated_or_external` | code or artifacts outside normal enforcement ownership | `vendor/**`, `storage/**`, `public/build/**`, `bootstrap/cache/**` | ## Allowed Provider-Owned Detail | Detail Class | Meaning | Examples | |---|---|---| | `provider_owned_profile_detail` | provider-specific detail is allowed where the provider itself is the subject | Microsoft tenant identifiers, authority tenant strings, consent URLs | | `provider_owned_support_detail` | lower-level support detail remains nested provider truth | provider-specific diagnostics or raw metadata | ## Role-Authority Invariants - `workspace_memberships` remain the only role-bearing authority source. - `managed_environment_memberships` remain a narrowing-only scope overlay. - Wrong-scope denials stay `404`. - In-scope capability denials stay `403`. - Direct role edits on managed-environment scope rows remain rejected. ## Invariants - `288` introduces no new persistence and no new product-facing workflow surface. - The same enforcement categories and the same Spec `289` follow-up boundary must appear across `spec.md`, `plan.md`, `tasks.md`, `quickstart.md`, `data-model.md`, the logical contract, and `checklists/requirements.md`. - The literal proof commands live only in `spec.md`, `plan.md`, `tasks.md`, and `quickstart.md`; the remaining artifacts reference that canonical command set rather than restating another variant. - Browser proof remains limited to the two named browser smoke files. - Baseline fallout remains classification-only and must not silently become repair scope. ## Out of Scope Data Changes - no database migrations - no new provider registry or provider-core abstraction layer - no new role family or persisted access overlay - no full-suite baseline artifact or new baseline ledger - no package execution state or workflow contract