# Core Library Architecture
This document describes the architecture of `waddling-errors`.
## Overview
The core library has two layers:
1. **Core types** (no_std) - Minimal types for error codes
2. **Doc generator** (std, behind `doc-gen` feature) - Registry + renderer system
---
## Core Types (no_std)
The foundation is intentionally minimal:
```
┌─────────────────────────────────────────────────────┐
│ Code<C, P> │
│ ┌──────────┬───────────┬─────────┬──────────┐ │
│ │ Severity │ Component │ Primary │ Sequence │ │
│ │ E │ Auth │ Token │ 001 │ │
│ └──────────┴───────────┴─────────┴──────────┘ │
│ ↓ │
│ "E.Auth.Token.001" │
└─────────────────────────────────────────────────────┘
```
### Files
| `severity.rs` | `Severity` enum (E, W, C, B, H, S, K, I, T) |
| `code.rs` | `Code<C, P>` struct - generic over component/primary |
| `traits.rs` | Trait hierarchy for extensibility |
### Trait Hierarchy
```
Level 1 (Required) Level 2 (Optional) Level 3 (Optional)
────────────────── ────────────────── ──────────────────
ComponentId ComponentIdDocumented ErrorMetadata
└─ as_str() └─ description() └─ full doc fields
└─ owner()
PrimaryId PrimaryIdDocumented FieldMeta
└─ as_str() └─ description() └─ field metadata
```
Users choose the level that fits their needs.
---
## Doc Generator (requires `doc-gen` feature)
A **registry + renderer** pattern for generating error documentation.
### Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ REGISTRATION PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ErrorDocBuilder DocRegistry │
│ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ .code() │ register() │ errors: HashMap │ │
│ │ .message() │ ───────────────► │ components: HashMap │ │
│ │ .hints() │ │ primaries: HashMap │ │
│ │ .tags() │ │ sequences: HashMap │ │
│ │ .build() │ └─────────────────────────┘ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ RENDERING PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ DocRegistry.render(renderers, role_filter) │
│ │ │
│ ├─► filter errors by role (Public/Developer/Internal) │
│ │ │
│ └─► for each Renderer: │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌────────────────────┐ │
│ │JsonRenderer │ │HtmlRenderer │ │ CatalogRenderer │ │
│ │ │ │ │ │ - Full │ │
│ │ → .json │ │ → .html │ │ - Compact │ │
│ └─────────────┘ └─────────────┘ │ - Minimal │ │
│ └────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
### Files
| `mod.rs` | Module exports |
| `registry.rs` | `DocRegistry` - central data store |
| `error_builder.rs` | `ErrorDocBuilder` - builder pattern for ErrorDoc |
| `types.rs` | Data structures (`ErrorDoc`, `ComponentMeta`, etc.) |
| `renderer.rs` | `Renderer` trait + `JsonRenderer`, `HtmlRenderer` |
| `catalog_renderer.rs` | `CatalogRenderer` for hash-to-error lookups |
| `render_methods.rs` | `DocRegistry` rendering methods |
| `validation.rs` | Link validation (`see_also` references) |
| `html/` | HTML template, customization, assets |
### Key Types
| `DocRegistry` | Central store for all error documentation |
| `ErrorDocBuilder` | Builder for creating `ErrorDoc` instances |
| `ErrorDoc` | Complete documentation for one error code |
| `Renderer` | Trait for output format abstraction |
| `ComponentMeta` | Metadata for a component (Auth, Database, etc.) |
| `PrimaryMeta` | Metadata for a primary category (Token, Query, etc.) |
| `SequenceMeta` | Metadata for a sequence number (001, 017, etc.) |
### Data Flow
```
1. BUILD ErrorDocBuilder.code("E.Auth.Token.001")
.message("Token expired")
.hints(["Refresh the token"])
.build()
│
▼
2. REGISTER DocRegistry.register(error_doc)
- Stores in errors HashMap
- Updates component/primary counts
│
▼
3. RENDER DocRegistry.render([JsonRenderer, HtmlRenderer], Role::Public)
- Filters errors by role
- Calls each renderer
- Writes output files
```
### Renderer Outputs
| Renderer | Output | Use Case |
|----------|--------|----------|
| `JsonRenderer` | `project.json` | API consumption, tooling |
| `HtmlRenderer` | `index.html` | Human-readable docs site |
| `CatalogRenderer` (Full) | `catalog.json` | Hash→error lookup with all fields |
| `CatalogRenderer` (Compact) | `catalog.json` | Production APIs (smaller) |
| `CatalogRenderer` (Minimal) | `catalog.json` | IoT/embedded (smallest) |
### Role-Based Filtering
Errors and their fields can be filtered by visibility:
```
Role::Public → End users see these
Role::Developer → Developers see these + Public
Role::Internal → Everyone sees everything
```
Filtering happens at two levels:
1. **Error level**: Entire errors can be role-gated
2. **Field level**: Individual hints/tags can be role-gated
---
## Feature Flags
```
┌─────────────────────────────────────────────────────┐
│ waddling-errors │
├─────────────────────────────────────────────────────┤
│ (default) │ Core types only (no_std) │
│ std │ Standard library support │
│ alloc │ Heap allocation without std │
│ metadata │ ErrorMetadata trait │
│ doc-gen │ Documentation generator (std) │
│ serde │ Serialization support │
│ runtime-hash │ Runtime hash computation │
│ macros │ Re-export waddling-errors-macros │
└─────────────────────────────────────────────────────┘
```
---
## Extension Points
### Custom Renderers
Implement the `Renderer` trait:
```rust
pub trait Renderer: Send + Sync {
fn format_name(&self) -> &str;
fn render(
&self,
registry: &DocRegistry,
errors: &[&ErrorDoc],
output_path: &Path,
filter_role: Option<Role>,
) -> std::io::Result<()>;
}
```
### Custom Components/Primaries
Implement `ComponentId`/`PrimaryId` traits (Level 1), optionally add documentation traits (Level 2).
---
## Related Documents
- [USAGE_GUIDE.md](USAGE_GUIDE.md) - How to use the library
- [FEATURE_FLAGS.md](FEATURE_FLAGS.md) - Feature flag details
- [DOC_GENERATION_GUIDE.md](DOC_GENERATION_GUIDE.md) - Doc generation walkthrough
- [../DESIGN_RATIONALE.md](../DESIGN_RATIONALE.md) - Why decisions were made