## Summary - implement the canonical shared fixture profile model with minimal, standard, and full semantics plus temporary legacy alias resolution - slim default factory behavior for operation runs, backup sets, provider connections, and provider credentials while keeping explicit heavy opt-in states - migrate the first console, navigation, RBAC, and drift caller packs to explicit lean helpers and wire lane comparison reporting into the existing Spec 206 seams - reconcile spec 207 docs, contracts, quickstart guidance, and task tracking with the implemented behavior ## Validation - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/CreateUserWithTenantProfilesTest.php tests/Unit/Factories/TenantFactoryTest.php tests/Unit/Factories/OperationRunFactoryTest.php tests/Unit/Factories/BackupSetFactoryTest.php tests/Unit/Factories/ProviderConnectionFactoryTest.php tests/Unit/Factories/ProviderCredentialFactoryTest.php tests/Feature/Guards/FixtureCostProfilesGuardTest.php tests/Feature/Guards/FixtureLaneImpactBudgetTest.php tests/Feature/Guards/TestLaneArtifactsContractTest.php tests/Feature/Console/ReconcileOperationRunsCommandTest.php tests/Feature/Console/ReconcileBackupScheduleOperationRunsCommandTest.php tests/Feature/Navigation/RelatedNavigationResolverMemoizationTest.php tests/Feature/Spec080WorkspaceManagedTenantAdminMigrationTest.php tests/Feature/BaselineDriftEngine/FindingFidelityTest.php` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `./scripts/platform-test-lane fast-feedback` - `./scripts/platform-test-lane confidence` - `./scripts/platform-test-report fast-feedback` - `./scripts/platform-test-report confidence` ## Lane outcome - `fast-feedback`: 136.400761s vs 176.73623s baseline, status `improved` - `confidence`: 394.5669s vs 394.383441s baseline, status `stable` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #240
24 KiB
Feature Specification: Shared Test Fixture Slimming
Feature Branch: 207-shared-test-fixture-slimming
Created: 2026-04-16
Status: Draft
Input: User description: "Spec 207 - Shared Test Fixture Slimming"
Spec Candidate Check (mandatory — SPEC-GATE-001)
- Problem: Shared test fixtures and factory defaults regularly create more tenant, user, workspace, membership, provider, session, and capability context than many tests actually need.
- Today's failure: Short, ordinary tests silently pay full-context setup cost, hidden helper side effects make tests harder to read, and lane improvements from Spec 206 are limited because per-test cost stays inflated.
- User-visible improvement: Contributors get a cheaper standard test setup, clearer fixture intent at the call site, and a more stable fast-feedback or confidence experience without reducing legitimate coverage.
- Smallest enterprise-capable version: Define a small fixture-profile model, make minimal setup the default, move heavy provider or membership or workspace behavior behind explicit opt-in paths, slim the most-used factories and helpers, migrate the highest-usage expensive callers, and add guard coverage plus before and after runtime comparison.
- Explicit non-goals: No full-suite reorganization, no blanket rewrite of every existing test, no removal of valid integration-heavy coverage that still reflects real business risk, no browser-strategy redesign, and no CI rollout redesign.
- Permanent complexity imported: Fixture-profile vocabulary, lean versus heavy helper entry points, lighter factory states, a transition layer for legacy callers, guard coverage, and short author guidance.
- Why now: Spec 206 already made suite cost visible. Without reducing per-test cost now, standard lanes will keep inheriting expensive defaults and later lane segmentation work will remain more expensive than necessary.
- Why not local: Local cleanups in one or two tests cannot stop the support layer from reintroducing hidden full-context setup across the suite. The default behavior must change at the shared-fixture level.
- Approval class: Cleanup
- Red flags triggered: "Foundation" language and a new profile vocabulary. Defense: this feature narrows and clarifies existing fixture behavior instead of adding new product runtime truth, new operator surfaces, or speculative platform abstractions.
- Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
- Decision: approve
Spec Scope Fields (mandatory)
- Scope: workspace
- Primary Routes: No end-user HTTP routes change. The affected surfaces are repository-level test fixtures, shared setup paths, factory defaults, contributor guidance, and runtime comparison outputs.
- Data Ownership: Workspace-owned test-support conventions, fixture profiles, migration guidance, guard coverage, and runtime comparison evidence. No tenant-owned product records are added or changed.
- RBAC: No end-user authorization behavior changes. The affected actors are repository contributors and reviewers who need a cheaper, clearer default test path.
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no new product persistence; only repository documentation, test support behavior, and runtime comparison evidence
- New abstraction?: yes, but limited to a small fixture-profile vocabulary for the shared test support layer
- New enum/state/reason family?: no
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: Contributors and reviewers cannot rely on the shared test support layer to stay cheap by default, so ordinary tests inherit hidden setup cost and the standard lanes remain slower than they need to be.
- Existing structure is insufficient because: shared helpers and factory defaults currently behave like opt-out full-context builders, which hides cost and makes later lane governance less effective.
- Narrowest correct implementation: keep the change inside the test support layer, a small fixture-profile model, the most-used factories and helpers, a limited caller migration pack, and guard coverage.
- Ownership cost: The team must maintain profile naming, transition guidance, guard tests, and a small amount of runtime comparison evidence as fixture behavior evolves.
- Alternative intentionally rejected: isolated caller-by-caller cleanup without changing shared defaults, because it would leave the hidden cost model intact and allow regressions to re-enter through new tests.
- Release truth: current-release repository truth that reduces existing suite cost and prepares the next heavy-suite segmentation step.
Problem Statement
TenantPilot's test suite is expensive not only because it is large, but because many shared fixtures act like full-context convenience builders by default.
The current pain is structural:
- Shared helpers often create broad tenant, user, workspace, membership, provider, session, or capability context even when the test only needs a narrow slice.
- Expensive context is commonly opt-out instead of opt-in.
- Factory defaults can trigger hidden cascades that create relationship graphs a test author did not clearly ask for.
- The real setup cost of a short test is hard to see during review.
- Standard lanes pay for integration-heavy defaults even when the business assertion is narrow.
If these defaults stay in place, the fast-feedback and confidence lanes introduced by Spec 206 will keep absorbing avoidable per-test cost as the suite grows.
Dependencies
- Depends on Spec 206 - Test Suite Governance & Performance Foundation for the baseline, lane vocabulary, and runtime comparison discipline.
- Recommended before Spec 208 - Filament or Livewire Heavy Suite Segmentation so per-test cost is reduced before the heaviest families are moved into sharper lane boundaries.
- Does not block ongoing feature delivery as long as new tests already follow the minimal-fixture discipline introduced here.
Goals
- Reduce per-test cost without reducing meaningful coverage.
- Make minimal fixtures the standard path for ordinary tests.
- Require explicit opt-in for provider, credential, membership, workspace, session, capability, and other integration-heavy setup.
- Reduce hidden helper and factory side effects.
- Make test intent easier to read because required context is visible at the call site.
- Prevent new tests from drifting back into expensive full-context defaults.
Non-Goals
- Reorganizing the full suite or redefining all lane boundaries.
- Rewriting every existing test in one pass.
- Removing valid provider, membership, workspace, or panel-adjacent tests that still need full context.
- Redesigning CI behavior or browser strategy.
- Refactoring unrelated application architecture outside the test support layer.
Assumptions
- Spec 206 baseline reporting is available or can be regenerated before lane impact is evaluated.
- Existing business-relevant coverage remains valuable; the goal is to lower setup cost, not to reduce confidence.
- Migration will be incremental, with a temporary transition layer where legacy callers still need heavier behavior.
User Scenarios & Testing (mandatory)
User Story 1 - Use A Minimal Fixture By Default (Priority: P1)
As a contributor adding or editing an ordinary test, I want the default shared setup path to create only the smallest valid context for the behavior under test so the test stays cheap and easy to understand.
Why this priority: This is the highest-frequency authoring path in the repository. If it stays expensive by default, every new test can quietly push lane cost upward.
Independent Test: Use the default shared fixture path and default factory states for a representative narrow test, then verify that no provider, credential, membership, workspace, session, capability, or other heavy add-ons appear unless the test asked for them.
Acceptance Scenarios:
- Given a contributor uses the default shared fixture path for a narrow test, When the test asks only for core context, Then only the smallest valid context is created and heavy add-ons are absent.
- Given a contributor uses a default factory state, When no heavy state is requested, Then extra relationship graphs are not created implicitly.
User Story 2 - Opt Into Heavy Context Deliberately (Priority: P1)
As a contributor working on behavior that truly depends on provider, membership, workspace, session, or workflow context, I want an explicit way to request that heavier setup so the test gets the right environment without hiding its cost.
Why this priority: Some tests genuinely need heavy context. The feature must preserve those cases while making the cost visible and intentional.
Independent Test: Select an explicit heavy profile or add-on state for a representative integration-heavy test and verify that the promised additional context is present while remaining clearly identifiable at the call site.
Acceptance Scenarios:
- Given a test requires heavy integration context, When the author selects an explicit heavy profile or add-on state, Then the required extra context is created.
- Given a reviewer inspects a heavy test setup, When the test asks for the heavier path, Then the setup clearly announces that it is requesting more than the minimal default.
User Story 3 - Migrate High-Usage Callers Safely (Priority: P2)
As a maintainer reducing suite cost, I want the most frequently used expensive setup paths migrated to lighter defaults without causing unnecessary mass breakage.
Why this priority: Shared defaults only pay off when the most-used callers move to the cheaper profiles that match their real needs.
Independent Test: Migrate a representative pack of high-usage callers, run their tests, and verify that narrow tests move to lighter profiles while legacy full-context callers remain available through the transition path until they are intentionally migrated.
Acceptance Scenarios:
- Given a high-usage caller only needs narrow context, When it is migrated, Then it uses a lighter profile and keeps its business assertions green.
- Given a legacy caller still depends on full context, When the transition path is used, Then the behavior remains available during migration and its heavier cost stays visible.
User Story 4 - Catch Fixture Cost Regressions Early (Priority: P2)
As a reviewer or maintainer, I want guard coverage and visible cost signals around shared fixtures so regressions in hidden setup cost are caught before they spread through the standard lanes.
Why this priority: Without early signals, expensive defaults quietly return and erase the benefit of the migration work.
Independent Test: Run guard coverage and runtime comparison after a shared-fixture change and confirm that unexpected extra context or lane regressions are detected.
Acceptance Scenarios:
- Given a shared helper or factory begins creating unexpected extra context, When guard coverage runs, Then the regression fails clearly.
- Given the main migration pack is complete, When runtime comparison is reviewed against the Spec 206 baseline, Then the affected standard lanes are stable or improved.
Edge Cases
- A legacy test depended on hidden session or capability mutation from a generic helper; the migration must expose that dependency rather than silently recreating it in the minimal path.
- A test needs one expensive add-on, such as provider context, without needing the rest of the full integration graph.
- A factory callback or model default quietly recreates a removed relationship graph even after a lean state is selected.
- A high-usage caller pack spans more than one fixture profile during the transition period and must remain readable rather than falling back to generic magic.
Requirements (mandatory)
Constitution alignment (required): This feature changes no end-user routes, no Microsoft Graph behavior, no queued operations, and no authorization planes. It does change repository-wide test support behavior, so the fixture-profile model, transition path, and guard coverage must remain explicit, reviewable, and measurable.
Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001): The only intentional new abstraction is a narrow fixture-profile model for the shared test support layer. It is justified because existing defaults hide cost and make lane governance ineffective. The implementation must prefer explicit, local behavior over a broad new framework and must not create new product persistence or speculative semantic layers.
Functional Requirements
- FR-001 Fixture Profile Model: The shared test support layer MUST define at least three clearly named fixture profiles: minimal, standard, and full or integration-heavy. Each profile MUST have a documented purpose and clearly bounded cost expectations.
- FR-002 Minimal Default: Shared fixtures MUST use the minimal profile as the default path for ordinary tests.
- FR-003 Explicit Heavy Opt-In: Provider, credential, membership, workspace, session, capability, and other integration-heavy setup MUST be created only when a test explicitly requests it.
- FR-004 Shared Helper Split: Central shared helpers MUST be split into clearly distinguishable light and heavy paths, whether by separate entry points or explicit profile selection, so the cost difference is visible to authors and reviewers.
- FR-005 Expensive Defaults Removed: Automatic provider connections, provider credentials, membership enrichment, workspace enrichment, session or capability state, and extra user or tenant relationships MUST no longer be silent defaults in the shared fixture path.
- FR-006 Factory State Discipline: The highest-usage test factories MUST provide lean defaults and clearly named add-on states for provider, membership, workspace, and operation-context needs. Defaults MUST avoid unnecessary cascades.
- FR-007 Hidden Cascade Audit: The most important test aggregates, including tenant, workspace, user, provider connection, provider credential, operation context, and other high-usage shared setup inputs, MUST be audited for callbacks, defaults, or repair behavior that silently create extra objects or state.
- FR-008 Transition Layer: A backwards-compatible transition path MUST exist so existing tests do not break unnecessarily while migration is in progress, heavier legacy behavior MUST remain clearly identifiable, and every legacy alias or full-context fallback MUST carry a declared removal trigger tied to migration-pack completion.
- FR-009 Caller Migration Pack: The most frequently used expensive callers in the fast-feedback and confidence lanes MUST be migrated to the lightest profile that still matches their business needs.
- FR-010 Cost Visibility: The test support layer MUST make heavy setup visible through naming, guidance, or guard signals so contributors can tell when they are requesting more than the minimal path.
- FR-011 Guard Coverage: Guard tests MUST verify that minimal profiles do not create hidden heavy context, heavy profiles create only their promised extra context, and fixture regression is detected early.
- FR-012 Coverage Preservation: The rollout MUST preserve legitimate provider, membership, workspace, and other integration-heavy coverage where that context is materially required.
- FR-013 Budget Validation: After the main migration pack, the affected standard lanes MUST be compared against the Spec 206 baseline and show stable or improved runtime.
- FR-014 Author Guidance: Contributors MUST have concise guidance explaining when to use minimal, standard, and full fixture paths and how to avoid reintroducing hidden setup cost.
Non-Functional Requirements
- NFR-001 Cheap-Default Bias: The cheapest valid setup path must be easier to reach than the heavy path.
- NFR-002 Readable Intent: Test setup must communicate required context more clearly than the current convenience-heavy defaults.
- NFR-003 Incremental Adoption: Migration must be possible in small slices without forcing a full-suite rewrite.
- NFR-004 Lane Benefit Preservation: Changes must reinforce, not undermine, the fast-feedback and confidence lanes defined in Spec 206.
Work Packages
Work Package A - Fixture Surface Inventory
- Catalogue the central shared helpers that are most frequently used in ordinary tests.
- Identify the highest-usage expensive caller paths.
- Record which hidden side effects currently inflate context or cost.
- Classify each hidden-cascade finding as removed, made explicit, retained-documented, or follow-up before caller migration begins.
- Distinguish where narrow context is enough versus where true full integration context is required.
Work Package B - Profile Design
- Finalize the minimal, standard, and full or integration-heavy profile model.
- Make the light versus heavy API boundary obvious to authors and reviewers.
- Move hidden helper semantics into explicit profile choices or clearly separate entry points.
- Ensure heavy paths announce themselves rather than hiding behind generic convenience names.
Work Package C - Factory Slimming
- Audit the most important factory defaults for hidden cascades.
- Introduce lean defaults and explicit heavy add-on states.
- Remove or isolate automatic graph inflation that is not required by most tests.
- Keep any unavoidable heavy behavior explicit and documented.
Work Package D - Caller Migration
- Migrate the most-used expensive callers to lighter profiles first.
- Retain full-context setup only where the business assertion genuinely needs it.
- Prioritize callers exercised by the fast-feedback and confidence lanes.
- Use the transition layer to avoid unnecessary broad breakage during migration.
Work Package E - Regression Pack
- Add guard coverage for minimal, standard, and full fixture semantics.
- Protect against reintroduction of hidden heavy defaults.
- Keep a small regression pack for legacy transition behavior until migration is complete.
- Validate lane impact against the Spec 206 budgets after the main migration slice.
Deliverables
- Slimmed shared test fixtures with a documented profile model.
- Leaner default states for the most-used factories and explicit heavy add-on states.
- A hidden-cascade audit for the key shared setup inputs with a recorded disposition for each named finding.
- A transition path for legacy callers.
- Guard coverage for fixture behavior and regression detection.
- Migration of the highest-usage expensive callers.
- Concise author guidance for minimal versus full fixture setup.
- A before and after runtime comparison against the Spec 206 baseline.
Risks
Hidden Dependency Breakage
Existing tests may rely on side effects that are currently invisible. Slimming defaults can expose those dependencies quickly.
Over-Slimming
If the minimal path removes context that is still meaningfully required, tests can become harder to write or understand.
API Proliferation
Too many helper variants could make the support layer harder to navigate than the current defaults.
Incomplete Migration
If shared defaults change but the highest-usage callers remain on legacy behavior, the lane-level impact will stay limited.
Rollout Guidance
- Start with the most-used and most expensive shared setup paths rather than trying to slim everything at once.
- Capture a pre-migration fast-feedback and confidence baseline through the existing Spec 206 wrappers before helper or factory edits begin.
- Finalize the profile model before migrating callers so the new naming is stable.
- Remove silent heavy defaults before expanding the migration pack.
- Use the transition layer to keep the rollout incremental and reviewable, but attach a removal trigger to every temporary alias or legacy full-context path.
- Measure lane impact after the main migration slice rather than waiting for total suite completion.
Design Rules
- Minimal first: The cheapest valid fixture is the default.
- No surprise provider setup: Provider or credential context is never created implicitly.
- No surprise session or capability mutation: Session or capability state changes require explicit intent.
- No hidden graph inflation: Factories must not silently inflate relationship graphs by default.
- Readable intent over helper magic: Slightly more explicit setup is acceptable when it makes the required context obvious.
- Heavy context must announce itself: Integration-heavy setup must be recognizable at the call site.
- Legacy heavy aliases stay temporary: Transitional helper aliases and legacy full-context fallbacks must declare how they will be retired.
Suggested Task Breakdown
- Inventory shared fixtures and high-usage callers.
- Finalize the fixture-profile model.
- Split shared helper APIs into light and heavy paths.
- Audit the most-used factory defaults.
- Introduce lean factory states and explicit heavy add-ons.
- Remove provider, credential, membership, workspace, session, and capability defaults that should be opt-in.
- Migrate the top caller pack.
- Add guard and regression coverage.
- Validate lane impact against the Spec 206 budgets.
- Publish concise author guidance.
Definition of Done
This feature is done when:
- the support layer has a clearly documented cheap default path,
- heavy defaults are explicit rather than silent,
- the central factories no longer create unnecessary hidden cascades by default,
- the highest-usage expensive callers have moved to the new lighter paths where appropriate,
- guard and regression coverage is green,
- the affected standard lanes are successfully validated against the Spec 206 baseline,
- and reviewers can tell from test setup whether a new test is asking for minimal, standard, or full integration context.
Recommended Next Spec
After this feature, the next recommended step is Spec 208 - Filament or Livewire Heavy Suite Segmentation, so the suite first reduces per-test cost and then sharpens lane boundaries for the heaviest families.
Key Entities (include if feature involves data)
- Fixture Profile: A named level of shared setup cost and scope, such as minimal, standard, or full or integration-heavy.
- Shared Fixture Path: A reusable setup path that creates only a defined amount of context for a test.
- Lean Factory State: A factory default or add-on state that keeps record creation limited to the context the test actually needs.
- Hidden Cascade Finding: An audited place where defaults, callbacks, or repair behavior silently create extra records or state.
- Legacy Transition Path: A temporary way to preserve heavier historical behavior while callers migrate to lighter profiles.
- Fixture Cost Signal: Naming, guidance, or guard coverage that makes a heavy setup request obvious.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: A documented fixture-profile model exists with minimal, standard, and full or integration-heavy levels, and all migrated call sites make the chosen level recognizable from the setup request.
- SC-002: The default shared fixture path and the default states of the highest-usage audited factories no longer create provider, credential, membership, workspace, session, or capability add-ons unless explicitly requested.
- SC-003: Guard coverage verifies both that minimal profiles stay lean and that heavy profiles create their promised extra context for the audited shared helpers and factories.
- SC-004: The top migration pack for the fast-feedback and confidence lanes is completed, and the migrated callers retain their intended business assertions without blanket fallback to legacy full-context setup.
- SC-005: Post-migration measurement shows that at least one affected standard lane improves wall-clock runtime by 10% or more versus the pre-migration baseline, and no affected standard lane regresses by more than 5% while coverage remains stable.
- SC-006: The hidden-cascade audit is completed for the named high-usage aggregates, and each finding is classified as removed, made explicit, or intentionally retained with a documented reason.
- SC-007: Contributors have concise author guidance for choosing the cheapest valid fixture path, and reviewers can identify when a new test is asking for heavy integration context.