|
|
|
@@ -0,0 +1,984 @@
|
|
|
|
|
openapi: 3.1.0
|
|
|
|
|
info:
|
|
|
|
|
title: TechLog Studio API
|
|
|
|
|
version: 1.0.0
|
|
|
|
|
description: Transport contract for the TechLog Studio authoring frontend.
|
|
|
|
|
license: { name: Proprietary, identifier: LicenseRef-Proprietary }
|
|
|
|
|
servers:
|
|
|
|
|
- url: /
|
|
|
|
|
security: []
|
|
|
|
|
paths:
|
|
|
|
|
/api/v1/studio/dashboard:
|
|
|
|
|
get:
|
|
|
|
|
operationId: getStudioDashboard
|
|
|
|
|
summary: Get the Studio dashboard
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Dashboard lists and totals, content: { application/json: { schema: { $ref: "#/components/schemas/StudioDashboard" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/documents:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listStudioDocuments
|
|
|
|
|
summary: List working copies
|
|
|
|
|
parameters:
|
|
|
|
|
- { $ref: "#/components/parameters/Query" }
|
|
|
|
|
- { $ref: "#/components/parameters/DocumentKind" }
|
|
|
|
|
- { $ref: "#/components/parameters/PublicationStatus" }
|
|
|
|
|
- { $ref: "#/components/parameters/NextAction" }
|
|
|
|
|
- { $ref: "#/components/parameters/ProjectId" }
|
|
|
|
|
- { $ref: "#/components/parameters/DocumentSort" }
|
|
|
|
|
- { $ref: "#/components/parameters/Cursor" }
|
|
|
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Working-copy cursor page, content: { application/json: { schema: { $ref: "#/components/schemas/DocumentPage" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
post:
|
|
|
|
|
operationId: createStudioDocument
|
|
|
|
|
summary: Create a working copy
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/CreateDocumentInput" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created working copy
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/WorkingCopy" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/documents/{documentId}:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/DocumentId" }]
|
|
|
|
|
get:
|
|
|
|
|
operationId: getStudioDocument
|
|
|
|
|
summary: Get a working copy and its current state
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Working-copy detail, content: { application/json: { schema: { $ref: "#/components/schemas/WorkingCopyDetail" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/DocumentNotFound" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
put:
|
|
|
|
|
operationId: saveStudioDocument
|
|
|
|
|
summary: Save a full working copy
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/SaveDocumentCommand" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Saved working-copy detail
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/WorkingCopyDetail" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/DocumentNotFound" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/documents/{documentId}/validate:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/DocumentId" }]
|
|
|
|
|
post:
|
|
|
|
|
operationId: validateStudioDocument
|
|
|
|
|
summary: Validate a saved working copy
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/ValidateDocumentCommand" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Validation report
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/ValidationReport" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/DocumentNotFound" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/documents/{documentId}/preview:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/DocumentId" }]
|
|
|
|
|
get:
|
|
|
|
|
operationId: getCurrentStudioPreview
|
|
|
|
|
summary: Get the latest preview and its computed state
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Preview detail, content: { application/json: { schema: { $ref: "#/components/schemas/PreviewDetail" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/PreviewNotFound" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
post:
|
|
|
|
|
operationId: createStudioPreview
|
|
|
|
|
summary: Create a public-layout preview
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/CreatePreviewCommand" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"201":
|
|
|
|
|
description: Created preview
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/PublicPreview" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/DocumentNotFound" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/documents/{documentId}/publish:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/DocumentId" }]
|
|
|
|
|
post:
|
|
|
|
|
operationId: publishStudioDocument
|
|
|
|
|
summary: Publish or republish a validated preview
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/PublishDocumentCommand" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Publication aggregate and immutable event
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/PublishResult" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/DocumentNotFound" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/publications/{publicationId}/unpublish:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/PublicationId" }]
|
|
|
|
|
post:
|
|
|
|
|
operationId: unpublishStudioPublication
|
|
|
|
|
summary: Unpublish the current publication
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/IdempotencyKey" }]
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/UnpublishCommand" } } } }
|
|
|
|
|
responses:
|
|
|
|
|
"200":
|
|
|
|
|
description: Updated publication aggregate and event
|
|
|
|
|
headers: { Idempotency-Replayed: { $ref: "#/components/headers/IdempotencyReplayed" } }
|
|
|
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/PublishResult" } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/PublicationNotFound" }
|
|
|
|
|
"409": { $ref: "#/components/responses/CommandConflict" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/publications:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listStudioPublications
|
|
|
|
|
summary: List immutable publication events
|
|
|
|
|
description: Events are ordered by occurredAt DESC, then publicationEventId.
|
|
|
|
|
parameters:
|
|
|
|
|
- { $ref: "#/components/parameters/Query" }
|
|
|
|
|
- { $ref: "#/components/parameters/PublicationEventType" }
|
|
|
|
|
- { $ref: "#/components/parameters/Cursor" }
|
|
|
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Publication cursor page, content: { application/json: { schema: { $ref: "#/components/schemas/PublicationPage" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/publications/{publicationEventId}/preview:
|
|
|
|
|
parameters: [{ $ref: "#/components/parameters/PublicationEventId" }]
|
|
|
|
|
get:
|
|
|
|
|
operationId: getStudioPublicationSnapshot
|
|
|
|
|
summary: Get an immutable publication snapshot
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Publication snapshot, content: { application/json: { schema: { $ref: "#/components/schemas/PublicationSnapshot" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"404": { $ref: "#/components/responses/PublicationSnapshotNotFound" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
/api/v1/studio/catalog:
|
|
|
|
|
get:
|
|
|
|
|
operationId: listStudioCatalog
|
|
|
|
|
summary: List catalog entries for editor pickers
|
|
|
|
|
parameters:
|
|
|
|
|
- { $ref: "#/components/parameters/CatalogType" }
|
|
|
|
|
- { $ref: "#/components/parameters/Query" }
|
|
|
|
|
- { $ref: "#/components/parameters/Cursor" }
|
|
|
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
|
|
|
responses:
|
|
|
|
|
"200": { description: Catalog cursor page, content: { application/json: { schema: { $ref: "#/components/schemas/CatalogPage" } } } }
|
|
|
|
|
"401": { $ref: "#/components/responses/AuthenticationRequired" }
|
|
|
|
|
"403": { $ref: "#/components/responses/AccessDenied" }
|
|
|
|
|
"422": { $ref: "#/components/responses/RequestValidationFailed" }
|
|
|
|
|
"503": { $ref: "#/components/responses/StudioUnavailable" }
|
|
|
|
|
components:
|
|
|
|
|
parameters:
|
|
|
|
|
DocumentId: { name: documentId, in: path, required: true, schema: { type: string, format: uuid } }
|
|
|
|
|
PublicationId: { name: publicationId, in: path, required: true, schema: { type: string, format: uuid } }
|
|
|
|
|
PublicationEventId: { name: publicationEventId, in: path, required: true, schema: { type: string, format: uuid } }
|
|
|
|
|
IdempotencyKey: { name: Idempotency-Key, in: header, required: true, schema: { type: string, minLength: 1, maxLength: 200 } }
|
|
|
|
|
Query: { name: q, in: query, description: Free-text query normalized as part of the opaque cursor, schema: { type: string, maxLength: 100 } }
|
|
|
|
|
Cursor: { name: cursor, in: query, description: Opaque cursor bound to normalized filters and sort, schema: { type: string, minLength: 1, maxLength: 2000 } }
|
|
|
|
|
Limit: { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 20 } }
|
|
|
|
|
DocumentKind: { name: kind, in: query, schema: { $ref: "#/components/schemas/RecordKind" } }
|
|
|
|
|
PublicationStatus: { name: publicationStatus, in: query, schema: { $ref: "#/components/schemas/PublicationStatus" } }
|
|
|
|
|
NextAction: { name: nextAction, in: query, schema: { $ref: "#/components/schemas/NextAction" } }
|
|
|
|
|
ProjectId: { name: projectId, in: query, schema: { type: string, format: uuid } }
|
|
|
|
|
DocumentSort: { name: sort, in: query, schema: { type: string, enum: [UPDATED_DESC, UPDATED_ASC, TITLE_ASC], default: UPDATED_DESC } }
|
|
|
|
|
PublicationEventType: { name: type, in: query, schema: { $ref: "#/components/schemas/PublicationEventType" } }
|
|
|
|
|
CatalogType: { name: type, in: query, required: true, schema: { $ref: "#/components/schemas/CatalogEntryType" } }
|
|
|
|
|
headers:
|
|
|
|
|
IdempotencyReplayed: { description: True when the original result was replayed, schema: { type: boolean } }
|
|
|
|
|
responses:
|
|
|
|
|
AuthenticationRequired: { description: Authentication required, x-error-codes: [AUTHENTICATION_REQUIRED], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
AccessDenied: { description: Studio access denied, x-error-codes: [STUDIO_ACCESS_DENIED], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
DocumentNotFound: { description: Document not found, x-error-codes: [DOCUMENT_NOT_FOUND], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
PreviewNotFound: { description: Document or preview not found, x-error-codes: [DOCUMENT_NOT_FOUND, PREVIEW_NOT_FOUND], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
PublicationNotFound: { description: Publication not found, x-error-codes: [PUBLICATION_NOT_FOUND], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
PublicationSnapshotNotFound: { description: Publication event or snapshot not found, x-error-codes: [PUBLICATION_EVENT_NOT_FOUND, PUBLICATION_SNAPSHOT_NOT_FOUND], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
CommandConflict:
|
|
|
|
|
description: Command conflicts with current state, freshness, or idempotency
|
|
|
|
|
x-error-codes: [VERSION_CONFLICT, PUBLICATION_CONFLICT, VALIDATION_STALE, PREVIEW_STALE, PREVIEW_EXPIRED, IDEMPOTENCY_KEY_REUSED]
|
|
|
|
|
content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } }
|
|
|
|
|
RequestValidationFailed: { description: Request validation failed, x-error-codes: [REQUEST_VALIDATION_FAILED], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
StudioUnavailable: { description: Studio unavailable, x-error-codes: [STUDIO_UNAVAILABLE], content: { application/problem+json: { schema: { $ref: "#/components/schemas/ProblemDetails" } } } }
|
|
|
|
|
schemas:
|
|
|
|
|
RecordKind: { type: string, enum: [CASE, REFERENCE, QUESTION] }
|
|
|
|
|
PublicationStatus: { type: string, enum: [NEVER_PUBLISHED, PUBLISHED, UNPUBLISHED] }
|
|
|
|
|
NextAction: { type: string, enum: [CONTINUE_EDITING, VALIDATE, FIX_VALIDATION, CREATE_PREVIEW, PUBLISH, NONE] }
|
|
|
|
|
RelationInput:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, targetId, reason, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: [string, "null"], format: uuid }
|
|
|
|
|
targetId: { type: [string, "null"], format: uuid }
|
|
|
|
|
reason: { type: string, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
Relation:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, targetId, reason, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
targetId: { type: string, format: uuid }
|
|
|
|
|
reason: { type: string, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
OrderedText:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, text, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
text: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
ReferenceRule:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, title, body, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
title: { type: string, minLength: 1, maxLength: 120 }
|
|
|
|
|
body: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
QuestionOption:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, title, description, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
title: { type: string, minLength: 1, maxLength: 120 }
|
|
|
|
|
description: { type: string, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
QuestionResolution:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [summary, evidenceTargetId, linkLabel]
|
|
|
|
|
properties:
|
|
|
|
|
summary: { type: string, maxLength: 100000 }
|
|
|
|
|
evidenceTargetId: { type: [string, "null"], format: uuid }
|
|
|
|
|
linkLabel: { type: string, maxLength: 120 }
|
|
|
|
|
WorkingCopyInputBase:
|
|
|
|
|
type: object
|
|
|
|
|
required: [kind, title, slug, summary, topicId, projectId, relations]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { $ref: "#/components/schemas/RecordKind" }
|
|
|
|
|
title: { type: string, maxLength: 120 }
|
|
|
|
|
slug:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { type: string, const: "" }
|
|
|
|
|
- { type: string, minLength: 3, maxLength: 100, pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" }
|
|
|
|
|
summary: { type: string, maxLength: 300 }
|
|
|
|
|
topicId: { type: [string, "null"], format: uuid }
|
|
|
|
|
projectId: { type: [string, "null"], format: uuid }
|
|
|
|
|
relations: { type: array, maxItems: 20, items: { $ref: "#/components/schemas/RelationInput" } }
|
|
|
|
|
CaseInput:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyInputBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, problem, conclusion, environment, reproduction, lastVerifiedOn, bodyMarkdown]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: CASE }
|
|
|
|
|
problem: { type: string, maxLength: 100000 }
|
|
|
|
|
conclusion: { type: string, maxLength: 100000 }
|
|
|
|
|
environment: { type: string, maxLength: 100000 }
|
|
|
|
|
reproduction: { type: string, maxLength: 100000 }
|
|
|
|
|
lastVerifiedOn: { type: [string, "null"], format: date }
|
|
|
|
|
bodyMarkdown: { type: string, maxLength: 100000 }
|
|
|
|
|
ReferenceInput:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyInputBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, purpose, rules, applyWhen, exceptions, examples, verifiedOn]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: REFERENCE }
|
|
|
|
|
purpose: { type: string, maxLength: 100000 }
|
|
|
|
|
rules: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/ReferenceRule" } }
|
|
|
|
|
applyWhen: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
exceptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
examples: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
verifiedOn: { type: [string, "null"], format: date }
|
|
|
|
|
QuestionInput:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyInputBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, questionStatus, facts, assumptions, unknowns, constraints, options, nextValidation, resolution]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: QUESTION }
|
|
|
|
|
questionStatus: { type: [string, "null"], enum: [OPEN, RESOLVED, null] }
|
|
|
|
|
facts: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
assumptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
unknowns: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
constraints: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
options: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/QuestionOption" } }
|
|
|
|
|
nextValidation: { type: string, maxLength: 100000 }
|
|
|
|
|
resolution:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/QuestionResolution" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
WorkingCopyInput:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/CaseInput" }
|
|
|
|
|
- { $ref: "#/components/schemas/ReferenceInput" }
|
|
|
|
|
- { $ref: "#/components/schemas/QuestionInput" }
|
|
|
|
|
discriminator:
|
|
|
|
|
propertyName: kind
|
|
|
|
|
mapping:
|
|
|
|
|
CASE: "#/components/schemas/CaseInput"
|
|
|
|
|
REFERENCE: "#/components/schemas/ReferenceInput"
|
|
|
|
|
QUESTION: "#/components/schemas/QuestionInput"
|
|
|
|
|
WorkingCopyBase:
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyInputBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [id, version, relations, updatedAt]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
version: { type: integer, minimum: 1 }
|
|
|
|
|
relations: { type: array, maxItems: 20, items: { $ref: "#/components/schemas/Relation" } }
|
|
|
|
|
updatedAt: { type: string, format: date-time }
|
|
|
|
|
CaseWorkingCopy:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, problem, conclusion, environment, reproduction, lastVerifiedOn, bodyMarkdown]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: CASE }
|
|
|
|
|
problem: { type: string, maxLength: 100000 }
|
|
|
|
|
conclusion: { type: string, maxLength: 100000 }
|
|
|
|
|
environment: { type: string, maxLength: 100000 }
|
|
|
|
|
reproduction: { type: string, maxLength: 100000 }
|
|
|
|
|
lastVerifiedOn: { type: [string, "null"], format: date }
|
|
|
|
|
bodyMarkdown: { type: string, maxLength: 100000 }
|
|
|
|
|
ReferenceWorkingCopy:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, purpose, rules, applyWhen, exceptions, examples, verifiedOn]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: REFERENCE }
|
|
|
|
|
purpose: { type: string, maxLength: 100000 }
|
|
|
|
|
rules: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/ReferenceRule" } }
|
|
|
|
|
applyWhen: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
exceptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
examples: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
verifiedOn: { type: [string, "null"], format: date }
|
|
|
|
|
QuestionWorkingCopy:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/WorkingCopyBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, questionStatus, facts, assumptions, unknowns, constraints, options, nextValidation, resolution]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: QUESTION }
|
|
|
|
|
questionStatus: { type: [string, "null"], enum: [OPEN, RESOLVED, null] }
|
|
|
|
|
facts: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
assumptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
unknowns: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
constraints: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
options: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/QuestionOption" } }
|
|
|
|
|
nextValidation: { type: string, maxLength: 100000 }
|
|
|
|
|
resolution:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/QuestionResolution" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
WorkingCopy:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/CaseWorkingCopy" }
|
|
|
|
|
- { $ref: "#/components/schemas/ReferenceWorkingCopy" }
|
|
|
|
|
- { $ref: "#/components/schemas/QuestionWorkingCopy" }
|
|
|
|
|
discriminator:
|
|
|
|
|
propertyName: kind
|
|
|
|
|
mapping:
|
|
|
|
|
CASE: "#/components/schemas/CaseWorkingCopy"
|
|
|
|
|
REFERENCE: "#/components/schemas/ReferenceWorkingCopy"
|
|
|
|
|
QUESTION: "#/components/schemas/QuestionWorkingCopy"
|
|
|
|
|
CreateDocumentInput: { $ref: "#/components/schemas/WorkingCopyInput" }
|
|
|
|
|
SaveDocumentCommand:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [expectedVersion, document]
|
|
|
|
|
properties:
|
|
|
|
|
expectedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
document: { $ref: "#/components/schemas/WorkingCopyInput" }
|
|
|
|
|
ValidateDocumentCommand:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [expectedVersion]
|
|
|
|
|
properties: { expectedVersion: { type: integer, minimum: 1 } }
|
|
|
|
|
ValidationIssue:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [code, severity, path, message]
|
|
|
|
|
properties:
|
|
|
|
|
code: { type: string, minLength: 1, maxLength: 100 }
|
|
|
|
|
severity: { type: string, enum: [ERROR, WARNING] }
|
|
|
|
|
path:
|
|
|
|
|
type: string
|
|
|
|
|
pattern: "^(?:/(?:[^~/]|~0|~1)*)*$"
|
|
|
|
|
description: JSON Pointer to the affected field
|
|
|
|
|
message: { type: string, minLength: 1, maxLength: 1000 }
|
|
|
|
|
ValidationReport:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [validationId, documentId, validatedVersion, status, issues, validatedAt, validUntil, dependencyRevision]
|
|
|
|
|
properties:
|
|
|
|
|
validationId: { type: string, format: uuid }
|
|
|
|
|
documentId: { type: string, format: uuid }
|
|
|
|
|
validatedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
status: { type: string, enum: [INVALID, WARNINGS, VALID] }
|
|
|
|
|
issues: { type: array, maxItems: 200, items: { $ref: "#/components/schemas/ValidationIssue" } }
|
|
|
|
|
validatedAt: { type: string, format: date-time }
|
|
|
|
|
validUntil: { type: string, format: date-time }
|
|
|
|
|
dependencyRevision: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
CreatePreviewCommand:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [expectedVersion, validationId]
|
|
|
|
|
properties:
|
|
|
|
|
expectedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
validationId: { type: string, format: uuid }
|
|
|
|
|
PublishDocumentCommand:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [expectedVersion, validationId, previewId, acknowledgedWarningCodes]
|
|
|
|
|
properties:
|
|
|
|
|
expectedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
validationId: { type: string, format: uuid }
|
|
|
|
|
previewId: { type: string, format: uuid }
|
|
|
|
|
acknowledgedWarningCodes: { type: array, uniqueItems: true, maxItems: 200, items: { type: string, minLength: 1, maxLength: 100 } }
|
|
|
|
|
UnpublishCommand:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [expectedPublicationRevision]
|
|
|
|
|
properties: { expectedPublicationRevision: { type: integer, minimum: 1 } }
|
|
|
|
|
DisplayTarget:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, label, publicPath]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
label: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
publicPath: { type: [string, "null"], maxLength: 500 }
|
|
|
|
|
ResolvedRelation:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, targetId, targetKind, title, publicPath, reason, order]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
targetId: { type: string, format: uuid }
|
|
|
|
|
targetKind: { type: string, enum: [CASE, REFERENCE, QUESTION, PROJECT, PROJECT_DECISION] }
|
|
|
|
|
title: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
publicPath: { type: [string, "null"], maxLength: 500 }
|
|
|
|
|
reason: { type: string, maxLength: 100000 }
|
|
|
|
|
order: { type: integer, minimum: 0 }
|
|
|
|
|
RenderContext:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [generatedAt, dependencyRevision]
|
|
|
|
|
properties:
|
|
|
|
|
generatedAt: { type: string, format: date-time }
|
|
|
|
|
dependencyRevision: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
PublicRenderModelBase:
|
|
|
|
|
type: object
|
|
|
|
|
required: [kind, slug, title, summary, publicPath, topic, project, relations, renderContext]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { $ref: "#/components/schemas/RecordKind" }
|
|
|
|
|
slug: { type: string, minLength: 3, maxLength: 100, pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$" }
|
|
|
|
|
title: { type: string, minLength: 1, maxLength: 120 }
|
|
|
|
|
summary: { type: string, minLength: 1, maxLength: 300 }
|
|
|
|
|
publicPath: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
topic: { $ref: "#/components/schemas/DisplayTarget" }
|
|
|
|
|
project:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/DisplayTarget" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
relations: { type: array, maxItems: 20, items: { $ref: "#/components/schemas/ResolvedRelation" } }
|
|
|
|
|
renderContext: { $ref: "#/components/schemas/RenderContext" }
|
|
|
|
|
InlineText:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, text]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: TEXT }
|
|
|
|
|
text: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
InlineContainer:
|
|
|
|
|
type: object
|
|
|
|
|
required: [type, children]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, enum: [EMPHASIS, STRONG] }
|
|
|
|
|
children: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
InlineCode:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, code]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: INLINE_CODE }
|
|
|
|
|
code: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
InlineLink:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, label, href]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: LINK }
|
|
|
|
|
label: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
href: { type: string, format: uri, maxLength: 2000 }
|
|
|
|
|
InlineStatus:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, label, tone]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: STATUS }
|
|
|
|
|
label: { type: string, minLength: 1, maxLength: 120 }
|
|
|
|
|
tone: { type: string, enum: [warning, evidence, neutral] }
|
|
|
|
|
Inline:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/InlineText" }
|
|
|
|
|
- { $ref: "#/components/schemas/InlineEmphasis" }
|
|
|
|
|
- { $ref: "#/components/schemas/InlineStrong" }
|
|
|
|
|
- { $ref: "#/components/schemas/InlineCode" }
|
|
|
|
|
- { $ref: "#/components/schemas/InlineLink" }
|
|
|
|
|
- { $ref: "#/components/schemas/InlineStatus" }
|
|
|
|
|
discriminator:
|
|
|
|
|
propertyName: type
|
|
|
|
|
mapping:
|
|
|
|
|
TEXT: "#/components/schemas/InlineText"
|
|
|
|
|
EMPHASIS: "#/components/schemas/InlineEmphasis"
|
|
|
|
|
STRONG: "#/components/schemas/InlineStrong"
|
|
|
|
|
INLINE_CODE: "#/components/schemas/InlineCode"
|
|
|
|
|
LINK: "#/components/schemas/InlineLink"
|
|
|
|
|
STATUS: "#/components/schemas/InlineStatus"
|
|
|
|
|
InlineEmphasis:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/InlineContainer" }
|
|
|
|
|
- { type: object, properties: { type: { type: string, const: EMPHASIS } } }
|
|
|
|
|
InlineStrong:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/InlineContainer" }
|
|
|
|
|
- { type: object, properties: { type: { type: string, const: STRONG } } }
|
|
|
|
|
HeadingBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, id, level, content]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: HEADING }
|
|
|
|
|
id: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
level: { type: integer, minimum: 2, maximum: 4 }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
ParagraphBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, content]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: PARAGRAPH }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
BlockquoteBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, content]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: BLOCKQUOTE }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
ListItem:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, content]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
ListBlockBase:
|
|
|
|
|
type: object
|
|
|
|
|
required: [type, items]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, enum: [UNORDERED_LIST, ORDERED_LIST] }
|
|
|
|
|
items: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/ListItem" } }
|
|
|
|
|
UnorderedListBlock:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/ListBlockBase" }
|
|
|
|
|
- { type: object, properties: { type: { type: string, const: UNORDERED_LIST } } }
|
|
|
|
|
OrderedListBlock:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/ListBlockBase" }
|
|
|
|
|
- { type: object, properties: { type: { type: string, const: ORDERED_LIST } } }
|
|
|
|
|
CodeBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, code, language, label]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: CODE_BLOCK }
|
|
|
|
|
code: { type: string, maxLength: 100000 }
|
|
|
|
|
language: { type: [string, "null"], maxLength: 100 }
|
|
|
|
|
label: { type: [string, "null"], maxLength: 200 }
|
|
|
|
|
DataTableColumn:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, label, alignment]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
label: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
alignment: { type: string, enum: [LEFT, CENTER, RIGHT] }
|
|
|
|
|
DataTableCell:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [columnId, content]
|
|
|
|
|
properties:
|
|
|
|
|
columnId: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
DataTableRow:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, cells]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
cells: { type: array, maxItems: 100, items: { $ref: "#/components/schemas/DataTableCell" } }
|
|
|
|
|
DataTableBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, id, caption, rowHeaderColumn, columns, rows]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: DATA_TABLE }
|
|
|
|
|
id: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
caption: { type: string, maxLength: 1000 }
|
|
|
|
|
rowHeaderColumn: { type: [integer, "null"], minimum: 1 }
|
|
|
|
|
columns: { type: array, minItems: 1, maxItems: 100, items: { $ref: "#/components/schemas/DataTableColumn" } }
|
|
|
|
|
rows: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/DataTableRow" } }
|
|
|
|
|
CalloutBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, tone, label, content]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: CALLOUT }
|
|
|
|
|
tone: { type: string, enum: [warning, info] }
|
|
|
|
|
label: { type: string, maxLength: 200 }
|
|
|
|
|
content: { type: array, maxItems: 1000, items: { $ref: "#/components/schemas/Inline" } }
|
|
|
|
|
EvidenceFigureBlock:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [type, key, alt, caption, zoom]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, const: EVIDENCE_FIGURE }
|
|
|
|
|
key: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
alt: { type: string, minLength: 1, maxLength: 1000 }
|
|
|
|
|
caption: { type: string, maxLength: 1000 }
|
|
|
|
|
zoom: { type: boolean }
|
|
|
|
|
CaseRenderBlock:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/HeadingBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/ParagraphBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/BlockquoteBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/UnorderedListBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/OrderedListBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/CodeBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/DataTableBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/CalloutBlock" }
|
|
|
|
|
- { $ref: "#/components/schemas/EvidenceFigureBlock" }
|
|
|
|
|
discriminator:
|
|
|
|
|
propertyName: type
|
|
|
|
|
mapping:
|
|
|
|
|
HEADING: "#/components/schemas/HeadingBlock"
|
|
|
|
|
PARAGRAPH: "#/components/schemas/ParagraphBlock"
|
|
|
|
|
BLOCKQUOTE: "#/components/schemas/BlockquoteBlock"
|
|
|
|
|
UNORDERED_LIST: "#/components/schemas/UnorderedListBlock"
|
|
|
|
|
ORDERED_LIST: "#/components/schemas/OrderedListBlock"
|
|
|
|
|
CODE_BLOCK: "#/components/schemas/CodeBlock"
|
|
|
|
|
DATA_TABLE: "#/components/schemas/DataTableBlock"
|
|
|
|
|
CALLOUT: "#/components/schemas/CalloutBlock"
|
|
|
|
|
EVIDENCE_FIGURE: "#/components/schemas/EvidenceFigureBlock"
|
|
|
|
|
CasePublicRenderModel:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/PublicRenderModelBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, problem, conclusion, environment, reproduction, lastVerifiedOn, bodyBlocks]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: CASE }
|
|
|
|
|
problem: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
conclusion: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
environment: { type: string, maxLength: 100000 }
|
|
|
|
|
reproduction: { type: string, maxLength: 100000 }
|
|
|
|
|
lastVerifiedOn: { type: string, format: date }
|
|
|
|
|
bodyBlocks: { type: array, maxItems: 10000, items: { $ref: "#/components/schemas/CaseRenderBlock" } }
|
|
|
|
|
ReferencePublicRenderModel:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/PublicRenderModelBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, purpose, rules, applyWhen, exceptions, examples, verifiedOn]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: REFERENCE }
|
|
|
|
|
purpose: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
rules: { type: array, minItems: 1, maxItems: 50, items: { $ref: "#/components/schemas/ReferenceRule" } }
|
|
|
|
|
applyWhen: { type: array, minItems: 1, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
exceptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
examples: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
verifiedOn: { type: string, format: date }
|
|
|
|
|
ResolvedQuestionResolution:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [summary, evidenceTarget, linkLabel]
|
|
|
|
|
properties:
|
|
|
|
|
summary: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
evidenceTarget: { $ref: "#/components/schemas/DisplayTarget" }
|
|
|
|
|
linkLabel: { type: string, minLength: 1, maxLength: 120 }
|
|
|
|
|
QuestionPublicRenderModel:
|
|
|
|
|
unevaluatedProperties: false
|
|
|
|
|
allOf:
|
|
|
|
|
- { $ref: "#/components/schemas/PublicRenderModelBase" }
|
|
|
|
|
- type: object
|
|
|
|
|
required: [kind, status, facts, assumptions, unknowns, constraints, options, nextValidation, resolution]
|
|
|
|
|
properties:
|
|
|
|
|
kind: { type: string, const: QUESTION }
|
|
|
|
|
status: { type: string, enum: [OPEN, RESOLVED] }
|
|
|
|
|
facts: { type: array, minItems: 1, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
assumptions: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
unknowns: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
constraints: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/OrderedText" } }
|
|
|
|
|
options: { type: array, maxItems: 50, items: { $ref: "#/components/schemas/QuestionOption" } }
|
|
|
|
|
nextValidation: { type: string, minLength: 1, maxLength: 100000 }
|
|
|
|
|
resolution:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/ResolvedQuestionResolution" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
PublicRenderModel:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/CasePublicRenderModel" }
|
|
|
|
|
- { $ref: "#/components/schemas/ReferencePublicRenderModel" }
|
|
|
|
|
- { $ref: "#/components/schemas/QuestionPublicRenderModel" }
|
|
|
|
|
discriminator:
|
|
|
|
|
propertyName: kind
|
|
|
|
|
mapping:
|
|
|
|
|
CASE: "#/components/schemas/CasePublicRenderModel"
|
|
|
|
|
REFERENCE: "#/components/schemas/ReferencePublicRenderModel"
|
|
|
|
|
QUESTION: "#/components/schemas/QuestionPublicRenderModel"
|
|
|
|
|
PublicPreview:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [previewId, documentId, previewVersion, validationId, createdAt, expiresAt, renderModel]
|
|
|
|
|
properties:
|
|
|
|
|
previewId: { type: string, format: uuid }
|
|
|
|
|
documentId: { type: string, format: uuid }
|
|
|
|
|
previewVersion: { type: integer, minimum: 1 }
|
|
|
|
|
validationId: { type: string, format: uuid }
|
|
|
|
|
createdAt: { type: string, format: date-time }
|
|
|
|
|
expiresAt: { type: string, format: date-time }
|
|
|
|
|
renderModel: { $ref: "#/components/schemas/PublicRenderModel" }
|
|
|
|
|
PreviewDetail:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [preview, state, currentDocumentVersion, currentValidationId]
|
|
|
|
|
properties:
|
|
|
|
|
preview: { $ref: "#/components/schemas/PublicPreview" }
|
|
|
|
|
state: { type: string, enum: [CURRENT, STALE, EXPIRED] }
|
|
|
|
|
currentDocumentVersion: { type: integer, minimum: 1 }
|
|
|
|
|
currentValidationId: { type: [string, "null"], format: uuid }
|
|
|
|
|
PublicationAggregate:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [publicationId, documentId, status, publishedVersion, publicationRevision, latestEventId, publicPath, updatedAt]
|
|
|
|
|
properties:
|
|
|
|
|
publicationId: { type: string, format: uuid }
|
|
|
|
|
documentId: { type: string, format: uuid }
|
|
|
|
|
status: { type: string, enum: [PUBLISHED, UNPUBLISHED] }
|
|
|
|
|
publishedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
publicationRevision: { type: integer, minimum: 1 }
|
|
|
|
|
latestEventId: { type: string, format: uuid }
|
|
|
|
|
publicPath: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
updatedAt: { type: string, format: date-time }
|
|
|
|
|
PublicationEventType: { type: string, enum: [PUBLISHED, REPUBLISHED, UNPUBLISHED] }
|
|
|
|
|
PublicationEvent:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [publicationEventId, publicationId, documentId, type, occurredAt, publishedVersion, sourcePublishedEventId, snapshotAvailable]
|
|
|
|
|
properties:
|
|
|
|
|
publicationEventId: { type: string, format: uuid }
|
|
|
|
|
publicationId: { type: string, format: uuid }
|
|
|
|
|
documentId: { type: string, format: uuid }
|
|
|
|
|
type: { $ref: "#/components/schemas/PublicationEventType" }
|
|
|
|
|
occurredAt: { type: string, format: date-time }
|
|
|
|
|
publishedVersion: { type: integer, minimum: 1 }
|
|
|
|
|
sourcePublishedEventId: { type: [string, "null"], format: uuid }
|
|
|
|
|
snapshotAvailable: { type: boolean }
|
|
|
|
|
PublicationSnapshot:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [event, renderModel]
|
|
|
|
|
properties:
|
|
|
|
|
event: { $ref: "#/components/schemas/PublicationEvent" }
|
|
|
|
|
renderModel: { $ref: "#/components/schemas/PublicRenderModel" }
|
|
|
|
|
PublishResult:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [publication, event]
|
|
|
|
|
properties:
|
|
|
|
|
publication: { $ref: "#/components/schemas/PublicationAggregate" }
|
|
|
|
|
event: { $ref: "#/components/schemas/PublicationEvent" }
|
|
|
|
|
DocumentSummary:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, title, kind, project, updatedAt, publicationStatus, publishedVersion, hasUnpublishedChanges, nextAction]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
title: { type: string, maxLength: 120 }
|
|
|
|
|
kind: { $ref: "#/components/schemas/RecordKind" }
|
|
|
|
|
project:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/DisplayTarget" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
updatedAt: { type: string, format: date-time }
|
|
|
|
|
publicationStatus: { $ref: "#/components/schemas/PublicationStatus" }
|
|
|
|
|
publishedVersion: { type: [integer, "null"], minimum: 1 }
|
|
|
|
|
hasUnpublishedChanges: { type: boolean }
|
|
|
|
|
nextAction: { $ref: "#/components/schemas/NextAction" }
|
|
|
|
|
PublicationAction: { type: string, enum: [VIEW_SNAPSHOT, VIEW_SOURCE_SNAPSHOT, UNPUBLISH] }
|
|
|
|
|
PublicationListItem:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [event, publication, document, availableActions]
|
|
|
|
|
properties:
|
|
|
|
|
event: { $ref: "#/components/schemas/PublicationEvent" }
|
|
|
|
|
publication: { $ref: "#/components/schemas/PublicationAggregate" }
|
|
|
|
|
document: { $ref: "#/components/schemas/DocumentSummary" }
|
|
|
|
|
availableActions: { type: array, uniqueItems: true, maxItems: 3, items: { $ref: "#/components/schemas/PublicationAction" } }
|
|
|
|
|
WorkingCopyDetail:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [document, currentValidation, latestPreview, currentPublication, dependencyRevision]
|
|
|
|
|
properties:
|
|
|
|
|
document: { $ref: "#/components/schemas/WorkingCopy" }
|
|
|
|
|
currentValidation:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/ValidationReport" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
latestPreview:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/PublicPreview" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
currentPublication:
|
|
|
|
|
oneOf:
|
|
|
|
|
- { $ref: "#/components/schemas/PublicationAggregate" }
|
|
|
|
|
- { type: "null" }
|
|
|
|
|
dependencyRevision: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
StudioDashboard:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [continueWriting, readyToPublish, recentPublications, totals]
|
|
|
|
|
properties:
|
|
|
|
|
continueWriting: { type: array, maxItems: 5, items: { $ref: "#/components/schemas/DocumentSummary" } }
|
|
|
|
|
readyToPublish: { type: array, maxItems: 5, items: { $ref: "#/components/schemas/DocumentSummary" } }
|
|
|
|
|
recentPublications: { type: array, maxItems: 5, items: { $ref: "#/components/schemas/PublicationListItem" } }
|
|
|
|
|
totals: { $ref: "#/components/schemas/DashboardTotals" }
|
|
|
|
|
DashboardTotals:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [documents, readyToPublish, publications]
|
|
|
|
|
properties:
|
|
|
|
|
documents: { type: integer, minimum: 0 }
|
|
|
|
|
readyToPublish: { type: integer, minimum: 0 }
|
|
|
|
|
publications: { type: integer, minimum: 0 }
|
|
|
|
|
DocumentPage:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [items, nextCursor]
|
|
|
|
|
properties:
|
|
|
|
|
items: { type: array, maxItems: 100, items: { $ref: "#/components/schemas/DocumentSummary" } }
|
|
|
|
|
nextCursor: { type: [string, "null"], maxLength: 2000 }
|
|
|
|
|
PublicationPage:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [items, nextCursor]
|
|
|
|
|
properties:
|
|
|
|
|
items: { type: array, maxItems: 100, items: { $ref: "#/components/schemas/PublicationListItem" } }
|
|
|
|
|
nextCursor: { type: [string, "null"], maxLength: 2000 }
|
|
|
|
|
CatalogEntryType: { type: string, enum: [TOPIC, PROJECT, RELATION, EVIDENCE] }
|
|
|
|
|
CatalogEntry:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [id, type, label, dependencyRevision]
|
|
|
|
|
properties:
|
|
|
|
|
id: { type: string, format: uuid }
|
|
|
|
|
type: { $ref: "#/components/schemas/CatalogEntryType" }
|
|
|
|
|
label: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
kind: { type: string, enum: [CASE, REFERENCE, QUESTION, PROJECT, PROJECT_DECISION] }
|
|
|
|
|
publicPath: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
dependencyRevision: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
CatalogPage:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [items, nextCursor]
|
|
|
|
|
properties:
|
|
|
|
|
items: { type: array, maxItems: 100, items: { $ref: "#/components/schemas/CatalogEntry" } }
|
|
|
|
|
nextCursor: { type: [string, "null"], maxLength: 2000 }
|
|
|
|
|
FieldError:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: false
|
|
|
|
|
required: [path, message]
|
|
|
|
|
properties:
|
|
|
|
|
path:
|
|
|
|
|
type: string
|
|
|
|
|
pattern: "^(?:/(?:[^~/]|~0|~1)*)*$"
|
|
|
|
|
description: JSON Pointer to the invalid field
|
|
|
|
|
message: { type: string, minLength: 1, maxLength: 1000 }
|
|
|
|
|
ProblemDetails:
|
|
|
|
|
type: object
|
|
|
|
|
additionalProperties: true
|
|
|
|
|
required: [type, title, status, detail, code]
|
|
|
|
|
properties:
|
|
|
|
|
type: { type: string, format: uri-reference }
|
|
|
|
|
title: { type: string, minLength: 1, maxLength: 200 }
|
|
|
|
|
status: { type: integer, minimum: 400, maximum: 599 }
|
|
|
|
|
detail: { type: string, minLength: 1, maxLength: 5000 }
|
|
|
|
|
code:
|
|
|
|
|
type: string
|
|
|
|
|
enum: [AUTHENTICATION_REQUIRED, STUDIO_ACCESS_DENIED, DOCUMENT_NOT_FOUND, PREVIEW_NOT_FOUND, PUBLICATION_NOT_FOUND, PUBLICATION_EVENT_NOT_FOUND, PUBLICATION_SNAPSHOT_NOT_FOUND, VERSION_CONFLICT, PUBLICATION_CONFLICT, VALIDATION_STALE, PREVIEW_STALE, PREVIEW_EXPIRED, IDEMPOTENCY_KEY_REUSED, REQUEST_VALIDATION_FAILED, STUDIO_UNAVAILABLE]
|
|
|
|
|
instance: { type: string, format: uri-reference }
|
|
|
|
|
traceId: { type: string, maxLength: 200 }
|
|
|
|
|
fieldErrors: { type: array, maxItems: 200, items: { $ref: "#/components/schemas/FieldError" } }
|
|
|
|
|
latestDocument: { $ref: "#/components/schemas/WorkingCopyDetail" }
|
|
|
|
|
latestPublication: { $ref: "#/components/schemas/PublicationAggregate" }
|
|
|
|
|
conflictingFields:
|
|
|
|
|
type: array
|
|
|
|
|
uniqueItems: true
|
|
|
|
|
maxItems: 200
|
|
|
|
|
items:
|
|
|
|
|
type: string
|
|
|
|
|
pattern: "^(?:/(?:[^~/]|~0|~1)*)*$"
|
|
|
|
|
retryable: { type: boolean }
|