Contributing
Repo layout
Section titled “Repo layout”provider/ Core contract: Provider, RRset, RRSetChange, Capabilities, optional interfaces, registry, name canonicalizationprovider/<name>/ One adapter per providercore/ Models + event-sourced aggregates (ORM++), migrationsapp/ Business functions (zones, Sync Groups, Templates, sources, DynDNS, certificates, users, teams …)httpapi/ Fiber v3 API + registration layer for EE/Cloudserver/ Reusable wiring (server.Run + options)auth/ acme/ mail/ Passwords/TOTP, ACME issuer (lego), SMTP deliveryjobs/ session/ Scheduler (drift, certificates, reminders), sessionsdemo/ In-memory provider + demo seed (DNSE_DEMO=on)ui/ webui/ Lit/Shoelace SPA + go:embed of the builddocs/ This documentationmake test # Go tests (race) + gofmt + vet + UI testsgo test -race ./...gofmt -l .go vet ./...The interface lives pre-built in the repo (webui/dist) so that go:embed
works. After changes to ui/, the build belongs in the same commit — CI
checks this:
cd ui && npm ci && npm run buildIntegration tests against a real PowerDNS
Section titled “Integration tests against a real PowerDNS”docker compose up -dPDNS_TEST_ENDPOINT=http://localhost:8081 PDNS_TEST_API_KEY=test-secret \ go test -race -run Integration -v ./provider/powerdns/Without the two variables, these tests are skipped. CI runs the same tests against a PowerDNS service container.
Adding a new provider
Section titled “Adding a new provider”An adapter lives under provider/<name>/ and implements:
| Method | Task |
|---|---|
Zones | list the account’s zones (for onboarding) |
RRsets | read the actual state of a zone |
ApplyChanges | write and delete record sets |
Health | verify credentials (connection test) |
It also includes a Descriptor (display name, credential fields, portal and
docs links, short guide) and the Capabilities. Errors are mapped to the
package’s sentinel values (ErrUnauthorized, ErrZoneNotFound,
ErrInvalidChange, ErrUnreachable) — the account states in the interface
hang off these.
desec (atomic bulk update) and digitalocean (individual records with
priority/weight) make good starting templates.
Branching model
Section titled “Branching model”- Default branch:
develop main: protected, only via merge request with a green pipeline- Conventional Commits in German
CI builds every module without go.work. Whoever adds a new dependency
therefore runs GOWORK=off go mod tidy — otherwise the checksums only end
up in the local go.work.sum and the pipeline fails.