Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e
This commit is contained in:
commit
7ca726caf2
659 files changed
+98171
No files matched your search
@@ -0,0 +1,3 @@
|
||||
# Contracts
|
||||
|
||||
`openapi.yaml` is the target public API contract and evolves with implementation tasks. JSON schemas define durable Qdrant payload and job envelope boundaries. Contract changes require compatibility review, tests and versioning where breaking.
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://ragcore.example.test/schemas/job-payload-envelope-v1.json",
|
||||
"title": "RAGCore Job Payload Envelope",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"job_type",
|
||||
"workspace_id",
|
||||
"idempotency_key",
|
||||
"payload"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"const": 1
|
||||
},
|
||||
"job_type": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_.-]+$"
|
||||
},
|
||||
"workspace_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"idempotency_key": {
|
||||
"type": "string",
|
||||
"minLength": 16,
|
||||
"maxLength": 256
|
||||
},
|
||||
"trace_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"payload": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,904 @@
|
||||
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}
|
||||
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://ragcore.example.test/schemas/qdrant-payload-v1.json",
|
||||
"title": "RAGCore Qdrant payload v1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"workspace_id",
|
||||
"space_id",
|
||||
"document_id",
|
||||
"document_version_id",
|
||||
"chunk_id",
|
||||
"source_id",
|
||||
"status",
|
||||
"content_type",
|
||||
"language",
|
||||
"trust_level",
|
||||
"text",
|
||||
"content_sha256",
|
||||
"embedding_profile",
|
||||
"chunk_profile"
|
||||
],
|
||||
"properties": {
|
||||
"workspace_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"space_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"document_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"document_version_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"chunk_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"parent_chunk_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"format": "uuid"
|
||||
},
|
||||
"source_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"status": {
|
||||
"const": "active"
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"maxLength": 80
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"maxLength": 16
|
||||
},
|
||||
"trust_level": {
|
||||
"enum": [
|
||||
"trusted_internal",
|
||||
"trusted_external",
|
||||
"unverified",
|
||||
"user_uploaded",
|
||||
"internet"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"maxLength": 500
|
||||
},
|
||||
"section_path": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"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
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"content_sha256": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{64}$"
|
||||
},
|
||||
"embedding_profile": {
|
||||
"type": "string"
|
||||
},
|
||||
"chunk_profile": {
|
||||
"type": "string"
|
||||
},
|
||||
"published_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user