## Summary - add explicit BaselineSnapshot lifecycle truth with conservative backfill and a shared truth resolver - block baseline compare from building, incomplete, or superseded snapshots and align workspace/tenant UI truth surfaces with effective snapshot state - surface artifact truth separately from operation outcome across baseline profile, snapshot, compare, and operation run pages ## Testing - integrated browser smoke test on the active feature surfaces - `vendor/bin/sail artisan test --compact tests/Feature/Filament/BaselineSnapshotTruthSurfaceTest.php tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php` - targeted baseline lifecycle and compare guard coverage added in Pest - `vendor/bin/sail bin pint --dirty --format agent` ## Notes - Livewire v4 compliance preserved - no panel provider registration changes were needed; Laravel 12 providers remain in `bootstrap/providers.php` - global search remains disabled for the affected baseline resources by design - destructive actions remain confirmation-gated; capture and compare actions keep their existing authorization and confirmation behavior - no new panel assets were added; existing deploy flow for `filament:assets` is unchanged Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #189
262 lines
7.8 KiB
YAML
262 lines
7.8 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: BaselineSnapshot Artifact Truth Operator Contract
|
|
version: 1.0.0
|
|
summary: Logical operator-action contract for baseline snapshot lifecycle and compare guards
|
|
description: |
|
|
This contract captures the intended request/response semantics for the operator-facing
|
|
capture, compare, and snapshot-truth flows in Spec 159. These are logical contracts for
|
|
existing Filament/Livewire-backed actions and read models, not a commitment to public REST endpoints.
|
|
servers:
|
|
- url: https://tenantpilot.local
|
|
tags:
|
|
- name: BaselineProfiles
|
|
- name: BaselineSnapshots
|
|
- name: BaselineCompare
|
|
paths:
|
|
/workspaces/{workspaceId}/baseline-profiles/{profileId}/captures:
|
|
post:
|
|
tags: [BaselineProfiles]
|
|
summary: Start a baseline capture
|
|
description: Starts a baseline capture attempt. The produced snapshot begins in `building` and becomes consumable only if finalized `complete`.
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
- $ref: '#/components/parameters/ProfileId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [sourceTenantId]
|
|
properties:
|
|
sourceTenantId:
|
|
type: integer
|
|
responses:
|
|
'202':
|
|
description: Capture accepted and queued
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [operationRunId, snapshot]
|
|
properties:
|
|
operationRunId:
|
|
type: integer
|
|
snapshot:
|
|
$ref: '#/components/schemas/BaselineSnapshotTruth'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/workspaces/{workspaceId}/baseline-profiles/{profileId}/effective-snapshot:
|
|
get:
|
|
tags: [BaselineProfiles]
|
|
summary: Resolve effective current baseline snapshot
|
|
description: Returns the latest complete snapshot that is valid as current baseline truth for the profile.
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
- $ref: '#/components/parameters/ProfileId'
|
|
responses:
|
|
'200':
|
|
description: Effective current baseline truth resolved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [profileId, effectiveSnapshot]
|
|
properties:
|
|
profileId:
|
|
type: integer
|
|
effectiveSnapshot:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/BaselineSnapshotTruth'
|
|
- type: 'null'
|
|
latestAttemptedSnapshot:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/BaselineSnapshotTruth'
|
|
- type: 'null'
|
|
compareAvailability:
|
|
$ref: '#/components/schemas/CompareAvailability'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/workspaces/{workspaceId}/baseline-snapshots/{snapshotId}:
|
|
get:
|
|
tags: [BaselineSnapshots]
|
|
summary: Read baseline snapshot truth
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
- $ref: '#/components/parameters/SnapshotId'
|
|
responses:
|
|
'200':
|
|
description: Snapshot truth returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BaselineSnapshotTruth'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/tenants/{tenantId}/baseline-compares:
|
|
post:
|
|
tags: [BaselineCompare]
|
|
summary: Start baseline compare
|
|
description: Starts compare only when the resolved or explicitly selected snapshot is consumable.
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
baselineSnapshotId:
|
|
type: integer
|
|
nullable: true
|
|
responses:
|
|
'202':
|
|
description: Compare accepted and queued
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [operationRunId, snapshot]
|
|
properties:
|
|
operationRunId:
|
|
type: integer
|
|
snapshot:
|
|
$ref: '#/components/schemas/BaselineSnapshotTruth'
|
|
'409':
|
|
description: Compare blocked because no consumable snapshot is available
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CompareAvailability'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
components:
|
|
parameters:
|
|
WorkspaceId:
|
|
name: workspaceId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
ProfileId:
|
|
name: profileId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
SnapshotId:
|
|
name: snapshotId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
TenantId:
|
|
name: tenantId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
|
|
responses:
|
|
Forbidden:
|
|
description: Member lacks the required capability
|
|
NotFound:
|
|
description: Workspace or tenant scope is not entitled, or the record is not visible in that scope
|
|
|
|
schemas:
|
|
BaselineSnapshotTruth:
|
|
type: object
|
|
required:
|
|
- id
|
|
- workspaceId
|
|
- baselineProfileId
|
|
- lifecycleState
|
|
- consumable
|
|
- capturedAt
|
|
properties:
|
|
id:
|
|
type: integer
|
|
workspaceId:
|
|
type: integer
|
|
baselineProfileId:
|
|
type: integer
|
|
lifecycleState:
|
|
type: string
|
|
enum: [building, complete, incomplete, superseded]
|
|
consumable:
|
|
type: boolean
|
|
capturedAt:
|
|
type: string
|
|
format: date-time
|
|
completedAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
failedAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
supersededAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
completionMeta:
|
|
type: object
|
|
additionalProperties: true
|
|
nullable: true
|
|
usabilityLabel:
|
|
type: string
|
|
examples: [Complete, Incomplete, Building, Superseded, Not usable for compare]
|
|
reasonCode:
|
|
type: string
|
|
nullable: true
|
|
reasonMessage:
|
|
type: string
|
|
nullable: true
|
|
|
|
CompareAvailability:
|
|
type: object
|
|
required:
|
|
- allowed
|
|
properties:
|
|
allowed:
|
|
type: boolean
|
|
effectiveSnapshotId:
|
|
type: integer
|
|
nullable: true
|
|
latestAttemptedSnapshotId:
|
|
type: integer
|
|
nullable: true
|
|
reasonCode:
|
|
type: string
|
|
nullable: true
|
|
enum:
|
|
- no_consumable_snapshot
|
|
- snapshot_building
|
|
- snapshot_incomplete
|
|
- snapshot_superseded
|
|
- invalid_snapshot_selection
|
|
reasonMessage:
|
|
type: string
|
|
nullable: true
|
|
nextAction:
|
|
type: string
|
|
nullable: true
|
|
examples:
|
|
- Wait for capture completion
|
|
- Re-run baseline capture
|
|
- Review failed capture |