PERUNLIGHT / ZONEHANDOFF 1.0.0
Illustrated manual · Linux edition · October 2026
Prerequisites: a Linux computer with Python 3.10+ and Chrome. Tested on Linux x86_64 with Python 3.10.12 and Chrome 152.0.7977.82. Other operating systems, browsers and provider integrations remain unverified.
ZoneHandoff-1.0.0 folder.python3 start.py. The application opens your browser. If it does not, copy the printed local address into Chrome. python3 start.py --no-browser suppresses automatic opening.The address starts with http://127.0.0.1: and uses an available port each run. Keep the terminal open while working. No pip install, internet connection, DNS binary or account is required to run the app. The Python runtime and browser themselves are not included.

Choose Load fictional example. It loads 10 existing records and 5 proposed records in nameserver-move mode. The inputs are original reserved .example data with documentation-only addresses; the mail strings are not deployable settings.
198.51.100.20.www CNAME remains unchanged.www CNAME follows the changed apex. SPF dependencies are not evaluated externally.
| Expected candidate | Result |
|---|---|
| Record count | 10 records in 9 RRsets |
| Website | A 198.51.100.20; unchanged www CNAME |
| Authority | NS ns1.new.example. and ns2.new.example.; proposed SOA with draft serial 2026100202 |
| Preserved services | MX, SPF, DMARC, DKIM and CRM data from the existing export |
| TTL | 3600 seconds on every example record |
The same expected data is in examples/expected-candidate.zone. The fixture is an example of file reconciliation, not a functioning mail configuration.
Ask the DNS operator for complete exports of the same domain, including both SOA and apex NS. Enter the domain as ASCII/Punycode, give the project a name, choose the existing and proposed files, then select Compare exports. Editing either source or the domain disables exports until you compare again; comparing changed sources resets all decisions. Use copies of your files and keep the originals.
Keep existing DNS is the default for your own files: old SOA and NS are retained and proposed authority is not applied. A website move does not inherently require moving nameservers. Prepare a nameserver move requires a linked, explicit proposed SOA/NS choice and external NS targets; local nameserver glue management is excluded.
| Accepted | Refused / excluded |
|---|---|
| UTF-8 BIND master files, optional BOM, LF/CRLF; 2 MiB and 5,000 RRs per file; IN class only | Binary data, CSV, screenshots, API/AXFR imports, reverse zones, multiple zones |
| A, AAAA, CNAME, MX, TXT, SRV, CAA, apex SOA and NS | DNSSEC, delegations/non-apex NS, DNAME, HTTPS/SVCB, unknown types, wildcards, internal/split-horizon deployments |
| $ORIGIN within the zone, $TTL, comments, multiline parentheses, inherited owner/TTL, relative names, quoted TXT segments and escapes | $INCLUDE, $GENERATE, out-of-zone owners, duplicate SOA, mixed TTLs in a single RRset, CNAME coexistence/cycles |
| Plain supported records and original source bytes | ALIAS, ANAME, POOL, proxy, geoip and failover markers, even in comments or quoted values; this conservative refusal can include false positives |
Identical duplicate records collapse with a visible count. TXT segment boundaries, byte escapes and TTLs are preserved semantically. Formatting/comments remain in the exact originals; candidate formatting is canonical. Comment review shows the first 500 comment-containing lines; the full original is always preserved.
Provider features entirely omitted from an export cannot be detected. A checked review box records an operator action; it never proves provider completeness. Do not remove unsupported data just to make an import pass—obtain an appropriate supported export or use another operator workflow.
The existing zone is the baseline. Existing-only sets default to preservation. Changed and proposed-only sets need a choice; multi-value sets are kept or replaced together. TTL-only changes also need a decision.
CNAME must be the only record type at its owner. When converting A to CNAME, explicitly remove the conflicting old A and adopt the new CNAME. Intermediate conflicts block candidate export until the complete owner is consistent. A CNAME cycle cannot be exported.

Local MX/SRV/CNAME dependencies on changed A/AAAA records are reported, including local CNAME chains. SPF is flagged for external/indirect review, never rewritten or evaluated. An unchanged MX may still point to a changed address. Add operator notes for DNSSEC/parent DS review, provider features, application/email tests and ownership.
When choices and local structural checks are complete, Download candidate handoff becomes available. The browser saves a ZIP using a sanitized project name. It does not overwrite imported files. Extract the handoff into a separate folder and open handoff.html to read or print the report (browser Print / Save as PDF).
| File | Purpose |
|---|---|
| candidate.zone | Complete draft, only when resolved; operator review required |
| existing-original.zone / proposed-original.zone | Exact original bytes, including BOM/newlines |
| decisions.csv | Review history, formula-leading text guarded for spreadsheets; project JSON retains lossless reasons |
| handoff.html | Printable decision table, dependencies, source hashes and manual checks |
| project.json | Raw encoded sources, hashes, exact choices/reasons and notes; reopen in the app |
| manifest.json / operator-notes.txt | Artifact hashes, unresolved status and manual operator sequence |
Unresolved choices enable Download blocked draft: no candidate.zone is included. A refused import can also export a blocked draft containing originals, a project and the refusal report; it has no parsed decisions CSV. Correct its source before it can reopen as a valid project.
Save project downloads a standalone project JSON. Use Reopen project in a later session to reproduce sources and choices. Unknown versions, modified hashes and stale decision identities are refused. No automatic save is performed.
After your DNS operator reviews a staging/import preview, obtain a fresh supported export. With a resolved project open, select it under Fresh BIND export and click Compare fresh export. Missing, unexpected and changed RRsets are all reported; authority differences are marked separately. TTL-only differences count as changes. Download the parity report as HTML and JSON in a separate ZIP.
For the fictional exercise, compare expected-candidate.zone: expect zero differences. Then remove the MX line from a copy and compare it: expect exactly one missing MX RRset.

| Symptom | Action |
|---|---|
| python3 not found / version too old | Install Python 3.10+ through your approved Linux software source, then reopen a terminal. No privileged installer is supplied. |
| Browser does not open / connection refused | Use the currently printed loopback URL, keep the terminal running and restart if it was closed. Ports change between runs. Do not expose this server to a network. |
| Import refused | Read the reason. Fix the export with the operator; do not discard unsupported records. Duplicate SOA and mixed TTLs are refused before normalization. |
| Candidate download disabled | Read Review's unresolved items: decide every changed/new set, give required reasons, resolve CNAME conflicts and record both required review actions for a nameserver move. |
| Source hash mismatch / stale project choices | Reimport the original zone files into a new project. Do not hand-edit encoded sources or decision identifiers. |
| Unexpected provider markers | The marker guard is deliberately conservative. A quoted word may trigger it. Use a different supported workflow rather than bypassing the guard. |
| Large file rejected | Per-source limits are 2 MiB and 5,000 records; project request limit is 8 MiB. Do not split a real zone and treat each fragment as complete. |
| Browser reload lost work | Reopen your last saved project. Unsaved in-memory choices cannot be recovered. |

Processing stays in your local Python process and browser. The app has no telemetry, account, cloud calls or external assets. It binds only 127.0.0.1 and checks Host, Origin and a session token for operations. Your browser or operating system may independently use network services; those are outside this app.
Projects and exports contain the full source TXT records, filenames and notes; treat them as potentially sensitive and share only with authorized operators. The app does not automatically persist state. Browser downloads are user-controlled and remain until you delete them. Do not include credentials in inputs or notes.
Save your project, then press Ctrl+C in the launch terminal and close the tab. To uninstall, delete the extracted app folder. Separately delete downloads you no longer need. No service, registry change or updater is installed.
All illustrations are screenshots of the running product. Native self-verification is distinct from independent release acceptance. The one-time USD 29 price is a product experiment; customer acceptance and sales are not established.