diff --git a/docs/architecture/auth.md b/docs/architecture/auth.md index 58c224e..e234284 100644 --- a/docs/architecture/auth.md +++ b/docs/architecture/auth.md @@ -1,6 +1,6 @@ --- status: draft -last_updated: 2026-06-07 +last_updated: 2026-06-09 --- # Authentication @@ -318,6 +318,13 @@ security consideration: | [035](decisions/035-streaminterface-messageinterface-split.md) | StreamInterface/MessageInterface | Credential presentation differs per (Transport, Interface) pair | | [037](decisions/037-api-keys-dynamic-config.md) | API keys in DynamicConfig | Hash-verified bearer tokens for service accounts | +## Phase 2 Implementation Notes + +- `ConfigIdentityProvider::resolve_from_token()` now handles API keys (`alk_` prefix) via SHA-256 hash verification with expiry checking +- `ApiKeyEntry` struct added to `AuthPolicy` with prefix, hash, scopes, description, expires_at fields +- API keys produce `Identity { id: prefix, scopes: from_entry, resources: {} }` +- Both AuthTokens (Ed25519 signed) and API keys (hash-verified bearer) go through `resolve_from_token()`, discriminated by format/prefix + ## References - [identity.md](identity.md) — Canonical Identity and IdentityProvider definitions diff --git a/docs/architecture/call-protocol.md b/docs/architecture/call-protocol.md index c339f24..0b1dc88 100644 --- a/docs/architecture/call-protocol.md +++ b/docs/architecture/call-protocol.md @@ -1,6 +1,6 @@ --- status: draft -last_updated: 2026-06-07 +last_updated: 2026-06-09 --- # Call Protocol @@ -526,6 +526,14 @@ agent service itself is built on top, not into the core. | [033](decisions/033-operationenv-irpc-call-protocol.md) | OperationEnv | Universal composition with three dispatch paths | | [035](decisions/035-streaminterface-messageinterface-split.md) | StreamInterface/MessageInterface | Call protocol accepts events from both interface categories | +## Phase 2 Implementation Notes + +- `SshSession::recv()` and `SshSession::send()` now functional — bridged to call protocol via `alknet-control:0` SSH channel using `ControlChannelBridge` with mpsc channels +- `FrameFramedReader`/`FrameFramedWriter` added to `call::frame` for async length-prefixed EventEnvelope I/O +- `RawFramingSession` implemented with first-frame auth: first frame's payload extracted as AuthToken, resolved via `IdentityProvider::resolve_from_token()`, session transitions to authenticated state on success +- `OperationEnv.credentials(service)` method added for outbound credential resolution (ADR-036) +- `CredentialProvider` trait and `CredentialSet` enum defined in `alknet_core::credentials` + ## References - [auth.md](auth.md) — Identity and `IdentityProvider` trait diff --git a/docs/architecture/configuration.md b/docs/architecture/configuration.md index ac8dfef..7a22bc1 100644 --- a/docs/architecture/configuration.md +++ b/docs/architecture/configuration.md @@ -1,6 +1,6 @@ --- status: draft -last_updated: 2026-06-07 +last_updated: 2026-06-09 --- # Configuration @@ -314,6 +314,14 @@ iroh_relay = "https://relay.alk.dev" | [029](decisions/029-identity-core-type.md) | Identity as core type | DynamicConfig.auth consumed by IdentityProvider | | [028](decisions/028-auth-irpc-service.md) | Auth as irpc service | ConfigService wraps DynamicConfig reloads | +## Phase 2 Implementation Notes + +- `DynamicConfig.auth` now includes `api_keys: Vec` (ADR-037) +- `DynamicConfig.credentials: HashMap` added for static outbound credentials (ADR-036) +- `ListenerConfig` restructured from flat struct to enum: `Stream { transport, interface }`, `Http { config: HttpListenerConfig }`, `Dns { config: DnsListenerConfig }` (ADR-035) +- `HttpListenerConfig` and `DnsListenerConfig` builder-pattern structs added +- `ListenerConfig::validate()` now validates all three variants + ## References - [research/configuration.md](../research/configuration.md) — Full analysis and proposed solution diff --git a/docs/architecture/interface.md b/docs/architecture/interface.md index 7d0a7c1..33df9ed 100644 --- a/docs/architecture/interface.md +++ b/docs/architecture/interface.md @@ -365,6 +365,20 @@ for listener in listeners { | [029](decisions/029-identity-core-type.md) | Identity as core type | Auth resolution across interfaces | | [031](decisions/031-forwarding-policy.md) | Forwarding policy | Layer 3 policy applied to Layer 2 channel requests | +## Phase 2 Implementation Notes + +- `Interface` trait renamed to `StreamInterface` throughout alknet-core (ADR-035 implemented) +- `MessageInterface` trait added with `handle_request(InterfaceRequest) -> Result` (ADR-035 implemented) +- `InterfaceRequest` and `InterfaceResponse` types implemented +- `HttpInterface` and `DnsInterface` stub structs added (Phase 5 for full implementation) +- `InterfaceConfig` split into `StreamInterfaceConfig` and `MessageInterfaceConfig` +- `StreamInterfaceKind` and `MessageInterfaceKind` enums added +- `ListenerConfig` restructured from flat struct to enum with `Stream`, `Http`, `Dns` variants +- `TransportKind::Dns` removed from the enum (DNS is a MessageInterface, not a transport) +- `TransportKind::WebTransport` updated from `{ host: String }` to `{ server_name: Option }` +- `RawFramingInterface` fully implemented with first-frame auth +- `SshSession::recv()`/`send()` bridge to call protocol via `alknet-control:0` channel implemented, using `ControlChannelBridge` with mpsc channels + ## References - [definitions.md](definitions.md) — Terminology disambiguation, credential presentation