// The procedure contracts of the archive module: schemas and names, no handler and no port. // // The module is a client of the platform's Archive service (B-wave contract ยง3.14): documents, their // versions and their retention live there, in the deployment's organization, and the bytes in the // platform's Blob store. A read reads; a change is an `effect` (it calls an external service and writes // nothing of this app's own). A version is made from a file the project holds, so a procedure names a // `fileId`, never a hash or a Blob reference of the caller's. The service's int64 fields are their digits // here, so what a page loads is JSON. import { procedure } from "@conusai-kit/core" import { z } from "zod" import { ARCHIVE_PERMISSIONS, RETENTION_BASES } from "./constants.js" const inProject = { org: z.string(), workspace: z.string(), project: z.string() } const page = { after: z.string().max(128).optional(), limit: z.number().int().min(1).max(200).optional() } /** What a form generates once per submission, so a retried request applies once. */ const requestId = z.string().uuid() const documentId = z.string().min(1).max(64) const fileId = z.string().uuid() /** A revision as its digits: the service's are 64-bit. */ const revision = z.string().regex(/^\d{1,19}$/) export const documentViewSchema = z.object({ documentId: z.string(), title: z.string(), /** An optional UNTDID 1001 document code. */ kind: z.string().nullable(), retentionClass: z.string(), legalHold: z.boolean(), status: z.enum(["active", "disposed"]), /** Whether the document is past changing: disposed, or erased. */ disposed: z.boolean(), revision, createdAt: z.string(), lastVersionAt: z.string(), disposedAt: z.string().nullable(), }) export type DocumentView = z.output export const versionViewSchema = z.object({ versionId: z.string(), sequence: z.number().int(), sha256: z.string(), mediaType: z.string(), /** Bytes, as digits. */ size: z.string(), createdAt: z.string(), }) export type VersionView = z.output export const retentionClassViewSchema = z.object({ code: z.string(), keepFor: z.string(), from: z.enum(RETENTION_BASES), createdAt: z.string(), }) export type RetentionClassView = z.output /** A version's immutable facts, as the use cases take them from the stored file. */ export interface VersionFacts { readonly sha256: string readonly mediaType: string readonly size: number readonly blobRef: string } const receipt = z.object({ documentId: z.string(), revision }) export type DocumentReceipt = z.output const documentPage = z.object({ rows: z.array(documentViewSchema), after: z.string().optional() }) export const documentList = procedure("archive.document.list") .kind("read") .scope("project") .permission(ARCHIVE_PERMISSIONS.read) .input(z.object({ ...inProject, q: z.string().max(200).optional(), ...page })) .output(documentPage) .contract() export const documentGet = procedure("archive.document.get") .kind("read") .scope("project") .permission(ARCHIVE_PERMISSIONS.read) .input(z.object({ ...inProject, documentId })) .output(z.object({ document: documentViewSchema, versions: z.array(versionViewSchema) })) .contract() export const documentRegister = procedure("archive.document.register") .kind("effect") .scope("project") .permission(ARCHIVE_PERMISSIONS.write) .input( z.object({ ...inProject, title: z.string().trim().min(1).max(200), kind: z .string() .regex(/^\d{1,4}$/) .optional(), retentionClass: z.string().min(1).max(64), fileId, requestId, }), ) .output(receipt) .contract() export const versionAdd = procedure("archive.version.add") .kind("effect") .scope("project") .permission(ARCHIVE_PERMISSIONS.write) .input(z.object({ ...inProject, documentId, revision, fileId, requestId })) .output(receipt) .contract() export const documentHold = procedure("archive.document.hold") .kind("effect") .scope("project") .permission(ARCHIVE_PERMISSIONS.manage) .input(z.object({ ...inProject, documentId, revision, legalHold: z.boolean(), requestId })) .output(receipt) .contract() export const documentDispose = procedure("archive.document.dispose") .kind("effect") .scope("project") .permission(ARCHIVE_PERMISSIONS.manage) .input(z.object({ ...inProject, documentId, revision, requestId })) .output(receipt) .contract() export const retentionList = procedure("archive.retention.list") .kind("read") .scope("project") .permission(ARCHIVE_PERMISSIONS.read) .input(z.object({ ...inProject, ...page })) .output(z.object({ rows: z.array(retentionClassViewSchema), after: z.string().optional() })) .contract() export const retentionCreate = procedure("archive.retention.create") .kind("effect") .scope("project") .permission(ARCHIVE_PERMISSIONS.manage) .input( z.object({ ...inProject, code: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/), /** An ISO 8601 duration such as P10Y; the service reads it. */ keepFor: z.string().min(2).max(64), from: z.enum(RETENTION_BASES), requestId, }), ) .output(z.object({ code: z.string() })) .contract() export const disposalList = procedure("archive.disposal.list") .kind("read") .scope("project") .permission(ARCHIVE_PERMISSIONS.read) .input(z.object({ ...inProject, ...page })) .output(documentPage) .contract()