/ ARCHITECTURE.md
ARCHITECTURE.md
  1  # Architecture
  2  
  3  ## Layer Diagram
  4  
  5  ```mermaid
  6  flowchart TD
  7      subgraph Presentation["Presentation Layer (6)"]
  8          CLI["auths-cli<br/><small>auths, auths-sign, auths-verify</small>"]
  9      end
 10  
 11      subgraph Infrastructure["Infrastructure Layer (5)"]
 12          INFRA_GIT["auths-infra-git<br/><small>Git audit adapter</small>"]
 13          INFRA_HTTP["auths-infra-http<br/><small>HTTP transport</small>"]
 14      end
 15  
 16      subgraph Services["Services Layer (4)"]
 17          SDK["auths-sdk<br/><small>workflows, clock injection</small>"]
 18          STORAGE["auths-storage<br/><small>Git/SQL storage adapters</small>"]
 19      end
 20  
 21      subgraph Domain["Domain Layer (3)"]
 22          ID["auths-id<br/><small>identity, attestation, KERI, traits</small>"]
 23          POLICY["auths-policy<br/><small>authorization evaluation</small>"]
 24      end
 25  
 26      subgraph Core["Core Layer (2)"]
 27          CORE["auths-core<br/><small>keychains, signing, ports</small>"]
 28      end
 29  
 30      subgraph Verification["Verification Layer (1)"]
 31          VERIFIER["auths-verifier<br/><small>FFI, WASM, minimal deps</small>"]
 32      end
 33  
 34      subgraph Crypto["Crypto Layer (0)"]
 35          CRYPTO["auths-crypto<br/><small>CryptoProvider, DID encoding</small>"]
 36      end
 37  
 38      CLI --> SDK
 39      CLI --> INFRA_GIT
 40      CLI --> INFRA_HTTP
 41      INFRA_GIT --> SDK
 42      SDK --> ID
 43      SDK --> CORE
 44      STORAGE --> ID
 45      ID --> CORE
 46      ID --> POLICY
 47      ID --> VERIFIER
 48      CORE --> VERIFIER
 49      CORE --> CRYPTO
 50      VERIFIER --> CRYPTO
 51  ```
 52  
 53  ## Dependency Direction Rule
 54  
 55  Dependencies flow **inward only**. Core crates must not reference adapter, server, or CLI crates.
 56  
 57  ```mermaid
 58  graph TD
 59      classDef core fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;
 60      classDef domain fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;
 61      classDef app fill:#fff3e0,stroke:#f57c00,stroke-width:2px;
 62      classDef outer fill:#fce4ec,stroke:#c2185b,stroke-width:2px;
 63  
 64      subgraph Presentation & Infrastructure
 65          CLI[CLI Crates]:::outer
 66          SRV[Server Crates]:::outer
 67          HTTP[infra-http]:::outer
 68          GIT[infra-git]:::outer
 69      end
 70  
 71      subgraph Application Layer
 72          SDK[auths-sdk]:::app
 73      end
 74  
 75      subgraph Domain Layer
 76          ID[auths-id]:::domain
 77      end
 78  
 79      subgraph Core Layer
 80          CORE[auths-core]:::core
 81      end
 82  
 83      %% Allowed Dependencies (Inward / Downward)
 84      CLI -->|Allowed| SDK
 85      SDK -->|Allowed| ID
 86      ID -->|Allowed| CORE
 87  
 88      SRV -->|Allowed| SDK
 89      SRV -->|Allowed| ID
 90      SRV -->|Allowed| CORE
 91  
 92      HTTP -->|Allowed| CORE
 93      GIT -->|Allowed| CORE
 94  
 95      %% Forbidden Dependencies (Outward / Upward)
 96      CORE -.->|Forbidden| ID
 97      CORE -.->|Forbidden| CLI
 98      CORE -.->|Forbidden| SRV
 99      ID -.->|Forbidden| SDK
100      SDK -.->|Forbidden| CLI
101  
102      %% Link Styling for emphasis (Optional, works in most markdown renderers)
103      linkStyle 0,1,2,3,4,5,6,7 stroke:#2e7d32,stroke-width:2px;
104      linkStyle 8,9,10,11,12 stroke:#c62828,stroke-width:2px,stroke-dasharray: 5 5;
105  ```
106  
107  Violations are caught by `cargo deny check bans` and `cargo clippy` (`disallowed-methods`).
108  
109  ## Port Inventory
110  
111  Ports are trait interfaces that decouple domain logic from infrastructure. Production adapters live in the appropriate infra crate under `src/adapters/`. Test doubles live in `auths-test-utils/src/fakes/` or `auths-test-utils/src/mocks/`.
112  
113  ### auths-verifier ports (`crates/auths-verifier/src/clock.rs`)
114  
115  | Trait | File | Adapter Crate | Production Adapter | Test Double |
116  |---|---|---|---|---|
117  | `ClockProvider` | `clock.rs` | `auths-verifier` | `SystemClock` | `MockClock` (test-utils fakes) |
118  
119  ### auths-core ports (`crates/auths-core/src/ports/`)
120  
121  | Trait | File | Adapter Crate | Production Adapter | Test Double |
122  |---|---|---|---|---|
123  | `ClockProvider` | `clock.rs` (re-exports from auths-verifier) | `auths-verifier` | `SystemClock` | `MockClock` |
124  | `IdentityResolver` | `network.rs` | `auths-infra-http` | `HttpIdentityResolver` | `FakeIdentityResolver` |
125  | `WitnessClient` | `network.rs` | `auths-infra-http` | `HttpWitnessClient` | inline fakes |
126  | `RegistryClient` | `network.rs` | `auths-infra-http` | `HttpRegistryClient` | inline fakes |
127  | `EventLogWriter` | `storage/event_log_writer.rs` | `auths-infra-git` | `GitEventLogWriter` | `FakeStorage` |
128  | `EventLogReader` | `storage/event_log_reader.rs` | `auths-infra-git` | `GitEventLogReader` | `FakeStorage` |
129  | `BlobReader` | `storage/blob_reader.rs` | `auths-infra-git` | `GitBlobReader` | `FakeStorage` |
130  | `BlobWriter` | `storage/blob_writer.rs` | `auths-infra-git` | `GitBlobWriter` | `FakeStorage` |
131  | `RefReader` | `storage/ref_reader.rs` | `auths-infra-git` | `GitRefReader` | `FakeStorage` |
132  | `RefWriter` | `storage/ref_writer.rs` | `auths-infra-git` | `GitRefWriter` | `FakeStorage` |
133  
134  ### auths-sdk ports (`crates/auths-sdk/src/ports/`)
135  
136  | Trait | File | Adapter Crate | Production Adapter | Test Double |
137  |---|---|---|---|---|
138  | `GitLogProvider` | `git.rs` | `auths-infra-git` | `SystemGitLogProvider` | `FakeGitLogProvider` |
139  | `GitConfigProvider` | `git_config.rs` | `auths-infra-git` | `SystemGitConfigProvider` | `FakeGitConfigProvider` |
140  | `GitDiagnosticProvider` | `diagnostics.rs` | `auths-sdk` | `PosixDiagnosticAdapter` | `FakeGitDiagnosticProvider` |
141  | `CryptoDiagnosticProvider` | `diagnostics.rs` | `auths-sdk` | `PosixDiagnosticAdapter` | `FakeCryptoDiagnosticProvider` |
142  | `ArtifactSource` | `artifact.rs` | `auths-cli` | `StdinArtifactSource` | inline fakes |
143  
144  ### auths-registry-server ports (`crates/auths-registry-server/src/ports/`)
145  
146  | Trait | File | Adapter Crate | Production Adapter | Test Double |
147  |---|---|---|---|---|
148  | `HttpAdapter` | `http.rs` | `auths-infra-http` | `ReqwestHttpAdapter` | `MockHttpAdapter` (mockall) |
149  | `PairingStore` | `pairing_store.rs` | `auths-registry-server` | `PostgresPairingStore` | `InMemoryPairingStore` |
150  | `SubscriptionStore` | `subscription_store.rs` | `auths-registry-server` | `PostgresSubscriptionStore` | — |
151  | `TenantMetadataStore` | `tenant_metadata_store.rs` | `auths-registry-server` | `PostgresTenantMetadataStore` | — |
152  | `TenantResolver` | `tenant_resolver.rs` | `auths-registry-server` | `FilesystemTenantResolver` | `SingleTenantResolver` |
153  
154  ## Bounded Context Guide
155  
156  ### auths-core
157  **Responsibility:** Ed25519 cryptography, platform keychains (macOS/Linux/Windows), port trait definitions for storage and network.
158  **Must NOT:** reference git2, axum, reqwest, or any presentation crate.
159  
160  ### auths-crypto
161  **Responsibility:** KERI key parsing, base64url encoding, low-level Ed25519 primitives.
162  **Must NOT:** reference any higher-layer crate.
163  
164  ### auths-id
165  **Responsibility:** Identity lifecycle state machine (inception, rotation, revocation), KEL (Key Event Log) domain logic and event validation, attestation port definitions (`AttestationSource`/`AttestationSink`).
166  **Must NOT:** reference auths-sdk, CLI, server crates, or git2 directly.
167  
168  ### auths-verifier
169  **Responsibility:** Standalone chain verification and signature checking. Designed for WASM, FFI, and minimal-dependency embedding. All time access via `ClockProvider` injection.
170  **Must NOT:** reference git2, auths-id, or any I/O crate.
171  
172  ### auths-sdk
173  **Responsibility:** Application-layer workflows (init, sign, verify, doctor). Orchestrates port traits without implementing I/O. All side effects are injected.
174  **Must NOT:** call `Utc::now()` directly, shell out, or write to disk.
175  
176  ### auths-cli
177  **Responsibility:** User-facing terminal commands, interactive prompts, JSON output mode.
178  **Must NOT:** contain business logic. All domain operations are delegated to auths-sdk workflows.
179  
180  ### auths-registry-server
181  **Responsibility:** HTTP API for KERI identity registration, KEL management, platform claims, multi-tenant routing.
182  **Must NOT:** contain domain logic beyond input validation and error translation to HTTP status codes.
183  
184  ### auths-auth-server
185  **Responsibility:** "Login with Auths" challenge-response authentication. Issues challenges, verifies signatures by resolving identity keys.
186  **Must NOT:** store private keys or implement key derivation logic.
187  
188  ### auths-infra-http
189  **Responsibility:** Production reqwest-backed implementations of `IdentityResolver`, `WitnessClient`, `RegistryClient` from auths-core.
190  **Must NOT:** contain business logic or be referenced by core/domain crates.
191  
192  ### auths-infra-git
193  **Responsibility:** Production git2-backed implementations of the storage ports defined in auths-core (`GitEventLogWriter`, `GitEventLogReader`, `GitBlobReader`, `GitBlobWriter`, `GitRefReader`, `GitRefWriter`) and git introspection ports from auths-sdk (`SystemGitLogProvider`, `SystemGitConfigProvider`).
194  **Must NOT:** contain business logic or be referenced by core/domain crates.
195  
196  ### auths-cache
197  **Responsibility:** Redis-backed tiered identity resolver with write-through archival to Git.
198  **Must NOT:** be referenced by core or domain crates.
199  
200  ### auths-index
201  **Responsibility:** SQLite-backed O(1) attestation index for fast lookups by device DID.
202  **Must NOT:** be referenced by core or domain crates.
203  
204  ### auths-test-utils
205  **Responsibility:** Shared test infrastructure — fakes, mocks, contract test macros, key fixtures.
206  **Must NOT:** be referenced in non-dev-dependencies (`publish = false` enforces this).
207  
208  ## Crate Dependency Graph
209  
210  ```mermaid
211  graph TD
212    auths-crypto
213    auths-verifier --> auths-crypto
214    auths-core --> auths-crypto
215    auths-core --> auths-verifier
216    auths-id --> auths-core
217    auths-id --> auths-crypto
218    auths-id --> auths-verifier
219    auths-id --> auths-policy
220    auths-id --> auths-index
221    auths-id --> auths-infra-git
222    auths-id --> auths-infra-http
223    auths-storage --> auths-id
224    auths-storage --> auths-core
225    auths-storage --> auths-index
226    auths-storage --> auths-verifier
227    auths-sdk --> auths-id
228    auths-sdk --> auths-core
229    auths-sdk --> auths-crypto
230    auths-sdk --> auths-verifier
231    auths-sdk --> auths-policy
232    auths-sdk --> auths-storage
233    auths-infra-git --> auths-sdk
234    auths-infra-git --> auths-core
235    auths-infra-git --> auths-verifier
236    auths-infra-http --> auths-core
237    auths-infra-http --> auths-verifier
238    auths-cli --> auths-sdk
239    auths-cli --> auths-id
240    auths-cli --> auths-core
241    auths-cli --> auths-crypto
242    auths-cli --> auths-verifier
243    auths-cli --> auths-storage
244    auths-cli --> auths-infra-git
245    auths-cli --> auths-infra-http
246    auths-cli --> auths-policy
247    auths-cli --> auths-index
248    auths-cli --> auths-telemetry
249  ```
250  
251  ## Key Patterns
252  
253  ### ClockProvider Injection
254  
255  Never call `Utc::now()` or `SystemTime::now()` directly in domain or application code. Always inject a `ClockProvider`:
256  
257  ```rust
258  use auths_verifier::clock::{ClockProvider, SystemClock};
259  use std::sync::Arc;
260  
261  pub struct MyService {
262      clock: Arc<dyn ClockProvider>,
263  }
264  
265  impl MyService {
266      pub fn production() -> Self {
267          Self { clock: Arc::new(SystemClock) }
268      }
269  
270      pub fn new(clock: Arc<dyn ClockProvider>) -> Self {
271          Self { clock }
272      }
273  }
274  ```
275  
276  In tests, use `MockClock` from `auths-test-utils` or define a local `TestClock`:
277  
278  ```rust
279  #[cfg(test)]
280  struct TestClock(chrono::DateTime<chrono::Utc>);
281  
282  #[cfg(test)]
283  impl ClockProvider for TestClock {
284      fn now(&self) -> chrono::DateTime<chrono::Utc> { self.0 }
285  }
286  ```
287  
288  The `clippy.toml` `disallowed-methods` entry enforces this at compile time in all crates with `#![deny(clippy::disallowed_methods)]`.
289  
290  ### Adding a New Port
291  
292  1. Define the trait in `src/ports/<name>.rs` in the lowest-layer crate that owns the abstraction.
293  2. Add `pub mod <name>;` and re-export from `src/ports/mod.rs`.
294  3. Implement the production adapter in the appropriate infra crate (`auths-infra-git`, `auths-infra-http`, etc.) under `src/adapters/<name>_adapter.rs`.
295  4. Add a fake to `auths-test-utils/src/fakes/<name>.rs` and a mock via `mockall::mock!` in `auths-test-utils/src/mocks/mod.rs`.
296  5. Inject via constructor: `fn new(..., port: Arc<dyn YourTrait>) -> Self`.
297  
298  ### Test Pyramid
299  
300  ```
301  Unit tests              — mocks/fakes, no I/O, <1ms each
302                          → auths-test-utils::mocks (mockall-generated)
303  
304  Integration boundary    — FakeRegistryBackend, no disk/network
305  contract tests          → auths-test-utils::fakes + contracts module
306  
307  E2E / disk tests        — real Git TempDir, real crypto
308                          → auths-test-utils::git::init_test_repo()
309  ```
310  
311  Network isolation for unit tests is enforced in CI via iptables (Linux `unit-tests-isolated` job). Unit tests that require network access are a bug.