openapi: 3.1.0
info:
  title: Shared Test Fixture Slimming Logical Contract
  version: 1.0.0
  summary: Logical contract for resolving fixture profiles, reading cascade audits, and comparing lane impact.
  description: |
    This is a logical contract for repository tooling, tests, and planning artifacts.
    It does not imply a new runtime HTTP service. It documents the expected semantics
    of fixture-profile resolution and lane-impact comparison so helper behavior,
    guard tests, and reporting remain consistent during the migration.
x-logical-contract: true
servers:
  - url: https://tenantatlas.local/logical
paths:
  /shared-fixtures/helpers/{helperName}/contexts:
    post:
      summary: Resolve the promised side effects of a helper for a selected fixture profile.
      operationId: resolveSharedFixtureContext
      parameters:
        - name: helperName
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HelperResolutionRequest'
      responses:
        '200':
          description: Logical resolution of the helper profile and its side effects.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HelperResolution'
  /shared-fixtures/audits/factories/{factoryName}:
    get:
      summary: Read the current cascade-audit result for a touched factory or model seam.
      operationId: getFactoryCascadeAudit
      parameters:
        - name: factoryName
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Current cascade-audit description for the requested seam.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FactoryCascadeAudit'
  /shared-fixtures/lane-impact/runs:
    post:
      summary: Compare pre- and post-migration lane measurements for a migration pack.
      operationId: compareFixtureLaneImpact
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LaneImpactComparisonRequest'
      responses:
        '200':
          description: Comparison result for the affected lanes against the current Spec 206 budgets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LaneImpactComparison'
components:
  schemas:
    ProfileId:
      type: string
      enum:
        - minimal
        - standard
        - full
    CostClass:
      type: string
      enum:
        - minimal
        - standard
        - integration-heavy
    TransitionStatus:
      type: string
      enum:
        - current
        - legacy-transition
        - planned-removal
    RemovalTrigger:
      type: string
      minLength: 1
    Disposition:
      type: string
      enum:
        - remove
        - make-explicit
        - retain-documented
        - follow-up
    LaneId:
      type: string
      enum:
        - fast-feedback
        - confidence
        - browser
        - heavy-governance
    SideEffects:
      type: object
      additionalProperties: false
      required:
        - workspace
        - workspaceMembership
        - tenantMembership
        - session
        - cache
        - providerConnection
        - providerCredential
        - uiContext
      properties:
        workspace:
          type: boolean
        workspaceMembership:
          type: boolean
        tenantMembership:
          type: boolean
        session:
          type: boolean
        cache:
          type: boolean
        providerConnection:
          type: boolean
        providerCredential:
          type: boolean
        uiContext:
          type: boolean
    HelperResolutionRequest:
      type: object
      additionalProperties: false
      required:
        - profileId
      properties:
        profileId:
          $ref: '#/components/schemas/ProfileId'
        legacyAlias:
          type: string
        expectedHeavyContext:
          type: boolean
    HelperResolution:
      type: object
      additionalProperties: false
      required:
        - helperName
        - defaultProfile
        - requestedProfile
        - canonicalProfile
        - costClass
        - sideEffects
        - transitionStatus
      properties:
        helperName:
          type: string
        defaultProfile:
          $ref: '#/components/schemas/ProfileId'
        requestedProfile:
          $ref: '#/components/schemas/ProfileId'
        canonicalProfile:
          $ref: '#/components/schemas/ProfileId'
        costClass:
          $ref: '#/components/schemas/CostClass'
        sideEffects:
          $ref: '#/components/schemas/SideEffects'
        transitionStatus:
          $ref: '#/components/schemas/TransitionStatus'
        legacyAliasUsed:
          type: boolean
        legacyAlias:
          type: string
        removalTrigger:
          $ref: '#/components/schemas/RemovalTrigger'
        notes:
          type: string
      allOf:
        - if:
            properties:
              requestedProfile:
                const: minimal
          then:
            properties:
              costClass:
                const: minimal
              sideEffects:
                properties:
                  providerConnection:
                    const: false
                  providerCredential:
                    const: false
                  cache:
                    const: false
                  uiContext:
                    const: false
    FactoryCascadeFinding:
      type: object
      additionalProperties: false
      required:
        - source
        - triggerCondition
        - createdObjects
        - disposition
      properties:
        source:
          type: string
          enum:
            - definition
            - attribute-callback
            - afterCreating
            - model-event
            - support-helper
        triggerCondition:
          type: string
        createdObjects:
          type: array
          minItems: 1
          items:
            type: string
        disposition:
          $ref: '#/components/schemas/Disposition'
        notes:
          type: string
    FactoryCascadeAudit:
      type: object
      additionalProperties: false
      required:
        - factoryName
        - defaultCostClass
        - findings
      properties:
        factoryName:
          type: string
        defaultCostClass:
          $ref: '#/components/schemas/CostClass'
        leanStates:
          type: array
          items:
            type: string
        heavyStates:
          type: array
          items:
            type: string
        findings:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/FactoryCascadeFinding'
    LaneImpactComparisonRequest:
      type: object
      additionalProperties: false
      required:
        - packId
        - laneMeasurements
      properties:
        packId:
          type: string
        laneMeasurements:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/LaneMeasurement'
    LaneMeasurement:
      type: object
      additionalProperties: false
      required:
        - laneId
        - baselineSeconds
        - postMigrationSeconds
        - budgetThresholdSeconds
      properties:
        laneId:
          $ref: '#/components/schemas/LaneId'
        baselineSeconds:
          type: number
          minimum: 0
        postMigrationSeconds:
          type: number
          minimum: 0
        budgetThresholdSeconds:
          type: number
          minimum: 0
    LaneImpactComparison:
      type: object
      additionalProperties: false
      required:
        - packId
        - results
      properties:
        packId:
          type: string
        results:
          type: array
          minItems: 1
          items:
            type: object
            additionalProperties: false
            required:
              - laneId
              - deltaSeconds
              - deltaPercent
              - budgetThresholdSeconds
              - status
            properties:
              laneId:
                $ref: '#/components/schemas/LaneId'
              deltaSeconds:
                type: number
              deltaPercent:
                type: number
              budgetThresholdSeconds:
                type: number
              status:
                type: string
                enum:
                  - improved
                  - stable
                  - regressed
              notes:
                type: string