905 lines
37 KiB
YAML
905 lines
37 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: RAGCore API
|
|
version: 1.2.1
|
|
description: Central secure local-first retrieval platform contract.
|
|
servers:
|
|
- url: https://ragcore.example.test
|
|
security:
|
|
- bearerAuth: []
|
|
tags:
|
|
- name: health
|
|
- name: control
|
|
- name: ingestion
|
|
- name: retrieval
|
|
- name: operations
|
|
paths:
|
|
/health/live:
|
|
get:
|
|
security: []
|
|
tags: [health]
|
|
operationId: getLiveness
|
|
responses:
|
|
'200':
|
|
description: Process is alive.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Health'}
|
|
/health/ready:
|
|
get:
|
|
security: []
|
|
tags: [health]
|
|
operationId: getReadiness
|
|
responses:
|
|
'200':
|
|
description: Required dependencies are ready.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Readiness'}
|
|
'503': {$ref: '#/components/responses/Problem'}
|
|
/v1/applications:
|
|
get:
|
|
tags: [control]
|
|
operationId: listApplications
|
|
parameters:
|
|
- {$ref: '#/components/parameters/Cursor'}
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
responses:
|
|
'200':
|
|
description: Applications visible to the caller.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApplicationPage'
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
post:
|
|
tags: [control]
|
|
operationId: createApplication
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ApplicationCreate'}
|
|
responses:
|
|
'201':
|
|
description: Application created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Application'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'409': {$ref: '#/components/responses/Problem'}
|
|
/v1/applications/{application_id}/credentials:
|
|
post:
|
|
tags: [control]
|
|
operationId: issueApplicationCredential
|
|
parameters:
|
|
- {$ref: '#/components/parameters/ApplicationId'}
|
|
- {$ref: '#/components/parameters/IdempotencyKey'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/CredentialIssueRequest'}
|
|
responses:
|
|
'201':
|
|
description: Credential issued; plaintext token is returned only here.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/CredentialIssued'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/knowledge-spaces:
|
|
get:
|
|
tags: [control]
|
|
operationId: listKnowledgeSpaces
|
|
parameters:
|
|
- {$ref: '#/components/parameters/Cursor'}
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
responses:
|
|
'200':
|
|
description: Authorized spaces.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/KnowledgeSpacePage'}
|
|
post:
|
|
tags: [control]
|
|
operationId: createKnowledgeSpace
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/KnowledgeSpaceCreate'}
|
|
responses:
|
|
'201':
|
|
description: Knowledge space created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/KnowledgeSpace'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'409': {$ref: '#/components/responses/Problem'}
|
|
/v1/knowledge-spaces/{space_id}/grants:
|
|
post:
|
|
tags: [control]
|
|
operationId: createSpaceGrant
|
|
parameters:
|
|
- {$ref: '#/components/parameters/SpaceId'}
|
|
- {$ref: '#/components/parameters/IdempotencyKey'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SpaceGrantCreate'}
|
|
responses:
|
|
'201':
|
|
description: Grant created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SpaceGrant'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/policies:
|
|
get:
|
|
tags: [control]
|
|
operationId: listPolicies
|
|
parameters:
|
|
- {$ref: '#/components/parameters/Cursor'}
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
responses:
|
|
'200':
|
|
description: Workspace policies visible to the caller.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/PolicyPage'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
post:
|
|
tags: [control]
|
|
operationId: createPolicy
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/PolicyCreate'}
|
|
responses:
|
|
'201':
|
|
description: Policy created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Policy'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
'409': {$ref: '#/components/responses/Problem'}
|
|
/v1/uploads:
|
|
post:
|
|
tags: [ingestion]
|
|
operationId: createUpload
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [space_id, file]
|
|
properties:
|
|
space_id: {type: string, format: uuid}
|
|
source_id: {type: [string, 'null'], format: uuid}
|
|
external_id: {type: [string, 'null'], maxLength: 512, description: 'The stable id of this item at its source (e.g. a wiki page id). Requires source_id -- without one there is nothing stable to deduplicate against. Ingesting the same (source_id, external_id) pair again creates a new version of the same document instead of a duplicate.'}
|
|
locale: {type: [string, 'null'], maxLength: 35, description: 'BCP-47-ish language tag for the content; defaults to en.'}
|
|
file: {type: string, format: binary}
|
|
responses:
|
|
'202':
|
|
description: Upload accepted and ingestion job created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AcceptedJob'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'413': {$ref: '#/components/responses/Problem'}
|
|
'415': {$ref: '#/components/responses/Problem'}
|
|
/v1/sources:
|
|
get:
|
|
tags: [ingestion]
|
|
operationId: listSources
|
|
parameters:
|
|
- {$ref: '#/components/parameters/Cursor'}
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
- name: space_id
|
|
in: query
|
|
schema: {type: string, format: uuid}
|
|
responses:
|
|
'200':
|
|
description: Authorized sources.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SourcePage'}
|
|
post:
|
|
tags: [ingestion]
|
|
operationId: createSource
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SourceCreate'}
|
|
responses:
|
|
'201':
|
|
description: Source created.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Source'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
/v1/sources/{source_id}/syncs:
|
|
post:
|
|
tags: [ingestion]
|
|
operationId: startSourceSync
|
|
parameters:
|
|
- {$ref: '#/components/parameters/SourceId'}
|
|
- {$ref: '#/components/parameters/IdempotencyKey'}
|
|
responses:
|
|
'202':
|
|
description: Synchronization scheduled.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AcceptedJob'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/documents:
|
|
get:
|
|
tags: [ingestion]
|
|
operationId: listDocuments
|
|
description: >-
|
|
Looks a document up by the sync client's own identity -- the primitive
|
|
a client uses to decide skip-vs-update by comparing content_sha256 /
|
|
source_fingerprint before ever uploading. With both filters: zero or
|
|
one item; an unmatched filter is an empty page, not a 404. With only
|
|
source_id: EVERY document that sync identity owns in the workspace
|
|
(active and retired, each with its searchable version when it has
|
|
one) -- the authoritative current set a sync client diffs its expected
|
|
set against instead of trusting its own memory. Bounded (a sync source
|
|
is a bounded set by construction), not paginated; no space_id/status
|
|
browse mode.
|
|
parameters:
|
|
- name: source_id
|
|
in: query
|
|
required: true
|
|
schema: {type: string, format: uuid}
|
|
- name: external_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string, maxLength: 512}
|
|
responses:
|
|
'200':
|
|
description: Zero or one matching document (with external_id), or every document of the source identity (without).
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/DocumentPage'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
/v1/documents/{document_id}:
|
|
get:
|
|
tags: [ingestion]
|
|
operationId: getDocument
|
|
parameters: [{$ref: '#/components/parameters/DocumentId'}]
|
|
responses:
|
|
'200':
|
|
description: Document with its active (published) version, if any.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Document'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/documents/{document_id}/versions:
|
|
get:
|
|
tags: [ingestion]
|
|
operationId: listDocumentVersions
|
|
description: Every version of the document regardless of state, newest first. Not paginated.
|
|
parameters: [{$ref: '#/components/parameters/DocumentId'}]
|
|
responses:
|
|
'200':
|
|
description: Every version of this document.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/DocumentVersionPage'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/documents/{document_id}/retire:
|
|
post:
|
|
tags: [ingestion]
|
|
operationId: retireDocument
|
|
description: >-
|
|
Soft-retires a document (source_deleted=true) via the existing
|
|
mark_source_deleted; never a hard delete. Idempotent. Callers should
|
|
only call this after a complete, successful source scan confirms the
|
|
item is genuinely gone -- a partial or failed scan must not retire
|
|
anything, per the reconcile rule in
|
|
docs/04_INGESTION/CONNECTORS.md. Not enforced server-side: there is
|
|
no concept of "a scan" on this side of the API.
|
|
parameters: [{$ref: '#/components/parameters/DocumentId'}]
|
|
responses:
|
|
'200':
|
|
description: The now-retired document.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Document'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/spaces/{space_id}/index/reconcile:
|
|
post:
|
|
tags: [ingestion]
|
|
operationId: reconcileSpaceIndex
|
|
description: >-
|
|
Brings the searchable index of ONE knowledge space in line with its
|
|
published, non-retired document versions: points that belong to a
|
|
superseded version or to a retired (source_deleted) document are
|
|
removed; nothing is re-embedded or inserted. Idempotent; scoped to
|
|
the given space only (other spaces in the same collection are never
|
|
read or written). The natural last step of a sync client's run after
|
|
it has uploaded new versions and retired vanished items.
|
|
parameters:
|
|
- name: space_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, format: uuid}
|
|
responses:
|
|
'200':
|
|
description: Reconciliation outcome (counts).
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SpaceIndexReconciliation'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
'503': {$ref: '#/components/responses/Problem'}
|
|
/v1/jobs/{job_id}:
|
|
get:
|
|
tags: [operations]
|
|
operationId: getJob
|
|
parameters: [{$ref: '#/components/parameters/JobId'}]
|
|
responses:
|
|
'200':
|
|
description: Job status.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Job'}
|
|
'401': {$ref: '#/components/responses/Problem'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/search:
|
|
post:
|
|
tags: [retrieval]
|
|
operationId: searchKnowledge
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SearchRequest'}
|
|
responses:
|
|
'200':
|
|
description: Authorized retrieval results.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/SearchResponse'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'503': {$ref: '#/components/responses/Problem'}
|
|
'422': {$ref: '#/components/responses/Problem'}
|
|
/v1/context:
|
|
post:
|
|
tags: [retrieval]
|
|
operationId: buildContext
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ContextRequest'}
|
|
responses:
|
|
'200':
|
|
description: Token-bounded context package.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ContextResponse'}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'422': {$ref: '#/components/responses/Problem'}
|
|
'503': {$ref: '#/components/responses/Problem'}
|
|
/v1/answers:
|
|
post:
|
|
tags: [retrieval]
|
|
operationId: createAnswer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AnswerRequest'}
|
|
responses:
|
|
'200':
|
|
description: Grounded answer or explicit non-answer.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AnswerResponse'}
|
|
text/event-stream:
|
|
schema: {type: string}
|
|
'400': {$ref: '#/components/responses/Problem'}
|
|
'403': {$ref: '#/components/responses/Problem'}
|
|
'422': {$ref: '#/components/responses/Problem'}
|
|
'429': {$ref: '#/components/responses/Problem'}
|
|
'503': {$ref: '#/components/responses/Problem'}
|
|
/v1/citations/{citation_id}:
|
|
get:
|
|
tags: [retrieval]
|
|
operationId: getCitation
|
|
parameters: [{$ref: '#/components/parameters/CitationId'}]
|
|
responses:
|
|
'200':
|
|
description: Authorized immutable citation.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Citation'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
/v1/feedback:
|
|
post:
|
|
tags: [retrieval]
|
|
operationId: createFeedback
|
|
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/FeedbackCreate'}
|
|
responses:
|
|
'201':
|
|
description: Feedback recorded.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Feedback'}
|
|
'404': {$ref: '#/components/responses/Problem'}
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: RAGCore service token or OIDC session token
|
|
parameters:
|
|
Cursor:
|
|
name: cursor
|
|
in: query
|
|
schema: {type: string, maxLength: 2048}
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
schema: {type: integer, minimum: 1, maximum: 100, default: 50}
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema: {type: string, minLength: 16, maxLength: 128}
|
|
ApplicationId: {name: application_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
SpaceId: {name: space_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
SourceId: {name: source_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
DocumentId: {name: document_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
JobId: {name: job_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
CitationId: {name: citation_id, in: path, required: true, schema: {type: string, format: uuid}}
|
|
responses:
|
|
Problem:
|
|
description: Stable problem-details response.
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
schemas:
|
|
SpaceIndexReconciliation:
|
|
type: object
|
|
required: [space_id, documents_total, documents_retired, searchable_versions, points_before, deleted_points, orphaned_documents, points_after]
|
|
properties:
|
|
space_id: {type: string, format: uuid}
|
|
documents_total: {type: integer}
|
|
documents_retired: {type: integer}
|
|
searchable_versions: {type: integer}
|
|
points_before: {type: integer}
|
|
deleted_points: {type: integer}
|
|
orphaned_documents: {type: integer}
|
|
points_after: {type: integer}
|
|
Health:
|
|
type: object
|
|
required: [status, service]
|
|
properties:
|
|
status: {const: ok}
|
|
service: {const: ragcore}
|
|
Readiness:
|
|
type: object
|
|
required: [status, components]
|
|
properties:
|
|
status: {enum: [ok, degraded, unavailable]}
|
|
components:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
required: [status]
|
|
properties:
|
|
status: {enum: [ok, unavailable]}
|
|
latency_ms: {type: [number, 'null'], minimum: 0}
|
|
code: {type: [string, 'null']}
|
|
Problem:
|
|
type: object
|
|
required: [type, title, status, code, trace_id]
|
|
properties:
|
|
type: {type: string, format: uri}
|
|
title: {type: string}
|
|
status: {type: integer, minimum: 400, maximum: 599}
|
|
code: {type: string, pattern: '^[A-Z0-9_]+$'}
|
|
detail: {type: [string, 'null']}
|
|
trace_id: {type: string}
|
|
retry_after_seconds: {type: [integer, 'null'], minimum: 0}
|
|
errors: {type: array, items: {type: object}}
|
|
ApplicationCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [slug, display_name]
|
|
properties:
|
|
slug: {type: string, pattern: '^[a-z0-9][a-z0-9.-]{1,62}$'}
|
|
display_name: {type: string, minLength: 1, maxLength: 120}
|
|
description: {type: [string, 'null'], maxLength: 1000}
|
|
scopes: {type: array, uniqueItems: true, items: {$ref: '#/components/schemas/ApplicationScope'}}
|
|
default_space_ids: {type: array, uniqueItems: true, items: {type: string, format: uuid}}
|
|
Application:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/ApplicationCreate'}
|
|
- type: object
|
|
required: [id, workspace_id, status, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
workspace_id: {type: string, format: uuid}
|
|
status: {enum: [active, disabled]}
|
|
created_at: {type: string, format: date-time}
|
|
ApplicationPage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/Application'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
CredentialIssueRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [name, scopes]
|
|
properties:
|
|
name: {type: string, minLength: 1, maxLength: 120}
|
|
scopes: {type: array, uniqueItems: true, items: {type: string}}
|
|
expires_at: {type: [string, 'null'], format: date-time}
|
|
CredentialIssued:
|
|
type: object
|
|
required: [id, token, token_prefix, scopes, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
token: {type: string, writeOnly: true}
|
|
token_prefix: {type: string}
|
|
scopes: {type: array, items: {type: string}}
|
|
created_at: {type: string, format: date-time}
|
|
expires_at: {type: [string, 'null'], format: date-time}
|
|
ApplicationScope:
|
|
enum: [search, context, answer, documents:read, citations:read, feedback:write, sources:sync]
|
|
PolicyCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [operation]
|
|
properties:
|
|
operation: {type: string, minLength: 1, maxLength: 120}
|
|
knowledge_space_id: {type: [string, 'null'], format: uuid}
|
|
required_scopes: {type: array, uniqueItems: true, items: {$ref: '#/components/schemas/ApplicationScope'}}
|
|
Policy:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/PolicyCreate'}
|
|
- type: object
|
|
required: [id, workspace_id, active, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
workspace_id: {type: string, format: uuid}
|
|
active: {type: boolean}
|
|
created_at: {type: string, format: date-time}
|
|
PolicyPage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/Policy'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
DataPolicy:
|
|
enum: [local_only, local_preferred, cloud_allowed, retrieval_only, no_generation]
|
|
KnowledgeSpaceCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [slug, display_name, data_policy]
|
|
properties:
|
|
slug: {type: string, pattern: '^[a-z0-9][a-z0-9._-]{1,100}$'}
|
|
display_name: {type: string, minLength: 1, maxLength: 120}
|
|
description: {type: [string, 'null'], maxLength: 2000}
|
|
data_policy: {$ref: '#/components/schemas/DataPolicy'}
|
|
minimum_trust: {enum: [trusted_internal, trusted_external, unverified, user_uploaded, internet]}
|
|
retention_days: {type: integer, minimum: 1, maximum: 3650, default: 90}
|
|
KnowledgeSpace:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/KnowledgeSpaceCreate'}
|
|
- type: object
|
|
required: [id, workspace_id, status, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
workspace_id: {type: string, format: uuid}
|
|
status: {enum: [active, disabled]}
|
|
created_at: {type: string, format: date-time}
|
|
KnowledgeSpacePage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/KnowledgeSpace'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
SpaceGrantCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [principal_type, principal_id, permissions]
|
|
properties:
|
|
principal_type: {enum: [application, user, role]}
|
|
principal_id: {type: string, format: uuid}
|
|
permissions: {type: array, uniqueItems: true, items: {enum: [read, search, context, answer, manage_sources, manage_space]}}
|
|
SpaceGrant:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/SpaceGrantCreate'}
|
|
- type: object
|
|
required: [id, space_id, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
space_id: {type: string, format: uuid}
|
|
created_at: {type: string, format: date-time}
|
|
SourceType: {enum: [upload, folder, git, website]}
|
|
SourceCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [space_id, type, name, config]
|
|
properties:
|
|
space_id: {type: string, format: uuid}
|
|
type: {$ref: '#/components/schemas/SourceType'}
|
|
name: {type: string, minLength: 1, maxLength: 160}
|
|
config: {type: object, description: Typed and redacted per connector; secrets use references.}
|
|
enabled: {type: boolean, default: true}
|
|
Source:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/SourceCreate'}
|
|
- type: object
|
|
required: [id, status, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
status: {enum: [active, disabled, degraded]}
|
|
last_sync_at: {type: [string, 'null'], format: date-time}
|
|
created_at: {type: string, format: date-time}
|
|
SourcePage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/Source'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
DocumentVersionStatus:
|
|
enum: [acquired, security_checked, parsed, normalized, chunked, embedded, indexed, validated, published, superseded, retired, failed]
|
|
DocumentVersion:
|
|
type: object
|
|
required: [id, document_id, status, source_fingerprint, content_sha256]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
document_id: {type: string, format: uuid}
|
|
status: {$ref: '#/components/schemas/DocumentVersionStatus'}
|
|
source_fingerprint: {type: string}
|
|
content_sha256: {type: string, pattern: '^[a-f0-9]{64}$'}
|
|
created_at: {type: [string, 'null'], format: date-time}
|
|
DocumentVersionPage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/DocumentVersion'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
Document:
|
|
type: object
|
|
required: [id, space_id, external_id, title, status]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
space_id: {type: string, format: uuid}
|
|
source_id: {type: [string, 'null'], format: uuid, description: 'Null for a document ingested without a source_id (e.g. an ad hoc upload).'}
|
|
external_id: {type: string}
|
|
title: {type: string}
|
|
status: {enum: [active, source_deleted]}
|
|
active_version: {oneOf: [{$ref: '#/components/schemas/DocumentVersion'}, {type: 'null'}]}
|
|
DocumentPage:
|
|
type: object
|
|
required: [items]
|
|
properties:
|
|
items: {type: array, items: {$ref: '#/components/schemas/Document'}}
|
|
next_cursor: {type: [string, 'null']}
|
|
JobStatus: {enum: [ready, leased, succeeded, retry_wait, terminal]}
|
|
Job:
|
|
type: object
|
|
required: [id, operation, status, attempt_count, max_attempts]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
operation: {type: string}
|
|
status: {$ref: '#/components/schemas/JobStatus'}
|
|
attempt_count: {type: integer, minimum: 0}
|
|
max_attempts: {type: integer, minimum: 1}
|
|
last_error_code: {type: [string, 'null']}
|
|
AcceptedJob:
|
|
type: object
|
|
required: [job_id, status_url]
|
|
properties:
|
|
job_id: {type: string, format: uuid}
|
|
status_url: {type: string, format: uri-reference}
|
|
SearchFilter:
|
|
type: object
|
|
additionalProperties: false
|
|
properties:
|
|
content_types: {type: array, uniqueItems: true, maxItems: 50, items: {type: string}}
|
|
languages: {type: array, uniqueItems: true, maxItems: 50, items: {type: string, minLength: 2, maxLength: 16}}
|
|
source_ids: {type: array, uniqueItems: true, maxItems: 50, items: {type: string, format: uuid}}
|
|
document_ids: {type: array, uniqueItems: true, maxItems: 50, items: {type: string, format: uuid}}
|
|
trust_levels: {type: array, uniqueItems: true, maxItems: 50, items: {enum: [trusted_internal, trusted_external, unverified, user_uploaded, internet]}}
|
|
SearchRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [query]
|
|
properties:
|
|
query: {type: string, minLength: 1, maxLength: 8000, pattern: '.*\S.*'}
|
|
requested_space_ids: {type: array, uniqueItems: true, maxItems: 50, items: {type: string, format: uuid}}
|
|
profile: {type: string, pattern: '^[a-z0-9][a-z0-9_-]{0,63}$', default: hybrid-v1}
|
|
max_results: {type: integer, minimum: 1, maximum: 50, default: 10}
|
|
filters: {$ref: '#/components/schemas/SearchFilter'}
|
|
include_debug: {type: boolean, default: false, description: Authorized Query Lab use only.}
|
|
Citation:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [id, document_id, document_version_id, title, excerpt, excerpt_sha256, source_uri]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
document_id: {type: string, format: uuid}
|
|
document_version_id: {type: string, format: uuid}
|
|
title: {type: string}
|
|
section: {type: [string, 'null']}
|
|
page_start: {type: [integer, 'null'], minimum: 1}
|
|
page_end: {type: [integer, 'null'], minimum: 1}
|
|
line_start: {type: [integer, 'null'], minimum: 1}
|
|
line_end: {type: [integer, 'null'], minimum: 1}
|
|
excerpt: {type: string}
|
|
excerpt_sha256: {type: string, pattern: '^[a-f0-9]{64}$'}
|
|
source_uri: {type: string, description: 'Stable internal locator ragcore://source/<source_id>.'}
|
|
source_id: {type: [string, 'null'], format: uuid, description: 'Canonical source the cited document belongs to.'}
|
|
source_name: {type: [string, 'null'], description: 'Registry name of the source (e.g. Uploads, Infra runbooks).'}
|
|
source_kind: {type: [string, 'null'], enum: [upload, folder, git, website, null]}
|
|
locator: {type: [string, 'null'], description: 'The item within the source (external id / path).'}
|
|
revision: {type: [string, 'null'], description: 'Connector revision of the cited version (e.g. a Git commit).'}
|
|
display: {type: string, description: 'Human-readable one-line provenance, e.g. "Network Design.pdf · p. 18 · Firewall Segmentation".'}
|
|
CitationResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [id, document_id, document_version_id, title, excerpt, excerpt_sha256, source_uri]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
document_id: {type: string, format: uuid}
|
|
document_version_id: {type: string, format: uuid}
|
|
title: {type: string}
|
|
section: {type: [string, 'null']}
|
|
page_start: {type: [integer, 'null'], minimum: 1}
|
|
page_end: {type: [integer, 'null'], minimum: 1}
|
|
line_start: {type: [integer, 'null'], minimum: 1}
|
|
line_end: {type: [integer, 'null'], minimum: 1}
|
|
excerpt: {type: string}
|
|
excerpt_sha256: {type: string, pattern: '^[a-f0-9]{64}$'}
|
|
source_uri: {type: string, description: 'Stable internal locator ragcore://source/<source_id>.'}
|
|
source_id: {type: [string, 'null'], format: uuid, description: 'Canonical source the cited document belongs to.'}
|
|
source_name: {type: [string, 'null'], description: 'Registry name of the source (e.g. Uploads, Infra runbooks).'}
|
|
source_kind: {type: [string, 'null'], enum: [upload, folder, git, website, null]}
|
|
locator: {type: [string, 'null'], description: 'The item within the source (external id / path).'}
|
|
revision: {type: [string, 'null'], description: 'Connector revision of the cited version (e.g. a Git commit).'}
|
|
display: {type: string, description: 'Human-readable one-line provenance, e.g. "Network Design.pdf · p. 18 · Firewall Segmentation".'}
|
|
SearchResult:
|
|
type: object
|
|
required: [chunk_id, text, rank, citation]
|
|
properties:
|
|
chunk_id: {type: string, format: uuid}
|
|
parent_chunk_id: {type: [string, 'null'], format: uuid}
|
|
text: {type: string}
|
|
rank: {type: integer, minimum: 1}
|
|
scores:
|
|
type: object
|
|
properties:
|
|
dense: {type: [number, 'null']}
|
|
sparse: {type: [number, 'null']}
|
|
fused: {type: [number, 'null']}
|
|
rerank: {type: [number, 'null']}
|
|
citation: {$ref: '#/components/schemas/Citation'}
|
|
SearchResponse:
|
|
type: object
|
|
required: [retrieval_run_id, effective_space_ids, results, degraded]
|
|
properties:
|
|
retrieval_run_id: {type: string, format: uuid}
|
|
effective_space_ids: {type: array, items: {type: string, format: uuid}}
|
|
results: {type: array, items: {$ref: '#/components/schemas/SearchResult'}}
|
|
degraded: {type: boolean}
|
|
degradation_codes: {type: array, items: {type: string}}
|
|
timings_ms: {type: object, additionalProperties: {type: number, minimum: 0}}
|
|
ContextRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [query]
|
|
properties:
|
|
query: {type: string, minLength: 1, maxLength: 8000, pattern: '.*\S.*'}
|
|
requested_space_ids: {type: array, uniqueItems: true, maxItems: 50, items: {type: string, format: uuid}}
|
|
profile: {type: string, pattern: '^[a-z0-9][a-z0-9_-]{0,63}$', default: hybrid-v1}
|
|
max_results: {type: integer, minimum: 1, maximum: 50, default: 10}
|
|
filters: {$ref: '#/components/schemas/SearchFilter'}
|
|
include_debug: {type: boolean, default: false, description: Authorized Query Lab use only.}
|
|
max_context_tokens: {type: integer, minimum: 256, maximum: 64000, default: 8000}
|
|
ContextBlockResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [text, citation_ids, token_count]
|
|
properties:
|
|
text: {type: string}
|
|
citation_ids: {type: array, minItems: 1, items: {type: string, format: uuid}}
|
|
token_count: {type: integer, minimum: 1}
|
|
AnswerabilityStatus: {enum: [answerable, partially_answerable, not_answerable, conflicting_evidence]}
|
|
ContextResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [retrieval_run_id, answerability, token_count]
|
|
properties:
|
|
retrieval_run_id: {type: string, format: uuid}
|
|
answerability: {$ref: '#/components/schemas/AnswerabilityStatus'}
|
|
answerability_reasons: {type: array, items: {type: string}}
|
|
blocks: {type: array, items: {$ref: '#/components/schemas/ContextBlockResponse'}}
|
|
citations: {type: array, items: {$ref: '#/components/schemas/CitationResponse'}}
|
|
token_count: {type: integer, minimum: 0}
|
|
degraded: {type: boolean, default: false, description: 'True when retrieval fell back from its normal path (e.g. an unreachable reranker) but still produced these citations from a safe fallback ranking.'}
|
|
degradation_reasons: {type: array, items: {type: string}}
|
|
AnswerRequest:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/ContextRequest'}
|
|
- type: object
|
|
properties:
|
|
generation_profile: {type: string, default: answer-local-balanced-v1}
|
|
stream: {type: boolean, default: false}
|
|
AnswerClaim:
|
|
type: object
|
|
required: [text, citation_ids]
|
|
properties:
|
|
text: {type: string}
|
|
citation_ids: {type: array, minItems: 1, items: {type: string, format: uuid}}
|
|
AnswerResponse:
|
|
type: object
|
|
required: [answer_id, retrieval_run_id, answerability, answer, citations, claims]
|
|
properties:
|
|
answer_id: {type: string, format: uuid}
|
|
retrieval_run_id: {type: string, format: uuid}
|
|
answerability: {$ref: '#/components/schemas/AnswerabilityStatus'}
|
|
answer: {type: string}
|
|
claims: {type: array, items: {$ref: '#/components/schemas/AnswerClaim'}}
|
|
citations: {type: array, items: {$ref: '#/components/schemas/Citation'}}
|
|
degraded: {type: boolean, default: false, description: 'True on a generation retry or when retrieval degraded (e.g. an unreachable reranker fell back to fused ranking) -- the answer and citations are still real, not fabricated.'}
|
|
degradation_reasons: {type: array, items: {type: string}}
|
|
FeedbackCreate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [target_type, target_id, rating]
|
|
properties:
|
|
target_type: {enum: [retrieval_run, answer]}
|
|
target_id: {type: string, format: uuid}
|
|
rating: {enum: [helpful, not_helpful, incorrect, incomplete, unsafe]}
|
|
comment: {type: [string, 'null'], maxLength: 4000}
|
|
Feedback:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/FeedbackCreate'}
|
|
- type: object
|
|
required: [id, created_at]
|
|
properties:
|
|
id: {type: string, format: uuid}
|
|
created_at: {type: string, format: date-time}
|