Commit Graph

152 Commits

Author SHA1 Message Date
bda18f6bef docs(architecture): sync secret-service spec with implementation and add unlock-passphrase-gap task
Update secret-service.md to reflect the actual alknet-secret implementation:
- Fix dependency names/versions: secp256k1 (not libsecp256k1), version 0.29,
  add tokio/irpc-derive/hmac/rand, use workspace refs
- Add SecretServiceActor and CacheConfig to public API
- Add ethereum.rs module to crate structure, fix test_vectors.rs filename
- DerivedKey is move-only (not Clone), matching the stronger security impl
- Update BIP39 pseudocode to actual derive_path_from_seed() API
- Document derive_password_string() convenience method
- Document SecretServiceActor::spawn() in irpc integration model
- Update Unlock variant to target state: { mnemonic, passphrase: Option }
- Add implementation gap note pointing to unlock-passphrase-gap task

Add tasks/integration/phase3/secret-service/unlock-passphrase-gap.md:
- Fix Unlock protocol variant to carry both mnemonic and BIP39 passphrase
- Currently the irpc message only has passphrase: String (used as mnemonic)
- The handle supports both parameters but the protocol can't convey them
2026-06-10 09:18:59 +00:00
e827e7d61f chore: update task review-alknet-secret-spec-conformance status to completed 2026-06-10 07:44:13 +00:00
1942e2c2cb chore: update task irpc-secret-protocol-integration status to completed 2026-06-10 07:43:02 +00:00
470473fbb9 feat(secret): wire SecretProtocol to irpc with SecretServiceActor
Apply #[rpc_requests(message = SecretMessage)] to SecretProtocol enum with
#[rpc(tx=oneshot::Sender<Result<T, SecretServiceError>>)] and #[wrap] attributes
on each variant. Add SecretServiceActor that wraps SecretServiceHandle and
processes SecretMessage variants via mpsc channel. Update DerivedKey
serialization to use is_human_readable() so postcard preserves private_key
bytes while JSON redacts them. Add Serialize/Deserialize to SecretServiceError
for irpc wire format compatibility. Add tokio dependency for actor runtime.
2026-06-10 07:41:53 +00:00
47968ee48d chore: update task key-caching-ttl status to completed 2026-06-10 07:33:15 +00:00
d152818aa2 Merge key-caching-ttl with conflict resolution: integrated cache with secp256k1 and derive-password 2026-06-10 07:33:08 +00:00
2d5113cc1f chore: update task secp256k1-ethereum-derivation status to completed 2026-06-10 07:30:36 +00:00
9390c27f7d Merge secp256k1-ethereum-derivation with conflict resolution in service.rs tests 2026-06-10 07:30:30 +00:00
18b4083a69 feat(secret): add TTL-based key cache with LRU eviction
Implement KeyCache in cache.rs with CachedKey (Zeroize-protected),
CacheConfig (TTL + max_entries), and lazy eviction. Wire cache into
SecretServiceInner: derive_* methods check cache before re-deriving,
Lock clears and zeroizes all cache entries, encrypt/decrypt use
cached encryption key. Per ADR-038 and OQ-SVC-04.
2026-06-10 07:30:10 +00:00
fb77338ace chore: update task derive-password-implementation status to completed 2026-06-10 07:29:06 +00:00
f4cacdbcaf feat(secret): add BIP-0032 secp256k1 derivation for Ethereum keys behind feature flag
Fix derive_ethereum_key to use BIP-0032 instead of SLIP-0010, which
incorrectly handled unhardened indices in the Ethereum path m/44'/60'/0'/0/0.
2026-06-10 07:29:05 +00:00
c0010c144b Add derive_password and derive_password_string methods to SecretServiceHandle
Implements deterministic password derivation using SLIP-0010 at the
given path. derive_password returns raw truncated key bytes;
derive_password_string returns Base64url-encoded (no padding) string.
Both require unlocked state (ServiceLocked if locked). Includes unit
tests for determinism, different paths, length truncation, locked
error, and Base64url encoding.
2026-06-10 07:26:59 +00:00
7bf0538416 chore: update task crypto-test-vectors status to completed 2026-06-10 07:05:25 +00:00
91cffcd276 test(secret): add BIP39, SLIP-0010, AES-256-GCM, and cross-consistency test vectors 2026-06-10 07:05:18 +00:00
31936ef008 chore: update task derivedkey-zeroize-security status to completed 2026-06-10 06:17:15 +00:00
460a589888 Merge remote-tracking branch 'origin/feat/derivedkey-zeroize-security' 2026-06-10 06:16:55 +00:00
eae47c366b feat(alknet-secret): make DerivedKey zeroize-on-drop, non-Clone, with redacted serialization
Per ADR-038, DerivedKey.private_key now derives Zeroize with #[zeroize(drop)]
ensuring sensitive key material is zeroized before deallocation. DerivedKey
is now move-only (no Clone), and JSON/debug output redacts private_key as
"[REDACTED]". Deserialization still works for postcard/irpc wire format.

Also fixes clippy needless_borrows_for_generic_args in encryption.rs and
applies cargo fmt to existing code.
2026-06-10 06:16:38 +00:00
74a9dafb57 chore: update task encryption-salt-kdf status to completed 2026-06-10 06:11:30 +00:00
8eb687afc0 docs(alknet-secret): document EncryptedData.salt as reserved for future KDF-based key derivation
Add module-level documentation explaining that the salt field is reserved
for Phase B KDF-based key rotation. Add doc comment on the salt field
clarifying it is not used in v1 key derivation. Add TODO(Phase B) comment
on salt generation in encrypt().
2026-06-10 06:10:34 +00:00
c88e97d7d5 chore: update task spec-update-secret-service status to completed 2026-06-10 06:08:57 +00:00
916ed91b79 docs: close 7 spec gaps in secret-service.md
Address implementation-identified gaps:
- Add irpc integration model (SecretServiceHandle vs Client<SecretProtocol>, dispatch paths)
- Add Key Caching subsection (derivation path as cache key, 1-hour TTL, LRU, cleared on Lock)
- Specify DerivedKey.private_key must derive Zeroize per ADR-038
- Add Password Derivation subsection (HMAC-SHA512, Base64url encoding)
- Add secp256k1 derivation note (BIP-0032 algorithm, feature flag)
- Document EncryptedData.salt as reserved for future KDF-based key rotation
- Add Test Vectors section (BIP39, SLIP-0010, AES-256-GCM known-answer)
- Mark OQ-SVC-04 as resolved
- Update dependencies (secp256k1 feature-gated, future KDF deps)
- Update crate structure diagram (add cache.rs, vectors_tests.rs)
2026-06-10 06:08:15 +00:00
83ea66b5d1 chore: prep Phase 3 tasks and workspace for alknet-secret development
- Add irpc (0.16) and irpc-derive (0.16) as workspace dependencies
- Add irpc, irpc-derive, and secp256k1 (optional) to alknet-secret Cargo.toml
- Clarify encryption-salt-kdf task: Option B (document salt as reserved) is the
  chosen path per spec update, removing Option A acceptance criteria
- Update irpc-secret-protocol-integration task with concrete irpc crate details:
  real crate on crates.io v0.16, #[rpc_requests] macro, workspace config,
  AuthProtocol pattern reference, DerivedKey serialization considerations
- Fix secp256k1-ethereum-derivation task: correct crate name is secp256k1
  (not libsecp256k1), add version pin 0.29
2026-06-10 05:57:27 +00:00
9ec7627d80 chore: add Phase 3 secret-service decomposition tasks
9 atomic tasks for alknet-secret spec conformance and gap closure,
derived from architect's implementation review. Dependencies form
a 5-generation graph starting with spec update, then parallel
implementation tasks, ending with a review gate.

Tasks address: DerivedKey zeroize security, key caching with TTL,
irpc protocol integration, password derivation, secp256k1/Ethereum
derivation, encryption salt/KDF, crypto test vectors, and final
spec conformance review.
2026-06-10 04:14:39 +00:00
04e969982e feat(secret): add alknet-secret crate and architecture spec for Phase 3
Create the alknet-secret crate with BIP39 mnemonic generation, SLIP-0010
Ed25519 HD key derivation, AES-256-GCM encryption, and SecretProtocol
irpc service definition. This is Phase 3.1 from the integration plan.

Architecture changes:
- Promote secret-service.md to reviewed status with full spec format
  (crate structure, public API, security model, phase progression,
   ADR/OQ cross-references, wire format compatibility section)
- Add ADR-038 (seed lifecycle and memory security): zeroize for v1,
  mlock deferred to Phase B
- Add OQ-SEC-01 (mlock/VirtualLock for seed RAM) to open-questions.md
- Update README.md with ADR-038 and secret-service status

Crate structure:
- src/mnemonic.rs: BIP39 phrase generation, validation, seed derivation
- src/derivation.rs: SLIP-0010 HD key derivation, path constants (74')
- src/encryption.rs: AES-256-GCM encrypt/decrypt, EncryptedData type
- src/protocol.rs: SecretProtocol irpc enum, DerivedKey, KeyType
- src/service.rs: SecretServiceHandle with Unlock/Lock lifecycle
- 40 passing tests (unit + integration + doc)
2026-06-09 13:49:53 +00:00
d1c57627c6 chore: update task review-core-bridge-phase2 status to completed 2026-06-09 11:37:34 +00:00
bcbe2f1761 docs: sync architecture docs with Phase 2 implementation state 2026-06-09 11:37:14 +00:00
dc3c8208df chore: update task axum-http-router-scaffold status to completed 2026-06-09 11:28:55 +00:00
d5d4b3c153 feat(core): add axum HTTP router scaffold with auth middleware and stealth handoff
Add http feature flag with axum, hyper, hyper-util, tower, and http-body-util
dependencies. Create http module with auth middleware (extracts Bearer token,
calls IdentityProvider::resolve_from_token, attaches Identity to extensions)
and router scaffold (default 404 fallback, no operational routes yet). Replace
send_fake_nginx_404 with axum router handoff when http feature is enabled;
fake 404 behavior preserved when http is disabled. Wire HttpInterface with
build_router() method and pass IdentityProvider through Server to handle_connection.
2026-06-09 11:27:27 +00:00
309a586403 chore: update task api-keys-dynamic-config status to completed 2026-06-09 11:02:13 +00:00
8429758697 Merge remote-tracking branch 'origin/feat/api-keys-dynamic-config' 2026-06-09 11:01:48 +00:00
1f55844935 feat(core): add API keys to DynamicConfig.auth and extend IdentityProvider token resolution 2026-06-09 11:01:33 +00:00
bdb0af499a chore: update task ssh-session-call-protocol-bridge status to completed 2026-06-09 10:57:51 +00:00
1282b87e5d Merge remote-tracking branch 'origin/feat/ssh-session-call-protocol-bridge' 2026-06-09 10:56:57 +00:00
30f2910567 feat(core): bridge SshSession recv/send to call protocol via alknet-control:0 channel
Implement the SSH session to call protocol bridge:
- Add FrameFramedReader/FrameFramedWriter for async I/O of length-prefixed EventEnvelope frames
- SshSession::recv() reads InterfaceEvent frames from the alknet-control:0 channel via mpsc
- SshSession::send() writes EventEnvelope frames to the alknet-control:0 channel via mpsc
- Add ControlChannelBridge implementing ControlChannelHandler for routing channel data
- SshHandler::channel_open_direct_tcpip routes alknet-control:0 to the bridge task
- Session Identity attached to every InterfaceEvent produced by recv()
- ControlChannelRouter gains take_handler() for non-control alknet-* channel routing
2026-06-09 10:56:29 +00:00
bfc92d4827 chore: update task raw-framing-interface-implementation status to completed 2026-06-09 10:53:33 +00:00
33f85a8448 Merge remote-tracking branch 'origin/feat/raw-framing-interface-implementation' 2026-06-09 10:53:14 +00:00
752ead9d9f feat(core): implement RawFramingInterface accept/recv/send with first-frame auth
Implement RawFramingSession with tokio::io::split for read/write halves,
BufReader/BufWriter for buffered I/O, and decode_with_remainder for
partial frame reassembly. Add first-frame authentication via
IdentityProvider::resolve_from_token(). Add RawFramingConfig.auth
field for IdentityProvider reference. Update SshInterface test for
new RawFramingConfig shape.
2026-06-09 10:52:54 +00:00
0be0df5e96 chore: update task credential-provider-trait status to completed 2026-06-09 10:52:33 +00:00
ff4ab71ed7 Merge remote-tracking branch 'origin/feat/credential-provider-trait' 2026-06-09 10:52:11 +00:00
f8b4fb66b3 Add CredentialProvider trait, CredentialSet enum, and ConfigCredentialProvider
Define the outbound authentication abstraction in alknet_core::credentials:
- CredentialProvider trait with get_credentials and refresh_credentials
- CredentialSet enum with ApiKey, Basic, Bearer, S3AccessKey, OidcToken, Custom variants
- ConfigCredentialProvider reads credentials from DynamicConfig.credentials
- SecretStoreCredentialProvider stub returns None for all lookups (Phase 3)
- Wire CredentialProvider into OperationEnv via credentials() method
- Add credentials HashMap field to DynamicConfig
2026-06-09 10:51:54 +00:00
4d5fec3619 chore: update task listenconfig-http-dns-stubs status to completed 2026-06-09 10:51:19 +00:00
aa7e843e2f feat(core): add HttpListenerConfig/DnsListenerConfig builders, ListenerConfig validation with is_valid_pair, and Server::run Http/Dns stubs 2026-06-09 10:50:19 +00:00
752e61df4f chore: update task stream-interface-message-interface-split status to completed 2026-06-09 10:35:34 +00:00
9e807883de feat(core): rename Interface to StreamInterface, add MessageInterface, restructure ListenerConfig
Per ADR-035: split Interface trait into StreamInterface (stream-based, SSH/RawFraming)
and MessageInterface (request/response, HTTP/DNS). Remove TransportKind::Dns (DNS is
a MessageInterface). Change WebTransport { host } to { server_name: Option<String> }.
Restructure ListenerConfig from flat struct to enum with Stream/Http/Dns variants.
2026-06-09 10:26:04 +00:00
d7538a7806 fix(tasks): correct Phase 2 task 1 and 2 to match actual codebase state
Task 1 (stream-interface-message-interface-split):
- Document that TransportKind::Dns EXISTS and must be removed (was incorrectly described as 'never added')
- Document that TransportKind::WebTransport has { host: String } and must be changed to { server_name: Option<String> }
- Document that ListenerConfig is a flat struct, not an enum, and must be restructured per ADR-035
- Move ListenerConfig restructuring, InterfaceConfig rename, and TransportKind cleanup into task 1 to avoid overlap with task 2
- Add HttpListenerConfig/DnsListenerConfig/StreamInterfaceKind/MessageInterfaceKind to task 1 scope

Task 2 (listenconfig-http-dns-stubs):
- Remove work now covered by task 1 (InterfaceConfig rename, TransportKind changes, ListenerConfig enum creation)
- Focus on wiring the new enum form into Server/ServeOptions/StaticConfig, adding constructors, validation, and accept loop stubs
2026-06-09 10:00:23 +00:00
aafee72f4c Decompose Phase 2 (Core Bridge) into 8 dependency-ordered tasks
Phase 2 completes the interface-to-protocol bridge and adds core types
that external crates depend on. The 8 tasks are organized into 5
generations with clear dependencies:

- Gen 1: StreamInterface/MessageInterface trait split (must go first)
- Gen 2: SshSession bridge, RawFraming impl, CredentialProvider (parallel)
- Gen 3: API keys in DynamicConfig (depends on CredentialProvider)
- Gen 4: ListenerConfig HTTP/DNS stubs + axum scaffold
- Gen 5: Review gate before Phase 3

Key design decisions:
- 2.4a/2.4b split: SecretStoreCredentialProvider deferred to Phase 3
- API keys (2.6) must land before axum scaffold (2.7)
- ListenerConfig (2.5) must land before axum scaffold (2.7)
- Gen 2 tasks are parallelizable (separate modules)
2026-06-09 09:33:22 +00:00
8f24fa6c09 Address Phase 2 sanity check issues in integration plan
- 2.1: Add prerequisites note (verify call::frame module, ControlChannelRouter
  wiring) before decomposition
- 2.2: Add raw framing auth design decision (first-frame auth event pattern
  instead of per-frame auth) — simpler, more secure, matches InterfaceEvent model
- 2.3: Add InterfaceConfig restructuring note, TransportKind::WebTransport
  tag addition (missed in Phase 1), note that TransportKind::Dns removal
  is a no-op (never added). Add scheduling note: do 2.3 early since
  subsequent tasks reference new trait names. Update ADR reference to 035.
- 2.4: Split into 2.4a (trait+enum+ConfigCredentialProvider) and 2.4b
  (SecretStoreCredentialProvider, Phase 3). Clarify that the Phase 2 impl
  is config-backed, not secret-backed.
- 2.5: Mark TransportKind::Dns removal as no-op since it was never added.
- 4.5: Note that doc sync round 1 is already done (commit cfc4400).
  Second sync needed after implementation to capture any deviations.
- Open questions: Mark OQ-IF-01 and OQ-IF-02 as resolved with ADR-035
  and ADR-031 references. Update OQ-P2-01 through P2-04 with ADR-036
  and resolution status.
2026-06-09 08:41:57 +00:00
cfc44008d3 Sync architecture specs with Phase 2 research findings
- Add definitions.md: normative terminology disambiguation (Interface, Service,
  Transport, Token, Identity, Domain, Scope, CredentialProvider, etc.)
- Add credentials.md: CredentialProvider trait and CredentialSet enum for
  outbound auth, mirroring IdentityProvider pattern for inbound auth
- Rewrite interface.md: StreamInterface/MessageInterface split (ADR-035),
  InterfaceRequest/InterfaceResponse, HttpInterface/DnsInterface stubs,
  ListenerConfig with Stream/Http/Dns variants, credential presentation table
- Update auth.md: API keys in DynamicConfig (ADR-037), credential presentation
  per (Transport, Interface) pair, ApiKeyEntry struct in AuthPolicy
- Update configuration.md: API keys, ListenerConfig with Http/Dns variants,
  expanded TOML config examples
- Update call-protocol.md: resolve OQ-IF-01 (InterfaceEvent carries
  EventEnvelope + Identity), add MessageInterface awareness to protocol
  adapter layer
- Update overview.md: three-layer model now includes StreamInterface/
  MessageInterface, CredentialProvider/CredentialSet exports, definitions.md
  reference, ADRs 035-037
- Update open-questions.md: resolve OQ-IF-01, OQ-IF-02, add OQ-P2-01
  through OQ-P2-04, add OQ-CP-01 through OQ-CP-04, add OQ-DEF-01,
  OQ-DEF-03, OQ-DEF-08
- Update README.md: add definitions.md, credentials.md, ADRs 035-037,
  phase2 research docs, current state description

Key architectural decisions:
- ADR-035: StreamInterface/MessageInterface split (two Layer 2 traits)
- ADR-036: CredentialProvider as core type (outbound auth, alknet_core::credentials)
- ADR-037: API keys as DynamicConfig auth (hash-verified bearer tokens)
2026-06-09 08:09:45 +00:00
d1af216334 Remove hardcoded HTTP routes from Phase 2.7 scaffold
The axum router scaffold now only includes auth middleware and stealth
handoff — no operational routes or path conventions. External HTTP path
routing (from_openapi inverse, custom S3/git/OpenAI paths) is deferred
to Phase 5 since it depends on the spec-generation work.
2026-06-09 06:15:22 +00:00
3a046546d4 Restructure integration plan: insert Phase 2 Core Bridge, renumber phases
- New Phase 2 (Core Bridge): SshSession recv/send, RawFramingInterface,
  StreamInterface/MessageInterface split, CredentialProvider trait,
  HTTP listener stub, API keys, axum scaffold
- Old Phase 2 (External Crates) → Phase 3
- Old Phase 3 (Integration) → Phase 4 (now includes doc sync)
- Old Phase 4 (Advanced) → Phase 5 (now includes full HTTP, git service)
- Updated open questions: resolved Phase 0/1 items, added Phase 2 OQs
- Updated inconsistencies: added items 8-11 (interface split, SshSession
  stubs, CredentialProvider gap, doc sync need)
2026-06-09 05:18:29 +00:00