Skip to content

feat(relay): add Rust, Python, and Node clients - #714

Merged
jeremi merged 9 commits into
mainfrom
agent/relay-client
Aug 11, 2026
Merged

feat(relay): add Rust, Python, and Node clients#714
jeremi merged 9 commits into
mainfrom
agent/relay-client

Conversation

@jeremi

@jeremi jeremi commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

  • add registry-relay-client as the canonical typed Rust SDK for the complete fixed Relay V2 HTTP surface
  • add thin Node.js and Python bindings with stable types, errors, package metadata, and release artifacts
  • extract product-neutral outbound HTTP, bearer/private-key-JWT, response bounds, trace, and Problem parsing for Evidence and Relay reuse
  • add registry-relay-http-contract so the server and SDK share route, media-type, and Problem identifiers without runtime coupling
  • add a real-router SDK acceptance journey, CI routing, identifier provenance, and release packaging beginning with 0.19.1
  • add a public cross-language API reference and a Python tutorial draft; the tutorial remains hidden until a matching release wheel passes reader-mode verification

Security and behavior

  • one caller-initiated Relay exchange per method, with no redirects, ambient proxies, transport retries, automatic pagination, or schema fetching
  • strict bounded response headers and bodies, canonical W3C trace correlation, exact registered six-member Problems, strong SHA-256 ETags, and bounded Retry-After
  • bounded CA bundles and exact private-key-JWT token requests; scope, resource, and body client_id limitations are explicit
  • bounded, cycle-safe Python and JavaScript input graphs before native conversion, including subprocess regression coverage for cyclic Node inputs
  • value-free errors and redacted Debug output throughout
  • distinct list and search request types enforce the closed server contract before I/O

Verification

  • affected Rust check, test, doc, and strict clippy gates passed
  • Relay client: 13 unit, 1 contract-parity, 11 HTTP-boundary, and 3 compile-fail documentation tests passed
  • real Relay router acceptance and Relay V2 product contract gates passed
  • Node build, 20 tests, generated declaration drift, strict TypeScript, license, and package checks passed
  • Python extension build, 27 tests, PEP 561 drift, license, wheel install, and offline smoke passed
  • Relay contracts, source neutrality, identifier generation, CI classifier, and release tooling tests passed
  • docs frontmatter, Markdown, Vale, full site checks, build, accessibility, IA, and link checks passed
  • independent final review found no remaining P1/P2 issues
  • cargo deny check passed advisories, bans, licenses, and sources; existing duplicate and yanked dependency warnings remain warnings

Follow-up

The Python tutorial is deliberately draft: true: v0.19.0 has no Relay client wheel, so only a local-candidate dry run was possible. Publish it after a v0.19.1 or later release provides the matching wheel and a clean reader-mode run passes.

The independent review also identified a likely pre-existing cyclic-input abort risk in the existing Evidence Node binding. It is outside this Relay package change and should receive the same bounded JavaScript graph hardening before its next release.

Comment thread crates/registry-relay-client-node/index.js Dismissed
Comment thread crates/registry-relay-client-py/tests/python/bootstrap.py Fixed
Comment thread crates/registry-relay-client-py/tests/python/test_errors.py Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f962e728d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Cargo.toml
Comment thread crates/registry-relay-client-node/client.d.ts Outdated
Comment thread crates/registry-relay-client-py/python/registry_relay_client/__init__.pyi Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b768f8565

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Cargo.toml
Comment thread crates/registry-relay-client/src/client.rs Outdated
Comment thread crates/registry-relay-client/src/client.rs Outdated
Comment thread docs/site/scripts/ops-posture-spec.test.mjs
Comment thread crates/registry-relay-client-node/client.js Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d10b77c608

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Cargo.toml
Comment thread crates/registry-relay-client-py/src/lib.rs Outdated
Comment thread crates/registry-relay-client-node/src/lib.rs
Comment thread crates/registry-relay-client/src/query.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a8b6483e47

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/registry-relay-client-node/src/lib.rs Outdated
Comment thread crates/registry-relay-client/src/query.rs Outdated
Comment thread crates/registry-relay-client-py/python/registry_relay_client/__init__.pyi Outdated
@jeremi
jeremi enabled auto-merge (squash) August 11, 2026 15:09
jeremi added 8 commits August 11, 2026 22:09
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi force-pushed the agent/relay-client branch from a8b6483 to ed81487 Compare August 11, 2026 15:10
@jeremi
jeremi disabled auto-merge August 11, 2026 15:17
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi enabled auto-merge (squash) August 11, 2026 15:32
@jeremi
jeremi merged commit ebe764f into main Aug 11, 2026
48 checks passed
@jeremi
jeremi deleted the agent/relay-client branch August 11, 2026 15:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 976a0fa72a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let (trace_id, etag) = metadata_parts(&metadata_value);
Ok(CompleteOutcome {
kind: "complete".into(),
value: serde_json::to_value(value).map_err(|_| serialization_error())?,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve 64-bit integers in Node responses

When Relay returns an integer domain property outside JavaScript's safe range, such as 9007199254740993, this serde_json::Value is handed to napi-rs while the workspace enables only async and serde-json, not napi6. In that configuration, napi-rs converts the i64 through a JavaScript Number, silently changing this example to 9007199254740992; the collection-page helpers repeat the same conversion. Relay accepts full SQLite i64 domain values, so preserve these values losslessly, such as through BigInt with matching declarations, or reject unsafe integers rather than returning corrupted records.

Useful? React with 👍 / 👎.

Comment on lines +608 to +610
|| !value
.bytes()
.all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'.' | b'_' | b'~'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce camelCase for request member names

When a caller supplies a field, list-filter, or lookup-selector name such as registration_status, this validator accepts it and the client performs authentication and HTTP I/O, but Relay deployments can only compile lower-camelCase property, filter, and selector names. Such requests therefore deterministically fail at the server (request.fields_invalid, filter.unknown_field, or an invalid lookup body). Apply Relay's valid_camel_identifier grammar here so RecordOptions::fields, ListRequest::filter, and LookupRequest::selector reject universally invalid names locally across Rust, Python, and Node.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants