{
  "markdown": "# HAAP Public Directory (`haap-directory`)\n\nThe federated **phone book** of the HAAP (Hermes Agent Alliance Protocol)\necosystem. HAAP agents register a signed capability manifest, prove they\ncontrol their messaging endpoint, keep their entry alive with signed\nheartbeats, and become discoverable by capability, geography, language and\nfree text.\n\n> **Phone book, not a notary — and never a judge.** Identity lives in the\n> agents' Ed25519 keys, not in the directory. The directory indexes signed\n> manifests and verifies endpoint control; its compromise must never allow\n> impersonation. It returns *labelled signals with provenance*, never a\n> \"safe / trusted\" verdict. See [`docs/SPEC.md`](docs/SPEC.md) for the full\n> architecture and trust model.\n\nThis is the production evolution of the in-memory reference registry that\nships inside the `haap` client package. It is **wire-compatible** with the\nunmodified `haap` client (`haap/registry_client.py`) and adds SQLite\npersistence, a canonical `/v1` API, an append-only audit chain, rate limiting\nand a hardened validation surface.\n\n## Status\n\nAll phases of the `docs/SPEC.md §7` build plan (F0–F6) are implemented, tested,\nand green. The full L0–L5 trust ladder is live.\n\n| Phase | Scope | State |\n|---|---|---|\n| **F0** | Repo skeleton, persistent SQLite store, `haap-dird` CLI, `/health`, config precedence | ✅ |\n| **F1** | L1 proof-of-endpoint registration on SQLite, persistence, upsert/expiry, stable error codes | ✅ |\n| **F2** | Search (capability / free-text AND / geo / pagination / trust filters), heartbeat (v1 signed + legacy), expiry prune | ✅ |\n| **F3** | L2 domain verification (DNS TXT / HTTPS well-known), injectable resolver, 90-day expiry | ✅ |\n| **F4** | L3 vouching (graph, paths, caps) + L4 reports, auto-suspend, decay, moderation, appeals | ✅ |\n| **F5** | L5 signed checkpoints, `/v1/audit/*` (head/log/checkpoints/verify/agent), response signing | ✅ |\n| **F6** | Federation mirror seam, Docker image, `/metrics`, rate-limit hardening, operator docs | ✅ |\n\nThe layered-trust design principle holds throughout: the directory returns\nlabelled signals with provenance (`domain_verified`, `vouches_in`, `reports`,\n`status`, `block_recommendation`, `audit_verifiable`) and **never** a\n\"safe/trusted\" verdict — the consumer always decides.\n\n## Install & run\n\nRequires Python 3.10+. The only runtime dependency is `cryptography`.\n\n```bash\npip install -e .            # or: pip install -e '.[dev]' for tests\nhaap-dird --db ./dird.db --host 127.0.0.1 --port 8444 --ttl-hours 24\n# or, from a source checkout without installing:\npython haap_dird.py --db ./dird.db --port 8444\n```\n\nOther CLI actions: `--gen-key` (mint/show the directory signing key),\n`--prune` (offline prune of expired entries), `--version`. Configuration\nprecedence is **CLI flags > `~/.haap/dird.json` > env `HAAP_DIRD_*` >\ndefaults** (see [`docs/OPERATE.md`](docs/OPERATE.md)).\n\n## API at a glance\n\nCanonical endpoints under `/v1`; legacy aliases keep the `haap` client working.\n\n| Method & path | Purpose |\n|---|---|\n| `POST /v1/register` · `/v1/register/complete` | L1 proof-of-endpoint registration (202 → 201) |\n| `POST /v1/heartbeat` | Signed heartbeat renews the entry's TTL |\n| `GET  /v1/search` · `/v1/agents/{fp}` | Search + full manifest with trust block |\n| `POST /v1/verify-domain` · `/v1/verify-domain/confirm` · `GET /v1/verify-domain/status` | L2 domain verification |\n| `POST /v1/vouches` · `DELETE /v1/vouches/{id}` · `GET /v1/agents/{fp}/vouches[/outgoing]` · `GET /v1/trust/paths` | L3 vouching |\n| `POST /v1/reports` · `GET /v1/agents/{fp}/reports` | L4 reports |\n| `POST /v1/reports/{id}/takedown` · `/v1/agents/{fp}/suspend` · `/unsuspend` · `/appeal` | L4 moderation |\n| `GET  /v1/audit/head` · `/log` · `/checkpoints` · `/verify` · `/agents/{fp}/audit` | L5 transparency chain |\n| `GET  /health` · `/metrics` | Observability |\n| `POST /register` · `/register/complete` · `/heartbeat`, `GET /search` · `/agents/{fp}` | Legacy aliases (identical semantics) |\n\nErrors use a stable envelope `{\"error\": {\"code\", \"message\", \"request_id\"}}`\nwith the code table in `docs/SPEC.md §4.10`.\n\n## Design notes / deviations from the SPEC\n\n- **Stdlib HTTP, not FastAPI.** The SPEC §6.1 *recommends* FastAPI but\n  explicitly allows stdlib; the underlying implementation brief mandates\n  \"stdlib first\". Building on `http.server` + `sqlite3` keeps the runtime\n  dependency footprint to just `cryptography`, makes legacy wire-compatibility\n  trivial (same stack as the reference), and removes a network-install step\n  from deployment. Validation that FastAPI/Pydantic would give for free is\n  implemented explicitly in `manifest.py` and the HTTP layer (size caps,\n  float/forbidden-field rejection, stable error codes).\n- **Canonical JSON is vendored** (`canonical.py`) rather than imported from\n  `haap`, so the directory has no hard import dependency on the client package\n  (SPEC §6.3). It is byte-for-byte identical and covered by the compatibility\n  test.\n- **One connection + a single write lock** with `BEGIN IMMEDIATE` transactions.\n  SQLite is single-writer; this keeps the L5 audit entry in the *same*\n  transaction as the state change it records, and is correct and simple at v1\n  scale.\n\n## Testing\n\n```bash\npython -m pytest -q\n# with the companion client available for the compatibility test:\nHAAP_REPO=/path/to/haap python -m pytest -q\n```\n\nThe suite covers every phase: the happy path and each rejection case with its\nstable code, update-vs-fresh, injected-clock expiry, search semantics, L2\ndomain verification (stub resolver), L3 vouching (graph, paths, caps, rules),\nL4 reports/auto-suspend/moderation/appeal, the L5 audit chain (link + tamper\ndetection + signed checkpoints), `/metrics`, rate-limit flood (429 +\n`Retry-After`), the federation mirror, and — when the companion `haap` checkout\nis present — the **unmodified** `haap` client registering, searching and\nheartbeating against this service.\n\nThe L2 `dns_txt` method shells out to the system `dig` binary\n(`bind9-dnsutils`); `https_well_known` works with the stdlib alone. In tests\nboth are driven through an injectable stub resolver, so neither is contacted.\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n",
  "bytes": 6222,
  "sha": "39a9a03aca9494613ee557826aa4eb53e1561583a3f44b054c6f8d2525025151",
  "repo_slug": "acoalex/haap-directory",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_acoalex_haap_directory_openwiki_index_md_73988fa9/readme"
}