TenantAtlas/specs/249-customer-review-workspace/contracts/customer-review-workspace.openapi.yaml
ahmido aacd82849a
Some checks failed
Main Confidence / confidence (push) Failing after 54s
feat(reviews): add CustomerReviewWorkspace with audit logging and RBAC enforcement (#289)
Add `CustomerReviewWorkspace` page for tenant pre-filtered reviews
Add customer workspace links to `EvidenceSnapshotResource`, `ReviewPackResource`, and `TenantReviewResource`
Implement audit logging for `TenantReviewOpened` and `ReviewPackDownloaded` actions
Update ReviewPack download controller to enforce tenant-scoped RBAC
Add tests for ReviewPack download authorization and audit logging

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #289
2026-04-28 07:15:41 +00:00

261 lines
7.3 KiB
YAML

openapi: 3.0.3
info:
title: TenantPilot Customer Review Workspace v1 (Conceptual)
version: 0.1.0
description: |
Conceptual contract for the read-oriented customer-safe workspace review
surface planned by Spec 249.
NOTE: The canonical page is planned as a native Filament / Livewire page in
the existing admin plane. The JSON response shapes below describe the
derived workspace view model for planning purposes; they do not require a
new public REST API in v1.
servers:
- url: /
paths:
/admin/reviews/workspace:
get:
summary: View the customer review workspace
description: |
Canonical admin-plane workspace page for customer-safe review
consumption. The page stays read-only and derives its rows from
existing tenant review, review-pack, evidence, and entitlement truth.
parameters:
- in: query
name: tenant_id
required: false
schema:
type: integer
description: |
Optional tenant prefilter carried from an existing tenant-scoped
review, review-pack, evidence, or dashboard entry point.
- in: query
name: source
required: false
schema:
type: string
description: Optional launch-context hint used for page highlighting only.
responses:
'200':
description: Workspace page rendered
content:
text/html:
schema:
type: string
application/json:
schema:
$ref: '#/components/schemas/CustomerReviewWorkspaceCollection'
'403':
description: Forbidden after workspace membership is established but required capability is missing
'404':
description: Not found for non-members or explicit out-of-scope tenant targeting
/admin/t/{tenant}/reviews/{review}:
get:
summary: Open the latest tenant review detail
description: |
Existing tenant-scoped review detail route reused as the primary inspect
action from the workspace page.
parameters:
- in: path
name: tenant
required: true
schema:
type: integer
- in: path
name: review
required: true
schema:
type: integer
responses:
'200':
description: Tenant review detail rendered
content:
text/html:
schema:
type: string
'403':
description: Forbidden for an entitled member missing the review capability
'404':
description: Not found for non-members or tenant / review mismatches
/admin/t/{tenant}/evidence/{evidenceSnapshot}:
get:
summary: Open evidence detail from the customer review flow
description: |
Existing tenant-scoped evidence detail route reused only as optional
proof when the actor explicitly asks for it and has the required
capability.
parameters:
- in: path
name: tenant
required: true
schema:
type: integer
- in: path
name: evidenceSnapshot
required: true
schema:
type: integer
responses:
'200':
description: Evidence detail rendered
content:
text/html:
schema:
type: string
'403':
description: Forbidden for an entitled member missing the evidence capability
'404':
description: Not found for non-members or tenant / evidence mismatches
/admin/review-packs/{reviewPack}/download:
get:
summary: Download the current review pack
description: |
Existing signed download route reused by the workspace page. The pack
must already exist, be ready, and not be expired.
parameters:
- in: path
name: reviewPack
required: true
schema:
type: integer
responses:
'200':
description: Review pack download stream
content:
application/zip:
schema:
type: string
format: binary
'403':
description: Forbidden due to missing signature or invalid signed URL
'404':
description: Review pack not found, not ready, or expired
components:
schemas:
CustomerReviewWorkspaceCollection:
type: object
required:
- workspace_id
- entries
properties:
workspace_id:
type: integer
tenant_prefilter_id:
type: integer
nullable: true
highlighted_tenant_id:
type: integer
nullable: true
launch_source:
type: string
nullable: true
entries:
type: array
items:
$ref: '#/components/schemas/CustomerReviewWorkspaceEntry'
empty_state_message:
type: string
nullable: true
CustomerReviewWorkspaceEntry:
type: object
required:
- tenant_id
- tenant_name
- review_pack_available
properties:
tenant_id:
type: integer
tenant_name:
type: string
latest_published_review_id:
type: integer
nullable: true
latest_review_generated_at:
type: string
format: date-time
nullable: true
latest_review_published_at:
type: string
format: date-time
nullable: true
review_outcome_label:
type: string
nullable: true
review_outcome_explanation:
type: string
nullable: true
key_findings_summary:
$ref: '#/components/schemas/FindingsSummary'
accepted_risk_summary:
$ref: '#/components/schemas/AcceptedRiskSummary'
review_pack:
$ref: '#/components/schemas/ReviewPackAccess'
evidence_proof:
$ref: '#/components/schemas/EvidenceProof'
primary_review_url:
type: string
nullable: true
redaction_note:
type: string
nullable: true
absence_note:
type: string
nullable: true
FindingsSummary:
type: object
nullable: true
properties:
total_visible:
type: integer
attention_required_count:
type: integer
summary_text:
type: string
AcceptedRiskSummary:
type: object
nullable: true
properties:
accepted_count:
type: integer
follow_up_required_count:
type: integer
summary_text:
type: string
ReviewPackAccess:
type: object
required:
- available
properties:
available:
type: boolean
review_pack_id:
type: integer
nullable: true
download_url:
type: string
nullable: true
status_message:
type: string
nullable: true
EvidenceProof:
type: object
nullable: true
properties:
evidence_snapshot_id:
type: integer
nullable: true
detail_url:
type: string
nullable: true
freshness_label:
type: string
nullable: true