PERUNLIGHT / ZONEHANDOFF 1.0.0

A DNS handoff you can review.

Illustrated manual · Linux edition · October 2026

1. Extract and start

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.

  1. Extract the complete buyer ZIP into a folder you own. Do not run files from inside the ZIP viewer.
  2. Open a terminal in the extracted ZoneHandoff-1.0.0 folder.
  3. Run 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.

ZoneHandoff home with source inputs and Load fictional example button
Actual running app: complete exports and preparation-only scope are visible before import.

2. First result: Brightfern Studio

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.

  1. Find brightfern.example. A and choose Use proposed to select 198.51.100.20.
  2. Leave existing-only MX, SPF TXT, DMARC TXT, DKIM TXT and CRM CNAME on Keep existing. The existing www CNAME remains unchanged.
  3. In Review, confirm adoption of the proposed SOA and NS together. For this fictional exercise, check the provider-review box after reading the limitation. For real work, make that review with your operator first.
  4. Review the warnings. The unchanged www CNAME follows the changed apex. SPF dependencies are not evaluated externally.
  5. Select Download candidate handoff, then Save project.
Record comparison showing existing and proposed data and explicit decisions
Every supported RRset appears with its TTL, complete data, status and choice. Multiple records of one owner/type form an RRset.
Expected candidateResult
Record count10 records in 9 RRsets
WebsiteA 198.51.100.20; unchanged www CNAME
AuthorityNS ns1.new.example. and ns2.new.example.; proposed SOA with draft serial 2026100202
Preserved servicesMX, SPF, DMARC, DKIM and CRM data from the existing export
TTL3600 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.

3. Import your own files

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.

AcceptedRefused / excluded
UTF-8 BIND master files, optional BOM, LF/CRLF; 2 MiB and 5,000 RRs per file; IN class onlyBinary data, CSV, screenshots, API/AXFR imports, reverse zones, multiple zones
A, AAAA, CNAME, MX, TXT, SRV, CAA, apex SOA and NSDNSSEC, 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 bytesALIAS, 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.

4. Decide and review

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.

Review panel with dependency warnings and both review confirmations selected
Local decisions complete does not mean live services are validated. Warnings remain visible after choices are complete.

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.

5. Export and reopen

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).

FilePurpose
candidate.zoneComplete draft, only when resolved; operator review required
existing-original.zone / proposed-original.zoneExact original bytes, including BOM/newlines
decisions.csvReview history, formula-leading text guarded for spreadsheets; project JSON retains lossless reasons
handoff.htmlPrintable decision table, dependencies, source hashes and manual checks
project.jsonRaw encoded sources, hashes, exact choices/reasons and notes; reopen in the app
manifest.json / operator-notes.txtArtifact 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.

6. Verify a fresh export

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.

Fresh snapshot comparison reports exactly one missing MX RRset
File parity catches the omitted MX in this exercise. It does not query live DNS, propagation or email delivery.

Troubleshooting

SymptomAction
python3 not found / version too oldInstall Python 3.10+ through your approved Linux software source, then reopen a terminal. No privileged installer is supplied.
Browser does not open / connection refusedUse 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 refusedRead the reason. Fix the export with the operator; do not discard unsupported records. Duplicate SOA and mixed TTLs are refused before normalization.
Candidate download disabledRead 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 choicesReimport the original zone files into a new project. Do not hand-edit encoded sources or decision identifiers.
Unexpected provider markersThe marker guard is deliberately conservative. A quoted word may trigger it. Use a different supported workflow rather than bypassing the guard.
Large file rejectedPer-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 workReopen your last saved project. Unsaved in-memory choices cannot be recovered.
Mixed TTL source refused with an explicit reason
A refusal does not produce a partial successful candidate.

Privacy, shutdown and uninstall

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.