Files
0pt/src/types/external-writeback.ts
T
adminandClaude Sonnet 5 c89731115c feat: add 0pt.query_source, 0pt.document_ocr, 0pt.write_external_record capabilities
Three new, tenant-agnostic P0 capabilities:

- 0pt.query_source: bounded, timeout/row-capped ad-hoc SQL query execution
  against registered database sources, via a Fabric/OneLake adapter
  (Azure AD credential-based mssql connection), with AUD0 audit events
  and an app/api/0pt/sources/[sourceId]/query endpoint.

- 0pt.document_ocr (document capture + extraction): mailbox-based document
  intake via Microsoft Graph, OCR/field extraction via Azure Document
  Intelligence, with capture/extraction API endpoints and services that
  never fabricate extracted values.

- 0pt.write_external_record (external writeback): a generic writeback-adapter
  contract plus a concrete Odoo bills adapter that matches partners via
  Fabric, backing an external-writeback-service for pushing records to
  downstream systems of record.

Known interim gaps:
- src/adapters/local-blob-store.ts is an interim ST0RE substitute pending
  the real ST0RE artifact-store integration.
- mssql is used by the Fabric/OneLake adapter but deliberately not yet
  added to package.json (pending `pnpm add mssql` once the concurrent
  session's package.json/dependency changes settle).

A separate, concurrently-active session has unrelated in-flight changes
in this same working tree (data-platform catalog/lineage/feature-store,
dataset quality, lakehouse/Iceberg docs, deploy scaffolding, package.json/
pnpm-lock.yaml updates, etc.) — none of that is touched or included here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 19:32:43 +02:00

63 lines
2.7 KiB
TypeScript

/**
* src/types/external-writeback.ts
* =================================
* Types for `0pt.write_external_record` -- "POST a validated, already-
* approved structured record to a registered external-system adapter."
* See ../services/external-writeback-service.ts for the service that
* implements this capability and ../adapters/writeback-adapter.ts for the
* adapter interface any external system plugs into.
*/
export type ExternalWriteStatus = "claimed" | "written" | "failed" | "skipped_duplicate";
/**
* One request to write a record to an external system. Deliberately generic
* -- nothing here is Odoo/invoice/Protosell-shaped. `payload` is whatever
* structured record the caller (e.g. an ACT0 workflow's 'write_record' step,
* or a direct API call) has already validated/approved; the registered
* adapter for `adapter_id` is solely responsible for interpreting it.
*/
export interface ExternalWriteRequest {
/** Which registered WritebackAdapter (../adapters/writeback-adapter.ts) handles this write,
* e.g. "odoo_bills". Looked up via ExternalWritebackService.registerAdapter. */
adapter_id: string;
/**
* Caller-supplied stable key that is the SAME across retries of "the same logical write" --
* e.g. a document_extraction_id, or an upstream system's own row id. This is what makes
* `writeExternalRecord` idempotent: calling it twice with the same (adapter_id,
* idempotency_key) pair never produces two external writes. See
* ExternalWritebackService's own module doc comment for the exact claim mechanism this
* ports forward from v0-datahub's proven invoice-bridge.ts Postgres-row CLAIM pattern.
*/
idempotency_key: string;
/** Free-form record-type tag the adapter interprets, e.g. "vendor_bill". Not validated by
* the generic service -- purely forwarded to the adapter. */
record_type: string;
/** The structured record itself -- adapter-specific shape, opaque to the generic service. */
payload: Readonly<Record<string, unknown>>;
tenant_id: string;
project_id: string;
actor_id: string;
correlation_id: string;
}
/** Persisted record of one write attempt (or claim) -- the generic service's own bookkeeping,
* independent of whatever the adapter itself may also persist. */
export interface ExternalWriteRecord {
write_id: string;
adapter_id: string;
idempotency_key: string;
record_type: string;
status: ExternalWriteStatus;
/** The external system's own id for the created record (e.g. an Odoo account.move id),
* populated once status is "written". */
external_id?: string;
error?: string;
tenant_id: string;
project_id: string;
actor_id: string;
correlation_id: string;
created_at: string;
updated_at?: string;
}