Codebase Conventions
This appendix summarizes the layout and conventions used in the Asset Core codebase for external readers and contributors.
Overview
Asset Core follows consistent patterns across all crates for structure, naming, and documentation. Understanding these conventions helps you navigate the code and maintain consistency when contributing.
Detailed explanation
Repository Layout
asset-core/
├── core/ # Runtime engine (L1/L2/L3)
├── daemon-write/ # HTTP write daemon
├── daemon-read/ # HTTP read daemon
├── acctl/ # CLI tool
├── telemetry/ # Shared metrics crate
├── api-contract/ # OpenAPI spec generation
├── assetcore-adapters/ # Protocol adapters
├── system-tests/ # E2E test harness
├── sdk-python/ # Python SDK
└── Docs/ # Architecture documentation
Crate Structure
Each crate follows this pattern:
crate/
├── Cargo.toml
├── README.md # Crate overview
├── AGENTS.md # Rules for LLM agents
└── src/
├── lib.rs # Public API
├── mod.rs files # Module organization
└── tests/ # Unit tests
Layer Architecture (L1/L2/L3)
The core crate enforces strict layer separation:
| Layer | Location | Responsibility |
|---|---|---|
| L1 | core/src/storage/ | Raw data structures |
| L2 | core/src/operations/ | Business logic, events |
| L3 | core/src/runtime/ | Transactions, undo |
Rules:
- L2 may call L1, not vice versa
- L3 may call L2, not vice versa
- No cross-layer imports except downward
Naming Conventions
Files: snake_case
ingress_orchestrator.rs
commit_log_driver.rs
Types: PascalCase
struct ValidatedCommit { ... }
enum ContainerKind { ... }
Functions: snake_case
fn prepare_commit(&mut self) -> Result<...>
Constants: SCREAMING_SNAKE_CASE
const MAX_BATCH_SIZE: usize = 1000;
Documentation Headers
Every source file includes a header:
// =============================================================================
// Module: ingress/orchestrator
// Description: Coordinates request sequencing and commit pipeline
// Purpose: Provide backpressure-aware ingestion
// Dependencies: worker, append, state
// =============================================================================
This helps LLM agents understand context without reading full implementations.
Error Handling
Errors use typed enums with context:
#[derive(Debug, thiserror::Error)]
pub enum CommitError {
#[error("Container {0} not found")]
ContainerNotFound(ContainerId),
#[error("Insufficient balance: requested {requested}, available {available}")]
InsufficientBalance {
requested: u64,
available: u64,
},
}
Errors map to HTTP status codes via the API layer.
Metrics Naming
Metrics follow a consistent pattern:
assetcore_{daemon}_{subsystem}_{metric}_{unit}
Examples:
assetcore_write_ingress_queue_depthassetcore_read_snapshot_publish_duration_secondsassetcore_write_commit_log_lag
Testing Patterns
Unit tests: Inline in source files
#[cfg(test)]
mod tests {
use super::*;
// ...
}
Integration tests: Under tests/ directory
System tests: In system-tests crate
AGENTS.md Files
Each crate has an AGENTS.md with rules for code-generation agents:
- Invariants to preserve
- Patterns to follow
- Files to consult before changes
- Common pitfalls
Read the relevant AGENTS.md before modifying any crate.
Implementation notes
No Unsafe in Hot Paths
Performance comes from data layout, not unsafe code:
- Structure-of-Arrays (SoA) for cache efficiency
- Dense IDs instead of hashing
- Pre-allocated buffers
No Strings on Hot Paths
Identifiers are integers:
type ContainerId = u64;
type ClassId = u64;
type InstanceId = u64;
Strings are only for user-facing names and configuration.
Determinism Requirements
Operations must be deterministic:
- No system time during replay
- No random values
- No external dependencies during commit
Events carry post-state so replay is idempotent.
When to read this
Read this appendix when:
- Onboarding to the codebase
- Contributing changes
- Understanding metric names
- Navigating unfamiliar areas
For API usage, the reference docs are more relevant.
See also
- Write Path Architecture - Pipeline details
- Runtime Model - Architectural overview