milestone 28: query provenance — every logged query is exactly explainable
Gates / frontend (push) Successful in 1m36s
Gates / test (push) Successful in 1m56s
Gates / test-aarch64 (push) Successful in 7m37s
Gates / package (push) Successful in 9m12s
Gates / container (push) Successful in 13s
CI / gates (push) Successful in 19m4s

query rows gain qclass, rcode, group, policy action and reason, the
matched rule or list entry with its source, cname and safe-search
targets, route kind, forward zone, and the resolver that actually
answered — the pool and local markers die. servfails are logged and
name the resolver that lost; post-parse protocol refusals become rows.
a detail page at /queries/:id renders the ordered explanation, and
coverage watermarks distinguish an empty history from a missing one.

the schema fingerprint changes: existing query history is recreated
with the old file kept aside and the reset filed as a resolved
diagnostic. fixes an oversized udp reply being rebuilt as noerror,
which handed clients a truncated nxdomain as success.
This commit is contained in:
2026-08-22 09:16:40 +02:00
parent 7e6cb507d2
commit 0fd6bbd312
65 changed files with 7036 additions and 685 deletions
+4
View File
@@ -33,11 +33,13 @@ comptime {
_ = @import("server/resolver_integration_test.zig");
_ = @import("storage/db.zig");
_ = @import("config/model.zig");
_ = @import("config/limits.zig");
_ = @import("config/validate.zig");
_ = @import("config/faults.zig");
_ = @import("storage/config_schema.zig");
_ = @import("storage/migrations.zig");
_ = @import("storage/querylog_schema.zig");
_ = @import("storage/provenance.zig");
_ = @import("storage/repositories/context.zig");
_ = @import("storage/repositories/crud.zig");
_ = @import("storage/repositories/groups_repo.zig");
@@ -92,6 +94,8 @@ comptime {
_ = @import("server/shutdown.zig");
_ = @import("server/phase7_integration_test.zig");
_ = @import("web/sse.zig");
_ = @import("web/coverage.zig");
_ = @import("web/provenance_view.zig");
_ = @import("server/query_sink.zig");
_ = @import("web/auth.zig");
_ = @import("web/api_limiter.zig");