Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ This repo is the single source of truth for the TrUAPI protocol. It vendors `dot
rust/crates/
truapi/ Rust trait + type definitions for protocol versions v0.1 and v0.2 (canonical)
truapi-codegen/ rustdoc JSON → TypeScript client + Rust dispatcher
truapi-macros/ #[wire(id = N)] proc-macro
truapi-macros/ #[wire(id = N)] proc-macro; SsoWire derive and
#[sso_service] for truapi-server's inter-host SSO protocol
One implementation module per macro; lib.rs holds entry points
truapi-platform/ Host syscall traits (storage, navigation, consent, ...)
truapi-provider/ network provider backends (WebSocket RPC or smoldot light-client)
truapi-server/ Rust runtime hosts implement; ships as WASM (browser/node)
Expand Down
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ See [`js/packages/truapi/README.md`](js/packages/truapi/README.md) for the full
rust/crates/
truapi/ Rust traits, versioned envelopes, and latest payload re-exports
truapi-codegen/ rustdoc JSON to TypeScript client + Rust dispatcher
truapi-macros/ #[wire(id = N)] proc-macro
truapi-macros/ TrUAPI wire annotations and inter-host SSO proc macros
truapi-platform/ Host syscall traits used by truapi-server (storage, navigation, consent, ...)
truapi-provider/ Network provider backends (WebSocket RPC or smoldot light-client)
truapi-server/ Host runtime: dispatcher, typed SCALE logic, chain signing, WASM surface
Expand All @@ -92,6 +92,8 @@ scripts/codegen.sh Regenerate the TS client from the Rust source
scripts/battery.sh Run the generated battery against both headless CLI host roles
```

See the [proc-macro guide](rust/crates/truapi-macros/README.md) for typed SSO handlers, their shared response envelope, and the macro implementation modules.

The Swift host adapter (the `TrUAPIHost` SPM package over the truapi-server
UniFFI core) lives under [`ios/truapi-host/`](ios/truapi-host), with its SPM
manifest at the repo root (`Package.swift`) so apps can consume it as a git-URL
Expand Down
3 changes: 3 additions & 0 deletions rust/crates/truapi-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }

[dev-dependencies]
trybuild = "1"

[lints]
workspace = true
80 changes: 80 additions & 0 deletions rust/crates/truapi-macros/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# TrUAPI proc macros

This crate provides TrUAPI wire annotations and versioned envelopes, plus
server-specific macros for inter-host SSO contracts.

Each macro has its own implementation module. [`lib.rs`](src/lib.rs) contains
the thin public entry points, which Rust requires at the proc-macro crate root.

| Macro | Input | Generated code |
| --- | --- | --- |
| [`service`](src/service.rs) | TrUAPI service trait | Required middleware metadata for codegen |
| [`wire`](src/wire.rs) | TrUAPI method | Wire IDs and flags for codegen |
| [`versioned_type!`](src/versioned_type.rs) | Versioned envelope declarations | SCALE enums and version conversion traits |
| [`SsoWire`](src/sso_wire.rs) | Hand-written `v1::RemoteMessage` enum | Request classification and wrapping, message names, and correlation helpers |
| [`sso_service`](src/sso_service.rs) | Dedicated inherent impl of SSO handlers | Request/response variant conversion, exhaustive dispatch, and handler reply conversion |

## Handler contract

Every method in the annotated impl is an endpoint. Its name selects a wire
request variant, its parameter declares the payload, and its return type names
the response's `Result` payload:

```rust
pub type GetAccountAliasResponse = Result<HostAccountGetAliasResponse, RingVrfError>;

#[truapi_macros::sso_service]
impl SigningHostSsoService {
async fn get_account_alias(
&self,
cx: &SsoRequestContext,
request: ProductRequest<HostAccountGetAliasRequest>,
) -> GetAccountAliasResponse {
self.signing_host
.account_alias(&cx.call, &cx.session, request)
.await
}
}
```

The method `get_account_alias` selects `GetAccountAliasRequest`; parameter types
can be canonical payloads or generic wrappers without request aliases.
The return type's name selects the wire response
variant, including when two handlers share one variant. Distinct variants may
carry identical result types; conversion belongs to the request, so those
responses remain distinguishable. Constructors and helpers belong in a separate impl.

Handler signatures expand to native async methods returning `SsoReply<Payload>`.
Bodies return the named `Result` or an explicit reply with a local transcript
outcome. Shared Rust code adds `Response<P> { responding_to, payload }`;
the generated request contract selects its wire variant. An inner async block
preserves `?` and early returns.

The generated `dispatch(&self, session, message)` method classifies the message,
creates context from the supplied signing session, and exhaustively selects a
handler. Without a session it returns the response's typed disconnected error.
Shared reply finishing supplies correlation and defaults the transcript outcome
to success or error; handlers classify operation-specific outcomes. Missing
handlers, undeclared wire variants, and incompatible payloads fail compilation.

The wire enum contains requests, responses, and disconnects in one SCALE tag
space. `SsoWire` projects its requests into `AnyRequest` through `classify()`.
Dispatch matches that request-only enum exhaustively, so a new wire request
cannot silently fall through without a handler.

## Server integration

These macros target contracts in `crate::host_logic::sso::{messages, wire}` and
`crate::runtime::{authority, sso_service}`. They are intended for invocation inside
`truapi-server`; the canonical `truapi` crate uses the other macros and has no
server runtime dependency. Wire encoding remains owned by the enum and payload
codec derives. Transport, consent, session revalidation, and business logic belong
to the server implementation.

The [compiler tests](tests/sso.rs) exercise the macros against minimal versions of
those contracts. They cover valid handlers, shared and explicit response pairing,
boxed requests, independent wire helpers, and invalid declarations:

```sh
cargo test -p truapi-macros --locked
```
Loading
Loading