Commit Graph
10 Commits
Author SHA1 Message Date
developer 2b84474228 Rewrite STATUS.md to match the tree after the bbolt/blocklist/acl/resolver fixes
ci / Console typecheck and build (push) Successful in 14s
ci / Go build, vet and test (push) Failing after 15s
ci / Binary with the console embedded (push) Skipped
ci / Container image (push) Skipped
Records the four bugs the first end-to-end run surfaced, what is green, what
is still without a suite, and what is in flight, so the next session does not
start from the previous plan.
2026-09-27 13:32:17 +00:00
developer 26134ba437 Fix the bbolt round trip, the blocklist gaps and the deploy set
ci / Console typecheck and build (push) Successful in 13s
ci / Go build, vet and test (push) Failing after 22s
ci / Binary with the console embedded (push) Skipped
ci / Container image (push) Skipped
The cache snapshot never loaded, so every restart was a cold cache. Snapshot
packed the whole key while Load decoded the record header out of the key's
remainder instead of the value, so every entry was skipped. The two sides are
now an explicit encodeRecord/decodeRecord pair with a version byte and a CRC-32C
trailer, so a future format change is detected instead of silently misparsed.
Load also drops entries that are already past ExpiresAt and rewrites the TTL to
the time actually left, so a served TTL never jumps back up across a restart.

Blocklist, all six gaps the failing tests were pointing at: a leading UTF-8 BOM
is stripped, "!allow example.com" works, SourceMeta exists for a source that
only ever contributed a rule, Pattern() reports the bare name again (the new
WireName() produces the wildcard form for the API), an RPZ record with no
explicit TTL inherits the zone default instead of whatever the reader left in
the RR, a hosts line with no address in the first field says so, and the
adblock parser handles CRLF and adblock-flavoured lines pasted into a plain
list. TestHolderSwapIsAtomic was asserting the wrong invariant — the swap was
always atomic, a name blocked by the old set is legitimately unblocked by the
new one.

Tests added for acl and resolver, both of which turned up real bugs:

- a PTR suffix matched across label boundaries, so a group scoped to
  example.com. also swallowed ample.com. and notexample.com. — a client could
  land in a group it does not belong to;
- the "*" catch-all was dropped from the rendered domain patterns, so the
  engine's per-query recompile lost the "everything" case;
- Upstream.Success never closed an open breaker, so a recovered upstream stayed
  excluded for the full cooldown;
- Exchange fanned out in parallel even under policy: failover.

Deploy set: go.mod requires Go 1.27.1 but CI pinned 1.23 and the Dockerfile
pinned golang:1.23-alpine, so neither could have built. The Dockerfile also
copied the source tree after the console bundle, which clobbered it.

The k8s set asked for hostNetwork with two replicas, but the server never sets
SO_REUSEPORT, so the second pod could not bind :53 and would crash-loop. It now
runs without hostNetwork behind a LoadBalancer Service, with a separate
ClusterIP Service for the Ingress (a headless Service cannot back one), a
ServiceAccount, an API-key Secret, per-pod PVCs, and a kustomization. The HPA
is gone: it cannot drive a StatefulSet. To let the API key come from that
Secret, config.Load now expands ${VAR} / ${VAR:-default} / ${NAME-default} and
fails to start on an unset variable with no default, so a missing secret is a
crash loop rather than an unauthenticated console. Expansion skips YAML
comments, so documenting ${VAR} in the ConfigMap does not break the file.

Verified: gofmt, go build, go vet clean; go test -race ./internal/... green
(acl, app, blocklist, cache, config, resolver, zonefile).
2026-09-27 13:30:43 +00:00
mats 3bcc10a029 Merge pull request 'Fix/web typecheck' (#1) from fix/web-typecheck into main
ci / Console typecheck and build (push) Failing after 16s
ci / Go build, vet and test (push) Failing after 2m59s
ci / Binary with the console embedded (push) Skipped
ci / Container image (push) Skipped
Reviewed-on: #1
2026-09-27 15:01:51 +02:00
developer 728374dfda STATUS.md: correct the deliverables section
ci / Console typecheck and build (pull_request) Failing after 23s
ci / Go build, vet and test (pull_request) Failing after 1m1s
ci / Binary with the console embedded (pull_request) Skipped
ci / Container image (pull_request) Skipped
Makefile, Dockerfile, .gitignore, CI workflow and two k8s manifests do
exist; only README.md is empty and the k8s set is partial.
2026-09-27 12:59:27 +00:00
developer aa12b03eb9 fix data races in cache, resolver, qlog; add cache/zonefile/blocklist tests; update STATUS
- cache.Entry.Hits and LRU.perShard become atomics; SetCapacity now evicts
  down to the new budget; packKey fully qualifies names before packing
- resolver.Pool rewritten copy-on-write (atomic.Pointer to an immutable
  state); Upstream is immutable with shared *upstreamStats, so health
  survives a Rebind and the query path stops racing the config hook
- Pool.Exchange no longer marks a dead upstream healthy: Success was
  called before the error check, so the breaker never tripped
- qlog live ring publishes through atomic pointers
- blocklist.Holder.Get nil-safe; Builder lists each source once
- web: fix toast(string) misuse that rendered empty mutation toasts
- add unit tests for cache (with benchmarks) and zonefile
- STATUS.md: green -race integration suite, remaining failures and the
  broken bbolt snapshot round trip documented
2026-09-27 12:59:02 +00:00
developer 10e8a9b91a more code 2026-09-27 12:34:58 +00:00
developer ee72257c64 more code 2026-09-27 11:34:26 +00:00
developer f24fd63e9a web: give the toast helper a real type and keep the dist bundle out of git
Blocklists, Clients, Domains and Upstreams each carried a ToastLike shim
that duck-typed a react-hot-toast style API. The console uses its own
Toast context, so notify() was calling toast('some message') with a string
where ToastOptions is expected: every mutation toast rendered an empty
title. They now take the toast function from useToast() and send a real
{ title, tone } payload, mapping 'fail' onto the danger tone.
2026-09-27 11:32:39 +00:00
developer 85453852d5 initial commit 2026-09-27 11:20:34 +00:00
mats 5b935301e5 first commit 2026-09-27 11:44:33 +02:00