Skip to content

Commit 92de91d

Browse files
committed
fix(iroh): compose framework identity and published RPC package
1 parent f1897fe commit 92de91d

6 files changed

Lines changed: 53 additions & 34 deletions

File tree

‎docs/how-to/iroh.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ route, and configure the worker to trust only the intermediary's exact address.
6666

6767
The same high-level client accepts both endpoint schemes:
6868

69-
```python
69+
```python test="skip"
7070
from vgi.client import Client
7171

7272
with Client.from_iroh("iroh://<endpoint-id>") as client:
@@ -78,7 +78,7 @@ with Client.from_iroh("httpi://<endpoint-id>/vgi") as client:
7878

7979
For a private relay:
8080

81-
```python
81+
```python test="skip"
8282
client = Client.from_iroh(
8383
"httpi://<endpoint-id>/vgi",
8484
relay_urls=["https://relay.example.com"],

‎pyproject.toml‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,6 @@ members = ["packages/vgi-fixtures"]
265265
[tool.uv.sources]
266266
# duckdb = { path = "/path/to/duckdb-python/dist/duckdb-*.whl" } # local engine-build override
267267
vgi-fixtures = { workspace = true }
268-
# Peer-identity support is on vgi-rpc main while 0.45.0 awaits publication.
269-
# The built wheel still declares the normal PyPI requirement above; this pin
270-
# only makes source-checkout development and CI reproducible in the interim.
271-
vgi-rpc = { git = "https://github.com/Query-farm/vgi-rpc-python.git", rev = "ab3108e242ed3fa35ee684c882f74813c35ad7ab" }
272268

273269
[dependency-groups]
274270
dev = ["lxml>=6.0.2", "pytest-timeout>=2.4.0", "vgi-fixtures"]

‎tests/test_serve.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,32 @@ def test_accepts_trusted_iroh_bridge_identity(self) -> None:
264264
)
265265
assert isinstance(app, falcon.App)
266266

267+
def test_iroh_identity_composes_with_explicit_peer_authentication(self, monkeypatch: pytest.MonkeyPatch) -> None:
268+
"""Adding Iroh evidence preserves existing providers and policy."""
269+
import falcon
270+
271+
seen: dict[str, Any] = {}
272+
provider = _StaticTailnetProvider()
273+
policy = peer_identity_primary("tailscale")
274+
275+
def fake_make_wsgi_app(server: object, **kwargs: Any) -> falcon.App:
276+
seen.update(server=server, **kwargs)
277+
return falcon.App()
278+
279+
monkeypatch.setattr("vgi_rpc.http.make_wsgi_app", fake_make_wsgi_app)
280+
create_app(
281+
_SingleWorker,
282+
describe=False,
283+
peer_identity_providers=(provider,),
284+
peer_authentication_policy=policy,
285+
iroh_bridge_issuer="test-mesh",
286+
)
287+
288+
providers = seen["peer_identity_providers"]
289+
assert providers[0] is provider
290+
assert len(providers) == 2
291+
assert seen["peer_authentication_policy"] is policy
292+
267293
def test_custom_prefix(self) -> None:
268294
"""Custom prefix is used in the app."""
269295
app = create_app(_SingleWorker, prefix="/api")

‎uv.lock‎

Lines changed: 14 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎vgi/client/client.py‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,11 +1137,7 @@ def _get_or_create_httpx_client(self) -> Any:
11371137
assert self._iroh_endpoint is not None
11381138
target = parse_iroh_uri(self._iroh_endpoint)
11391139
native_transport = IrohHttpTransport(self._iroh_endpoint, **self._iroh_options)
1140-
iroh_headers = (
1141-
{"Authorization": f"Bearer {self._bearer_token}"}
1142-
if self._bearer_token is not None
1143-
else None
1144-
)
1140+
iroh_headers = {"Authorization": f"Bearer {self._bearer_token}"} if self._bearer_token is not None else None
11451141
self._httpx_client = httpx2.Client(
11461142
base_url=f"http://{target.endpoint_hex}",
11471143
transport=cast("Any", native_transport),

‎vgi/serve.py‎

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -335,31 +335,32 @@ def create_app(
335335
"introspect_rate_limit": _resolve_introspect_rate_limit(introspect_rate_limit),
336336
}
337337

338-
peer_identity_providers: tuple[Any, ...] = ()
339-
peer_authentication_policy: Any = None
338+
effective_peer_identity_providers = tuple(peer_identity_providers)
339+
effective_peer_authentication_policy = peer_authentication_policy
340340
if iroh_bridge_issuer is not None:
341341
from vgi_rpc.http import iroh_forwarded_header_provider
342342
from vgi_rpc.rpc import observe_peer_identity, peer_identity_primary
343343

344344
trusted_iroh_addresses = tuple(iroh_trusted_proxy_addresses) or ("127.0.0.1",)
345-
peer_identity_providers = (
345+
effective_peer_identity_providers += (
346346
iroh_forwarded_header_provider(
347347
issuer=iroh_bridge_issuer,
348348
trusted_proxy_addresses=trusted_iroh_addresses,
349349
),
350350
)
351-
peer_authentication_policy = (
352-
peer_identity_primary("iroh") if iroh_authenticate else observe_peer_identity
353-
)
351+
if effective_peer_authentication_policy is None:
352+
effective_peer_authentication_policy = (
353+
peer_identity_primary("iroh") if iroh_authenticate else observe_peer_identity
354+
)
354355

355356
wsgi_app = make_wsgi_app(
356357
server,
357358
prefix=prefix,
358359
cors_origins=cors_origins,
359360
token_key=signing_key,
360361
authenticate=authenticate,
361-
peer_identity_providers=peer_identity_providers,
362-
peer_authentication_policy=peer_authentication_policy,
362+
peer_identity_providers=effective_peer_identity_providers,
363+
peer_authentication_policy=effective_peer_authentication_policy,
363364
peer_service_name=peer_service_name,
364365
peer_resolution_timeout=peer_resolution_timeout,
365366
peer_provider_concurrency=peer_provider_concurrency,
@@ -368,8 +369,6 @@ def create_app(
368369
otel_config=otel_config,
369370
max_stream_response_bytes=max_stream_response_bytes,
370371
max_externalized_response_bytes=max_externalized_response_bytes,
371-
peer_identity_providers=peer_identity_providers,
372-
peer_authentication_policy=peer_authentication_policy,
373372
enable_landing_page=False,
374373
**introspect_kwargs,
375374
)
@@ -623,9 +622,7 @@ def serve(
623622
try:
624623
raw_port = int(raw_port_text)
625624
except ValueError:
626-
raise SystemExit(
627-
f"--iroh-raw-upstream expects [HOST:]PORT, got {iroh_raw_upstream!r}"
628-
) from None
625+
raise SystemExit(f"--iroh-raw-upstream expects [HOST:]PORT, got {iroh_raw_upstream!r}") from None
629626

630627
worker = worker_cls(quiet=quiet, log_level=effective_level)
631628
# Iroh is also a directly addressable RPC endpoint, so advertise

0 commit comments

Comments
 (0)