The live EDGAR getcurrent atom feed is served as ISO-8859-1, not UTF-8, so
plain xml.Unmarshal errored ('encoding "ISO-8859-1" declared but
Decoder.CharsetReader is nil') and parseEdgarAtom returned zero entries — the
endpoint answered 200 with count:0 in prod. Give the decoder a CharsetReader
(golang.org/x/net/html/charset) so any declared charset decodes. The unit test
now uses an ISO-8859-1 fixture with a Latin-1 byte as a regression guard.
Proven against the live feed: 100 entries decode cleanly.
- GET/PUT /v1/world/dashboard: per-identity dashboard config through the existing
store.Settings (namespace 'dashboard') — no new table; mirrors /v1/world/monitors
- generalize identityFor -> identityForDoc: one bearer->identity gate for the
namespaced settings store (monitors + dashboard resolve through it)
- bump hanzoai/sqlite v0.3.0 -> v0.3.2 (vendored pure-Go, zero modernc.org/*).
The vendored engine gates FTS5 behind -tags sqlite_fts5; add it to the Dockerfile
go build (was implicit under v0.3.0's modernc backend) or store.Open degrades
- tests: dashboard round-trip + per-identity isolation + 401/400/405 boundary gates
Not released. Ships as 2.4.18 AFTER 2.4.17 (layout) is live+stable.
Make news/feeds INSTANT and give world one place to query everything.
Feed hot cache (two-tier, ONE way to read a feed body):
- L1 per-pod in-mem mirror (sub-ms hot reads) + L2 hanzo-kv (shared across
pods, survives restart). A body warmed by any pod is instantly served by
every pod; a restarted pod reads the still-warm shared cache instead of
cold-starting. Graceful degrade to L1-only when hanzo-kv is unreachable.
- Background warmer: on boot + every ~5m (jittered) fetches every warm feed,
write-throughs the body, and folds items into the lake. rss-proxy and
feeds-batch serve from the warm cache and never block on upstream while any
cached copy exists (stale-while-revalidate; revalidation runs in background).
- Demand-driven warm set (fleet-wide via hanzo-kv) + a curated seed of the
crypto / financial-regulation / crypto-news feeds so a brand-new pod warms
THOSE first. Cross-pod fetch dedupe via shared copy freshness.
Ingested-data lake (embedded SQLite, modernc.org/sqlite — pure Go, FTS5):
- One normalized `items` table (id, kind, source, ts, title, text, tickers,
country, geo, payload) fed by feed news AND world-model observations, so
everything is searchable/countable together.
- GET /v1/world/search (FTS5 bm25 ranking; filters kind/since/country/ticker)
and GET /v1/world/analytics (totals, by kind/source, top tickers). Rolling
retention window with an hourly prune job. Write-behind ingest (never on the
request path).
Per-identity settings (same SQLite DB, own table):
- GET/PUT /v1/world/settings, bearer-gated, keyed by (org, user_sub, project)
from IAM userinfo, so a signed-in dashboard syncs across devices. Anonymous
→ 401 (client keeps localStorage).
Everything degrades cleanly (never-5xx): no hanzo-kv → per-pod cache; no SQLite
→ empty search/analytics + settings say not-stored. Binary stays CGO-free
(CGO_ENABLED=0). go directive + Dockerfile bumped to 1.25 for modernc.
Latency (local, warm): feeds-batch warm 0.5-1.9ms vs 154ms cold; search 0.8-1.5ms.
Claude-Session: https://claude.ai/code/session_013jh8aka8q8RvhhVQ1psMeW