Added
-
The dense-cluster tunnel scan now runs on Pi-hole data, not only Zeek. A family of
generated-looking names used to stop being identifiable in a Pi-hole report once it grew
large enough to form its own cluster: below that size its domains surfaced individually,
above it no finding named them and only a counts-only row remained, reporting how many
domains had formed how many clusters. Such a family is now recovered when its names concentrate under a single
registrable domain. Recovery is bounded and the bounds are measured: a family sprayed
across many domains is still outside the scan, an encoding whose labels only sometimes
look generated can still slip the member-fraction bar, and a cluster the scan inspects
and rejects produces no row. Pi-hole findings stay capped at MEDIUM, because the volume
evidence is not permitted to corroborate on a source that records no resolution outcome.
Disabling the scan returns Pi-hole to its previous aggregate disclosure, which now says
the scan was disabled rather than claiming a source limitation. The calibration record is
published in the DNS evidence page. -
An evidence ledger: what has actually been measured, and what has not.
docs/EVIDENCE.md carries one
row for every detector, not only the ones with results behind them: what was measured and
on what population, what that supports and does not, and what is still owed. Five detectors
now have published calibration conclusions underdocs/evidence/; two are measured with the
write-up still owed; and two have no calibration campaign at all, which the ledger says
plainly. Nearly all of it rests on one estate, and each record says so itself. If you want to
help change that, FIELDKIT.md
is the door.
Changed
-
Reports are written to be read. A first-time reader described sigwood's output as mostly
cryptic, and the pass below answers that verdict rather than a lint. None of it changes what
sigwood finds: the detectors and their thresholds are untouched, and the same run produces the
same findings, with the same evidence, that it did before. What changed is how those findings
are put on the page. Two qualifications, so the sentence above is not read wider than it
holds: the wording of some human-facing notes changed, whichjsoncarries verbatim in
run_summary.notesand has always documented as prose rather than contract; and one dns
display cell was renamed, which is projection and never reachedjsonorcsv. The
individual changes follow. -
Severity is spelled out, everywhere a person reads it. The text report showed
[H],
[M],[L]and[I]; a novice reader took those for magnitudes, times and sizes in a single
sitting, while the spelled word decoded unaided. Text now readshigh,medium,lowand
info, padded so mixed rows keep their columns; the html report spells and capitalizes the
same words in its summary cards, its row pills and its group headers.jsonkeeps its
lowercase token andcsvits column, both unchanged. -
Verbose reports put the prose before the machine facts. At
-vand-vvthe order is now
description, then next steps, then evidence, with the data window last. Previously the
imperative advice sat below the evidence block, and a reader who bounced off the evidence
never reached the part telling them what to do. Adjacent findings are separated by one blank
line, which the dense default view still does without. -
Each detector group says what that detector looks for. A one-line mission renders beneath
the group header on both reading surfaces, so a reader meetingbeaconordnsblockfor the
first time is told what question it asks before being shown its answers. A report also carries
one pointer, once, to the tier that explains why each finding surfaced, and it appears only
when a group actually rendered. -
Level-zero rows name what they hold. dns counts read as
names,queriesandclients;
beacon's composite reads asrhythm. The dns tables now carry their labels once as column
headers rather than repeating them on every row, which is what the html tables already did.
The dns lexical score is labelledentropy score, and the wordscoreis doing work: the
number is a weighted lexical measure with no units, so a bareentropyheading invites a
reader to take it as a count of bits, which it is not. -
Evidence timestamps are readable and unambiguous. Instants inside the evidence block used
to render as raw machine strings in UTC while the report's own window was shown in local time,
so two lines of one block could describe the same moment and appear to disagree. Accepted
instants now follow the report's display timezone, carry theirlocalorUTClabel, and
include seconds where a distinction depends on them, such as an authentication failure and the
success that followed it. -
ssl and dnsblock findings explain themselves in plain language. An ssl row said which
internal signals fired; it now says that no server name was offered, or that a certificate did
not validate, and it keeps the measured validation status that separates an expired
certificate from a self-signed one. dnsblock descriptions say in words what its counts mean,
keeping the distinction between complete daily coverage and coverage that cannot be confirmed.
Both are rendering only: the machine payloads under them are unchanged. -
The html report carries sigwood's own identity, and dns entities are one click to copy.
Detector names in group headers wear the wordmark's serif and colour, so the page reads as
sigwood's document at every section boundary rather than only in the corner. A dns domain cell
selects whole on one click, with no visual marking, and that convenience is absent from print. -
[detectors.beacon].bin_secondsis no longer a configuration key. The beacon detector bins a
flow's connection times before looking for a rhythm, and every other number in that scorer - the
score threshold, the period band it will consider, the peak-prominence normalization, and the
reference score quoted in the documentation - was tuned against a 30-second bin. Changing the bin
therefore did not adjust sensitivity; it produced scores that could not be compared with any of
those numbers, including the threshold deciding whether a finding appeared at all. The value is
now fixed in the detector. A configuration file still carrying the key keeps working: sigwood
reportsconfig: ignoring unknown setting [detectors.beacon].bin_secondsand continues with the
calibrated value.
Fixed
-
sigwood now tells you when a syslog archive's dates look re-dated. RFC 3164 and Pi-hole
logs carry no year, so sigwood stamps them with the current one. That silently moves an
archive more than a year old into the last twelve months, and those dates then flow into
windows, timelines and finding data windows looking entirely confident. Where the file still
carries its original modification time, sigwood now says so once per file:timestamps parse 730 days newer than the file itself was last written. It explains rather than repairs: the
dates are still wrong. It is deliberately conservative: the two-day threshold exists
because a log shipped from a distant timezone legitimately parses up to 26 hours ahead, and a
copy made without preserving the modification time cannot be flagged at all. See
RFC 3164 syslog and Pi-hole timestamps carry no year in
KNOWN-ISSUES.md for
what it can and cannot see. -
On a daily-rotating Zeek tree, a default run now includes today's events. sigwood anchored
its default window on the newest dated log directory and stopped at that day's last second, so
anything written since midnight - which lives only in the livecurrent/spool - was read from
disk and then filtered back out. A plainsigwood /opt/zeek/logsat three in the afternoon
showed you nothing from that afternoon. The window's lower bound still selects the last N dated
days; the upper bound is now open, so the live spool is included. Two consequences worth knowing:
a 7-day default can now span eight calendar dates, because it covers seven archived days plus
today so far; and a log line stamped in the future - clock skew, a misconfigured sensor - is now
admitted rather than silently dropped, which is how every other source already behaved. -
A large group of Pi-hole domains no longer disappears without a word. On Pi-hole data,
domains that clustered together produced no findings and nothing was said about them, so a burst
of random lookups that grew large enough to form its own cluster stopped being identifiable - and
where every domain clustered, the run reported no findings at all. A run now adds one
informational row saying how many domains formed how many clusters. That row carries counts only,
and no domain name reaches it. This shipped first as a disclosure over unexamined clusters; the
Added entry above then extended the scan itself to Pi-hole, so in this release the row appears
when dense-cluster scanning is switched off. -
Detectors skipped for the same reason are now reported on one line. Pointing sigwood at a
single source -sigwood /var/log/pihole/- previously printed one warning per skipped detector
and repeated all of them in the report, so a first run could spend ten lines on sources you do
not have. Detectors sharing an identical reason are now grouped, and the reason text is unchanged:
a source that is configured but outside the paths you named still says so, rather than being
described as unconfigured. Machine output is unaffected - the JSON report still carries a
separate reason for every skipped detector. -
A malformed
[sigwood].home_netnow stops the run at startup instead of quietly disabling your
topology. Written as a bare string -home_net = "10.0.0.0/8"rather than
home_net = ["10.0.0.0/8"]- the value was read as a list of single characters, none of which is
a network. Depending on which detectors ran, that either silently left sigwood with no internal
networks at all, so every address was treated as external and direction-aware analysis lost its
meaning, or surfaced as an unhelpful error from thescandetector. sigwood now checks the value
when it loads your configuration, names the offending entry, and shows the array form.