Express intent
Upload a file, upsert/select an entity, grant a role, subscribe to events. App code supplies business inputs, not internal table rows or protobuf plumbing.
Every SDK is generated from the same proto descriptor and held to one cross-language
conformance contract: identical metadata headers, credential handling, authz-cache semantics, and
refresh single-flight behavior. udb sdk generate regenerates all six from the embedded
descriptor set.
import os from udb_client.project import UdbProject with UdbProject.connect( target="127.0.0.1:50051", tenant_id="acme", project_id="billing", bearer_token=os.environ["UDB_TOKEN"], ) as udb: pdf = open("invoice.pdf", "rb").read() udb.storage.upload_file("invoice.pdf", pdf, {"content_type": "application/pdf"}) udb.authz.allow_role("reader", "invoice", "data.select") rows = udb.data.table("invoice").select(where={"status": "open"})
import ( "os" udb "github.com/fahara02/udb/sdk/go/udbclient" ) project, _ := udb.Connect(ctx, udb.Config{ Target: "127.0.0.1:50051", TenantID: "acme", ProjectID: "billing", Credentials: udb.Credentials{Bearer: os.Getenv("UDB_TOKEN")}, }) defer project.Close() pdf, _ := os.ReadFile("invoice.pdf") _, _ = project.Storage.UploadFile(ctx, "invoice.pdf", pdf, udb.WithContentType("application/pdf")) invoices := project.Entity("invoice", udb.Key("invoice_id")) rows, _ := invoices.Select(ctx, map[string]any{"status": "open"})
import { readFile } from "node:fs/promises"; import { UdbProject } from "@udb_plus/sdk"; const udb = await UdbProject.connect({ target: "127.0.0.1:50051", tenantId: "acme", projectId: "billing", credentials: { bearerToken: process.env.UDB_TOKEN }, }); const pdf = await readFile("invoice.pdf"); await udb.storage.uploadFile("invoice.pdf", pdf, { contentType: "application/pdf" }); await udb.authz.allowRole("reader", { resource: "invoice", action: "data.select" });
use Fahara02\UdbLaravel\UdbProject; $udb = UdbProject::connect([ 'target' => '127.0.0.1:50051', 'tenantId' => 'acme', 'projectId' => 'billing', 'credentials' => ['bearerToken' => getenv('UDB_TOKEN')], ]); $pdf = file_get_contents('invoice.pdf'); $udb->storage()->uploadFile('invoice.pdf', $pdf, ['contentType' => 'application/pdf']); $udb->authz()->allowRole('reader', [ 'resource' => 'invoice', 'action' => 'data.select', ]);
The simple client is a thin workflow layer over served RPCs. It should make normal app code short, but it must not become a second protocol or move broker invariants into client conventions.
Upload a file, upsert/select an entity, grant a role, subscribe to events. App code supplies business inputs, not internal table rows or protobuf plumbing.
Own workflow helpers, byte transfer, token/session handling, typed errors, read-fence helpers, generated entity APIs, and exact sequence tests.
Own tenant/project authority, RLS, object placement, lifecycle state, idempotency, read-after-write guarantees, and fail-closed security decisions.
Descriptors and manifests drive SDK surfaces, operation kind, retry boundaries, entity metadata, native service recipes, and benchmark fixtures.
Advanced deployments: add authTarget/auth_target when the native control-plane listener is separate from the data-plane target. Add explicit scopes, purpose, deadlines, and raw generated RPC calls when building admin tools, benchmarks, or integrations that need exact protocol access.
The simple-client plan changes the docs priority: lead with workflow helpers for common product code, then show the raw generated clients as an escape hatch. These helpers are thin wrappers over served UDB RPCs and each has sequence tests so the SDK cannot hide proof reads or extra authority.
| Workflow | Use this surface | What the SDK does | What stays broker-owned |
|---|---|---|---|
| Upload bytes | storage.uploadFile / upload_file | Register upload, PUT to broker-minted URL, finalize. | Bucket choice, object key, quota, lifecycle state. |
| Download file | storage.downloadFile | Prefer one presigned URL call; stream bytes only when requested or needed. | Access decision, file metadata, object-store authorization. |
| CRUD records | data.table("invoice") / Entity(...) | Pack filters and records into the DataBroker request shape, decode native records. | RLS, tenant/project binding, backend routing, query execution. |
| Grant a role | authz.allowRole / allow_role | Emit one CreatePolicyRule call, no hidden list/get probe. | Caller authority, policy validity, audit, effective scopes. |
| Read after write | metadata.afterWrite(receipt) | Convert the write receipt into one read fence for the next read only. | Durable visibility, wait semantics, replica safety. |
| Events | events.subscribe(topic).ready() | Open the stream and expose an explicit readiness boundary before publish. | CDC envelope order, outbox delivery, broker-side matching. |
| Advanced/admin work | generated, Raw, service stubs | Expose exact RPC access without forcing every app through raw request bodies. | Protocol contract, method security, lifecycle rules. |
// Presigned URL path: one GetDownloadUrl RPC. const link = await udb.storage.downloadFile(fileId, { expiresInMinutes: 15 }); // Fallback path: one DownloadFile stream, reassembled by the SDK. const bytes = await udb.storage.downloadFile(fileId, { stream: true });
const write = await udb.data.upsert({ message_type: "Invoice", record_json: Buffer.from(JSON.stringify(invoice)), return_record: true, }); const receipt = udb.metadata.receiptFromResponse(write); const call = receipt ? udb.metadata.afterWrite(receipt) : undefined; const rows = await udb.data.table("Invoice").select({ where: { invoice_id: invoice.invoice_id }, call, });
All six SDKs are generated from the same descriptor and participate in conformance. Publishing maturity differs by ecosystem, so the docs separate generated parity from package availability.
| Language | Generated surface | Install path | Primary facade |
|---|---|---|---|
| Go | DataBroker + native services | go get github.com/fahara02/udb/sdk/go@v0.3.6 | udbclient.Connect |
| Python | DataBroker + native services | pip install udb-client==0.3.6 | UdbProject.connect |
| TypeScript | DataBroker + native services | npm i @udb_plus/sdk@0.3.6 | UdbProject.connect |
| PHP | DataBroker + native services | composer require fahara02/udb-laravel:^0.3.6 | UdbProject::connect |
| C# | Generated client surface | dotnet add package Udb.Client --version 0.3.6 | generated client + metadata helpers |
| Java | Generated client surface | build from checkout until Maven Central publishing lands | generated client + Spring-oriented helpers |
The same x-tenant-id, x-purpose, x-correlation-id, scopes, and project headers across all six languages — bearer as authorization, API key as x-api-key.
Concurrent token refreshes collapse to one RefreshToken RPC, and the refreshed credential is hot-swapped into every outbound channel — verified per language.
A cross-language conformance runner asserts metadata, credential, authz-cache TTL, and policy-bundle-signature behavior; missing tooling or a failing suite is a release failure.
udb scaffold emits a starter project; udb sdk generate
regenerates all six clients from the descriptor; udb proto export hands you the full proto tree.