Skip to content

Commit f866098

Browse files
committed
Bring parity with macula-go-sdk: direct-dial, UCAN, RPC telemetry facts
cabi/go.mod was pinned to a2365b1 -- the commit immediately before macula-go-sdk's entire parity push (direct-dial, periodic re-advertise, supervised pubsub, UCAN, cert-chain, telemetry facts, streaming/content direct-dial reuse). Bumped to 1bd1ae4 (current master). Added, following this repo's existing cabi handle/errOut pattern exactly: - Direct-dial: resolveDirect/callDirect/advertiseDirect (+WithCertChain variants), streamOpenDirect(+WithCertChain), putDirect/getDirect. Verified live: a real RESULT payload through resolve+dial+call, not merely reaching the call stage (the weaker bar that hid a real bug in macula-go-sdk's own AdvertiseDirect earlier in this SDK family's development) -- see examples/08_*. - UCAN: new Ucan/UcanPayload classes (create/verify/decode/introspect), Session::callWithUcan, Session::serveWaitForCallGated. Found and fixed a real design bug while building the live test: a call rejected by policy never reaches the lookup rendezvous, so the Go wrapper's ServeOneCallGated returns nil (success) via a path PHP could not tell apart from a real PendingCall -- fixed by surfacing a distinguishable errCallRejectedByPolicy. Verified live end-to-end: an unauthorized call is refused with BOLT#4 Unauthorized before any PHP handler code runs, an authorized one reaches and is answered by it -- see examples/09_*. - RPC telemetry facts: no new export needed, confirmed (not assumed) via an independent watcher session observing rpc.sent_v1/rpc.completed_v1 land during a plain call() -- see examples/11_rpc_telemetry_facts_check.php. - Cert-chain: wiring verified reachable and produces the real, specific Go-side error for malformed input; a full positive round trip needs an Ed25519 X.509 leaf cert matching an external KeyPair's raw public key, which PHP's openssl extension does not straightforwardly support -- deliberately not attempted rather than faked; the underlying algorithm itself is already verified live in macula-go-sdk/macula-rust-sdk, both thin wrappers over which this SDK is not. Deliberately NOT exposed, documented in README and inline: periodic re-advertise and the supervised PubSub wrapper (RunPublisher/RunSubscriber) are both background-loop-shaped Go APIs; a PHP process can trivially loop calling advertiseDirect()/subscribe()+recvEvent() itself, so wrapping a second Go-side loop across the FFI boundary would add only callback plumbing, not new capability. 21 pre-existing PHPUnit tests still pass unchanged.
1 parent 59ce093 commit f866098

18 files changed

Lines changed: 1577 additions & 9 deletions

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,27 @@
1919

2020
---
2121

22-
**Status, 2026-08-28 — feature-complete, live-verified end to end**
22+
**Status, 2026-08-30 — feature-complete, live-verified end to end**
2323
(PHP → `ext-ffi` → Go C ABI → QUIC → a real production station), matching
2424
[`macula-go-sdk`](https://github.com/macula-io/macula-go-sdk) and
2525
[`macula-rust-sdk`](https://github.com/macula-io/macula-rust-sdk):
2626
handshake, unary RPC, PubSub, content transfer, and streaming RPC, every
27-
primitive in both caller and provider roles.
27+
primitive in both caller and provider roles, plus direct-dial (resolve a
28+
procedure via the mesh DHT and dial its serving station in one hop,
29+
plain and cert-chain-authorized), UCAN (mint/verify/introspect and
30+
policy-gated serving), and RPC telemetry auto-facts (no extra code needed
31+
on this side -- they fire automatically underneath `call()`/
32+
`serveWaitForCall()`, inherited straight from `macula-go-sdk`).
33+
34+
Two capabilities present in `macula-go-sdk` are intentionally NOT exposed
35+
here: periodic re-advertise and the supervised PubSub wrapper
36+
(`RunPublisher`/`RunSubscriber`) are both background-loop-shaped APIs on
37+
the Go side. A PHP process can trivially host the same external behavior
38+
itself -- call `advertiseDirect()`/`advertise()` again on your own
39+
schedule inside a `while` loop for the former, and loop `subscribe()` +
40+
`recvEvent()` yourself for the latter -- so wrapping a second, Go-side
41+
loop across the FFI boundary would only add callback plumbing this SDK's
42+
synchronous design otherwise avoids entirely, not new capability.
2843

2944
A PHP client for the [Macula](https://github.com/macula-io/macula) wire
3045
protocol. Architecturally this is a thin binding, not a third from-scratch
@@ -79,6 +94,10 @@ yourself is a single command that takes a few seconds.
7994
| Content transfer (single-block + chunked) ||| Content-addressed, BLAKE3/SHA-256, Merkle-verified |
8095
| Streaming RPC (STREAM_OPEN/DATA/END/REPLY) ||| Provider via `streamAccept()` — no rendezvous needed, unlike unary RPC |
8196
| RPC advertise/unadvertise ||| |
97+
| Direct-dial RPC (`resolveDirect`/`callDirect`/`advertiseDirect`) ||| Resolves a procedure via the mesh DHT and dials its station in one hop; `WithCertChain` variants add managed-realm org authorization |
98+
| Direct-dial streaming/content (`streamOpenDirect`/`putDirect`/`getDirect`) ||| `getDirect` only resolves content a station/relay announced — a leaf identity can't legitimately publish a `content_announcement`, matching `macula-go-sdk`'s own scope |
99+
| UCAN (mint/verify/introspect, policy-gated serving) ||| `Ucan::create`/`verify`/`decode`; `Session::callWithUcan`/`serveWaitForCallGated` — a rejected caller is refused before any PHP handler runs |
100+
| RPC telemetry facts (`rpc.sent_v1`/`rpc.completed_v1`/`rpc.received_v1`/`rpc.replied_v1`) ||| Automatic, no extra call needed — inherited from `macula-go-sdk`'s `Session.Call`/`ServeOneCallGated` |
82101

83102
## Structure
84103

0 commit comments

Comments
 (0)