core/abi/proto/v1/db.proto
Alex Dunmow 704b046727 feat(abi): wasm plugin ABI protobuf schema v1 (WO-WZ-001)
Defines the host<->guest wire contract for the .so -> wazero migration as a
repo-local buf module (abi/proto/v1, generated Go in abi/v1):

- manifest.proto: PluginManifest mirroring every static field of
  plugin.PluginRegistration (abi_version, deps, block/template registrations,
  admin pages, settings schema, theme presets, fonts, master pages, AI
  actions, RBAC method roles, CSS manifest, icon packs, directory
  extensions, job types, RAG fetcher types, settings panel, hook flags,
  core service bindings)
- invoke.proto: bn_invoke envelope, Hook catalog (RENDER_BLOCK,
  RENDER_TEMPLATE, HANDLE_HTTP, JOB, LOAD, UNLOAD, RAG_FETCH, MEDIA_HOOK,
  DESCRIBE), AbiError, and job/lifecycle/rag/media/describe payloads
- render.proto: RenderBlock/RenderTemplate payloads + RenderContext
  enumerating every ctx value from blocks/context.go (incl. BlockContext 1:1)
- http.proto: buffered HttpRequest/HttpResponse for HANDLE_HTTP
- db.proto: guest sql-driver messages (DbValue oneof over pgx-mappable
  types, query/exec/tx with host-side tx handles, SQLSTATE-carrying DbError)
- capability.proto: HostCall envelope + one request/response pair per
  CoreServices interface method (content, settings+update, gating, crypto,
  menus, datasources, users, subscriptions, media.deposit, email.send,
  ai.text_call, ai.tools.register, bridge, jobs.submit, embeddings, rag,
  reviews, badges.refresh)

The abi/ buf module is deliberately separate from the repo-root config:
proto/ is the shared block/proto submodule (service API contracts); the ABI
is SDK-internal and versions in lockstep with the guest shim. New `make abi`
target runs buf lint + generate. docs/wasm-abi.md documents the ptr+len
calling convention (bn_alloc, bn_invoke, packed u64), hook catalog, error
semantics, abi_version evolution rules, and the full registration/
CoreServices coverage tables.

Verified: `cd abi && buf lint` exit 0; `go build ./...` exit 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:47:00 +08:00

109 lines
2.7 KiB
Protocol Buffer

// db.proto — DB driver messages (WO-WZ-001).
//
// The guest SDK ships a database/sql driver that marshals query text + args
// out through these messages and rows back, so sqlc-generated plugin code
// works unchanged. The host executes on a connection under the per-plugin
// Postgres role. Transactions map to a host-side handle held per guest call
// chain, with a hard deadline so a guest can never pin a connection.
syntax = "proto3";
package abi.v1;
import "google/protobuf/timestamp.proto";
option go_package = "git.dev.alexdunmow.com/block/core/abi/v1;abiv1";
// DbValue is one pgx-mappable parameter or column value.
message DbValue {
oneof kind {
// SQL NULL (the bool carries no information; true by convention).
bool null = 1;
bool bool_value = 2;
int64 int64_value = 3;
double float64_value = 4;
string string_value = 5;
bytes bytes_value = 6;
google.protobuf.Timestamp timestamp_value = 7;
// UUID in canonical string form.
string uuid_value = 8;
// JSON/JSONB payload bytes.
bytes jsonb_value = 9;
// NUMERIC in decimal string form (lossless).
string numeric_value = 10;
// text[] array.
TextArray text_array_value = 11;
}
}
// TextArray is a Postgres text[] value.
message TextArray {
repeated string values = 1;
}
// DbRow is one result row; values align with DbRowsResponse.columns.
message DbRow {
repeated DbValue values = 1;
}
// DbError carries a database failure back to the guest driver.
message DbError {
// Postgres SQLSTATE when available (e.g. "23505"); empty otherwise.
string code = 1;
string message = 2;
}
// DbQueryRequest executes a rows-returning statement.
message DbQueryRequest {
string sql = 1;
repeated DbValue args = 2;
// Transaction handle from DbTxBeginResponse; 0 = no transaction
// (autocommit).
uint64 tx_handle = 3;
}
// DbRowsResponse returns the full buffered result set.
message DbRowsResponse {
repeated string columns = 1;
repeated DbRow rows = 2;
DbError error = 3;
}
// DbExecRequest executes a statement without returning rows.
message DbExecRequest {
string sql = 1;
repeated DbValue args = 2;
// Transaction handle from DbTxBeginResponse; 0 = no transaction.
uint64 tx_handle = 3;
}
message DbExecResponse {
int64 rows_affected = 1;
DbError error = 2;
}
// DbTxBeginRequest opens a host-side transaction for this call chain.
message DbTxBeginRequest {}
message DbTxBeginResponse {
// Opaque handle referencing the host-side transaction; never 0 on success.
uint64 tx_handle = 1;
DbError error = 2;
}
message DbTxCommitRequest {
uint64 tx_handle = 1;
}
message DbTxCommitResponse {
DbError error = 1;
}
message DbTxRollbackRequest {
uint64 tx_handle = 1;
}
message DbTxRollbackResponse {
DbError error = 1;
}