69 lines
2.9 KiB
TypeScript
69 lines
2.9 KiB
TypeScript
// The tables of the knowledge module. Three.
|
|
//
|
|
// `knowledge_collection` is one named collection of documents, project-owned; the collection name
|
|
// is the slug procedures take (a procedure's input carries slugs, never ids). `knowledge_document`
|
|
// is one file's indexing state in one collection — the row the UI's progress states read, and the
|
|
// idempotency key of the index job (a file is indexed into a collection once, and re-indexing the
|
|
// same pair resumes the one row). `knowledge_config` is the organization's enablement state: the
|
|
// durable answer to "is document AI on", which backend serves it and where the managed vector
|
|
// service was linked. No secret ever lands here: the Qdrant API key lives in the deployment
|
|
// environment, not in a tenant row.
|
|
|
|
import { defineEntity, idSchema, instantSchema } from "@conusai-kit/data"
|
|
import { z } from "zod"
|
|
import { DOCUMENT_STATUSES } from "./statuses.js"
|
|
|
|
export const collections = defineEntity({
|
|
name: "collection",
|
|
table: "knowledge_collection",
|
|
tenancy: "project",
|
|
fields: {
|
|
name: z.string().min(1).max(100),
|
|
createdBy: z.string().min(1).max(128),
|
|
},
|
|
unique: [["name"]],
|
|
})
|
|
|
|
export const documents = defineEntity({
|
|
name: "document",
|
|
table: "knowledge_document",
|
|
tenancy: "project",
|
|
fields: {
|
|
collectionName: z.string().min(1).max(100),
|
|
/** The row of the files module this document indexes: an opaque id, never a foreign key. */
|
|
fileId: idSchema,
|
|
filename: z.string().min(1).max(255),
|
|
status: z.enum(DOCUMENT_STATUSES),
|
|
/** A stable failure code when the indexing failed; null otherwise. */
|
|
error: z.string().max(200).nullable(),
|
|
indexedAt: z.string().nullable(),
|
|
requestedBy: z.string().min(1).max(128),
|
|
},
|
|
// One row per (collection, file): a re-index resumes the same row instead of duplicating it.
|
|
unique: [["collectionName", "fileId"]],
|
|
indexes: [["collectionName"]],
|
|
})
|
|
|
|
export const config = defineEntity({
|
|
name: "config",
|
|
table: "knowledge_config",
|
|
tenancy: "org",
|
|
fields: {
|
|
enabled: z.boolean(),
|
|
/** Which search backend serves this organization: the local vector store or the managed service. */
|
|
backend: z.enum(["vectors", "platform"]),
|
|
/** Where the vector backing came from: an operator-configured endpoint or a managed link. */
|
|
source: z.enum(["operator", "managed"]),
|
|
/** The linked managed service's id, when source is managed. */
|
|
serviceId: z.string().max(128).nullable(),
|
|
/** The operator- or link-configured endpoint, when there is one to show. Never a key. */
|
|
url: z.string().max(500).nullable(),
|
|
updatedBy: z.string().min(1).max(128),
|
|
/** When the configuration last changed; the managed updated_at is the row's own bookkeeping. */
|
|
configuredAt: instantSchema,
|
|
},
|
|
})
|
|
|
|
/** Every table this module owns, in the order a migration creates them. */
|
|
export const KNOWLEDGE_ENTITIES = Object.freeze([collections, documents, config])
|