tasks: decompose ADR-029/030/031/032/034/035 source sync into 17 tasks
Decompose the source-to-spec sync for the core and call crates into atomic, dependency-ordered tasks for implementation agents: Core (7 tasks + review): - peer-entry-model: PeerEntry struct, AuthPolicy.peers (ADR-030 keystone) - credential-store-trait: CredentialStore/InMemoryCredentialStore/StoreError (ADR-031/035) - identity-store-trait: IdentityStore async write trait (ADR-035) - config-identity-provider-peerentry: ConfigIdentityProvider PeerEntry resolution (ADR-030) - fingerprint-normalization: ed25519:hex for raw keys across quinn/iroh (ADR-030 §6) - three-remote-roles-docs: document ADR-034 roles and verifier selection - review-core-sync: phase gate before call consumes new identity semantics Call (9 tasks + review): - retire-remote-safe: remove ADR-028 machinery, AccessControl is the gate (ADR-029 §3) - operation-context-forwarded-for: forwarded_for field, wire-ingress only (ADR-032) - peer-composite-env: PeerCompositeEnv, PeerId=Identity.id, remove UUID (ADR-029/030) - operation-env-invoke-peer: invoke_peer/peer_contains/PeerRef (ADR-029 §2) - services-list-accesscontrol-filtered: AccessControl filter, list-peers opt-in (ADR-029 §6) - call-client-verifier-selection: TLS client-auth, verifier by PeerEntry (OQ-29, ADR-034) - from-call-forwarded-for: populate forwarded_for, peer-keyed registration (ADR-029 §5, ADR-032) - dispatch-peer-identity: AccessControl::check(peer_identity), PeerId from resolution (ADR-029 §3, ADR-030 §5) - review-call-sync: phase gate for the call sync Validated: 58 tasks, no cycles, logical topo order, two review checkpoints.
This commit is contained in:
155
tasks/call/review-call-sync.md
Normal file
155
tasks/call/review-call-sync.md
Normal file
@@ -0,0 +1,155 @@
|
||||
---
|
||||
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
|
||||
Reference in New Issue
Block a user