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 Repository Seed Contract

This contract is the shared handoff surface for external AHRI TRE language binding repositories. It applies to the Python, Julia, and R repositories created from ADR-0005:

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

The language repositories own host-language package code, dependency lockfiles, CI, publication, dataframe conversion, and documentation. This Rust workspace owns the runtime artifacts, public protocol, stable C ABI, managed local runtime behavior, package manifests, fixtures, and compatibility contract that those repositories consume.

Ordinary package installation must consume prebuilt AHRI TRE runtime artifacts. It must not require Cargo, Zig, Rust toolchains, PostgreSQL development headers, this repository’s target directory, or this repository’s dev container. Developer overrides may point at a staged package or local checkout, but those overrides are for wrapper development only.

Required Runtime Artifacts

Every binding repository must be able to consume a staged or released AHRI TRE runtime package with this layout:

ahri-tre-<version>-<target>/
  bin/
    ahri-tre
    ahri-tred
  include/
    ahri_tre_ffi_c.h
  lib/
    libahri_tre_ffi_c.so or libahri_tre_ffi_c.dylib
    libduckdb.so or libduckdb.dylib
    <other bundled runtime libraries>
  share/ahri-tre/
    manifest.json
    installer.json
    README.md

The package manifest is the machine-readable contract for wrapper runtime discovery. Binding repositories should discover package-relative paths from share/ahri-tre/manifest.json and installer metadata rather than assuming Cargo target paths, repository-relative paths, or global PATH entries.

The required wrapper-facing artifacts are:

ArtifactRequired use
Stable C ABI shared libraryLoaded by the binding as the single unsafe lower layer.
Generated C headerUsed to compile or verify the wrapper’s FFI declarations.
Client bootstrap exampleDocuments Deployment identity, Trusted-runtime origin, TLS trust, and profile selection without embedding credentials.
Support filesPackage README, installer metadata, and dependency reports used for diagnostics and setup.
Manifest metadataschema_version, package version, target, platform, C ABI artifacts, runtime libraries, validation commands, and installer/runtime discovery paths.
Bundled runtime librariesDuckDB and any other redistributable libraries needed by the C ABI, CLI, daemon, or wrapper runtime.

Package-relative paths in manifests and installer metadata must not expose Restricted local references. Binding packages may copy, bundle, or depend on these runtime artifacts according to their language ecosystem, but they should keep the same artifact names and discovery semantics.

Protocol Compatibility

Protocol compatibility is the behavioral compatibility boundary. Binding package versions do not need to move in lockstep with the Rust workspace, runtime package version, CLI version, or C ABI crate version.

At startup, a binding must load the C ABI library and inspect:

  • ahri_tre_abi_version()
  • ahri_tre_library_version()
  • ahri_tre_protocol_version()
  • ahri_tre_protocol_compatibility_minimum()
  • ahri_tre_protocol_compatibility_maximum()
  • ahri_tre_protocol_compatibility_rule()

Each binding release must declare:

  • the AHRI TRE protocol version range it supports
  • the runtime artifact version it bundles or expects
  • the C ABI surface version it was written against

The binding should fail fast when the loaded runtime’s protocol range does not cover the binding’s required public protocol behavior. Library package versions and language package versions are support and provenance metadata; they are not substitutes for protocol compatibility checks.

Host-language convenience functions must generate public protocol request JSON and parse public protocol response JSON. New datastore, governance, provenance, lake, or workflow semantics must be added to the app and protocol layers in this Rust workspace before a binding exposes them.

Client Bootstrap And Trusted Runtime

A binding exposes optional explicit Client bootstrap selection at construction. Omission selects /etc/ahri-tre/client.toml; an explicit missing or invalid document fails without fallback. The C ABI validates Deployment identity, Trusted-runtime HTTPS origin, and TLS trust, then retains the immutable transport capability in its opaque client and session handles. Profiles are server-discovered and selected by logical identifier.

Binding repositories must not recreate the removed local runtime surface. They do not expose endpoint-only or never-start modes, daemon binary overrides, daemon discovery, local auto-start, or runtime lifecycle helpers. Protocol operations and profile selection go through the authenticated Trusted runtime described by the selected Client bootstrap.

C ABI Ownership And Concurrency

The C ABI owns unsafe-boundary memory and handle rules. Each binding must wrap those rules in idiomatic host-language objects without weakening them.

ValueOwnerCleanup
ahri_tre_client *Caller after successful client creationahri_tre_client_free()
ahri_tre_session *Caller after successful session selectionahri_tre_session_close()
ahri_tre_result *Caller after execution, selection, or lifecycle helper successahri_tre_result_free()
Owned stringsCallerahri_tre_string_free()
Owned byte buffersCallerahri_tre_bytes_free(ptr, len) with the exact returned length

Borrowed JSON strings, payload descriptor strings, and borrowed payload bytes are valid only until the owning result handle is freed. Bindings must copy data before releasing the result when host-language objects need to outlive the call scope.

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. Different handles may be used concurrently only within the guarantees of the daemon and selected-session layer.

Host-language finalizers should be defensive cleanup aids, not the primary runtime ownership model. They may release client, session, result, string, and byte-buffer resources; they must not stop the user-scoped daemon unless the user explicitly requested a runtime stop operation.

Safe Diagnostics

Binding diagnostics should preserve the structured AHRI TRE protocol and lifecycle failure shapes while keeping sensitive material out of logs, exceptions, test snapshots, and package artifacts.

Diagnostics must not expose:

  • raw request bodies
  • passwords, OAuth tokens, refresh tokens, bearer tokens, passfiles, or credential material
  • raw PostgreSQL connection strings that contain secrets
  • Restricted local references or developer workstation paths
  • lake internals, DuckLake catalog internals, runtime storage roots, sockets, or secret-bearing runtime paths
  • raw handle addresses or other process-local implementation details

Wrappers should surface safe fields from public protocol failure envelopes, safe protocol warnings, ABI status classes, and private lifecycle diagnostics. When a wrapper adds host-language exceptions or logs, the exception message should remain useful without reintroducing secrets or local runtime internals.

Payload Handling

Control-plane requests and responses use JSON. Large or tabular payloads use protocol data-plane references plus Arrow IPC, Parquet, or descriptor-only export artifacts.

Bindings should:

  • inspect protocol response JSON before assuming a payload exists
  • inspect ahri_tre_result_payload_count() and payload descriptors
  • accept descriptor-only payloads as valid results
  • copy borrowed payload bytes before freeing the result when needed
  • convert Arrow IPC bytes to host-language dataframe objects at the binding edge
  • keep Parquet as the durable exported dataset format

Payload descriptors may contain safe protocol refs, media types, suggested names, sizes, and byte-availability flags. They must not contain runtime Lake locations, datastore connection details, credentials, or local temporary paths.

Development Overrides

The ordinary binding install path is a prebuilt runtime artifact. Development overrides are allowed only as explicit local-development hooks.

A binding repository may support overrides for:

  • a local staged runtime package under dist/
  • an unpacked release archive
  • a local C ABI shared library and generated header
  • an explicit projected Client bootstrap fixture

Override configuration must be visibly separate from normal package discovery. Bindings may use their own visibly test-only runner inputs, but never a retired AHRI TRE product name or ordinary package-discovery fallback. Override diagnostics should report the override class without leaking Restricted local references or secret-bearing locations.

Representative Smoke Scenarios

Every binding repository should include a small smoke suite that can run against a staged or released AHRI TRE runtime artifact without cloning this Rust workspace.

The shared smoke expectations are:

ScenarioMinimum assertion
ABI and protocol introspectionThe binding loads the C ABI library, reads ABI/library/protocol compatibility fields, and rejects an unsupported range.
Client bootstrapExplicit and canonical-default selection validate Deployment, origin, and TLS trust; explicit failure never falls back.
Trusted-runtime transportA profile request reaches the authenticated HTTPS origin with the selected Deployment and produces a protocol response.
Protocol JSON executionA representative public protocol request returns a protocol response envelope through a client or selected-session handle.
Failure envelope parsingAn invalid or unauthorized representative request yields a protocol-shaped failure that the binding surfaces without treating ABI status as workflow status.
Arrow IPC payload accessA representative tabular response exposes Arrow IPC bytes or a safe descriptor that the binding can convert at the host-language edge.
Ownership cleanupClient, session, result, string, and byte-buffer cleanup paths do not leak or double-free during normal and error flows.
RedactionLogs, exceptions, snapshots, and diagnostics omit credentials, raw request bodies, Restricted local references, lake internals, and secret-bearing runtime paths.

These smoke tests prove the shared contract. Full host-language API coverage, dataframe conversion matrices, package-manager checks, and publication workflows belong in each external binding repository.

Seed Repository Checklist

Each external seed repository should start with:

  • a language-native package skeleton
  • a .devcontainer/ folder for that language and its tools
  • a PostgreSQL service modelled on this repository’s development environment
  • an Application-selected Lake mount at the canonical container-visible path
  • runtime artifact discovery code based on package manifests and installer metadata
  • C ABI declarations generated from or checked against ahri_tre_ffi_c.h
  • a thin unsafe wrapper layer with deterministic cleanup
  • protocol compatibility checks at startup
  • private runtime lifecycle helpers
  • generic public protocol JSON execution helpers
  • Arrow IPC and Parquet payload entrypoints
  • smoke scripts for the representative scenarios above
  • handoff documentation that points back to this contract, ADR-0004, ADR-0005, the C ABI chapter, and the installation package guide

After seeding, ongoing package implementation should happen in the external repository’s issue tracker rather than in this Rust workspace.