---
id: call/review-call-sync
name: Review alknet-call ADR-029/030/032/034 sync for spec conformance
status: pending
depends_on: [call/operation-env-invoke-peer, call/services-list-accesscontrol-filtered, call/call-client-verifier-selection, call/from-call-forwarded-for, call/dispatch-peer-identity]
scope: broad
risk: low
impact: phase
level: review
---

## Description

Review the alknet-call implementation after the ADR-029/030/032/034 sync for
spec conformance, pattern consistency, and correctness. This is the quality
checkpoint at the end of the call phase — the most complex sync in this batch.

### Review Checklist

1. **remote_safe/trusted_peer retirement** (ADR-029 §3):
   - No `remote_safe` field on `HandlerRegistration`
   - No `trusted_peer` on `CallClient`
   - No `RemoteFilter` in dispatch
   - No `list_operations_peer_scoped` / `services_list_handler_peer_scoped`
   - No ADR-028 test remnants
   - Peer authorization via `AccessControl::check(peer_identity)` only

2. **PeerCompositeEnv conformance** (ADR-029 §1, ADR-030 §4-5):
   - `PeerCompositeEnv` with peer-keyed `connections: HashMap<PeerId, ...>`
   - `connection_order: Vec<PeerId>` (insertion order for `PeerRef::Any`)
   - `PeerId = Identity.id` (stable `peer_id`, not UUID)
   - `compose_root_env` builds `PeerCompositeEnv` per call
   - Connection with no resolved identity → not attached (no PeerId)
   - `CompositeOperationEnv` removed (all call sites migrated)
   - Singular-connection case works (degenerate single-entry map)

3. **invoke_peer / PeerRef conformance** (ADR-029 §2):
   - `PeerRef::Specific(PeerId)` / `PeerRef::Any` enum
   - `OperationEnv::invoke_peer` with default-impl (back-compat)
   - `OperationEnv::peer_contains` with default-impl
   - `PeerCompositeEnv` overrides with real peer-keyed routing
   - `PeerRef::Specific` → no fallthrough (NOT_FOUND if peer doesn't serve op)
   - `PeerRef::Any` → insertion-order first-match
   - Reachability check (`scoped_env.allows`) gates before routing

4. **forwarded_for conformance** (ADR-032):
   - `OperationContext.forwarded_for: Option<Identity>` field
   - `build_root_context` populates from `call.requested.forwarded_for`
   - `OperationEnv::invoke` sets `None` for composed children (wire-ingress only)
   - `AccessControl::check` never reads `forwarded_for` (structural invariant)
   - `from_call` handler populates `forwarded_for` from `context.identity`

5. **services/list AccessControl-filtered** (ADR-029 §6):
   - `services/list` filters by `AccessControl::check(calling_peer_identity)`
   - Op with `AccessControl::default()` listed to any peer
   - Op with `required_scopes` hidden from unauthorized peers
   - `services/list-peers` opt-in (peer-attributed, AccessControl-filtered)
   - `services/schema` unchanged

6. **CallClient verifier selection** (OQ-29, ADR-034):
   - Client presents Ed25519 key as RFC 7250 raw public key client cert
   - `AcceptAnyServerCertVerifier` removed (security hole)
   - Verifier by `PeerEntry` presence: `Some` → fingerprint pin, `None` + X.509 → CA, `None` + Ed25519 → fail closed
   - `CallCredentials.remote_identity: None` is load-bearing (not placeholder)
   - No-env-vars invariant preserved (credentials from Capabilities)

7. **from_call peer-keyed registration** (ADR-029 §5):
   - `from_call` registers into peer's sub-overlay
   - Same-peer collision = error (`SamePeerCollision`)
   - Cross-peer collision dissolves (separate sub-overlays)
   - `namespace_prefix` defaults to `None` (optional local-naming sugar)
   - `forwarded_for` populated from hub's `context.identity`

8. **dispatch_peer_identity** (ADR-029 §3, ADR-030 §5):
   - `dispatch_requested` resolves peer `Identity`
   - `AccessControl::check(peer_identity)` is the sole authorization gate
   - `PeerId` from `connection.identity().id` (not UUID)
   - Connection with no identity → no PeerId, not in PeerCompositeEnv

9. **ADR conformance**:
   - ADR-029: peer-keyed overlays, PeerRef routing, AccessControl-based peer auth, retire remote_safe
   - ADR-030: PeerId = Identity.id = PeerEntry.peer_id (stable)
   - ADR-032: forwarded_for (metadata only, wire-ingress only, never in ACL)
   - ADR-034: three remote roles, verifier selection by PeerEntry presence

10. **Security constraints**:
    - Capabilities non-serializable, zeroized, immutable (unchanged)
    - No secret material on wire (unchanged)
    - `forwarded_for` is metadata, not authority (AccessControl::check never reads it)
    - Internal ops → NOT_FOUND from wire (unchanged)
    - Reachability check bounds composition (unchanged)
    - No-env-vars invariant (credentials from Capabilities, not env vars)
    - `AcceptAnyServerCertVerifier` removed (no security hole for X.509)

11. **Pattern consistency**:
    - `OperationEnv` is a trait (not concrete) — preserved
    - `PeerCompositeEnv` uses `contains()` probe before dispatch — preserved
    - Authority switch on `internal: true` — preserved
    - Deadline inheritance — preserved
    - Metadata fresh on composition (`HashMap::new()`) — preserved

12. **Test coverage**:
    - PeerCompositeEnv routing (session, peers in order, base fallthrough)
    - PeerRef::Specific (routes, NOT_FOUND on missing peer)
    - PeerRef::Any (insertion-order first-match)
    - forwarded_for (populated, None for composed children, never in ACL)
    - services/list AccessControl-filtered
    - AccessControl::check peer authorization (allowed, FORBIDDEN, Internal NOT_FOUND)
    - CallClient verifier selection (fingerprint pin, CA, fail closed)
    - from_call forwarded_for + peer-keyed registration + collision rules

## Acceptance Criteria

- [ ] No `remote_safe`/`trusted_peer`/`RemoteFilter` references remain
- [ ] `PeerCompositeEnv` matches ADR-029 §1 (peer-keyed, insertion order)
- [ ] `PeerId = Identity.id` (stable, not UUID)
- [ ] `invoke_peer`/`peer_contains`/`PeerRef` match ADR-029 §2
- [ ] `forwarded_for` matches ADR-032 (metadata only, wire-ingress only, never in ACL)
- [ ] `services/list` AccessControl-filtered; `services/list-peers` opt-in
- [ ] CallClient verifier selection matches ADR-034 §3
- [ ] `from_call` peer-keyed registration + forwarded_for + collision rules
- [ ] `AccessControl::check(peer_identity)` is the sole authorization gate
- [ ] `AcceptAnyServerCertVerifier` removed
- [ ] No-env-vars invariant preserved
- [ ] `OperationEnv` is a trait (not concrete)
- [ ] Test coverage adequate for all new functionality
- [ ] `cargo fmt --check -p alknet-call` passes
- [ ] `cargo clippy -p alknet-call` passes with no warnings
- [ ] All tests pass

## References

- docs/architecture/crates/call/README.md
- docs/architecture/crates/call/call-protocol.md
- docs/architecture/crates/call/operation-registry.md
- docs/architecture/crates/call/client-and-adapters.md
- docs/architecture/decisions/029-peer-graph-routing-model.md
- docs/architecture/decisions/030-peerentry-and-identity-id-decoupling.md
- docs/architecture/decisions/032-forwarded-for-identity.md
- docs/architecture/decisions/034-outgoing-only-x509-and-three-peer-roles.md

## Notes

> This is the most complex sync in this batch. The review should verify that
> the peer-keyed routing model (ADR-029), the stable PeerId (ADR-030), the
> forwarded_for metadata field (ADR-032), and the verifier selection (ADR-034)
> all work correctly together. The `OperationEnv` trait-object design is
> load-bearing — verify it's still a trait, not concrete. The
> `AccessControl::check`-based peer authorization is the security property —
> verify no parallel gate remains. If deviations are found, document and fix
> before considering the call sync complete.

## Summary

> To be filled on completion