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
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:
@@ -37,17 +37,27 @@ export function useClientNames(): ClientNames {
|
||||
);
|
||||
}
|
||||
|
||||
export function ClientName({ ip, names }: { ip: string; names: ClientNames }) {
|
||||
/**
|
||||
* The name the loaded list gives this address right now, or null when it gives
|
||||
* none. Callers that must distinguish "named" from "bare address" — rather than
|
||||
* just render whichever applies — read this instead of re-deriving precedence.
|
||||
*/
|
||||
export function clientLabel(ip: string, names: ClientNames): { text: string; learned: boolean } | null {
|
||||
const client = names.get(ip);
|
||||
if (client === undefined || (client.name === "" && client.learned_name === "")) {
|
||||
return <span {...stylex.props(shared.mono)}>{ip}</span>;
|
||||
}
|
||||
if (client === undefined) return null;
|
||||
if (client.name !== "") return { text: client.name, learned: false };
|
||||
if (client.learned_name !== "") return { text: client.learned_name, learned: true };
|
||||
return null;
|
||||
}
|
||||
|
||||
export function ClientName({ ip, names }: { ip: string; names: ClientNames }) {
|
||||
const label = clientLabel(ip, names);
|
||||
if (label === null) return <span {...stylex.props(shared.mono)}>{ip}</span>;
|
||||
// The name replaces the address on screen, so the address stays reachable
|
||||
// as the tooltip rather than disappearing from the row entirely.
|
||||
if (client.name !== "") return <span title={ip}>{client.name}</span>;
|
||||
return (
|
||||
<span title={ip} {...stylex.props(shared.learnedName)}>
|
||||
{client.learned_name}
|
||||
<span title={ip} {...stylex.props(label.learned && shared.learnedName)}>
|
||||
{label.text}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user