Files
2026-06-05 15:34:21 +02:00

2.9 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

A self-hosted HTTP service that looks up Swedish phone numbers ("who is calling me?") by scraping reverse-lookup sites. Providers are WASM components (Component Model / WASI p2) loaded from a directory at startup; the host does all fetching and caching. Design spec: docs/superpowers/specs/2026-06-05-wasm-provider-service-design.md.

Commands

just test                  # build components + run all tests (preferred)
just run                   # build components + run the service
just build                 # release build of everything
cargo test -p whoareyou-provider-hitta      # provider parser tests (native, no WASM)
cargo test -p whoareyou-server --test component   # WIT-boundary integration test
cargo +nightly fmt         # always nightly, not stable
cargo clippy --workspace
./fetch-fixture <number>   # refresh an HTML fixture from hitta.se

The integration test needs the component built first — run via just test, or cargo build --release --target wasm32-wasip2 -p whoareyou-provider-hitta before bare cargo test.

Architecture

  • wit/provider.wit — the provider contract (metadata/requests/parse). Components are pure: no network, no filesystem. The HOST fetches URLs.
  • crates/providers/hitta — parse logic in parser.rs is plain Rust, unit-tested natively against fixtures/hitta/*.html; component.rs is thin WIT glue, compiled only for wasm32 (cargo test never touches WASM here). hitta.se serves Next.js App Router pages — data lives in RSC flight payloads (self.__next_f.push), NOT __NEXT_DATA__ (that's the dead 2019 format kept in old fixtures as a Failed-path regression case).
  • crates/server — lib + thin bin. service.rs holds the ProviderHandle + Fetch traits and LookupService (moka cache, TTL 24h, key provider:number; fetch failures are NOT cached). wasm.rs implements ProviderHandle over wasmtime (fresh Store per call, epoch deadline ≈5s — spawn_epoch_thread must run once at startup or runaway guests hang instead of trapping). http.rs is axum: GET /api/v1/number/{number}, GET /healthz.

Gotchas

  • Components build with plain cargo build --target wasm32-wasip2 — no cargo-component. Output name uses underscores: whoareyou_provider_hitta.wasm; the justfile copies it to components/hitta.wasm (gitignored).
  • One provider failing maps to a per-provider status in the JSON response — never a non-200 for the whole lookup. parse_failed in logs (WARN) means a site changed its markup: refresh a fixture with ./fetch-fixture and fix the parser.
  • ParseError::NoData vs Failed: a fetched page with no phone data is NoData (normal); a page that doesn't match the expected structure is Failed (scraper rot). Don't conflate them.