Files
alknet/docs/architecture/decisions/027-crate-decomposition.md
glm-5.1 19b3d3a078 docs: write Phase 0 architecture foundation — ADRs 026-034, spec docs, and task updates
Phase 0a — ADRs (9 new):
- ADR-026: Transport/interface separation (three-layer model)
- ADR-027: Crate decomposition (core, secret, storage, flowgraph, napi, CLI)
- ADR-028: Auth as irpc service (AuthProtocol behind feature flag)
- ADR-029: Identity as core type (Identity + IdentityProvider in alknet-core)
- ADR-030: Static/dynamic config split (ArcSwap, ConfigReloadHandle)
- ADR-031: Forwarding policy (rule-based allow/deny, TransportKind-aware)
- ADR-032: Event boundary discipline (domain, irpc, call protocol boundaries)
- ADR-033: OperationEnv universal composition (three dispatch paths)
- ADR-034: Head/worker terminology (replace hub/spoke)

Phase 0b — New spec documents (7):
- identity.md, services.md, interface.md, configuration.md,
  storage.md, flowgraph.md, secret-service.md

Updated existing docs:
- auth.md: reference identity.md for canonical definitions, add AuthProtocol
- open-questions.md: resolve OQ-12, OQ-16, OQ-18, OQ-22, OQ-23-25
- README.md: add all new docs, ADRs 026-034

Marked 19 architecture tasks as completed.
2026-06-07 09:32:58 +00:00

6.6 KiB

ADR-027: Crate Decomposition

Status

Accepted

Context

alknet-core currently contains everything: transport, SSH, auth, config, the call protocol handler, and the server accept loop. As the project grows to include SQLite-backed identity, HD key derivation, and metagraph storage, core would need to depend on rusqlite, bip39, petgraph, and other heavy dependencies — unacceptable for a library crate that CLI users embed.

Different deployment topologies need different subsets:

  • A minimal CLI tunnel only needs core, transport, and auth types
  • A head node needs SQLite-backed identity and the secret service
  • A flowgraph visualization tool only needs petgraph operations

Circular dependencies must be avoided. alknet-storage implements alknet-core's IdentityProvider trait, so alknet-core cannot depend on alknet-storage. alknet-storage references alknet-secret's EncryptedData wire format, but not as a crate dependency.

Decision

Decompose the project into six crates with a strict acyclic dependency graph.

Crate Structure

  1. alknet-core — Transport, SSH, call protocol, config, auth types, identity, OperationSpec, Interface trait. The foundational crate that everything else depends on (by type, not by crate dep in some cases).

    • Depends on: russh, tokio, irpc (feature-gated), serde, arc-swap
    • Does NOT depend on: alknet-secret, alknet-storage, alknet-flowgraph
  2. alknet-secret — BIP39 mnemonic generation, SLIP-0010 Ed25519 HD key derivation, AES-256-GCM encryption, SecretProtocol irpc service.

    • Depends on: bip39, ed25519-bip32 (or rust-bip32-ed25519), aes-gcm, sha2, irpc
    • Does NOT depend on: alknet-core, alknet-storage
  3. alknet-storage — SQLite-backed metagraph, identity tables, ACL graph, honker integration, StorageProtocol irpc service.

    • Depends on: rusqlite (via honker), honker, petgraph, jsonschema, irpc
    • Does NOT depend on alknet-core (but implements alknet-core's IdentityProvider trait via the trait, not a crate dep)
    • Does NOT depend on alknet-secret (but references EncryptedData type format for wire compatibility)
  4. alknet-flowgraphFlowGraph<N,E> over petgraph, operation graph, call graph, type compatibility checking.

    • Depends on: petgraph, serde, jsonschema, thiserror
    • Does NOT depend on: alknet-core, alknet-storage, alknet-secret
  5. alknet-napi — Node.js native addon. Exposes alknet-core to Node.js.

    • Depends on: alknet-core
    • Does NOT depend on: alknet-secret, alknet-storage, alknet-flowgraph
  6. alknet (CLI binary) — Assembles everything.

    • Depends on: alknet-core, alknet-secret (feature), alknet-storage (feature), alknet-flowgraph (feature), toml

Dependency Graph

                  alknet-secret
                 /             \
                /               \
alknet-core ←────                ←── alknet-storage
     ↑               \           /
     │                alknet-flowgraph
     │
alknet-napi
alknet (CLI binary — assembles everything)

Narrow Interface Points

Three types serve as the narrow interface points between crates:

  1. Identity — Defined in alknet_core::auth. Used by auth handler, forwarding policy, and call protocol. alknet-storage implements IdentityProvider to produce instances.

  2. IdentityProvider — Trait defined in alknet_core::auth. Implemented by ConfigIdentityProvider (in core) and StorageIdentityProvider (in alknet-storage). The CLI/NAPI layer wires the concrete implementation.

  3. OperationSpec — Defined in alknet_core::call. Used by the operation registry and by alknet-flowgraph for type compatibility checking. The bridge is serialization — flowgraph serializes to JSON, storage persists it.

irpc Feature Flag

irpc is a feature flag in alknet-core. When disabled, auth and config go through IdentityProvider and ConfigReloadHandle directly — no irpc overhead. Nodes that only do SSH tunneling don't need the service layer.

In alknet-secret and alknet-storage, irpc is an independent dependency, not feature-gated. These crates always define irpc service protocols because they are used in production deployments where the service layer is active.

alknet-storage's Relationship to alknet-core

alknet-storage does NOT depend on alknet-core as a crate. Instead:

  • alknet-storage defines its own IdentityProvider impl that matches alknet-core's trait signature. The trait is re-exported or defined locally with #[cfg(feature = "alknet-core")] interop.
  • In practice, the CLI binary crate depends on both and wires them together. alknet-storage provides StorageIdentityProvider; alknet-core takes impl IdentityProvider.

alknet-storage's Relationship to alknet-secret

alknet-storage does NOT depend on alknet-secret as a crate. Instead:

  • alknet-storage and alknet-secret share the EncryptedData wire format (key version, salt, IV, ciphertext). This is a type-level compatibility, not a crate dependency.
  • alknet-secret encrypts; alknet-storage stores the encrypted blob in a SecretNode in the metagraph. The bridge is serialization.

Consequences

  • Positive: Core is lean. No database, no crypto, no petgraph. CLI users get a small binary.
  • Positive: Services are pluggable. alknet-secret and alknet-storage can be swapped for alternative implementations.
  • Positive: No circular dependencies. The dependency graph is a DAG.
  • Positive: Deployment topology determines which crates to include. A CLI tunnel uses only alknet-core. A head node uses everything.
  • Positive: irpc is feature-gated in core. Minimal deployments don't pay for service layer overhead.
  • Negative: IdentityProvider trait interop between alknet-core and alknet-storage requires careful versioning. If the trait signature changes, both crates must update.
  • Negative: EncryptedData wire format compatibility between alknet-secret and alknet-storage is implicit (not enforced by the type system). A shared types crate could be extracted if needed, but adds another crate dependency.

References