waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
# Waddling Error Sequence Conventions

**Version**: 0.2.0  
**Status**: Active Convention  
**Enforcement**: SHOULD (Recommended, not required)

---

## Overview

To maximize consistency across the Waddling ecosystem, certain sequence numbers have **reserved semantic meanings**. Projects **SHOULD** use these conventions when the error matches the semantic category.

This makes error codes instantly recognizable across ALL Waddling projects.

---

## Benefits

- **Instant Recognition**: `.001` always means "missing" across all projects
-**Cross-Project Learning**: Understand one project → understand all
-**Searchability**: Search for `.001` finds all "missing" errors ecosystem-wide
-**Documentation**: Document patterns once, reference everywhere
-**Predictability**: Users can guess error meanings from sequence alone

---

## Reserved Sequences (001-030)

These sequences have standardized semantic meanings across the Waddling ecosystem.

**Organization Pattern:**
- **001-010**: Input/Data Validation - Problems with provided data
- **011-020**: State/Lifecycle - Object state and lifecycle issues  
- **021-030**: Resource/Storage - External resource access issues

### Input/Data Validation Errors (001-010)

| Sequence | Semantic      | Meaning                                    | Typical Severity |
|----------|---------------|--------------------------------------------|------------------|
| **001**  | MISSING       | Required parameter/argument not provided   | Error            |
| **002**  | MISMATCH      | Values don't match expected type/length    | Error            |
| **003**  | INVALID       | Format/validation failed                   | Error            |
| **004**  | OVERFLOW      | Value too large for container/type         | Error            |
| **005**  | UNDERFLOW     | Value too small for requirement            | Error            |
| **006**  | OUTOFBOUNDS   | Index/value outside valid range            | Error            |
| **007**  | DUPLICATE     | Duplicate entry in collection/set          | Error            |
| **008**  | DENIED        | Permission/access denied                   | Error            |
| **009**  | UNSUPPORTED   | Feature not supported                      | Error            |
| **010**  | DEPRECATED    | Feature deprecated (warning)               | Warning          |

#### Examples

```rust
use waddling_errors::{ErrorCode, Severity};

// .001 = MISSING (input not provided)
const ERR_MISSING_PARAM: ErrorCode = 
    ErrorCode::new(Severity::Error, "API", "PARAM", 1);
// Error: [E.API.PARAM.001] Required parameter 'api_key' not provided

// .002 = MISMATCH (type/length mismatch)
const ERR_LENGTH_MISMATCH: ErrorCode = 
    ErrorCode::new(Severity::Error, "CRYPTO", "LENGTH", 2);
// Error: [E.CRYPTO.LENGTH.002] Expected 32 bytes, got 16

// .003 = INVALID (validation failed)
const ERR_INVALID_PATTERN: ErrorCode = 
    ErrorCode::new(Severity::Error, "PATTERN", "REGEX", 3);
// Error: [E.PATTERN.REGEX.003] Invalid regex syntax

// .007 = DUPLICATE (duplicate in collection)
const ERR_DUPLICATE_ENTRY: ErrorCode = 
    ErrorCode::new(Severity::Error, "DB", "ENTRY", 7);
// Error: [E.DB.ENTRY.007] Duplicate entry in unique constraint

// .010 = DEPRECATED
const WARN_DEPRECATED_API: ErrorCode = 
    ErrorCode::new(Severity::Warning, "API", "FUNC", 10);
// Warning: [W.API.FUNC.010] Function deprecated, use new_api() instead
```

---

### State/Lifecycle Errors (011-020)

| Sequence | Semantic       | Meaning                                    | Typical Severity |
|----------|----------------|--------------------------------------------|------------------|
| **011**  | UNINITIALIZED  | Object/resource not initialized            | Error            |
| **012**  | ALREADYINIT    | Already initialized (double-init)          | Error            |
| **013**  | CLOSED         | Resource closed/disposed                   | Error            |
| **014**  | CANCELLED      | Operation was cancelled                    | Error            |
| **015**  | INPROGRESS     | Operation already in progress              | Blocked          |
| **016**  | NOTREADY       | Not ready for operation                    | Error/Blocked    |
| **017**  | TIMEOUT        | Operation timed out                        | Blocked/Error    |
| **018**  | STALE          | Resource/state is stale/outdated           | Warning/Error    |
| **019**  | *(reserved)*   | Reserved for future use                    | -                |
| **020**  | *(reserved)*   | Reserved for future use                    | -                |

#### Examples

```rust
// .011 = UNINITIALIZED
const ERR_NOT_INITIALIZED: ErrorCode = 
    ErrorCode::new(Severity::Error, "ENGINE", "STATE", 11);
// Error: [E.ENGINE.STATE.011] Engine not initialized, call init() first

// .012 = ALREADYINIT
const ERR_ALREADY_INIT: ErrorCode = 
    ErrorCode::new(Severity::Error, "ENGINE", "STATE", 12);
// Error: [E.ENGINE.STATE.012] Engine already initialized

// .014 = CANCELLED
const ERR_CANCELLED: ErrorCode = 
    ErrorCode::new(Severity::Error, "TASK", "STATE", 14);
// Error: [E.TASK.STATE.014] Operation cancelled by user

// .015 = INPROGRESS
const BLOCKED_IN_PROGRESS: ErrorCode = 
    ErrorCode::new(Severity::Blocked, "TASK", "STATE", 15);
// Blocked: [B.TASK.STATE.015] Compilation in progress

// .017 = TIMEOUT
const ERR_OPERATION_TIMEOUT: ErrorCode = 
    ErrorCode::new(Severity::Error, "NET", "TIMEOUT", 17);
// Error: [E.NET.TIMEOUT.017] Operation timed out after 30s
```

---

### Resource/Storage Errors (021-030)

| Sequence | Semantic       | Meaning                                    | Typical Severity |
|----------|----------------|--------------------------------------------|------------------|
| **021**  | NOTFOUND       | Resource/entity not found in storage       | Error            |
| **022**  | ALREADYEXISTS  | Resource already exists (create conflict)  | Error            |
| **023**  | CONFLICT       | Version/data conflict (concurrent edit)    | Error            |
| **024**  | LOCKED         | Resource locked by another process         | Blocked          |
| **025**  | CORRUPTED      | Data corrupted/integrity check failed      | Critical         |
| **026**  | EXHAUSTED      | Resource exhausted (out of memory, etc.)   | Critical/Error   |
| **027**  | UNAVAILABLE    | Service/resource temporarily unavailable   | Error/Blocked    |
| **028**  | UNREACHABLE    | Network/host unreachable                   | Error            |
| **029**  | DISCONNECTED   | Connection lost/dropped                    | Error            |
| **030**  | *(reserved)*   | Reserved for future use                    | -                |

#### Examples

```rust
// .021 = NOTFOUND (resource doesn't exist)
const ERR_FILE_NOT_FOUND: ErrorCode = 
    ErrorCode::new(Severity::Error, "IO", "FILE", 21);
// Error: [E.IO.FILE.021] File 'config.toml' not found

// .022 = ALREADYEXISTS (create conflict)
const ERR_FILE_EXISTS: ErrorCode = 
    ErrorCode::new(Severity::Error, "IO", "FILE", 22);
// Error: [E.IO.FILE.022] File already exists, cannot overwrite

// .023 = CONFLICT (version/data conflict)
const ERR_VERSION_CONFLICT: ErrorCode = 
    ErrorCode::new(Severity::Error, "DB", "VERSION", 23);
// Error: [E.DB.VERSION.023] Version conflict - concurrent modification

// .024 = LOCKED
const BLOCKED_MUTEX: ErrorCode = 
    ErrorCode::new(Severity::Blocked, "THREAD", "MUTEX", 24);
// Blocked: [B.THREAD.MUTEX.024] Resource locked, waiting...

// .025 = CORRUPTED
const CRIT_CORRUPTED: ErrorCode = 
    ErrorCode::new(Severity::Critical, "DATA", "INTEGRITY", 25);
// Critical: [C.DATA.INTEGRITY.025] Checksum failed - data corrupted

// .027 = UNAVAILABLE
const ERR_SERVICE_UNAVAILABLE: ErrorCode = 
    ErrorCode::new(Severity::Error, "API", "SERVICE", 27);
// Error: [E.API.SERVICE.027] Database temporarily unavailable

// .028 = UNREACHABLE
const ERR_HOST_UNREACHABLE: ErrorCode = 
    ErrorCode::new(Severity::Error, "NET", "HOST", 28);
// Error: [E.NET.HOST.028] Remote host unreachable

// .029 = DISCONNECTED
const ERR_CONNECTION_LOST: ErrorCode = 
    ErrorCode::new(Severity::Error, "NET", "CONN", 29);
// Error: [E.NET.CONN.029] Connection dropped unexpectedly
```

---

## Project-Specific Sequences (031-897)

Use for **domain-specific errors** that don't fit reserved semantic categories.

Projects have complete freedom in this range - use whatever makes sense for your domain.

#### Examples

```rust
const ERR_MAC_VERIFICATION: ErrorCode = 
    ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 31);

const ERR_HMAC_COMPUTE: ErrorCode = 
    ErrorCode::new(Severity::Error, "CRYPTO", "HMAC", 32);

const ERR_UNEXPECTED_TOKEN: ErrorCode = 
    ErrorCode::new(Severity::Error, "parser", "SYNTAX", 50);

const ERR_AST_MALFORMED: ErrorCode = 
    ErrorCode::new(Severity::Error, "parser", "AST", 51);
```

---

## Success/Completion Sequences (998-999)

| Sequence | Semantic       | Meaning                                    | Typical Severity |
|----------|----------------|--------------------------------------------|------------------|
| **998**  | PARTIAL        | Partial success (some items succeeded)     | Success/Warning  |
| **999**  | COMPLETE       | Full completion (all succeeded)            | Success/Completed|

#### Examples

```rust
// .999 = COMPLETE
const SUCCESS_REDACTION: ErrorCode = 
    ErrorCode::new(Severity::Success, "REDACT", "DONE", 999);
// Success: [S.REDACT.DONE.999] Redaction completed successfully

const COMPLETE_COMPILE: ErrorCode = 
    ErrorCode::new(Severity::Completed, "BUILD", "DONE", 999);
// Completed: [K.BUILD.DONE.999] Compilation finished

// .998 = PARTIAL
const SUCCESS_PARTIAL: ErrorCode = 
    ErrorCode::new(Severity::Success, "BUILD", "RESULT", 998);
// Success: [S.BUILD.RESULT.998] 8/10 files compiled successfully
```

---

## Usage Guidelines

### ✅ DO: Use Reserved Sequences When Semantically Appropriate

```rust
// Good - follows convention
const ERR_MISSING_KEY: ErrorCode = 
    ErrorCode::new(Severity::Error, "CRYPTO", "KEY", 1);  // .001 = MISSING

const ERR_TYPE_MISMATCH: ErrorCode = 
    ErrorCode::new(Severity::Error, "TYPE", "CHECK", 2);  // .002 = MISMATCH
```

### ✅ DO: Use Project-Specific Sequences (031-897) for Domain Logic

```rust
// Good - domain-specific, no reserved semantic fits
const ERR_MAC_VERIFY: ErrorCode = 
    ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 31);

const ERR_PATTERN_COMPLEX: ErrorCode = 
    ErrorCode::new(Severity::Warning, "PATTERN", "PERF", 45);
```

### ❌ DON'T: Redefine Reserved Sequences with Different Meanings

```rust
// BAD - .001 should mean "missing", not "corrupted"
const ERR_CORRUPTED: ErrorCode = 
    ErrorCode::new(Severity::Error, "DATA", "CHECK", 1);  // ❌ Wrong!

// CORRECT - use .025 for corruption
const ERR_CORRUPTED: ErrorCode = 
    ErrorCode::new(Severity::Critical, "DATA", "CHECK", 25);  // ✅ Right!
```

### ✅ DO: Document Deviations

If you must deviate from conventions, document why:

```rust
// Using .050 instead of .001 because our "missing" has domain-specific meaning
const ERR_CUSTOM_MISSING: ErrorCode = 
    ErrorCode::new(Severity::Error, "CUSTOM", "LOGIC", 50);
```

---

## Quick Reference Table

| Range     | Usage                          | Examples                              |
|-----------|--------------------------------|---------------------------------------|
| 001-010   | Input/Data validation          | Missing param, mismatch, invalid, duplicate |
| 011-020   | State/Lifecycle                | Uninitialized, closed, cancelled, timeout   |
| 021-030   | Resource/Storage               | Not found, already exists, locked, corrupted|
| 031-897   | Project-specific (free use)    | Domain-specific logic                 |
| 898-997   | *(reserved for future)*        | Reserved for future conventions       |
| 998-999   | Success/completion (reserved)  | Partial success, full completion      |

---

## Cross-Project Examples

### Crypto Library

```rust
// Input validation (001-010)
const ERR_MISSING_SALT: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "SALT", 1);
const ERR_LENGTH_MISMATCH: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "LENGTH", 2);
const ERR_INVALID_KEY: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "KEY", 3);

// Resource errors (021-030)
const CRIT_MAC_CORRUPTED: ErrorCode = ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 25);

// Domain-specific (031+)
const ERR_HMAC_COMPUTE: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "HMAC", 31);
const SUCCESS_REDACT: ErrorCode = ErrorCode::new(Severity::Success, "REDACT", "DONE", 999);
```

### Compiler/Parser

```rust
// Input validation (001-010)
const ERR_MISSING_SEMICOLON: ErrorCode = ErrorCode::new("parser", "SYNTAX", 1);
const ERR_TYPE_MISMATCH: ErrorCode = ErrorCode::new("semantic", "TYPE", 2);
const ERR_INVALID_SYNTAX: ErrorCode = ErrorCode::new("parser", "SYNTAX", 3);

// State errors (011-020)
const ERR_NOT_INITIALIZED: ErrorCode = ErrorCode::new("ENGINE", "STATE", 11);

// Resource errors (021-030)
const ERR_FILE_NOTFOUND: ErrorCode = ErrorCode::new("io", "FILE", 21);
const BLOCKED_MUTEX: ErrorCode = ErrorCode::new("linker", "MUTEX", 24);

const COMPLETE_BUILD: ErrorCode = ErrorCode::new("build", "DONE", 999);
```

### Web API Service

```rust
// Input validation (001-010)
const ERR_MISSING_HEADER: ErrorCode = ErrorCode::new(Severity::Error, "HTTP", "HEADER", 1);
const ERR_INVALID_JSON: ErrorCode = ErrorCode::new(Severity::Error, "JSON", "PARSE", 3);
const ERR_DENIED: ErrorCode = ErrorCode::new(Severity::Error, "AUTH", "PERM", 8);

// State errors (011-020)
const ERR_SESSION_CLOSED: ErrorCode = ErrorCode::new(Severity::Error, "SESSION", "STATE", 13);
const ERR_TIMEOUT: ErrorCode = ErrorCode::new(Severity::Error, "REQUEST", "TIMEOUT", 17);

// Resource errors (021-030)
const ERR_USER_NOTFOUND: ErrorCode = ErrorCode::new(Severity::Error, "DB", "USER", 21);
const ERR_EMAIL_EXISTS: ErrorCode = ErrorCode::new(Severity::Error, "DB", "EMAIL", 22);
const ERR_DB_UNAVAILABLE: ErrorCode = ErrorCode::new(Severity::Error, "DB", "CONN", 27);
```

**Notice the pattern**: Across ALL projects:
- **001-010**: Input problems (missing param, invalid format, denied access)
- **011-020**: State problems (not initialized, closed, timeout)
- **021-030**: Resource problems (not found, already exists, unavailable)

**Users instantly understand error semantics just from the sequence number!**

---

## Enforcement

See `docs/ENFORCEMENT.md` for strategies to enforce these conventions.

**Summary**: These are **SHOULD** guidelines (RFC 2119), not strict requirements. Projects are encouraged but not forced to follow them.

---

## Evolution

This convention document may be updated in future versions to:
- Add new reserved sequences in empty slots (019-020, 030, 898-997)
- Refine semantic definitions based on real-world usage
- Document common patterns that emerge

**Stability Promise**: Existing reserved sequences (001-030, 998-999) will **never change meaning** in v0.x or v1.x. Only additions will be made to empty slots.

**Version 0.2.0 Changes** (this version):
- Reorganized into clear matrix pattern: Input/Data (0s), State/Lifecycle (10s), Resource/Storage (20s)
- Moved DUPLICATE from 014 → 007 (it's input validation, not state)
- Moved TIMEOUT from 007 → 017 (it's state/lifecycle, not input)
- Moved CONFLICT from 015 → 023 (it's resource conflict, not state)
- Added STALE (018) for outdated state detection
- Reordered resource errors for better logical flow

---

## References

- RFC 2119 (MUST/SHOULD/MAY): https://www.rfc-editor.org/rfc/rfc2119
- Semantic Versioning: https://semver.org/
- HTTP Status Codes (inspiration): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

---

**Made with 🦆 by the Waddling team**