Spaces:
Running on Zero
Running on Zero
| # HearthNet β Spec Set Overview | |
| This directory is the implementation-level specification for HearthNet. It supersedes the design-level PRD for any conflict on the wire format, file layout, or API surface. | |
| The documents are intentionally redundant in some places so each module spec can be read independently during implementation. | |
| --- | |
| ## 0. How to read this set | |
| Read in this order: | |
| 1. **00-OVERVIEW.md** (this file) β module map, dependency graph, build order | |
| 2. **GLOSSARY.md** β canonical names for every entity that appears in more than one doc | |
| 3. **CAPABILITY_CONTRACT.md** β the wire-level source of truth; everything else must comply | |
| 4. **cross-cutting/X01..X04** β concerns that touch every module | |
| 5. **modules/M01..M13** β per-module specs in dependency order | |
| Cross-references between documents use the shorthand `[M03 Β§4.2]` (module 3, section 4.2) or `[CONTRACT Β§7.1]` (the contract document, section 7.1). | |
| --- | |
| ## 1. Module map | |
| ### Numbered modules (from PRD v2 Β§20) | |
| | ID | Module | Spec file | Concern | | |
| |-----|-------------------------|----------------------------------------------|------------------------------------------------------| | |
| | M01 | Identity & manifests | `modules/M01-identity.md` | Crypto identity, signing, verification, manifests | | |
| | M02 | Discovery | `modules/M02-discovery.md` | Finding peers on a LAN or via relay | | |
| | M03 | Capability bus | `modules/M03-bus.md` | Routing requests to capabilities | | |
| | M04 | LLM service | `modules/M04-llm.md` | Language model inference capabilities | | |
| | M05 | RAG service | `modules/M05-rag.md` | Retrieval-augmented generation | | |
| | M06 | Marketplace service | `modules/M06-marketplace.md` | Community posts, offers, requests | | |
| | M07 | File / blobs | `modules/M07-file-blobs.md` | Content-addressed storage and transfer | | |
| | M08 | UI | `modules/M08-ui.md` | Gradio dashboard + topology viz + mobile | | |
| | M09 | Emergency detector | `modules/M09-emergency.md` | Internet up/down detection + mode transitions | | |
| | M10 | Chat service | `modules/M10-chat.md` | Direct messages + store-and-forward | | |
| | M11 | Embedding service | `modules/M11-embedding.md` | Text and image embedding capabilities | | |
| | M12 | CLI | `modules/M12-cli.md` | `hearthnet` command-line entry points | | |
| | M13 | Onboarding | `modules/M13-onboarding.md` | First-run UX, invite QR, key generation flow | | |
| ### Cross-cutting modules | |
| | ID | Module | Spec file | Concern | | |
| |-----|-----------------|----------------------------------------|------------------------------------------------------| | |
| | X01 | Transport | `cross-cutting/X01-transport.md` | HTTP server, HTTP client, TLS, streaming, backpressure | | |
| | X02 | Events | `cross-cutting/X02-events.md` | Event log, Lamport clocks, snapshots, gossip sync | | |
| | X03 | Observability | `cross-cutting/X03-observability.md` | Logging, metrics, tracing, self-diagnostics | | |
| | X04 | Config | `cross-cutting/X04-config.md` | Configuration loading and validation | | |
| --- | |
| ## 2. Dependency graph | |
| ``` | |
| ββββββββββββ | |
| β config β X04 | |
| ββββββ¬ββββββ | |
| β (everyone reads it) | |
| ββββββββββββββββ΄βββββββββββββββ | |
| βΌ βΌ | |
| βββββββββββ βββββββββββββββ | |
| β identityβ M01 βobservabilityβ X03 | |
| ββββββ¬βββββ βββββββββββββββ | |
| β | |
| ββββββββββΌβββββββββββββ¬βββββββββββββ | |
| βΌ βΌ βΌ βΌ | |
| ββββββββ βββββββββββ βββββββββββ ββββββββββββ | |
| βeventsβ βdiscoveryβ βtransportβ β blobs β X02 / M02 / X01 / part-of-M07 | |
| ββββ¬ββββ ββββββ¬βββββ ββββββ¬βββββ ββββββ¬ββββββ | |
| β β β β | |
| β βββββββββ¬ββββ β | |
| β βΌ β | |
| β βββββββββββ β | |
| β β bus β M03 β | |
| β ββββββ¬βββββ β | |
| β β β | |
| β βββββββββββ¬βββββ΄βββββ¬βββββββββ β | |
| β βΌ βΌ βΌ βΌ βΌ | |
| β βββββββ ββββββββ ββββββββββ ββββββββββ | |
| β β llm β βembed β β rag β β file β M04 / M11 / M05 / M07 | |
| β βββββββ ββββ¬ββββ βββββ¬βββββ ββββββββββ | |
| β β β | |
| β βββββββββββ (rag uses embed) | |
| β | |
| β ββββββββββββββ ββββββββ | |
| βββΊβ marketplaceβ β chat β M06 / M10 | |
| β ββββββββββββββ ββββββββ | |
| β β β | |
| ββββββββββββββ β | |
| β | |
| βββββββββββΌβββββββββββ | |
| β emergency β M09 | |
| ββββββββββ¬ββββββββββββ | |
| β | |
| ββββββββββΌββββββββββββ | |
| β ui β M08 | |
| ββββββββββββββββββββββ | |
| β | |
| ββββββββββΌββββββββββββ | |
| β onboarding β M13 | |
| ββββββββββββββββββββββ | |
| β | |
| ββββββββββΌββββββββββββ | |
| β cli β M12 | |
| ββββββββββββββββββββββ | |
| ``` | |
| Hard rules: | |
| - **No service imports from another service.** Services talk to each other only via the bus. | |
| - **No layer below the bus imports anything above it.** Transport never imports a service; identity never imports the bus. | |
| - **The bus does not know what services exist** at build time. Services register themselves at startup. | |
| - **UI never imports a service directly.** It calls capabilities via the bus. | |
| --- | |
| ## 3. File tree (Python package layout) | |
| ``` | |
| hearthnet/ | |
| βββ __init__.py | |
| βββ __main__.py # python -m hearthnet β cli.main() | |
| βββ version.py # __version__ = "0.1.0" | |
| β | |
| βββ config.py # X04 | |
| β | |
| βββ identity/ # M01 | |
| β βββ __init__.py | |
| β βββ keys.py | |
| β βββ manifest.py | |
| β βββ tokens.py # Phase 2 | |
| β | |
| βββ observability/ # X03 | |
| β βββ __init__.py | |
| β βββ logging.py | |
| β βββ metrics.py | |
| β βββ tracing.py | |
| β βββ doctor.py | |
| β | |
| βββ events/ # X02 | |
| β βββ __init__.py | |
| β βββ log.py | |
| β βββ lamport.py | |
| β βββ types.py | |
| β βββ replay.py | |
| β βββ snapshot.py | |
| β βββ sync.py | |
| β | |
| βββ discovery/ # M02 | |
| β βββ __init__.py | |
| β βββ mdns.py | |
| β βββ udp.py | |
| β βββ peers.py # peer registry (in-memory) | |
| β βββ relay.py # Phase 2 | |
| β | |
| βββ transport/ # X01 | |
| β βββ __init__.py | |
| β βββ server.py | |
| β βββ client.py | |
| β βββ streams.py | |
| β βββ backpressure.py | |
| β βββ tls.py | |
| β | |
| βββ blobs/ # M07 (the storage half) | |
| β βββ __init__.py | |
| β βββ store.py | |
| β βββ chunker.py | |
| β βββ transfer.py | |
| β | |
| βββ bus/ # M03 | |
| β βββ __init__.py | |
| β βββ capability.py | |
| β βββ registry.py | |
| β βββ router.py | |
| β βββ health.py | |
| β βββ schema.py | |
| β βββ trace.py | |
| β | |
| βββ services/ # L4 | |
| β βββ __init__.py | |
| β βββ base.py | |
| β βββ llm/ # M04 | |
| β β βββ __init__.py | |
| β β βββ service.py | |
| β β βββ tokenizers.py | |
| β β βββ backends/ | |
| β β βββ __init__.py | |
| β β βββ base.py | |
| β β βββ llama_cpp.py | |
| β β βββ ollama.py | |
| β β βββ lmstudio.py | |
| β β βββ hf_api.py | |
| β β βββ anthropic_api.py | |
| β βββ embedding/ # M11 | |
| β β βββ __init__.py | |
| β β βββ service.py | |
| β β βββ backends.py | |
| β βββ rag/ # M05 | |
| β β βββ __init__.py | |
| β β βββ service.py | |
| β β βββ chunker.py | |
| β β βββ ingest.py | |
| β β βββ store.py | |
| β βββ file/ # M07 (the service half) | |
| β β βββ __init__.py | |
| β β βββ service.py | |
| β βββ marketplace/ # M06 | |
| β β βββ __init__.py | |
| β β βββ service.py | |
| β β βββ post.py | |
| β β βββ views.py | |
| β βββ chat/ # M10 | |
| β βββ __init__.py | |
| β βββ service.py | |
| β βββ delivery.py | |
| β βββ views.py | |
| β | |
| βββ emergency/ # M09 | |
| β βββ __init__.py | |
| β βββ detector.py | |
| β βββ state.py | |
| β | |
| βββ ui/ # M8 + M13 | |
| β βββ __init__.py | |
| β βββ app.py | |
| β βββ topology.py | |
| β βββ theme.py | |
| β βββ onboarding.py # M13 | |
| β βββ tabs/ | |
| β β βββ __init__.py | |
| β β βββ ask.py | |
| β β βββ chat.py | |
| β β βββ marketplace.py | |
| β β βββ files.py | |
| β β βββ emergency.py | |
| β β βββ settings.py | |
| β βββ mobile/ # static assets | |
| β βββ index.html | |
| β βββ app.js | |
| β βββ style.css | |
| β | |
| βββ cli.py # M12 | |
| βββ node.py # Orchestrator (composes everything) | |
| βββ doctor.py # (re-export of observability.doctor) | |
| tests/ | |
| βββ unit/ # per-module | |
| β βββ test_identity_keys.py | |
| β βββ test_identity_manifest.py | |
| β βββ test_events_log.py | |
| β βββ ... | |
| βββ integration/ # multi-node | |
| βββ test_three_node_mesh.py | |
| βββ test_emergency_mode.py | |
| βββ test_rejoin_sync.py | |
| ``` | |
| --- | |
| ## 4. Canonical conventions | |
| ### 4.1 Type aliases (use these names everywhere) | |
| ```python | |
| NodeID = str # "ed25519:XXXX-XXXX-XXXX-XXXX" | |
| CommunityID = str # "ed25519:..." | |
| CapabilityName = str # "llm.chat" | |
| Version = tuple[int, int] # (1, 0) | |
| Lamport = int | |
| CID = str # "blake3:..." | |
| EventID = str # ULID | |
| TraceID = str # ULID | |
| SchemaHash = str # "blake3:..." | |
| WallClock = str # RFC 3339 UTC: "2026-05-26T08:14:22Z" | |
| Signature = str # "ed25519:<base64-url-nopad>" | |
| Topic = str # "marketplace.post.created" | |
| ErrorCode = Literal[ | |
| "not_found", "capacity_exceeded", "schema_mismatch", "unauthorized", | |
| "revoked", "internal_error", "not_implemented", "timeout", "partition", | |
| "invalid_signature", "expired", "rate_limited", "bad_request", | |
| ] | |
| TrustLevel = Literal["unknown", "member", "trusted", "anchor"] | |
| Profile = Literal["anchor", "hearth", "spark", "bridge"] | |
| Stability = Literal["experimental", "beta", "stable"] | |
| ``` | |
| These are defined in `hearthnet.types` and re-exported by every module that uses them. Never invent a synonym. | |
| ### 4.2 Naming | |
| - Functions: `snake_case`, verb-first (`load_keys`, `verify_signature`, `route_request`) | |
| - Classes: `PascalCase`, noun (`NodeManifest`, `CapabilityBus`, `RagService`) | |
| - Constants: `SCREAMING_SNAKE` (`MANIFEST_TTL_SECONDS`) | |
| - Module-private: leading underscore (`_compute_canonical_json`) | |
| - Async functions: same naming as sync, no `async_` prefix | |
| - Protocols / interfaces: `PascalCase` ending in capability noun (`LlmBackend`, `Service`) | |
| ### 4.3 Error handling | |
| - All errors that cross a process boundary become an `HearthNetError` with an `ErrorCode` | |
| - All errors that stay in-process are domain exceptions inheriting from `HearthNetError` | |
| - Never raise `RuntimeError` or bare `Exception` in production code | |
| - Logging exceptions: always with `exc_info=True` so traceback survives | |
| ### 4.4 Async vs sync | |
| - I/O is async (asyncio) | |
| - CPU-bound work (PDF parsing, embedding) runs in `asyncio.to_thread` or a dedicated process pool | |
| - Public APIs are async unless explicitly noted (`load_keys` is sync, returns from disk) | |
| ### 4.5 Time | |
| - All wall-clock timestamps in events: RFC 3339 UTC, e.g. `2026-05-26T08:14:22Z` | |
| - All durations: integers in seconds, named `*_seconds` (never `*_secs`, `*_s`) | |
| - Logical ordering: Lamport clocks; wall clock is advisory only | |
| ### 4.6 Sizes | |
| - Bytes: integers, named `*_bytes` | |
| - KB/MB/GB shown to users only at the UI layer, never in protocol/event payloads | |
| --- | |
| ## 5. Build order (hackathon-aligned) | |
| Strictly follow this order. Each step is independently demoable. | |
| | Step | Modules built | What you can demo | | |
| |------|----------------------------------------|------------------------------| | |
| | 1 | X04 (config), X03 (logging only) | Process boots, logs to file | | |
| | 2 | M01 (identity, manifests) | `hearthnet init` works | | |
| | 3 | X02 (events log + Lamport, no sync) | Marketplace events persist | | |
| | 4 | X01 (transport, server only) | Two nodes can ping each other| | |
| | 5 | M02 (discovery, mDNS only) | Two nodes find each other | | |
| | 6 | M03 (bus with fake echo service) | A capability call round-trips| | |
| | 7 | M04 (LLM, llama.cpp or LM Studio backend) | Real LLM call across nodes | | |
| | 8 | M11 (embeddings) | Embed text via the bus | | |
| | 9 | M05 (RAG) | RAG-grounded answer | | |
| | 10 | M08 (UI shell + topology viz) | Visible mesh, visible routing| | |
| | 11 | M09 (emergency detector) | Banner toggles on cable yank | | |
| | 12 | M06 (marketplace) | Post visible across nodes | | |
| | 13 | M10 (chat) | Cross-node DM | | |
| | 14 | M07 (file/blobs) | CID-addressed file transfer | | |
| | 15 | M12 (CLI), M13 (onboarding) | First-run UX polished | | |
| | 16 | X02 sync, X03 metrics, X03 doctor | Production-ish polish | | |
| --- | |
| ## 6. Versioning of this spec set | |
| Every spec file carries a header `Spec version: vX.Y` and a `Last touched: <date>`. Bump the minor on additive changes, the major on breaking changes. The contract document's version is the version everyone else complies with β module specs may lag by one minor. | |
| The Python package version (`hearthnet.version.__version__`) and the contract version are independent. The contract version appears in the `version` field of every node manifest and is checked at handshake. | |
| --- | |
| ## 7. Out-of-band documents | |
| Not in this spec set but referenced: | |
| - **PRD v2** (`../HEARTHNET_PRD_v2.md`) β vision, scope, monetisation, phased roadmap | |
| - **README** (in repo root, written later) β user-facing quickstart | |
| - **THREAT_MODEL.md** (Phase 2) β formal security write-up | |
| - **DEPLOYMENT.md** (Phase 2) β for the appliance and relay-tier operators | |