Commit Graph
58 Commits
Author SHA1 Message Date
Gary HansenandClaude Fable 5 e8f56a1ef4 feat(receiver): storage layer and webhook payload compat
Dual-dialect store (SQLite via modernc.org, MySQL via go-sql-driver,
both pure Go) with order-tolerant start/complete upserts, filtered and
paginated listing, and aggregate queries (per-day, top domains, query
types, statuses, duration percentiles, top clients). Sender gains
optional EXPLOREDNS_WEBHOOK_TOKEN bearer auth; a round-trip test pins
receiver structs byte-compatible with the sender payloads.

Note: go directive moves to 1.25.0, required by modernc.org/sqlite.
CI reads the version from go.mod so GOTOOLCHAIN=local stays satisfied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 02:43:50 +10:00
gary d96f25b1d6 Merge pull request 'feat/release-telemetry-webui' (#28) from feat/release-telemetry-webui into main
Deploy / deploy (push) Successful in 2m26s
CI / docker (push) Successful in 10m19s
Release / docker (push) Successful in 1m32s
Release / binaries (push) Successful in 2m55s
CI / test (push) Successful in 10m4s
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/28
v1.1.0
2026-07-07 15:11:17 +00:00
Gary HansenandClaude Fable 5 1ba89f416e docs: release process, server config, four-region topology
CI / test (pull_request) Successful in 1m28s
CI / docker (pull_request) Has been skipped
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:31:35 +10:00
Gary HansenandClaude Fable 5 8593e0f322 feat(web): live detail tree, server map, favicon
dns.squish.net-style traversal detail tree (refid-parented via longest
prefix, collapsible .0 resolve subtrees, completed-earlier markers, raw
log fallback), a servers card with Leaflet/OSM map lazy-loaded from CDN
and client-side geojs.io geolocation with graceful degradation, and a
delegation-tree favicon (ico + svg).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:31:35 +10:00
Gary HansenandClaude Fable 5 d8ef805a6a feat(api): rate limiting, webhook telemetry, server fingerprints, region
- per-client-IP token bucket on POST /api/traverse (EXPLOREDNS_RATE_LIMIT,
  default 30/1h; direct localhost exempt, proxied clients are not)
- optional usage webhooks (EXPLOREDNS_WEBHOOK_URL): start/complete JSON
  events, fire-and-forget with 5s timeout + one retry so a dead receiver
  never delays a job
- post-traversal version.bind fingerprinting exposed at
  GET /api/traverse/{id}/servers (pending until ready) and announced via
  an SSE "servers" event; never delays job completion
- /api/health reports the serving Fly region (FLY_REGION) for observing
  anycast routing from a roaming client

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:31:34 +10:00
Gary HansenandClaude Fable 5 94e41fe5b5 feat(release): version stamping and tag-triggered release workflow
--version/-V on the CLI, version in /api/health via Server.SetVersion,
Makefile/Dockerfile ldflags stamping from git describe, and a release
workflow on v* tags: both binaries for linux/darwin (amd64+arm64) and
windows/amd64 with SHA256SUMS attached to the Gitea release
(idempotent — reuses an existing hand-written release and skips
already-uploaded assets), plus version-tagged Docker images.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:31:34 +10:00
gary 391d849a5f Merge pull request 'rework/dnstraverse-parity' (#27) from rework/dnstraverse-parity into main
Deploy / deploy (push) Successful in 1m26s
CI / test (push) Successful in 2m35s
CI / docker (push) Successful in 13m10s
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/27
v1.0.0
2026-07-07 12:14:05 +00:00
Gary HansenandClaude Fable 5 874374f03f docs: record two-region Fly scaling (syd + iad)
CI / test (pull_request) Successful in 2m36s
CI / docker (pull_request) Has been skipped
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:08:07 +10:00
Gary HansenandClaude Fable 5 ccf0e6b0dc fix: data race on test DNS handler flag under -race
TestClientAgainstLocalServer captured RecursionDesired into a plain bool
from the miekg server handler goroutine and read it from the test
goroutine; the UDP round-trip gives no happens-before edge, so CI's
-race run flagged it. Use atomic.Bool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:08:06 +10:00
Gary HansenandClaude Fable 5 ccfd3fd156 build: add Fly.io deployment process
CI / test (pull_request) Failing after 2m45s
CI / docker (pull_request) Has been skipped
fly.toml (Dockerfile.web, scale-to-zero in syd, /api/health checks),
make deploy / deploy-status targets, a Gitea workflow deploying on v*
tags or manual dispatch via FLY_API_TOKEN, and README instructions
covering first-time setup and the server's runtime env knobs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 21:50:30 +10:00
Gary HansenandClaude Fable 5 111b8bf48e feat(web): harden server for public exposure
- hard per-traversal deadline (EXPLOREDNS_JOB_TIMEOUT, default 5m) so
  every job reaches a terminal state; timed-out jobs report error with
  any partial results instead of masquerading as complete
- cap concurrent traversals (EXPLOREDNS_MAX_JOBS, default 8) returning
  429 when saturated
- CORS off by default (the embedded SPA is same-origin); opt in via
  EXPLOREDNS_CORS_ORIGIN

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 21:50:29 +10:00
Gary HansenandClaude Fable 5 d71c7fbef2 feat: rework engine and CLI for dnstraverse parity
Port the traversal engine to the Ruby dnstraverse model so behaviour and
output match dns.squish.net:

- dns: single RD=0 query path (RD=1 only for upstream root discovery),
  per-run packet cache, EDNS0 512-fallback with warnings, UDP->TCP on
  truncation; fix --retries 0 and --root-server IP-literal handling;
  drop all hardcoded 127.0.0.1:53 resolvers
- traverse: hierarchical per-branch InfoCache, 7-step response
  classification with the full 10-status vocabulary, bailiwick
  partitioning, strictly-deeper lame-referral rule, refid grammar with
  .0 resolve subtrees and childset digits, per-IP branching at 1/n
  weight, cache-based glue resolution with noglue/loop dead ends, CNAME
  restarts from the deepest cached zone, fast-mode memoization,
  probability aggregation with Ruby-identical stats keys (sums to 1.0)
- output: byte-for-byte reference text format pinned by a golden test,
  reference CLI defaults, working --quiet/--show-X=false, TTY-aware
  colour, deduplicated deterministic JSON
- web: adapt API/SPA to the new engine, SSE events carry refid/status,
  fix subscribe/snapshot duplicate-event race and a statusCls TDZ bug,
  align SPA type list with the backend
- delete the old engine and dead code (net -4,350 lines)

Verified against live runs of the reference Ruby engine across five
domains (answers, NXDOMAIN, null MX, CNAME restart, glueless resolve)
with no divergences beyond the documented typo fixes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 21:42:06 +10:00
Gary HansenandClaude Fable 5 af15c9c2d4 docs: add dnstraverse reference spec, rework design, and golden tooling
Reconstructed behaviour spec of dns.squish.net / Ruby dnstraverse 0.1.14
(inputs, traversal semantics, probability model, verbatim output formats,
sourced from the live site, Wayback captures, and the Ruby source), the
engine rework design that maps it onto Go, a point-in-time codebase review,
golden reference captures, and tools/golden/run-reference.sh for running
the reference Ruby engine locally (clone is gitignored, GPL-3 dev-only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 21:41:47 +10:00
multica-agent c74b218349 Merge pull request 'fix: rename module path to gitea.hansenits.com.au/hits/ExploreDNS' (#24) from agent/development-manager/b41cb0eb into main
CI / test (push) Failing after 3h2m21s
CI / docker (push) Has been cancelled
2026-06-17 12:06:51 +00:00
fe74ec61a2 fix: remove tracked binaries covered by .gitignore
CI / test (pull_request) Failing after 3h3m3s
CI / docker (pull_request) Has been cancelled
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-17 22:05:30 +10:00
851203e8f6 fix: merge main into PR branch, resolve CI and go.mod conflicts
- Keep go-version-file: 'go.mod' from PR (reads Go version from go.mod)
- Keep gitea.hansenits.com.au module path in coverage check
- Pick up .gitignore bin/* entry from main
- go.mod: keep go 1.24.0 directive from main (GOTOOLCHAIN=local)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-17 22:05:16 +10:00
Gary cf280a9f2b fix: update .gitignore to include bin directory
CI / test (push) Failing after 3h6m19s
CI / docker (push) Has been cancelled
2026-06-17 12:11:11 +10:00
gary 1f23f482c1 Merge pull request 'fix: pin go directive to 1.24.0 and add GOTOOLCHAIN=local to CI (HAN-410)' (#25) from agent/go-expert-developer/6b3715f8 into main
CI / test (push) Failing after 3h1m13s
CI / docker (push) Has been cancelled
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/25
2026-06-10 10:14:16 +00:00
17e2c47e4a fix: pin go directive to 1.24.0 and add GOTOOLCHAIN=local to CI
CI / test (pull_request) Failing after 3h13m49s
CI / docker (pull_request) Has been cancelled
The CI was consistently failing because go.mod declared 'go 1.25.6',
which triggered Go's GOTOOLCHAIN=auto mechanism to auto-download Go
1.25.6 on the CI runner. That pre-release build lacks the 'covdata'
tool, causing 'go test -race -coverprofile=coverage.out ./...' to exit
non-zero on cmd/ packages (which have no test files), even though all
actual tests passed.

Fix:
- Lower go directive from 1.25.6 to 1.24.0 (minimum required by deps)
- Set go-version: '1.24' in setup-go to match
- Add GOTOOLCHAIN=local to every go command in ci.yml to prevent any
  further auto-download regardless of future go.mod changes

All tests pass locally with GOTOOLCHAIN=local.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-10 09:17:07 +10:00
671a23e6e1 fix: update CI to use Go version from go.mod and fix module path in coverage check
CI / test (pull_request) Failing after 3h13m3s
CI / docker (pull_request) Has been cancelled
- Replace hardcoded go-version '1.24' with go-version-file: 'go.mod' so CI
  always uses the toolchain version that matches the module's requirements
  (go.mod currently declares go 1.25.6)
- Fix 'Check internal package coverage' step: update grep pattern from
  old module path 'github.com/hits/ExploreDNS/internal' to the renamed
  path 'gitea.hansenits.com.au/hits/ExploreDNS/internal'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-09 15:17:29 +10:00
5d4fa94286 fix: rename Go module path to gitea.hansenits.com.au/hits/ExploreDNS
CI / test (pull_request) Failing after 1m32s
CI / docker (pull_request) Has been skipped
- Update go.mod module declaration
- Update all internal import paths in .go files
- Update go install lines in README.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 23:17:00 +10:00
gary 683a2a69fa Merge pull request 'Fix DNS resolution: NS name bug, glue bypass, FormatRecord duplicate header, result deduplication' (#23) from agent/go-expert-developer/da16f960 into main
CI / test (push) Failing after 2m49s
CI / docker (push) Has been skipped
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/23
2026-06-08 10:21:08 +00:00
gary 2983846f74 Merge pull request 'docs: add web interface documentation' (#21) from agent/go-expert-developer/17032578 into main
CI / test (push) Failing after 1m30s
CI / docker (push) Has been skipped
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/21
2026-06-08 10:15:10 +00:00
1a0cb1f301 docs: document web interface server in README
CI / test (pull_request) Failing after 3m36s
Add Web Interface section covering:
- How to build the server binary (make build-server / make build-all)
- How to run it with the --addr flag
- What the web UI does and all API endpoints (POST /api/traverse,
  GET /api/traverse/{id}, SSE stream, GET /api/health)
- Request/response shapes and SSE event format

Also update Makefile with build-server and build-all targets, and
expand Project Structure and Development sections to include the
new cmd/server/ and web/api/ packages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 18:12:06 +10:00
3da28da9a2 Fix NS resolution, deduplicate results, fix FormatRecord duplication
CI / test (pull_request) Failing after 2m31s
Three bugs fixed:

1. processReferral was calling ResolveNS with ref.Name (the query domain,
   e.g. '800adventures.com.au.') instead of ref.Bailiwick (the NS hostname,
   e.g. 'ns-a.hansenits.com.'). This caused the sub-traversal to look up the
   wrong name and always fail to find the nameserver's IP address.

2. In ResolveNS (and Referral.Resolve), child referrals whose name matched the
   visited set were unconditionally skipped. When the .com TLD returns glue A
   records for the target NS alongside its delegation, the child referral has
   addresses and should be queried directly rather than skipped.

3. FormatRecord was prepending the DNS header fields and then appending
   rr.String() which already includes those same fields, producing doubled
   output like 'example.com. 300 IN A example.com. 300 IN A 1.2.3.4'.
   Now simply returns rr.String().

Additional improvements:
- Results section deduplicates terminal results: same NS failure or same
  (NS, answer) pair is merged with summed probability, avoiding the same
  nameserver appearing 15 times with 6.7% each.
- Result lines now include the NS hostname (from Bailiwick) and use the
  compact rdata format, e.g. '33% ns-a.hansenits.com answered with 13.54.63.231'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 18:07:38 +10:00
43af39dfd7 Add Dockerfiles and CI pipeline for Docker build/push
CI / test (push) Failing after 2m13s
CI / docker (push) Has been skipped
CI / test (pull_request) Failing after 2m44s
CI / docker (pull_request) Has been skipped
- Dockerfile.cli: multi-stage build for exploredns CLI tool
- Dockerfile.web: multi-stage build for the HTTP API/web server
- Both use golang:1.24-alpine builder + alpine:3.21 final image
- CI pipeline docker job builds and pushes to gitea.hansenits.com.au registry on push to main/master

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 17:56:32 +10:00
multica-agent 25e6039bde Improve DNS output: distinguish NS resolution failures from domain errors (#20)
CI / test (push) Failing after 2m19s
2026-06-08 05:59:33 +00:00
multica-agent d6063eb636 feat: DNS host selection - fix code review issues (HAN-400) (#19)
CI / test (push) Failing after 1m58s
2026-06-08 03:25:37 +00:00
multica-agent 93959c9f11 fix: API quality fixes from code review (HAN-398) (#17)
CI / test (push) Failing after 1m21s
2026-06-07 18:52:18 +00:00
multica-agent 2fe8adcfcc feat: web frontend SPA for ExploreDNS (HAN-388) (#18)
CI / test (push) Failing after 1m22s
2026-06-07 18:47:17 +00:00
multica-agent e59597a191 feat: HTTP API server with SSE and SPA serving (HAN-389) (#16)
CI / test (push) Failing after 4m55s
2026-06-07 18:31:28 +00:00
dd667f734c fix: remove duplicate test declarations from PR #12/#13 conflict
CI / test (push) Has been cancelled
Phase 4.2 (PR #12) and test coverage improvement (PR #13) independently
added overlapping test functions. Remove duplicates from PR #13 files:

- internal/dns/iterative_test.go: remove TestExtractNSNames,
  TestExtractNSNamesEmpty, TestIterativeQueryWithExchangeSuccess,
  TestIterativeQueryWithExchangeNilResponse, TestIterativeQueryWithExchangeTCPFallback
  (kept in roots_test.go and query_test.go from PR #12)
- internal/output/coverage_test.go: remove TestRRDataStringDefault,
  TestContainsString, TestCollectUniqueServerIPs, TestNewFormatterNilWriter
  (kept in stats_test.go and formatter_test.go from PR #12)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 04:30:06 +10:00
dbd9322a1b test: merge PR #13 test coverage improvements into main
Resolves merge conflicts between Phase 4.2 comprehensive test suite and
the test coverage improvement branch:
- config_test.go: take PR's better table-driven tests + keep main's extra tests
- coverage_test.go: keep main's Phase 4.2 comprehensive tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 04:24:56 +10:00
multica-agent bb3e9d3e36 Merge pull request 'docs: comprehensive documentation (HAN-387)' (#15) from feat/han-387-documentation into main
CI / test (push) Failing after 1m20s
2026-06-07 18:10:22 +00:00
ee20ed51f6 docs: comprehensive documentation for HAN-387
CI / test (pull_request) Failing after 1m19s
- README.md: full project overview, installation, quick start, CLI reference,
  output format descriptions, architecture overview, and dnstraverse comparison
- GoDoc: package-level documentation for traverse, dns, config, output, and
  fingerprint packages
- GoDoc: TraverserConfig and TraversalResult type comments in traverser.go

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 04:05:15 +10:00
45e15297f4 test: improve coverage to >80% on all core packages
CI / test (pull_request) Failing after 2m11s
Add comprehensive test coverage for internal packages:

- internal/config: 66.2% → 98.5%
- internal/dns: 67.8% → 84.3%
- internal/output: 48.8% → 89.1%
- internal/traverse: 56.3% → 86.9%

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 03:57:29 +10:00
multica-agent e6e07941a5 feat: comprehensive test suite (Phase 4.2) (#12)
CI / test (push) Failing after 1m30s
2026-06-07 17:54:15 +00:00
multica-agent fe1afe2a97 Phase 4.1: Error handling, edge cases, and robustness (#11)
CI / test (push) Failing after 2m36s
2026-06-07 17:24:00 +00:00
multica-agent 76f5010a5e feat: implement DNS server fingerprinting (HAN-384) (#10)
CI / test (push) Has been cancelled
2026-06-07 16:56:51 +00:00
multica-agent 35be7539b4 Merge pull request 'feat: implement output formatting and display (HAN-383)' (#9) from agent/go-expert-developer/f3b1b7cf into main
CI / test (push) Has been cancelled
2026-06-07 16:40:00 +00:00
8e7beacc22 fix: address code review issues on PR #9
CI / test (pull_request) Waiting to run
- gofmt main.go to fix tab indentation in main() body
- stats.go ComputeSummary: return nil when Answers and ByType are empty
- dns/types.go: remove duplicate ParseQueryType (dead code)
- formatter.go: log hook errors to stderr when Debug > 0; add Debug to Config
- text.go referralID: remove redundant depth==0 branch
- text.go writeServers: remove version lookup placeholder string

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 02:32:58 +10:00
Gary Hansenandmultica-agent 5a54834c5f feat: implement output formatting and display (HAN-383)
CI / test (pull_request) Failing after 2m2s
Add text and JSON formatters with real-time progress via traverser hooks,
summary statistics, and CLI integration for --show-* and --json flags.

Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 02:21:13 +10:00
multica-agent 876542b2de feat: implement CLI flags and configuration handling (HAN-382) (#8)
CI / test (push) Failing after 3m57s
2026-06-07 16:08:39 +00:00
gary feb5c68b39 feat: implement referral resolution for nameserver names without glue records (HAN-381) (#7)
CI / test (push) Failing after 2m58s
Co-authored-by: Hansen IT Solutions <gary@hansenits.com>
Co-committed-by: Hansen IT Solutions <gary@hansenits.com>
2026-06-07 06:09:49 +00:00
gary 39529dacbb feat: implement traversal engine (HAN-380) (#6)
CI / test (push) Failing after 1m26s
Co-authored-by: Hansen IT Solutions <gary@hansenits.com>
Co-committed-by: Hansen IT Solutions <gary@hansenits.com>
2026-06-06 03:41:14 +00:00
gary 194bc97526 Merge pull request 'feat: implement CachingResolver with per-server query caching' (#5) from agent/go-expert-developer/f5bcb2fe into main
CI / test (push) Failing after 3h13m21s
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/5
2026-06-05 06:05:01 +00:00
Garyandmultica-agent db3ad498f6 feat: implement CachingResolver with per-server query caching
CI / test (pull_request) Failing after 3h13m39s
Add Resolver interface, BasicResolver, and CachingResolver to internal/dns.

CachingResolver wraps any Resolver with an in-memory cache keyed by
(server IP, name, type, class). Cache entries respect DNS TTL from
responses, falling back to a configurable default TTL. Thread-safe
using sync.RWMutex. Includes Len, Clear, and PurgeExpired methods
for cache management.

Closes HAN-379 (Phase 2.2).

Co-authored-by: multica-agent <github@multica.ai>
2026-06-05 15:58:46 +10:00
gary 6a3cdb9abe Merge pull request 'feat: implement root server discovery (HAN-378)' (#4) from agent/go-expert-developer/beb90b99 into main
CI / test (push) Has been cancelled
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/4
2026-06-05 05:52:28 +00:00
Garyandmultica-agent 924fcbd43a feat: implement root server discovery (HAN-378)
CI / test (pull_request) Failing after 1m17s
Add RootServer struct and DiscoverRoots function that queries the local
resolver for NS records of the root zone, resolves each root name to
A/AAAA addresses, and returns a list of RootServer structs.

Supports:
- Default: discovers a single root server from local resolver
- --root-server override to target a specific root server
- --all-root-servers to discover all 13 root servers
- --root-aaaa flag to include IPv6 addresses

Includes unit tests for all helper functions and integration tests
that skip gracefully when no resolver is available.

Co-authored-by: multica-agent <github@multica.ai>
2026-06-05 15:44:59 +10:00
gary 42a37adbee Merge pull request 'feat: add DNS query/response layer with miekg/dns' (#3) from agent/go-expert-developer/ad0c58a4 into main
CI / test (push) Has been cancelled
Reviewed-on: http://gitea.hansenits.com.au/hits/ExploreDNS/pulls/3
2026-06-05 05:37:38 +00:00