TenantAtlas/specs/206-test-suite-governance/contracts/test-suite-governance.logical.openapi.yaml
ahmido 3c38192405 Spec 206: implement test suite governance foundation (#239)
## Summary

This PR implements Spec 206 end to end and establishes the first checked-in test suite governance foundation for the platform app.

Key changes:
- add manifest-backed test lanes for fast-feedback, confidence, browser, heavy-governance, profiling, and junit
- add budget and report helpers plus app-local artifact generation under `apps/platform/storage/logs/test-lanes`
- add repo-root Sail-friendly lane/report wrappers
- switch the default contributor test path to the fast-feedback lane
- introduce explicit fixture profiles and cheaper defaults for shared tenant/provider test setup
- add minimal/heavy factory states for tenant and provider connection setup
- migrate the first high-usage and provider-sensitive tests to explicit fixture profiles
- document budgets, taxonomy rules, DB reset guidance, and the full Spec 206 plan/contracts/tasks set

## Validation

Executed during implementation:
- focused Spec 206 guard/support/factory validation pack: 31 passed
- provider-sensitive regression pack: 29 passed
- first high-usage caller migration pack: 120 passed
- lane routing and wrapper validation succeeded
- pint completed successfully

Measured lane baselines captured in docs:
- fast-feedback: 176.74s
- confidence: 394.38s
- heavy-governance: 83.66s
- browser: 128.87s
- junit: 380.14s
- profiling: 2701.51s
- full-suite baseline anchor: 2624.60s

## Notes

- Livewire v4 / Filament v5 runtime behavior is unchanged by this PR.
- No new runtime routes, product UI flows, or database migrations are introduced.
- Panel provider registration remains unchanged in `bootstrap/providers.php`.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #239
2026-04-16 13:58:50 +00:00

396 lines
11 KiB
YAML

openapi: 3.1.0
info:
title: Test Suite Governance Logical Contract
version: 1.0.0
summary: Logical run and reporting contract for checked-in test lanes.
description: |
This is a logical contract for repository tooling, not a promise that a new
HTTP service will be introduced. It documents the expected semantics of lane
execution and lane reporting so commands, tasks, or wrappers can remain
consistent as the implementation evolves.
x-logical-contract: true
servers:
- url: https://tenantatlas.local/logical
paths:
/test-lanes/{laneId}/runs:
post:
summary: Start a lane run through a checked-in command entry point.
operationId: startTestLaneRun
parameters:
- name: laneId
in: path
required: true
schema:
$ref: '#/components/schemas/LaneId'
responses:
'202':
description: Lane execution accepted and resolved to a checked-in command path.
content:
application/json:
schema:
$ref: '#/components/schemas/LaneRunAccepted'
/test-lanes/{laneId}/reports/latest:
get:
summary: Read the most recent report produced for a lane.
operationId: getLatestTestLaneReport
parameters:
- name: laneId
in: path
required: true
schema:
$ref: '#/components/schemas/LaneId'
responses:
'200':
description: Latest report summary for the requested lane.
content:
application/json:
schema:
$ref: '#/components/schemas/LaneReport'
components:
schemas:
LaneId:
type: string
enum:
- fast-feedback
- confidence
- heavy-governance
- browser
- profiling
- junit
GovernanceClass:
type: string
enum:
- fast
- confidence
- heavy
- support
ArtifactMode:
type: string
enum:
- summary
- junit-xml
- profile-top
- budget-report
BudgetStatus:
type: string
enum:
- within-budget
- warning
- over-budget
BudgetBaselineSource:
type: string
enum:
- measured-current-suite
- measured-lane
BudgetEnforcement:
type: string
enum:
- report-only
- warn
- hard-fail
BudgetLifecycleState:
type: string
enum:
- draft
- measured
- documented
- enforced
LaneRunAccepted:
type: object
additionalProperties: false
required:
- laneId
- governanceClass
- commandRef
- parallelMode
- artifactModes
- includedFamilies
- excludedFamilies
- budgetThresholdSeconds
- budgetBaselineSource
- budgetEnforcement
- budgetLifecycleState
properties:
laneId:
$ref: '#/components/schemas/LaneId'
governanceClass:
$ref: '#/components/schemas/GovernanceClass'
commandRef:
type: string
description: Checked-in command reference, such as a Composer script name.
parallelMode:
type: string
enum:
- required
- optional
- forbidden
artifactModes:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ArtifactMode'
includedFamilies:
type: array
minItems: 1
items:
type: string
excludedFamilies:
type: array
items:
type: string
nonBrowserFeatureIntegrationSelectorCount:
type: integer
minimum: 0
includedSelectors:
type: array
items:
type: string
excludedSelectors:
type: array
items:
type: string
budgetThresholdSeconds:
type: integer
minimum: 1
budgetBaselineSource:
$ref: '#/components/schemas/BudgetBaselineSource'
budgetEnforcement:
$ref: '#/components/schemas/BudgetEnforcement'
budgetLifecycleState:
$ref: '#/components/schemas/BudgetLifecycleState'
baselineDeltaTargetPercent:
type: integer
minimum: 1
maximum: 100
artifactDirectory:
type: string
const: storage/logs/test-lanes
description: App-root relative directory for emitted artifacts. The first slice fixes this to storage/logs/test-lanes.
allOf:
- if:
properties:
laneId:
const: fast-feedback
then:
required:
- baselineDeltaTargetPercent
properties:
baselineDeltaTargetPercent:
const: 50
parallelMode:
const: required
excludedFamilies:
allOf:
- contains:
const: browser
- contains:
const: heavy-governance
- if:
properties:
laneId:
const: confidence
then:
properties:
parallelMode:
const: required
includedFamilies:
allOf:
- contains:
const: unit
- contains:
const: non-browser-feature-integration
nonBrowserFeatureIntegrationSelectorCount:
minimum: 1
excludedFamilies:
allOf:
- contains:
const: browser
- contains:
const: heavy-governance
- if:
properties:
laneId:
const: profiling
then:
properties:
governanceClass:
const: support
parallelMode:
const: forbidden
artifactModes:
contains:
const: profile-top
- if:
properties:
laneId:
const: junit
then:
properties:
governanceClass:
const: support
artifactModes:
contains:
const: junit-xml
- if:
properties:
laneId:
const: browser
then:
properties:
includedFamilies:
contains:
const: browser
LaneReport:
type: object
additionalProperties: false
required:
- laneId
- finishedAt
- wallClockSeconds
- budgetThresholdSeconds
- budgetBaselineSource
- budgetEnforcement
- budgetLifecycleState
- budgetStatus
- slowestEntries
- familyBudgetEvaluations
- artifacts
properties:
laneId:
$ref: '#/components/schemas/LaneId'
finishedAt:
type: string
format: date-time
wallClockSeconds:
type: number
minimum: 0
budgetThresholdSeconds:
type: integer
minimum: 1
budgetBaselineSource:
$ref: '#/components/schemas/BudgetBaselineSource'
budgetEnforcement:
$ref: '#/components/schemas/BudgetEnforcement'
budgetLifecycleState:
$ref: '#/components/schemas/BudgetLifecycleState'
baselineDeltaTargetPercent:
type: integer
minimum: 1
maximum: 100
budgetStatus:
$ref: '#/components/schemas/BudgetStatus'
slowestEntries:
type: array
minItems: 10
items:
$ref: '#/components/schemas/SlowEntry'
familyBudgetEvaluations:
type: array
minItems: 1
items:
$ref: '#/components/schemas/FamilyBudgetEvaluation'
artifacts:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ArtifactRecord'
allOf:
- if:
properties:
laneId:
const: fast-feedback
then:
properties:
baselineDeltaTargetPercent:
const: 50
- if:
properties:
laneId:
const: profiling
then:
properties:
artifacts:
contains:
type: object
required:
- artifactMode
properties:
artifactMode:
const: profile-top
- if:
properties:
laneId:
const: junit
then:
properties:
artifacts:
contains:
type: object
required:
- artifactMode
properties:
artifactMode:
const: junit-xml
SlowEntry:
type: object
additionalProperties: false
required:
- subject
- durationSeconds
- laneId
properties:
subject:
type: string
durationSeconds:
type: number
minimum: 0
laneId:
$ref: '#/components/schemas/LaneId'
familyId:
type: string
ArtifactRecord:
type: object
additionalProperties: false
required:
- artifactMode
- relativePath
properties:
artifactMode:
$ref: '#/components/schemas/ArtifactMode'
relativePath:
type: string
pattern: ^storage/logs/test-lanes/
machineReadable:
type: boolean
FamilyBudgetEvaluation:
type: object
additionalProperties: false
required:
- familyId
- thresholdSeconds
- baselineSource
- enforcement
- lifecycleState
- measuredSeconds
- budgetStatus
properties:
familyId:
type: string
thresholdSeconds:
type: integer
minimum: 1
baselineSource:
$ref: '#/components/schemas/BudgetBaselineSource'
enforcement:
$ref: '#/components/schemas/BudgetEnforcement'
lifecycleState:
$ref: '#/components/schemas/BudgetLifecycleState'
measuredSeconds:
type: number
minimum: 0
budgetStatus:
$ref: '#/components/schemas/BudgetStatus'
matchedSelectors:
type: array
items:
type: string