Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Binding Contracts And Roadmap

AHRI_TRE_RS is designed so language bindings stay thin. Bindings should expose the application services through stable interface contracts; they should not create a second domain model, a second persistence format, or a second control plane for each client language.

ADR-0005 sets the repository boundary for those bindings. Full Python, Julia, and R package implementations live in separate repositories:

LanguageExternal repository seed
Pythonahri-tre-py
Juliaahri-tre-jl
Rahri-tre-r

This Rust workspace owns the public protocol, stable C ABI, Client bootstrap runtime, runtime artifacts, package manifests, compatibility fixtures, and wrapper-author contract. The language repositories own package code, language-specific CI, publication, documentation, dataframe ergonomics, and ongoing host-language issue tracking. The shared Binding Repository Seed Contract is the handoff contract each external repository consumes.

Shared Boundary Model

ConcernBinding contract
In-memory tabular boundaryApache Arrow RecordBatch values
Persisted analytical datasetsParquet
Binary tabular transportArrow IPC stream or file
Command, status, and metadata responsesJSON over HTTP
Client dataframesLocal language representations only

The Rust workspace treats Arrow as the neutral tabular boundary. Python, Julia, and R users may naturally work with pandas, Polars, Julia DataFrame, Arrow.jl tables, tibbles, or R data.frame values, but those are binding-local representations. They are adapters around the shared Arrow, Parquet, Arrow IPC, and JSON contracts rather than canonical wire or storage models.

This keeps the Rust service independent of any single client dataframe library and lets each binding choose idiomatic conversion points without changing the core workflow semantics.

Implemented Foundation

The binding foundation currently exists below the language wrapper layer:

  • ahri_tre_tabular owns reusable Arrow RecordBatch validation, Parquet read/write helpers, Arrow IPC helpers, and AHRI_TRE Arrow metadata handling.
  • ahri_tre_app owns workflow-facing services that bindings should call through a stable lower-level interface instead of reimplementing workflows.
  • ahri_tre_protocol, ahri_tre_daemon, and ahri_tre_cli provide the local JSON/control-plane direction over app workflows. The final JSON-over-HTTP service remains roadmap work.
  • ahri_tre_ffi_c exposes the stable C protocol-adapter ABI: startup introspection, immutable Client bootstrap selection, opaque client/session/result handles, authenticated Trusted-runtime protocol JSON execution, response JSON access, optional attached payload access, and matching cleanup functions. It intentionally exposes no local daemon lifecycle or transport overrides and is not one C function per workflow.
  • ahri_tre_python, ahri_tre_julia, and ahri_tre_r are scaffold crates retained only as transitional workspace placeholders and compatibility shims. Their exported Rust functions are not public language APIs and should not grow into package implementations in this repository.

C ABI First

The stable C ABI is the implemented language-neutral low-level interface. It defines:

  • opaque handles for sessions and result objects
  • explicit memory ownership and cleanup rules
  • stable error and diagnostic envelopes
  • JSON control-plane payload exchange for commands and metadata
  • Arrow IPC or file-oriented handles for tabular payloads
  • smoke tests proving the ABI is usable outside Rust

The C ABI is stable enough for Python, Julia, and R wrappers to share. The wrappers can focus on idiomatic packaging and dataframe conversion rather than each binding discovering its own unsafe Rust boundary.

Wrapper and C ABI compatibility checks should use Protocol version compatibility, not the Rust crate version, Rust package version, C ABI library identity, or host-language package version. Local installations expose that contract through ahri-tre version --format json: the JSON version field identifies the CLI executable package, C ABI startup introspection identifies the loaded shared library and ABI surface, each language package has its own ecosystem version, and protocol.current plus protocol.compatibility identify the public control-plane contract the executable speaks.

Wrapper authors can inspect the same JSON payload contract through ahri-tre schema list --format json and ahri-tre schema get <schema-id> --format json. The protocol schema IDs, such as protocol.response-envelope.v2, protocol.dataset.catalog.v2, and protocol.semantic-model.catalog.v2, are the binding-facing DTO contract for control-plane responses. They are useful for generated typed result objects, contract fixtures, and cross-language smoke tests, while Arrow IPC and Parquet remain the data-plane contracts for tabular payloads.

Backlog: P1.21 Build stable C ABI.

Language Wrapper Roadmap

BindingCurrent statusIntended first useful surface
PythonExternal seed repository plus transitional scaffold crateahri-tre-py consumes staged runtime artifacts, implements the wrapper API, and runs contract smoke tests outside this workspace.
JuliaExternal seed repository plus transitional scaffold crateahri-tre-jl consumes staged runtime artifacts, implements the wrapper API, and runs contract smoke tests outside this workspace.
RExternal seed repository plus transitional scaffold crateahri-tre-r consumes staged runtime artifacts, implements the wrapper API, and runs contract smoke tests outside this workspace.
CFirst stable generic protocol adapterGenerated header, startup introspection, client/session/result lifecycle, response JSON and optional payload access, ownership rules, and smoke tests.

The first useful Rust-workspace outcome for each host language is a seed and contract handoff: artifact discovery, protocol compatibility checks, managed runtime lifecycle coverage, generic protocol JSON execution, safe diagnostics, payload handling, and smoke fixtures. Full host-language APIs, dataframe conversion matrices, package-manager checks, documentation sites, CI matrices, and publication workflows belong in the external binding repositories.

C ABI Wrapper Author Contract

The stable C ABI is the layer Python, Julia, R, and other wrappers should bind to before exposing idiomatic host-language APIs. Wrapper startup should inspect the loaded library with ahri_tre_abi_version() and ahri_tre_library_version(), then decide behavioral compatibility from ahri_tre_protocol_version(), ahri_tre_protocol_compatibility_minimum(), ahri_tre_protocol_compatibility_maximum(), and ahri_tre_protocol_compatibility_rule(). Wrappers should fail fast when their required protocol support is outside that range; package and crate versions are support metadata, not the protocol compatibility contract.

The ABI owns unsafe-boundary lifecycle only. Client handles wrap adapter state, session handles wrap selected session context, and result handles own protocol response JSON plus any attached payload descriptors or bytes. Borrowed response JSON, payload descriptor strings, and borrowed byte views stay valid only until the owning result handle is freed. Owned string and byte copies must be released with ahri_tre_string_free() and ahri_tre_bytes_free() respectively. Daemon-backed data-plane outputs use those result-owned payload accessors for Arrow IPC bytes and descriptor-only export artifacts; runtime target paths and lake internals are not wrapper-facing data.

Cleanup functions accept NULL as a no-op. Double-free, freeing foreign pointers, freeing with the wrong function, freeing copied bytes with the wrong length, and concurrent mutation or cleanup of the same handle are caller errors. First-stable same-handle concurrent use is not thread-safe unless a future ABI symbol explicitly documents otherwise.

Wrapper construction accepts only optional Client bootstrap selection. A wrapper passes an explicit projected document through client_bootstrap_path or leaves it NULL for /etc/ahri-tre/client.toml. Construction validates Deployment identity, Trusted-runtime origin, and TLS trust before returning the opaque handle. Profiles are server-discovered and selected by logical identifier. Explicit selection failures do not fall back. Wrappers must not reintroduce endpoint, local daemon, binary override, never-start, or auto-start configuration above ABI v2.

Workflow semantics stay in public protocol envelopes. C callers submit serialized protocol request JSON with ahri_tre_client_execute_protocol_json() or ahri_tre_session_execute_protocol_json() and read the returned protocol response JSON from the result handle. Python, Julia, and R packages may add typed convenience functions above that generic layer, but those functions should generate protocol requests and parse protocol responses rather than depending on a workflow-specific C ABI.

New TRE workflow semantics must land in ahri_tre_app and ahri_tre_protocol first. A language wrapper may expose a convenient host API only after the behavior is available through the shared protocol contract.

The dedicated book chapter Stable C ABI explains the ABI’s functioning and wrapper-author contract in more detail. The generated header and minimal C examples live in crates/ahri_tre_ffi_c.

External Python, Julia, and R repositories must also follow the shared Binding Repository Seed Contract. That contract is the discoverable handoff for ADR-0005: it defines the runtime artifact layout, manifest discovery rules, protocol compatibility checks, Client bootstrap policy, C ABI ownership rules, redaction expectations, payload handling, development overrides, and representative smoke scenarios that every language repository should share.

Backlog:

Binding Rules

Bindings should preserve the same architectural boundaries as the Rust workspace:

  • domain types remain free of runtime database, lake, or OAuth handles
  • application workflows remain the semantic source of truth
  • PostgreSQL metadata access remains behind the libpq-based adapter
  • DuckDB, DuckLake, and Lake location logic remain behind the lake adapter
  • OAuth/OIDC behavior stays separate from libpq wiring
  • JSON control-plane responses remain machine-readable and stable
  • dataframe conversion happens at the edge of each language binding

These rules are especially important while the binding crates are still scaffolds. A thin wrapper is allowed to make AHRI_TRE convenient in a host language; it is not allowed to bypass governance, provenance, datastore session, or lake semantics.

Protocol 2 cutover

Current source clients require protocol 2.0.0 (minimum and maximum), independently of C ABI 2 and package 0.11.0. Match a source-built library and CLI by revision and artifact digest; old released runtime artifacts do not acquire v2 support through a package-version comparison. Read streaming results through the verified empty completion using the existing content-transfer API.

The Rust Python/R/Julia crates and bindings/ folders are placeholders. ADR-0005 seed directories under tmp/ are absent in this checkout; no new host-language wrapper or native artifact publication is claimed. The implemented Python ctypes qualification consumer uses the exported C functions and protocol introspection. External packages must adopt these same references, Session semantics and stream ownership before declaring support for a v2 runtime artifact.