Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c8502be
Initial plan
Copilot Mar 12, 2026
3a11714
docs: add RFC-conformance.md and update table-of-contents
Copilot Mar 12, 2026
8a84d37
fix: return REFUSED for out-of-zone queries (RFC 1034 §6.2)
Copilot Mar 13, 2026
f614b76
test: remove duplicate out-of-zone test
Copilot Mar 13, 2026
dcc9831
feat: add apex SOA to authority for NXDOMAIN and NODATA responses (RF…
Copilot Mar 13, 2026
e3fc9e1
refactor: use rcode/authority/answer variables in zone reader block, …
Copilot Mar 13, 2026
e412051
Refactor _update_response
indisoluble Mar 13, 2026
63562bd
Fix test-docker.yml
indisoluble Mar 13, 2026
c40e60c
feat: validate QDCOUNT == 1, return FORMERR for zero or multiple ques…
Copilot Mar 13, 2026
7b89c2e
Refactor test_dns_server_udp_handler.py
indisoluble Mar 13, 2026
9339165
Refactor test_dns_server_udp_handler.py
indisoluble Mar 13, 2026
1c57a64
feat: validate QCLASS == IN, return REFUSED for non-IN queries
Copilot Mar 13, 2026
d372199
feat: validate QCLASS == IN, return REFUSED for non-IN queries
indisoluble Mar 13, 2026
29c7a5d
feat: validate QCLASS == IN, return REFUSED for non-IN queries
indisoluble Mar 13, 2026
285781c
feat: validate opcode, return NOTIMP for non-QUERY opcodes
Copilot Mar 13, 2026
54db0e9
test: assert Level 1 DNS response header fields (QR, ID, RA, TC, AA)
Copilot Mar 14, 2026
ec09227
test: assert answer/authority/additional section shape for all respon…
Copilot Mar 14, 2026
5c862cd
test: add malformed wire input tests and resolve RFC-conformance.md u…
Copilot Mar 14, 2026
c377605
docs: add manual-validation.md and scripts/validate-level1.sh for Lev…
Copilot Mar 14, 2026
b55df57
feat: add wire-level integration tests and clean up docker behavior a…
Copilot Mar 14, 2026
41a20f5
refactor: reposition component integration tests and add Docker healt…
Copilot Mar 14, 2026
580cad9
refactor: rename test-docker.yml to test-integration.yml, add multi-q…
Copilot Mar 14, 2026
5582579
fix: align validate-tests.yml with renamed workflow and add new docs …
Copilot Mar 14, 2026
eae097e
docs: narrow integration-test docstring, fix script wording, remove r…
Copilot Mar 14, 2026
9db039d
ci: fix workflow name case in validate-tests.yml and remove redundant…
Copilot Mar 14, 2026
6f29f87
refactor: rename DnsServerZoneUpdaterThreated to DnsServerZoneUpdater…
Copilot Mar 14, 2026
0a1069e
docs: clarify validate-tests CI trigger model in project-rules.md §7
Copilot Mar 14, 2026
a6b9feb
docs: remove manual-validation artifacts (docs/manual-validation.md a…
Copilot Mar 14, 2026
3e448a2
docs: rewrite RFC-conformance.md as present-state reference document
Copilot Mar 14, 2026
fadf560
docs: promote RFC-conformance.md to Minimum Reading Set and align REA…
Copilot Mar 14, 2026
eb233d7
feat: return FORMERR for malformed wire with recoverable DNS header (…
Copilot Mar 14, 2026
7902153
docs: replace stale "remaining gap" framing with "broader-than-Level-…
Copilot Mar 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: test docker
name: test integration

on:
push:
Expand All @@ -24,11 +24,6 @@ jobs:
run: |
docker build -t a-healthy-dns:test .

- name: test docker image builds successfully
run: |
# Verify the image was created
docker images a-healthy-dns:test

- name: test docker image with alias zone configuration
run: |
# Create an isolated network for deterministic container-to-container checks
Expand Down Expand Up @@ -75,7 +70,6 @@ jobs:
DNS_HOST="127.0.0.1"
DNS_PORT="53053"
BACKEND_IP="172.28.0.10"
EXPECTED_NS="ns1.test.example.com."

wait_for_a_record() {
local fqdn="$1"
Expand All @@ -95,56 +89,83 @@ jobs:
return 1
}

assert_dns_status() {
local fqdn="$1"
local rtype="$2"
local expected_status="$3"
local output
local actual_status
for fqdn in \
"www.test.example.com" \
"www.test.other.com" \
"www.test.another.com"; do
wait_for_a_record "${fqdn}"
done

- name: test health-check-driven dns state transitions
run: |
set -euo pipefail

output="$(dig +time=1 +tries=1 +noall +comments @"${DNS_HOST}" -p "${DNS_PORT}" "${fqdn}" "${rtype}")"
actual_status="$(printf '%s\n' "${output}" | sed -n 's/.*status: \([A-Z]*\).*/\1/p' | head -n 1)"
DNS_HOST="127.0.0.1"
DNS_PORT="53053"
BACKEND_IP="172.28.0.10"
MAX_RETRIES=20

if [ "${actual_status}" = "${expected_status}" ]; then
echo "[OK] ${rtype} ${fqdn} ${actual_status}"
return 0
fi
wait_for_a_record() {
local fqdn="$1"
local answer

echo "[FAIL] ${rtype} ${fqdn} expected=${expected_status} got=${actual_status:-none}"
printf '%s\n' "${output}"
for _ in $(seq 1 "${MAX_RETRIES}"); do
answer="$(dig +short +time=1 +tries=1 @"${DNS_HOST}" -p "${DNS_PORT}" "${fqdn}" A)"
printf '%s\n' "${answer}" | grep -qx "${BACKEND_IP}" && {
echo "[OK] A present: ${fqdn}"
return 0
}
sleep 1
done

echo "[FAIL] A never appeared: ${fqdn}"
dig +nocmd +noall +comments +answer @"${DNS_HOST}" -p "${DNS_PORT}" "${fqdn}" A || true
return 1
}

assert_ns_record() {
local zone="$1"
local ns_answer

ns_answer="$(dig +short +time=1 +tries=1 @"${DNS_HOST}" -p "${DNS_PORT}" "${zone}" NS)"
printf '%s\n' "${ns_answer}" | grep -qx "${EXPECTED_NS}" || {
echo "[FAIL] NS ${zone}"
printf '%s\n' "${ns_answer}"
exit 1
}
echo "[OK] NS ${zone}"
wait_for_a_record_gone() {
local fqdn="$1"
local answer

for _ in $(seq 1 "${MAX_RETRIES}"); do
answer="$(dig +short +time=1 +tries=1 @"${DNS_HOST}" -p "${DNS_PORT}" "${fqdn}" A)"
[ -z "${answer}" ] && {
echo "[OK] A removed: ${fqdn}"
return 0
}
sleep 1
done

echo "[FAIL] A still present after backend went down: ${fqdn}"
dig +nocmd +noall +comments +answer @"${DNS_HOST}" -p "${DNS_PORT}" "${fqdn}" A || true
return 1
}

# Verify state transitions for hosted zone and all alias zones
for fqdn in \
"www.test.example.com" \
"www.test.other.com" \
"www.test.another.com"; do
wait_for_a_record "${fqdn}"
done

for zone in \
"test.example.com" \
"test.other.com" \
"test.another.com"; do
assert_ns_record "${zone}"
# Stop backend — health checks will fail; DNS must remove A records from all zones
docker stop a-healthy-dns-backend
for fqdn in \
"www.test.example.com" \
"www.test.other.com" \
"www.test.another.com"; do
wait_for_a_record_gone "${fqdn}"
done

assert_dns_status "www.test.other.com" "AAAA" "NOERROR"
assert_dns_status "missing.test.other.com" "A" "NXDOMAIN"
assert_dns_status "www.not-configured.example.org" "A" "NXDOMAIN"
# Restart backend — health checks will succeed; DNS must re-add A records to all zones
docker start a-healthy-dns-backend
for fqdn in \
"www.test.example.com" \
"www.test.other.com" \
"www.test.another.com"; do
wait_for_a_record "${fqdn}"
done

- name: test docker-compose configuration
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/validate-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: validate tests

on:
workflow_run:
workflows: ["test docker", "test python code", "test version"]
workflows: ["test integration", "test python code", "test version"]
types:
- completed
branches:
Expand All @@ -24,7 +24,7 @@ jobs:
COMMIT_SHA="${{ github.event.workflow_run.head_sha }}"
echo "Validating workflows for commit: $COMMIT_SHA"

WORKFLOWS=("Test Docker" "Test Python Code" "Test Version")
WORKFLOWS=("test integration" "test python code" "test version")

for workflow in "${WORKFLOWS[@]}"; do
echo "Checking workflow: $workflow"
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Requires Python 3.10+.
| [docs/docker.md](docs/docker.md) | Docker deployment: image details, Compose, deployment patterns, container management, security, and orchestration |
| [docs/configuration-reference.md](docs/configuration-reference.md) | All CLI flags and Docker env vars with defaults and examples |
| [docs/troubleshooting.md](docs/troubleshooting.md) | Common issues, debugging, and operational procedures |
| [docs/RFC-conformance.md](docs/RFC-conformance.md) | RFC conformance target, current coverage status, and required changes for Level 1 authoritative UDP |
| [docs/manual-validation.md](docs/manual-validation.md) | Manual wire-level validation guide using `dig` and `tcpdump` |
| [docs/project-brief.md](docs/project-brief.md) | Goals, non-goals, constraints, requirements |
| [docs/system-patterns.md](docs/system-patterns.md) | Architecture and design patterns |
| [docs/project-rules.md](docs/project-rules.md) | Toolchain, QA commands, CI/CD workflow, naming conventions |
Expand Down
Loading