## Summary - separate provider-missing policy presence from local ignore semantics by introducing `missing_from_provider_at` - update policy, backup, and restore surfaces so current-state capture stays honest while historical restore continuity remains available - add focused sync, Filament, backup, restore, localization, and badge coverage for the new provider-missing behavior ## Scope - policy sync and model truth - policy resource visibility, badges, labels, and action gating - backup/export eligibility and restore continuity messaging - spec 261 artifacts and focused tests ## Validation - feature-specific Pest coverage is included in the branch - validation was not re-run as part of this commit/push/PR handoff Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #316
300 lines
8.5 KiB
YAML
300 lines
8.5 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: TenantPilot Provider-Missing Policy Visibility & Restore Continuity v1 (Conceptual)
|
|
version: 0.1.0
|
|
description: |
|
|
Conceptual contract for the Provider-Missing Policy Visibility & Restore
|
|
Continuity v1 planning package.
|
|
|
|
These paths describe existing Filament admin and tenant-scoped routes reused by
|
|
implementation. The schemas document the derived policy-presence, current
|
|
backup-eligibility, and historical restore-continuity contract expected over
|
|
existing policy, backup, and restore truth; they do not define a new public
|
|
REST API.
|
|
servers:
|
|
- url: /
|
|
paths:
|
|
/admin/t/{tenant}/policies:
|
|
get:
|
|
summary: View tenant policies with distinct local-ignore and provider-missing states
|
|
parameters:
|
|
- in: path
|
|
name: tenant
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- in: query
|
|
name: visibility
|
|
required: false
|
|
description: |
|
|
`ignored` includes both `ignored_locally` and
|
|
`ignored_locally_provider_missing`. `provider_missing` includes both
|
|
`provider_missing` and `ignored_locally_provider_missing`.
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- active
|
|
- ignored
|
|
- provider_missing
|
|
- all
|
|
responses:
|
|
'200':
|
|
description: Policy list rendered
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PolicyIndexPageModel'
|
|
'403':
|
|
description: Forbidden for an in-scope actor missing the existing policy capability
|
|
'404':
|
|
description: Not found for non-members, tenant mismatches, or out-of-scope targets
|
|
|
|
/admin/t/{tenant}/policies/{policy}:
|
|
get:
|
|
summary: View one tenant policy with provider-presence continuity context
|
|
parameters:
|
|
- in: path
|
|
name: tenant
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- in: path
|
|
name: policy
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Policy detail rendered
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PolicyDetailModel'
|
|
'403':
|
|
description: Forbidden for an in-scope actor missing the existing policy capability
|
|
'404':
|
|
description: Not found for non-members, tenant mismatches, or inaccessible policy targets
|
|
|
|
/admin/t/{tenant}/backup-sets/create:
|
|
get:
|
|
summary: Open current backup selection with provider-missing eligibility rules
|
|
parameters:
|
|
- in: path
|
|
name: tenant
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Backup-set creation surface rendered
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BackupSelectionModel'
|
|
'403':
|
|
description: Forbidden for an in-scope actor missing the existing backup capability
|
|
'404':
|
|
description: Not found for non-members, tenant mismatches, or out-of-scope targets
|
|
|
|
/admin/t/{tenant}/restore-runs/create:
|
|
get:
|
|
summary: Open restore item selection with historical continuity for provider-missing policies
|
|
parameters:
|
|
- in: path
|
|
name: tenant
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- in: query
|
|
name: backup_set_id
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Restore-run creation surface rendered
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RestoreSelectionModel'
|
|
'403':
|
|
description: Forbidden for an in-scope actor missing the existing restore capability
|
|
'404':
|
|
description: Not found for non-members, tenant mismatches, or inaccessible backup targets
|
|
|
|
components:
|
|
schemas:
|
|
PolicyVisibilityState:
|
|
type: string
|
|
description: |
|
|
Combined state remains explicit as `ignored_locally_provider_missing`.
|
|
List filters continue to expose it through both the `ignored` and
|
|
`provider_missing` filter tokens.
|
|
enum:
|
|
- active
|
|
- ignored_locally
|
|
- provider_missing
|
|
- ignored_locally_provider_missing
|
|
|
|
PolicyActionEligibility:
|
|
type: object
|
|
required:
|
|
- can_sync
|
|
- can_export_current
|
|
- can_restore_history
|
|
properties:
|
|
can_sync:
|
|
type: boolean
|
|
can_export_current:
|
|
type: boolean
|
|
can_restore_history:
|
|
type: boolean
|
|
blocked_reason:
|
|
type: string
|
|
nullable: true
|
|
description: |
|
|
Primary current-state action blocker. When both `ignored_at` and
|
|
`missing_from_provider_at` are present, this resolves to
|
|
`provider_missing` because fresh provider-backed capture is not
|
|
possible; local ignore remains secondary context.
|
|
enum:
|
|
- ignored_locally
|
|
- provider_missing
|
|
|
|
PolicyListRow:
|
|
type: object
|
|
required:
|
|
- id
|
|
- display_name
|
|
- policy_type
|
|
- visibility_state
|
|
- action_eligibility
|
|
properties:
|
|
id:
|
|
type: integer
|
|
display_name:
|
|
type: string
|
|
policy_type:
|
|
type: string
|
|
visibility_state:
|
|
$ref: '#/components/schemas/PolicyVisibilityState'
|
|
ignored_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
missing_from_provider_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
last_synced_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
action_eligibility:
|
|
$ref: '#/components/schemas/PolicyActionEligibility'
|
|
|
|
PolicyIndexPageModel:
|
|
type: object
|
|
required:
|
|
- rows
|
|
properties:
|
|
rows:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PolicyListRow'
|
|
|
|
PolicyDetailModel:
|
|
type: object
|
|
required:
|
|
- policy
|
|
- historical_restore_available
|
|
properties:
|
|
policy:
|
|
$ref: '#/components/schemas/PolicyListRow'
|
|
historical_restore_available:
|
|
type: boolean
|
|
continuity_message:
|
|
type: string
|
|
nullable: true
|
|
|
|
BackupSelectionRow:
|
|
type: object
|
|
required:
|
|
- policy_id
|
|
- label
|
|
- eligible
|
|
properties:
|
|
policy_id:
|
|
type: integer
|
|
label:
|
|
type: string
|
|
eligible:
|
|
type: boolean
|
|
blocked_reason:
|
|
type: string
|
|
nullable: true
|
|
description: |
|
|
Primary current backup blocker. When a policy is both locally ignored
|
|
and provider-missing, this remains `provider_missing` because current
|
|
capture cannot proceed.
|
|
enum:
|
|
- ignored_locally
|
|
- provider_missing
|
|
secondary_local_ignore:
|
|
type: boolean
|
|
description: |
|
|
True when the row is also locally ignored. This remains secondary
|
|
context when `blocked_reason` resolves to `provider_missing`.
|
|
historical_continuity_available:
|
|
type: boolean
|
|
|
|
BackupSelectionModel:
|
|
type: object
|
|
required:
|
|
- rows
|
|
properties:
|
|
rows:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/BackupSelectionRow'
|
|
|
|
RestoreSelectionRow:
|
|
type: object
|
|
required:
|
|
- backup_item_id
|
|
- label
|
|
- selectable
|
|
properties:
|
|
backup_item_id:
|
|
type: integer
|
|
label:
|
|
type: string
|
|
selectable:
|
|
type: boolean
|
|
provider_missing_notice:
|
|
type: boolean
|
|
continuity_message:
|
|
type: string
|
|
nullable: true
|
|
|
|
RestoreSelectionModel:
|
|
type: object
|
|
required:
|
|
- rows
|
|
properties:
|
|
rows:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RestoreSelectionRow' |