Commit Graph

298 Commits

Author SHA1 Message Date
e4a25947d6 feat(call): remote_safe field on HandlerRegistration (ADR-028)
Adds the v1 data shape for peer-scoped default-deny registry filtering,
the one-way-door piece of the call-completion batch (ADR-028):

- HandlerRegistration gains pub remote_safe: bool, defaulting false across
  all provenance (Local, Session, FromOpenAPI, FromMCP, FromCall,
  FromJsonSchema) per ADR-028 §4. HandlerRegistration::new() keeps its
  existing 6-arg signature (defaults remote_safe: false), so all current
  call sites compile unchanged.
- Chainable HandlerRegistration::remote_safe(bool) setter + a
  OperationRegistryBuilder::remote_safe() helper that marks the
  most-recently-registered op (tracked via last_name, not HashMap
  iteration order which is unspecified).
- Field is data-only here — the filtering behavior (dispatch path +
  services/list hide) is wired in call/client/call-client, not this task.
  services/list is unchanged.
- Tests: default false, setter flips field, all six provenance variants
  default false, builder setter marks last op, existing call sites
  unchanged. 178 tests pass, clippy clean.

Refs: tasks/call/registry/remote-safe-marking.md
Refs: docs/architecture/decisions/028-callclient-peer-scoped-registry-filtering.md
2026-06-26 12:51:18 +00:00
2649e068e5 docs(arch): call-completion — ADR-028 peer-scoped filtering + client-and-adapters spec + tasks
Resolves the four gap-analysis decisions (DC-1..4) blocking the alknet-call
client/adapter surface specced in ADR-017:

- ADR-028 (new): locks the one-way door for DC-1 — CallClient registry is
  default-deny (remote_safe: bool on HandlerRegistration, default false across
  all provenance); share-global is an explicit trusted-peer opt-in; filtering
  is a dispatch-time read over the single Layer-0 registry, not a copy.
- client-and-adapters.md (new spec): operationally fills the gap ADR-017 left
  to implementation — CallClient, from_call, from_jsonschema, OperationAdapter
  trait, adapter location map, no-env-vars invariant, exchange-of-operations
  pattern. Keeps call-protocol.md and operation-registry.md under the
  700-line split threshold.
- ADR-017 amended: records DC-2/3/4 v1 defaults (auto-on-reconnect,
  error-on-collision, Result error type) and points DC-1 at ADR-028.
- OQ-25..28 (new): two-way-door remainders (remote_safe shape, AdapterError
  variants, re-import trigger, namespace collision) with v1 defaults recorded.
- Index/cross-ref updates across READMEs and the two existing call specs.

Tasks: 6 task files under tasks/call/ decomposing the completion work along
the gap-analysis priority order — remote-safe-marking (one-way door, first)
→ call-client (phase-risk) → from-call → operation-adapter-trait →
from-jsonschema (parallel with call-client) → review-completion. Graph
validated with taskgraph; parallelism designed in (from-jsonschema runs
concurrent with call-client/from-call once the trait lands).
2026-06-26 12:25:13 +00:00
6940d9858d docs(research): alknet-http phase-0 findings — HTTP server + client + MCP adapters
Phase 0 exploration for alknet-http (greenfield crate, no existing arch):
HTTP server (axum, ProtocolHandler for h2/http1.1, h3 deferred), HTTP client
(reqwest, the from_openapi/from_mcp forwarding handlers), MCP streamable HTTP
(feature-gated, stdio excluded as security position), to_openapi/to_mcp
projections.

Records: 8 design points (DH-3 HTTP→call operation mapping as the load-bearing
one), the settled adapter location map (from alknet-call gap analysis), the
no-env-vars invariant (Capabilities → from_openapi handler → HTTP header as the
credential injection point), and the prerequisite on alknet-call's
OperationAdapter trait being defined first.
2026-06-25 12:46:25 +00:00
79d8561bb4 docs(research): alknet-call completion gap analysis — CallClient + from_call + OperationAdapter
Gap analysis for completing alknet-call: the server-side core (~5.7k lines,
159 tests) is implemented, but the client side (CallClient), the bilateral
exchange mechanism (from_call), and the adapter contract (OperationAdapter
trait) are specced in ADR-017 and unimplemented.

Records: implementation state (verified against src/), 5 decisions needed
(peer-scoped registry filtering as the load-bearing one), the settled adapter
location map (trait + from_call + from_jsonschema in alknet-call; from_openapi/
from_mcp in alknet-http), the no-env-vars invariant (Capabilities → from_openapi
handler → HTTP header), and the exchange-of-operations runner pattern with
dispatch as the concrete downstream consumer.
2026-06-25 12:44:49 +00:00
db1dcd362f docs(research): revise alknet-ssh phase-0 — SOCKS5+forwarding in v1, TCP listener for git-over-ssh
Incorporates user clarifications: SOCKS5 and bidirectional port forwarding are
core non-negotiable v1 features (the VPN-like use case + the 3.5k-clones
demand). Adds DP-10 for the bare-TCP SSH listener as a first-class path needed
for future git-over-SSH, with config shape reserved in v1 (off-by-default,
default-deny). Grounds the client/forwarding recommendations in the dispatch
downstream consumer at /workspace/@alkdev/dispatch, which is a textbook russh
SSH client + direct-tcpip forwarder the user wants to replace with this stack.

alknet-ssh now owns both server and client + SOCKS5-server in v1; the SOCKS5
codec may extract to a separate crate later (two-way door).
2026-06-25 08:46:35 +00:00
d758a71490 docs(research): alknet-ssh phase-0 findings — stream wiring, russh 0.60.2, decision points
Phase 0 exploration for alknet-ssh: confirms SSH-over-QUIC-bistream via
tokio::io::join (no custom adapter needed, per reference impl), russh 0.60.2
generic run_stream/connect_stream, and channel-into-bistream multiplexing.

Surfaces 9 decision points for Phase 1: host key sourcing (vault-derived vs
config), channel policy v1 surface, client + SOCKS5 crate split, crypto
backend, auth method coverage, and a stream-handling POC to close russh's
upstream test gap.
2026-06-25 08:06:45 +00:00
011db05a52 test: implement coverage #005 Tier-A suggestions (S1-S4, S8)
Add 165 tests covering the directly-testable surface identified in
coverage review #005. Workspace coverage rises 87.1% -> 91.2%
(5759/6615 -> 6505/7135); all 389 tests pass, clippy clean.

- S1 (connection.rs): dispatch_envelope across all five event-type arms
  for Call + Subscribe, plus SubscriptionStream poll_next branches and
  SubscriptionStream::closed.
- S2 (types.rs): map_quinn/iroh_connection_error for TimedOut/Reset/
  ApplicationClosed/other, plus HandlerError + StreamError Debug/Display/
  source for every variant.
- S3 (config.rs): Ed25519SecretKey from_bytes/as_bytes round-trip,
  sign+verify, tampered-message rejection, Debug non-leakage.
- S4 (endpoint.rs): build_rustls_server_config RawKey/SelfSigned/Acme
  arms, build_quinn_server_config_from_rustls, load_private_key/
  load_cert_chain error paths, has_iroh_identity branches,
  AcceptAnyCertVerifier trait methods, Ed25519SigningKey trait impls
  (choose_scheme both branches, algorithm, public_key, sign, scheme),
  RawKeyCertResolver + AlknetEndpoint Debug. endpoint.rs 56% -> 73%.
- S8 (vault protocol.rs): the existing redacted-deserialize test passed
  for the wrong reason (JSON string failed Vec<u8> coercion before the
  guard). Two new tests exercise the guard directly via a [REDACTED] byte
  array (rejected) and a real payload (accepted). protocol.rs -> 100%.

Deferred to follow-up: S5 (loopback quinn integration test, the real
unlock for accept/dispatch/stream paths), S6 (ACME event-loop extraction),
S7 (adapter abort arm). Review #005 updated with the resolution.
2026-06-25 05:43:59 +00:00
32dcc05658 docs(reviews): add coverage analysis #005
First dedicated coverage pass (cargo-llvm-cov --workspace --all-features).
Workspace at 87.1% line coverage (5759/6615), all 224 tests pass. Vault
and registry layers are essentially fully covered; gaps concentrate in
endpoint.rs (56%), types.rs (57%), and connection.rs (54%), all stemming
from tests using MockConnection whose open_bi/accept_bi return Err.

Eight suggestions (S1-S8) ordered by leverage: pure-function tests for
dispatch_envelope / map_*_connection_error / error Display+Debug (S1-S3),
Tier A directly-callable TLS/rustls helpers in endpoint.rs (S4), one
loopback quinn integration test as the real unlock across four files (S5),
ACME event-loop extraction via synthetic stream (S6, the flagged research
item), and two small remaining gaps (S7-S8). No critical or warning
findings — this is a testing-infrastructure gap, not a logic gap.
2026-06-25 04:32:51 +00:00
00edfc0889 feat(core): ADR-027 — RawKey decoupling, client cert request, ACME integration
Three tasks implementing ADR-027:

1. core/rawkey-decouple-from-iroh: TlsIdentity::RawKey now uses
   Ed25519SecretKey (alknet-core-owned wrapper over ed25519_dalek)
   instead of iroh::SecretKey. RawKeyCertResolver and Ed25519SigningKey
   un-gated from #[cfg(all(quinn, iroh))] to #[cfg(quinn)] only.
   Quinn-only builds (default) now support RFC 7250 raw-key identity.
   iroh transport converts via iroh::SecretKey::from_bytes.

2. core/endpoint-request-client-cert: replaced with_no_client_auth()
   with AcceptAnyCertVerifier — a custom ClientCertVerifier that
   requests client certs but doesn't require them or verify against
   a CA. alknet's identity model is fingerprint-based (the
   authorized_fingerprints set is the trust anchor), not PKI-based.
   Peer certs are extracted at the TLS layer for fingerprinting;
   peers without certs connect normally.

3. core/acme-integration: TlsIdentity::Acme variant (domains,
   cache_dir, directory, contact) + AcmeDirectory enum. TlsSetup
   two-phase construction: synchronous for X509/RawKey/SelfSigned,
   async for Acme (spawns AcmeState event loop, builds ServerConfig
   with ResolvesServerCertAcme). acme-tls/1 ALPN added when ACME is
   active; dispatch_quinn guard closes challenge connections
   gracefully (challenge is TLS-layer-handled). acme feature gate
   keeps rustls-acme out of non-ACME builds.

Workspace: build/test/clippy green across all 3 feature configs
(quinn-only, quinn+iroh, quinn+acme, all-features). 331 tests, 0
failures, 0 warnings.
2026-06-24 20:29:43 +00:00
d94d7a132a docs(adr-027): TLS identity redesign — ACME + RawKey decoupling
ADR-027 resolves the architectural gap surfaced when ACME integration
became a concrete target:

1. TlsIdentity::Acme variant — static config data (domains, cache_dir,
   directory, contact) with async AcmeState constructed at endpoint
   setup via two-phase TlsSetup (not stuffed into the Clone-able enum).

2. TlsIdentity::RawKey decoupled from the iroh feature — uses
   Ed25519SecretKey (alknet-core-owned wrapper over ed25519_dalek)
   instead of iroh::SecretKey. Raw-key TLS identity (RFC 7250, the
   default for most alknet nodes) now works in quinn-only builds.
   iroh transport converts via SecretKey::from_bytes.

3. ACME feature-gated behind new acme feature (rustls-acme optional
   dep). Non-ACME builds don't compile it.

4. dispatch_quinn guard for acme-tls/1 challenge connections — TLS-ALPN-01
   is handled at the rustls cert resolver layer during the handshake;
   the guard closes challenge connections gracefully instead of logging
   a misleading "no handler" warning.

Research confirmed QUIC (quinn) handles ACME challenges differently than
TCP (reverse-proxy): quinn gives no ClientHello peek hook, but the
challenge is fully answered at the cert resolution step before the
connection surfaces to the application. No handler registration needed.

Spec updates: config.md, endpoint.md, open-questions.md (OQ-12),
overview.md + README.md (ADR index), ADR-010 (cross-ref).

Tasks: core/rawkey-decouple-from-iroh (gen 1, no deps),
core/acme-integration (gen 2, depends on rawkey). Graph: 36 tasks.
2026-06-24 12:29:24 +00:00
97216764ea fix: resolve review #004 findings W1-W4 + close review gate
W1 (call/protocol/abort-cascade-wiring): wire AbortCascade into
CallAdapter handle_stream for EVENT_ABORTED. Cascades with
AbortPolicy::AbortDependents, aborts root, no descendant frames on
wire (ADR-016 Decision 2). Two integration tests added.

W2 (core/endpoint-client-fingerprint): extract TLS client cert
fingerprint in dispatch_quinn (SHA256:<hex> of leaf cert DER via
peer_identity) and dispatch_iroh (ed25519:<hex> of peer NodeId).
Fingerprint format documented in auth.md. Server config change
(with_no_client_auth → request-but-don't-require) deferred to new
follow-up task core/endpoint-request-client-cert.

W3 (vault/mnemonic-debug-redaction): replace Mnemonic derive(Debug)
with manual redacting impl (phrase: "[REDACTED]"). Seed confirmed
no Debug impl. Redaction test added.

W4 (core/auth-apikey-resources): Option B — drop entry.resources from
spec. External identities (token/fingerprint) grant scopes only;
resource-scoped ACLs are composition-internal (ADR-015/022). auth.md
corrected + limitation documented. Two tests confirm empty resources.

review-post-impl-fixes: all 4 verified, workspace green (326 tests,
0 failures, 0 clippy warnings). Review #004 status → resolved.

Graph: 34 tasks, 12 gens.
2026-06-24 11:00:54 +00:00
d149932e2a tasks: decompose review #004 findings into 4 fix tasks + review gate
W1 (call/protocol/abort-cascade-wiring): wire AbortCascade into CallAdapter
handle_stream for EVENT_ABORTED. W2 (core/endpoint-client-fingerprint):
extract TLS client cert fingerprint in dispatch_quinn/dispatch_iroh.
W3 (vault/mnemonic-debug-redaction): replace Mnemonic derive(Debug) with
redacting impl. W4 (core/auth-apikey-resources, level: research): decide
whether ApiKeyEntry should carry resources, then implement or drop from
spec. review-post-impl-fixes gates on all four. Graph: 33 tasks, 12 gens.
2026-06-24 10:02:03 +00:00
d904dfc243 docs(reviews): add post-implementation sanity check #004
28-task implementation review across alknet-vault, alknet-core, alknet-call.
Zero critical findings; 4 warnings (W1: AbortCascade implemented but never
invoked by CallAdapter; W2: endpoint hard-codes tls_client_fingerprint=None;
W3: Mnemonic Debug leaks seed phrase; W4: ApiKeyEntry missing resources
field); 5 suggestions. Build clean, 332 tests pass, default clippy clean.
2026-06-23 22:13:20 +00:00
2c83e31e38 tasks: mark call/review-call completed — all 28 tasks done 2026-06-23 15:55:56 +00:00
4696c9a304 docs(call): record review-call pass — implementation conforms to spec (task: call/review-call)
Review of alknet-call crate against operation-registry.md, call-protocol.md,
and ADRs 005/012/014/015/016/017/022/023/024. All registry types, protocol types,
security constraints, and pattern consistency checks conformant. No source
deviations found. 159 tests pass; build/clippy/fmt/test clean.

Refs: docs/architecture/crates/call/README.md
2026-06-23 15:55:33 +00:00
23b76a240a docs(call): record review-call pass — implementation conforms to registry/protocol/ADR spec
call/review-call verified the alknet-call crate against operation-registry.md,
call-protocol.md, and ADRs 005/012/014/015/016/017/022/023/024. All
registry types, protocol types, security constraints (Capabilities
non-serializable/zeroized/immutable, metadata non-propagation, internal
ops -> NOT_FOUND, reachability bounds, UUID v4 request IDs), and pattern
consistency (OperationEnv trait, CompositeOperationEnv contains-probe,
authority switch, deadline inheritance) are conformant. 159 tests green;
build/clippy(fmt check) clean. No source changes required.
2026-06-23 15:55:10 +00:00
93589d4f52 tasks: mark call/protocol/abort-cascade completed 2026-06-23 15:50:38 +00:00
8aa384ccfa feat(call): implement abort cascade for nested calls (ADR-016) (task: call/protocol/abort-cascade)
Implement AbortCascade in protocol/abort.rs per ADR-016: PendingEntry stores
parent_request_id (Call & Subscribe) and a started flag for tree indexing.
AbortCascade::cascade_abort walks the call tree by parent_request_id and aborts
descendants per AbortPolicy (AbortDependents aborts all; ContinueRunning aborts
only unstarted via mark_started()). Returns sorted list of aborted IDs; unknown
root silently discarded. 20 unit tests covering depth-3 cascade, mixed
Call/Subscribe, determinism, both policies.

Refs: docs/architecture/crates/call/call-protocol.md
Implements: ADR-016
2026-06-23 15:50:05 +00:00
3317bc8d1a feat(call): implement abort cascade for nested calls (ADR-016) (task: call/protocol/abort-cascade)
- PendingEntry stores parent_request_id (Call and Subscribe) and started flag
  for abort-cascade tree indexing
- register_call/register_subscribe accept optional parent_request_id
- AbortCascade::cascade_abort walks the call tree by parent_request_id and
  aborts descendants per AbortPolicy (AbortDependents: all; ContinueRunning:
  unstarted only). Returns sorted list of aborted request IDs
- call.aborted for unknown request_id silently discarded (empty result)
- Composed child request_ids stay internal (not sent as call.requested)
- mark_started() tracks dispatch state for ContinueRunning decisions
- 20 unit tests covering AbortDependents/ContinueRunning, depth-3 tree,
  unknown root, mixed Call/Subscribe, determinism
2026-06-23 15:49:07 +00:00
bea19de3cf tasks: mark call/protocol/call-adapter completed 2026-06-23 15:39:54 +00:00
2ff09a728c feat(call): implement CallAdapter — ProtocolHandler for alknet/call (task: call/protocol/call-adapter)
Implement CallAdapter in protocol/adapter.rs: ProtocolHandler for ALPN
alknet/call with stream handling, per-request identity resolution (auth_token
overrides connection identity, falls back on failure), root context construction
(internal:false, deadline, capabilities+scoped_env from registration bundle),
env composition (CompositeOperationEnv with Layer 0 base + Layer 2 connection
overlay + optional Layer 1 session overlay), operationId leading slash stripped,
ResponseEnvelope→EventEnvelope conversion, PendingRequestMap sweeper, connection
drop fails all pending. SessionOverlaySource trait. 22 unit tests.

Refs: docs/architecture/crates/call/call-protocol.md
Implements: ADR-002, ADR-012, ADR-014, ADR-015, ADR-017, ADR-022, ADR-024
2026-06-23 15:39:28 +00:00
fc9f93e893 feat(call): implement CallAdapter (ProtocolHandler for alknet/call) with stream handling, identity resolution, root context construction (task: call/protocol/call-adapter)
- CallAdapter struct with registry, identity_provider, session_source, default_timeout (30s)
- new(), with_session_source(), with_timeout() constructors
- SessionOverlaySource trait defined (overlay_for) for agent-crate integration
- ProtocolHandler::alpn() returns b"alknet/call"
- handle() sets connection identity from AuthContext, spawns accept_bi loop,
  reads EventEnvelope frames via FrameFramedReader, dispatches call.requested
  to the operation registry, writes ResponseEnvelope as EventEnvelope via
  FrameFramedWriter
- Per-request identity resolution: AuthContext.identity used by default,
  auth_token in payload overrides via IdentityProvider::resolve_from_token();
  resolution failure falls back to connection-level identity
- build_root_context sets internal: false, deadline (now + default_timeout),
  capabilities and scoped_env from registration bundle, parent_request_id: None
- compose_root_env builds CompositeOperationEnv (Layer 0 curated base +
  Layer 2 connection overlay + optional Layer 1 session overlay)
- operationId leading slash stripped before registry lookup
- ResponseEnvelope -> EventEnvelope conversion (Ok -> call.responded,
  Err -> call.error)
- PendingRequestMap sweeper runs every 10s, evicts expired wire entries
- Connection drop: fail_all pending with INTERNAL "connection closed",
  return Ok(())
- Stream reset: FrameFramedReader error closes stream; other streams unaffected
- Handler panic: stream task isolated via tokio::spawn, sweep cleans entry
- Tests: alpn, constructors, slash strip, identity resolution (override/fallback),
  root context (internal=false, deadline, capabilities, scoped_env), env
  composition (layers aggregate, session overlay), dispatch round-trip,
  internal op from wire -> NOT_FOUND, ACL denied -> FORBIDDEN, auth_token
  overrides connection identity, unknown op -> NOT_FOUND, no-slash resolution,
  ResponseEnvelope -> EventEnvelope conversions
2026-06-23 15:38:50 +00:00
0d0f0f8da6 tasks: mark core/review-core completed 2026-06-23 15:33:16 +00:00
061069910b fix(core): gate RawKey TLS helpers on quinn+iroh for clean iroh-only builds (task: core/review-core)
Review of alknet-core found one issue: RawKeyCertResolver/Ed25519SigningKey/
std::path::Path were gated on #[cfg(feature = "iroh")] but only used in the
quinn TLS path — caused clippy -D warnings failures on iroh-only builds.
Re-gated to #[cfg(all(feature = "quinn", feature = "iroh"))]. All 4 feature
combinations now pass clippy -D warnings; 55 tests pass.

Review confirmed: all core types, config, auth, and endpoint implementations
are spec-conformant.
2026-06-23 15:32:23 +00:00
4774364c72 fix(core): gate RawKey TLS helpers on quinn+iroh for clean iroh-only builds (task: core/review-core)
The RawKeyCertResolver, Ed25519SigningKey, and std::path::Path imports
were gated on #[cfg(feature = "iroh")] but are only used in the quinn
TLS server-config path (build_rustls_server_config RawKey arm). With
iroh-only builds (--no-default-features --features iroh), these became
dead code and triggered clippy -D warnings failures.

Re-gated to #[cfg(all(feature = "quinn", feature = "iroh"))] so they
only compile when both features are active (the combination that
actually uses raw-key TLS via quinn). std::path::Path is now
#[cfg(feature = "quinn")] since it is only used by quinn's
load_cert_chain/load_private_key helpers.

Verified: cargo clippy passes with -D warnings across all four feature
combinations (none, quinn, iroh, quinn+iroh). cargo test --all-features
passes 55 tests. cargo fmt --check clean.
2026-06-23 15:31:42 +00:00
60556bbe0c tasks: mark core/endpoint and call/protocol/call-connection completed 2026-06-23 15:18:56 +00:00
c68050ae0f feat(call): implement CallConnection with imported-ops overlay and call/subscribe/abort (task: call/protocol/call-connection)
Implement CallConnection in protocol/connection.rs with Layer 2 imported-ops
overlay (Arc<RwLock<HashMap>>), register_imported/register_imported_all,
overlay_env() returning an OperationEnv that dispatches to imported ops,
and call()/subscribe()/abort() methods that open a stream, send call.requested,
register in PendingRequestMap, spawn a stream reader, and correlate responses
by ID. Connection drop drops the overlay. Exposed MockConnection +
Connection::from_mock in alknet-core for cross-crate testing. 9 new connection
tests (102 total in alknet-call).

Refs: docs/architecture/crates/call/call-protocol.md
Implements: ADR-012, ADR-017, ADR-024
2026-06-23 15:17:55 +00:00
7b92749acd tasks: mark core/endpoint completed 2026-06-23 15:16:33 +00:00
ddc6c07fea feat(call): implement CallConnection with imported-ops overlay (Layer 2) and call/subscribe/abort methods
Implements CallConnection in src/protocol/connection.rs representing an
established alknet/call connection (either direction). Holds the Layer 2
imported-ops overlay (ADR-024) as Arc<RwLock<HashMap>>.

- register_imported / register_imported_all add to the connection overlay
- overlay_env returns an OperationEnv dispatching to imported ops; contains()
  returns true only for ops in the overlay
- call() opens a stream, sends call.requested, registers in PendingRequestMap,
  spawns a stream reader, resolves on first call.responded
- subscribe() sends call.requested and yields call.responded until
  call.completed/call.aborted via a SubscriptionStream wrapping the mpsc receiver
- abort() sends call.aborted for the request ID and removes the pending entry
- connection drop drops the overlay (no explicit deregistration needed)

Exposes MockConnection trait and Connection::from_mock in alknet-core so
cross-crate tests can construct mock connections without real QUIC. Removes
two unused test helpers in env.rs that triggered dead-code warnings under
-D warnings. Adds parking_lot dep for the overlay RwLock and pending Mutex.

9 new connection tests (102 total in alknet-call). Clippy clean.
2026-06-23 15:16:10 +00:00
79bc6ffb31 feat(core): implement AlknetEndpoint, HandlerRegistry, accept loops, TLS identity, graceful shutdown (task: core/endpoint)
Implement the ALPN router and endpoint in endpoint.rs: AlknetEndpoint with
quinn+iroh accept loops (both feature-gated, both Option), HandlerRegistry
(new/register/get/alpn_strings with panic-on-duplicate), dispatch via
tokio::spawn by ALPN, AuthContext construction from connection
(alpn/remote_addr/fingerprint/identity), TLS identity modes (RawKey RFC 7250
via on-the-fly cert resolver, X509 from files, SelfSigned via rcgen),
EndpointError enum, graceful shutdown with drain timeout + force close.
ACME deferred as TODO per task spec. 55 tests (--all-features), 52 (default),
47 (no-default); clippy clean across all 3 feature combos.

Refs: docs/architecture/crates/core/endpoint.md
Implements: ADR-010
2026-06-23 15:14:26 +00:00
8d056a2b59 feat(core): implement AlknetEndpoint, HandlerRegistry, accept loops (quinn + iroh), TLS identity (RawKey/X509/SelfSigned), and graceful shutdown (task: core/endpoint) 2026-06-23 15:12:14 +00:00
3484373d84 tasks: mark call/registry/service-discovery completed 2026-06-23 14:55:42 +00:00
8cc16de9f0 feat(call): implement services/list and services/schema built-in operations (task: call/registry/service-discovery)
Implement services/list and services/schema in registry/discovery.rs: spec
constructors, factory handlers taking Arc<OperationRegistry>, JSON serialization
of OperationSpec (incl. error_schemas per ADR-023), leading-slash normalization
for services/schema, NOT_FOUND for unknown ops, INVALID_INPUT for missing name.
Both registered as Local provenance with empty authority/env/caps and empty
AccessControl.

Refs: docs/architecture/crates/call/operation-registry.md
Implements: ADR-023
2026-06-23 14:55:09 +00:00
bb4e32e849 feat(call): implement services/list and services/schema built-in operations (task: call/registry/service-discovery) 2026-06-23 14:54:17 +00:00
4f10af2295 tasks: mark call/registry/operation-env completed 2026-06-23 14:53:42 +00:00
99ef22db3e feat(call): implement LocalOperationEnv and CompositeOperationEnv (task: call/registry/operation-env)
Implement LocalOperationEnv (Layer 0 — Arc<OperationRegistry>, reachability check,
authority switch, fresh metadata, inherited deadline/env) and CompositeOperationEnv
(session → connection → base overlay dispatch via contains() probe per ADR-024).
ScopedOperationEnv checked before overlay dispatch. 13 new env tests (93 total).

Refs: docs/architecture/crates/call/operation-registry.md
Implements: ADR-024
2026-06-23 14:53:05 +00:00
7e824af022 feat(call): implement LocalOperationEnv and CompositeOperationEnv (task: call/registry/operation-env)
Expand the minimal OperationEnv trait from the operation-context task with
concrete dispatch implementations per ADR-024:

- LocalOperationEnv (Layer 0): wraps Arc<OperationRegistry>. invoke_with_policy
  runs the scoped_env reachability check (ADR-015/022), looks up the
  registration, then constructs a child OperationContext with internal: true,
  identity = parent.handler_identity.as_identity() (the ADR-015 authority
  switch), fresh metadata (HashMap::new() — ADR-014 security constraint, no
  parent metadata propagation), inherited deadline (parent.deadline, not a
  fresh 30s), inherited env (parent.env.clone() — Arc::clone per ADR-024), and
  the child's own composition_authority + scoped_env from its registration.
  contains() uses the default impl (returns true — curated registry contains
  everything it can dispatch).

- CompositeOperationEnv (per-call, ADR-024): composes session (Layer 1),
  connection (Layer 2), and base (Layer 0) trait objects. invoke_with_policy
  runs the same reachability check, then probes overlays in order via
  contains() (the overlay-dispatch contract from review #003 C9), dispatching
  to the first overlay that contains the op. contains() aggregates all layers.

The trait-object design is load-bearing: making OperationEnv concrete would
close the session-overlay and connection-overlay patterns. Same integration-
point pattern as IdentityProvider (ADR-004).

Tests cover: allowed/disallowed reachability, internal-flag propagation,
authority switch (child identity = parent handler_identity), fresh metadata,
inherited deadline, composite session-overlay dispatch, composite fall-through
to base, composite connection-overlay dispatch when session lacks op, and
composite contains aggregation.
2026-06-23 14:51:48 +00:00
31fd8a73ac tasks: mark call/registry/handler-registration completed 2026-06-23 14:42:01 +00:00
3aae9d1323 feat(call): implement handler registration and operation registry (task: call/registry/handler-registration)
Implement Handler, HandlerRegistration, OperationProvenance, OperationRegistry
(register/registration/invoke/list_operations), and OperationRegistryBuilder
(new/with_local/with_leaf/with_leaf_provenance/with/build) in registry/registration.rs.
invoke enforces visibility (Internal from wire → NOT_FOUND), ACL with authority
switch (internal: true → handler_identity.as_identity(), internal: false → caller
identity), and handler dispatch. 21 unit tests.

Refs: docs/architecture/crates/call/operation-registry.md
Implements: ADR-015, ADR-022, ADR-024
2026-06-23 14:40:50 +00:00
7345ef5442 Implement handler registration and operation registry
Implements the dispatch core for the call protocol per ADR-022 and ADR-024:

- Handler async closure type alias returning ResponseEnvelope
- HandlerRegistration bundle: spec, handler, provenance, composition
  authority, scoped env, capabilities
- OperationProvenance enum with all 6 variants (Local, FromOpenAPI,
  FromMCP, FromCall, FromJsonSchema, Session)
- OperationRegistry with register/registration/invoke/list_operations
- invoke flow: visibility check (Internal from wire -> NOT_FOUND),
  ACL with authority switch (internal: true -> handler_identity,
  internal: false -> caller identity), handler dispatch
- OperationRegistryBuilder with new/with_local/with_leaf/with_leaf_provenance/with/build
- make_handler helper for boxing async handlers
- 21 unit tests covering invoke, visibility, ACL authority switch,
  builder provenance, and lookup behavior
2026-06-23 14:40:13 +00:00
c2c88833db tasks: mark call/registry/operation-context completed 2026-06-23 14:30:37 +00:00
fbc30d281e feat(call): implement OperationContext, AbortPolicy, CompositionAuthority, ScopedOperationEnv (task: call/registry/operation-context)
Implement operation context types in registry/context.rs: OperationContext (10
fields, internal pub(crate) + is_internal()), AbortPolicy (AbortDependents
default), CompositionAuthority (none/new/as_identity for ACL), ScopedOperationEnv
(empty/new/allows), generate_request_id (UUID v4). Added minimal OperationEnv
trait in registry/env.rs (invoke/invoke_with_policy/contains) so the env field
compiles — operation-env task will expand with LocalOperationEnv and
CompositeOperationEnv. 37 unit tests.

Refs: docs/architecture/crates/call/operation-registry.md
Implements: ADR-015, ADR-022, ADR-024
2026-06-23 14:29:18 +00:00
3b9c480dad Implement OperationContext, AbortPolicy, CompositionAuthority, ScopedOperationEnv
Implements the operation context types in registry/context.rs (ADR-015,
ADR-022, ADR-024): OperationContext with all 10 fields (internal is
pub(crate) for writes, read via is_internal()), AbortPolicy enum with
AbortDependents default, CompositionAuthority with synthetic Identity
projection for ACL, ScopedOperationEnv reachability set, and
generate_request_id() (UUID v4). Adds a minimal OperationEnv trait
forward-declaration in registry/env.rs so the context env field compiles;
the operation-env task will expand it.
2026-06-23 14:27:46 +00:00
de91f3bdb0 tasks: mark call/protocol/pending-request-map completed 2026-06-23 14:25:58 +00:00
f92e7af13f feat(call): implement PendingRequestMap for call correlation (task: call/protocol/pending-request-map)
Implement PendingRequestMap in protocol/pending.rs with Call (oneshot) and
Subscribe (mpsc) entries, ID-based correlation (ADR-012), timeout-based eviction,
fail_all for connection close, and silent discard of unknown request IDs. 17 unit
tests.

Refs: docs/architecture/crates/call/call-protocol.md
Implements: ADR-012
2026-06-23 14:24:44 +00:00
e63a36ede0 Implement PendingRequestMap for call protocol
Correlates call.responded events back to call.requested by request ID
(stream-agnostic per ADR-012). Manages Call (oneshot) and Subscribe
(mpsc) entries with timeout-based eviction and fail_all on connection
close. Unknown request IDs are silently discarded.
2026-06-23 14:23:49 +00:00
dabb0d8b68 tasks: mark vault/spec-sync-remove-drift completed 2026-06-23 14:17:39 +00:00
d0f633c71d docs(vault): remove drift tracking artifacts, bump vault docs to stable (task: vault/spec-sync-remove-drift)
Remove the Known Source Drift table from vault/README.md. Remove all 'known
drift'/'current source uses X' prose from Security Constraints in README,
encryption.md, service.md (constraint statements preserved). Remove stale
ADR-025/postcard notes in protocol.md. Bump all 5 vault doc frontmatter to
status: stable. Update architecture/README.md vault doc statuses to stable
and Current State to remove 'pending ADR-025/026 refactor' language.

Refs: docs/architecture/crates/vault/README.md (drift cleanup)
2026-06-23 14:17:10 +00:00
482901db74 tasks: mark core/config completed 2026-06-23 14:16:38 +00:00
323ee85d40 docs(vault): remove drift tracking artifacts, bump vault docs to stable
The vault spec-to-implementation sync is complete. Remove the drift
tracking tools that were only needed during sync:

- Remove the Known Source Drift table from vault/README.md
- Remove 'known drift' / 'current source uses X' prose from Security
  Constraints sections in vault/README.md, encryption.md, and service.md.
  The permanent constraint statements (OsRng for IVs, zeroized drop,
  no unwrap, etc.) are preserved.
- Remove the drift paragraph in encryption.md Key Versioning.
- Remove stale 'to be updated per ADR-025' / 'postcard tests to be
  removed' notes in protocol.md References.
- Bump status: draft -> stable in the frontmatter of all vault docs
  (README, mnemonic-derivation, encryption, service, protocol).
- Update architecture/README.md: vault doc status entries to stable,
  Current State paragraph reflects vault implementation complete (no
  'pending ADR-025/026 refactor' language).
2026-06-23 14:15:13 +00:00