HearthNet-Nemotron / docs /00-OVERVIEW.md
Chris4K's picture
prd splitted + contracts
6f9a5fd
|
Raw
History Blame
17.3 kB

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)

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