Builds the Twig environment with theme, translator and extensions, and renders templates for web controllers.

What Kernel::boot() built for this process: the configuration, the logger, the loaded module registry and, once something asks for it, the database.

The one place a process is booted: index.php, dynamic_update.php, install/index.php and bin/poweradmin all call boot() and work from the BootContext it returns. Nothing below the entry points reaches for the configuration singleton.

Sets the gettext locale and text domain for a supported locale from the locale directory.

Process-level setup Kernel::boot() runs before routing: timezone and session cookie.

The parsed command line: one command word, "--name=value" options and the remaining positional words. Options may appear before or after the command.

One bin/poweradmin command. The metadata is static so the registry can print usage and validate options before the service graph is booted.

The actor of a console run: nobody (the system itself) unless the caller named a user with --as-user, in which case that user's permissions apply.

The commands bin/poweradmin knows, keyed by name. Each entry is a factory that builds the command from the booted service graph.

api-keys:create - issues an API key owned by the acting user (--user=) and prints the secret once. ApiKeyService enforces the same rules as the web form: API enabled, api_manage_keys or ueberuser, and api.max_keys_per_user.

zone:list - the zones the actor may view, one row per zone.

zone:show <id|name> - the records of one zone, one row per record, in the order the web zone editor shows them. The actor needs the same view permission as for opening the zone in the browser; a refusal exits 1.

The bin/poweradmin entry point: parses the command line, boots the same service graph the web controllers use (without a session) and runs one registered command as an explicitly named actor.

Writes the tabular output of a command as tab-separated lines (a header row, then one line per row) or as a JSON list of objects keyed by the lower-cased column names.

Shared base for API controllers: enforces the api.enabled switch, parses JSON input and shapes JSON responses.

Serves the Swagger UI page at /api/docs when API documentation is enabled.

Serves the OpenAPI JSON specification at /api/docs/json, generated from the V2 controller attributes.

Answers every miss on a headless install, where there is no web interface to render a 404 page with.

Unauthenticated readiness probe reporting whether Poweradmin can reach its own dependencies. Disabled by default.

Base for session-authenticated internal API endpoints: requires a login and the X-CSRF-Token header on writes.

Internal endpoint /api/internal/user-preferences: reads, updates and resets the logged-in user's preferences.

Internal endpoint /api/internal/validation: validates a record against a zone before it is submitted.

Internal endpoint /api/internal/zone: lists or fetches zones the logged-in user may view.

Base for /api/v2 endpoints: API key or Basic auth, key scope enforcement, request logging and wrapped responses.

Answers every /api/v1 path with 410 Gone and a pointer to v2.

/api/v2/change-requests: lists and shows filed change requests, applies a reviewer's decision and lets a requester withdraw their own request.

POST /api/v2/dynamic-dns: updates the A/AAAA records of a hostname in a zone the caller owns.

/api/v2/groups/{id}/members: lists, adds and removes the users in a group.

/api/v2/groups/{id}/zones: lists, assigns and unassigns the zones a group owns.

/api/v2/groups: lists, creates, updates and deletes user groups.

Carries the OpenAPI spec-level attributes (info, servers, security schemes) for the v2 API. Annotation-only: the class holds no runtime code and exists so the spec root does not live on an arbitrary endpoint controller. The docs generator scans this directory and picks the attributes up from here.

/api/v2/permission-templates: lists, creates, updates and deletes permission templates.

/api/v2/permissions: read-only listing of the permission catalogue and single permissions.

The JSON shape of a record on /api/v2. The list endpoints report the fully qualified name, the single-record endpoints the name relative to the zone; both are contract and neither may drift without the other being reviewed.

The JSON shape of a zone on /api/v2: the listing carries a summary, the single-zone endpoints the full detail.

/api/v2/users: lists, creates, updates and deletes users and assigns their permission template.

/api/v2/zones/{id}/dnssec: reports the signing status of a zone and signs or unsigns it.

/api/v2/zones/{id}/metadata: lists, reads, replaces and deletes PowerDNS metadata kinds on a zone.

/api/v2/zones/{id}/owners: lists, adds and removes the users who own a zone.

/api/v2/zone-templates/{id}/records: lists, creates, updates and deletes the records of a zone template.

/api/v2/zone-templates: lists, creates, updates and deletes zone templates.

/api/v2/zones/{id}/change-requests: files change requests for a zone without writing to it. Answers 404 while approval.enabled is off.

/api/v2/zones: lists, creates, updates and deletes zones.

/api/v2/zones/{id}/rrsets: lists, replaces and deletes records grouped by name and type.

POST /api/v2/zones/{id}/records/bulk: applies a list of create, update and delete record operations.

/api/v2/zones/{id}/records: lists, creates, updates and deletes single records in a zone.

Handles the change-password form for the logged-in user; LDAP, OIDC and SAML users are refused.

Handles the forgot-password form: takes an email address and sends the password reset link.

Handles the forgot-username form: sends the username to the submitted email address if it is on file.

Renders the login page with its CSRF token and the enabled OIDC and SAML providers.

Logs the user out, clearing the session and redirecting to the OIDC or SAML provider's logout when used.

Handles the MFA setup page: app or email enrolment, verification, disabling and recovery code regeneration.

Handles the MFA verification step after login, with throttling of failed attempts.

Handles the OIDC provider callback at /oidc/callback: completes the login or reports the provider error.

Starts the OIDC login flow by redirecting to the chosen or first configured provider.

"Continue as" on the login page: lifts the signed-out mark set at logout so the next page signs the web server's user in again.

Handles the password reset form reached from the emailed token link and sets the new password.

Handles the SAML assertion (/saml/acs) and single logout (/saml/sls) endpoints.

Starts the SAML login flow by redirecting to the chosen or first configured identity provider.

Serves the SAML service provider metadata XML at /saml/metadata.

Handles the user agreement page: shows the text and records the user's acceptance.

Base for every web controller: config, database, session, permissions, CSRF, validation and Twig rendering.

Handles the add-DNSSEC-key form for a zone: validates key type, bits and algorithm, then creates the key.

Renders the DNSSEC key overview for a zone and handles the unsign-zone action.

Handles the delete confirmation for a DNSSEC key and removes it from the zone on confirmed POST.

Renders the DS and DNSKEY records page for a zone.

Renders the DNSSEC key detail page that confirms activating or deactivating a key.

Base for the pages that add, edit, toggle, delete, import and export DNSSEC keys: one shared gate.

Streams a DNSSEC private key as an ISC (BIND "Private-key-format") file, the format PowerDNS returns on per-key GETs of /cryptokeys.

Imports a DNSSEC private key into a zone via the PowerDNS API. Takes ISC (BIND) text or an RSA, ECDSA or EdDSA PEM key, which is converted to ISC.

Handles the POST that activates or deactivates a DNSSEC key, then returns to the zone's DNSSEC page.

Shared flow for the log listing pages (API, user, group and zone logs): filter parsing, pagination with last-page clamping, and CSV/JSON export.

Renders the API request log page for admins with filters and CSV/JSON export.

Renders the group log page with filters and CSV/JSON export.

Renders the user log page with filters and CSV/JSON export.

Renders the zone log page, limited to owned zones for users without the view-others permission.

Handles the add-record form for a zone: checks edit rights, validates the record and saves one or several rows.

Handles the batch PTR form: creates PTR records for an IPv4 or IPv6 network, optionally with forward records.

Handles the bulk add-records form for a zone: parses one record per line and saves them as one changeset.

Handles the delete-record confirmation page and removes the record, plus its PTR counterpart when ticked.

Handles bulk record deletion from search results: shows the selected records and deletes them on confirmation.

Handles the zone comment form: shows the comment and saves it when the user may edit the zone.

Handles the edit-record form: validates the change, saves it and syncs the matching PTR record when ticked.

Renders the record change log page for admins with filters, pagination and CSV/JSON export.

Admin UI for managing per-record-type default TTLs. The repository drives ReverseTtlResolver::resolveTtlForType(), so values entered here take effect for every record-creation path (UI + API).

Ends a controller run whose response is already written: the error page, the redirect header or the JSON body went out, and nothing may follow it.

Handles the add-supermaster form: validates the IP and nameserver, then stores the supermaster entry.

Renders the database consistency page for admins and applies the fix actions it offers.

Handles the delete-supermaster confirmation page and removes the supermaster on confirmed POST.

Handles the edit-supermaster form: updates the IP, nameserver and account of a supermaster.

Renders the dashboard after login with the cards allowed by the user's permissions.

Renders the supermasters list at /supermasters.

Answers unmatched routes with a 404 page, or a JSON error for API callers.

Renders the PowerDNS server status page from the API's server info and statistics.

Unauthenticated liveness probe. Answers if the process can serve a request and checks nothing else, so it still reports ok while the database is down.

Serves static assets like CSS, JS, images and fonts.

Handles the add-zone-template form: validates name and description, then creates the template.

Handles the add-record form of a zone template and marks the template as modified on success.

Handles the delete-zone-template confirmation page and deletes the template on confirmed POST.

Handles the delete confirmation for a zone template record and marks the template modified after deletion.

Renders the zone template edit page and handles detail, record, save-as and linked-zone updates.

Handles the edit form for one zone template record and saves the change on POST.

Renders the list of zones linked to one zone template.

Renders the zone templates list at /zones/templates.

Handles the save-zone-as-template form: creates a zone template from the zone's records.

Handles the POST that marks a zone template as the default or clears the default flag.

Handles unlinking selected zones from a zone template, with a confirmation step.

Handles the add-group form at /groups/add: validates the name and group template, then creates the group.

Handles the add-permission-template form: validates the fields and creates the template with its permissions.

Handles the add-user form: guards the template choice, creates the user, assigns groups and mails credentials.

Renders the API key list page and links to the add, edit, delete and regenerate actions.

Handles the delete-group confirmation page and deletes the group on confirmed POST.

Handles the delete-permission-template confirmation page and deletes the template on confirmed POST.

Handles the delete-user page: deletes the user and transfers or deletes each of their zones as chosen.

Handles the edit-group form: updates the name, description and permission template of a group.

Handles the edit-permission-template form: updates the template's details and permission set.

Handles the edit-user form: updates the profile, password, template and group memberships of a user.

Renders the groups list page at /groups.

Renders the permission templates list at /permissions/templates.

Handles the group members page: adds and removes users in a group.

Handles the group zones page: assigns zones to a group and removes them.

Handles the POST that removes one user from a group from the edit-group page.

Handles the POST that removes one zone from a group from the edit-group page.

Handles the POST that removes a user from one group from the edit-user page.

Handles the user preferences page: rows per page, form positions, display toggles and timezone.

Renders the users list and saves the inline edits submitted from it.

Handles the add-primary-zone form: validates name and kind, applies the template and creates the zone.

Handles the add-secondary-zone form: validates the name and primary address, then creates the SLAVE zone.

Handles the bulk registration form: creates a primary zone from a template for each submitted domain name.

Shows one change request with its before/after actions and takes the reviewer's approve or reject decision, or the requester's cancellation.

Handles the delete-zone confirmation page and deletes the zone on confirmed POST.

Handles bulk zone deletion from the zone lists: shows the selected zones and deletes them on confirmation.

Renders the zone edit page with its record table and handles record, comment, template and signing changes.

Handles reading and replacing raw PowerDNS domain metadata for a single zone.

Lists change requests: reviewers see the zones their approve level covers, everyone else sees the requests they filed.

Renders the forward zone list with pagination, letter filter and sorting; also handles the API sync action.

Lists network -> view mappings (PowerDNS 5.0+) and exposes inline add/edit/remove actions. Admin-only; hidden behind the supportsViews() capability gate, which covers the version, the backend and views=yes.

Renders the reverse zone list with pagination and sorting.

Lists PowerDNS views (5.0+) and the zones they contain. Also exposes inline add/remove actions. The whole feature is admin-only and hidden when the connected server cannot serve views, whether through its version, its backend or its views setting (capability gate).

Handles the search page: finds zones and records by name or content with paging and sorting.

Manage which zones a producer zone publishes in its catalog.

Handles the zone ownership page: adds and removes user and group owners of a zone.

Shapes an unhandled throwable into an HTTP response for the front controller.

The requesting client as resolved once per request: the address behind any trusted proxy and the sanitized user agent. Built by the composition root and handed to everything that logs, throttles or audits by client.

Opt-in paging and substring filtering for API list endpoints. paginate() and filterContains() serve lists that are already loaded, e.g. records, which come from the PowerDNS API in API backend mode; isPastEnd() and extra() also serve lists paged in SQL, such as change requests.

Sort order requested through the sort query parameter of an API list endpoint.

The one place a Domain refusal becomes an HTTP status. API controllers call this where they used to read a status number off the result.

Snapshot of the $_GET, $_POST and $_SERVER superglobals with typed accessors for controllers.

Static helpers classifying the current request from server globals: API route detection and JSON response negotiation.

Framing, content-type sniffing and referrer headers sent on every response; Kernel::boot() calls send() once per process.

The bundled modules, keyed by the name used under modules. in the configuration.

Loads the modules listed in the manifest and answers which are enabled for the current user.

The module-facing service surface: the collaborators a module controller may obtain from the core through BaseController::moduleServices().

Shapes change requests for the list, review and edit-page templates.

The zone editor's view model: maps the facts the controller has already resolved (zone, permissions, preferences, listing) onto the variables edit.html reads. Everything derived for the page - editability flags, record locks, the comment conflict, the offered record types - is computed here from those inputs alone.

Prepares the zone-list owner and group cells: the first entries stay visible, the rest collapse into a "+N more" tooltip label.

Which users a zone-owner picker offers, and which one it shows again after a refused submit. Whether the caller may pick other users is decided by the permission layer and passed in.

Describes the page-number list for a Pagination object, with ellipses around the current page.

Maps a refused record write to the record form input it should highlight.

Decorates the zone editor's record rows with the display fields the template expects, and with whether each row may be edited.

Puts a zone-editor submission that was refused as stale back into the freshly read record listing, so the warning does not also cost the operator their edits.

Labels the record search rows for the search page. The gateways return disabled as a bool; the translated Yes/No goes into disabled_label.

Attaches the labelled SOA breakdown to record rows so the templates can show it.

Describes the 0-9, a-z, IDN and "Show all" filter links on the forward zone list page.

Removes the web interface from the route collection when interface.web_enabled is false, leaving an API-only (headless) surface.

Matches the request against routes.yaml and enabled module routes, then runs the matched controller.

The actor of an API request: the owner of the key (or the Basic auth user) that authenticated it. Built once per request after authentication succeeds.

Authenticates API requests by the X-API-Key header and loads the key's user.

Result of an authenticator run: the decision, the login message on failure, and the application path the caller should redirect to when the request was a login post.

Starts or ends a session with a flash message, then redirects to login; API requests get a 401 JSON instead.

Authenticates API requests with HTTP Basic credentials against the users table.

Generates, stores and validates the per-session CSRF token carried by the _token form field.

Re-checks the account behind a session an identity provider established. SQL and LDAP sessions re-verify the account on every request; OIDC and SAML ones would not.

Session login against an LDAP directory, with lockout tracking, a cached bind result and MFA hand-off.

Decides whether a user-supplied password may be sent to an LDAP simple bind.

Records attempts in login_attempts and enforces the password- and MFA-stage lockouts per user and IP.

What the login form posted: the fields SessionAuthenticator reads before handing the attempt to an authenticator.

Renders the MFA verification email through Twig and sends it with MailService.

Reads the oidc provider settings, discovers endpoints and validates the permission template mapping.

Runs the OIDC login flow: builds the authorization redirect and turns the callback into a session.

Verifies reCAPTCHA v2/v3 responses with Google for the login form.

Reads the user the web server or an authenticating proxy signed in, from the remote_user settings. A server variable is set by the web server itself; a header is believed only from an address in remote_user.trusted_proxies.

Keeps the session in step with the user the web server signed in: starts a session for them, ends one whose web server user changed or went away, and leaves sessions started by any other sign-in method alone.

The actor every service of one request shares. It starts as whatever the bootstrap knows (the session user); an API controller rebinds it to the key owner once authentication succeeds, so services built before and after that point agree on who is acting.

Reads the saml provider and SP settings and builds the OneLogin toolkit settings array.

Runs the SAML login flow: builds the IdP redirect, consumes the assertion and handles single logout.

Per-request login pipeline: CSRF and reCAPTCHA on the form, session expiry, then the SQL or LDAP authenticator.

Session login against the users table with lockout checks, hash upgrades and MFA hand-off.

Hashes and verifies user passwords across bcrypt, argon2 and the legacy md5 formats.

Creates or updates the local user for an LDAP, OIDC or SAML login and maps their groups to a permission template.

Opens the PDO connection from the configured credentials, wrapping failures in a readable error.

Factory for creating DNS backend provider instances.

Orchestration service for DNS data reads.

Builds the DNSSEC provider for the configured PowerDNS API, or a null provider when the API is not set up.

Detects and caches the connected PowerDNS server version so admins can see it in the UI and so error reports include it without a manual lookup.

Reads server info and metrics from the PowerDNS API and probes secondary servers for the status page.

Centralized factory for creating repository instances.

The collaborators a controller is built from. In production Kernel::controllerEnvironment() derives one from the booted context (config file check, database connection, session authentication); a test passes one straight to the constructor with stubbed services, most usefully a stub ControllerServiceFactory, which the create*() accessors on BaseController all route through. Both paths construct the controller the same way.

The services controllers ask for, split by concern into five factories that each memoize their per-request instances. The flat accessors below delegate to them so call sites and test doubles keep one entry point.

Sessions, credentials, MFA, API keys and the audit trail. The session, redirect and authentication services are one instance per request.

The connection to the DNS backend: the provider, its API client, and the repositories and record managers that read and write through it. Every memoized instance is shared for the request so read caches are not split.

Record writes and the change-approval flow around them: managers, reverse record creation, comments, and the change request pipeline.

Users, groups, permissions and preferences. The permission service is memoized so its per-user cache spans the whole request.

Zone lifecycle: creation, ownership, templates, signing, metadata and the zone lists.

Renders the transactional email templates under templates/emails, with custom overrides, through Twig.

Sends application email over the configured transport: PHP mail(), sendmail, SMTP or the log.

Builds the dyndns2 request value object and the update service that handles it.

Whether a user may add records to a zone directly, as RecordAddService::open() answers it. Each add-record entry point words the refusal codes itself.

Words a successful RecordAddResult for the add-record page and the zone editor.

Outcome of adding one record from a form, with the companion PTR or A record the operator asked for alongside it.

The add-record flow shared by the add-record page, the inline form on the zone editor and the record wizards: open() applies the same gates in the same order, and add() normalises name, content and TTL the same way and follows the same rules for the companion PTR or A record.

Reads and writes the comment attached to a record.

Keeps the comment on an A/AAAA record and its PTR counterpart in sync when either is created or edited.

One record edit as the edit-record form or an API PUT submits it. The caller has already found and authorised the stored row; the service normalises the submitted values and writes.

Outcome of editing one record: the write itself, the row as it is stored afterwards, and how the PTR sync went when one was asked for.

The single-record edit flow shared by the edit-record page and the API PUT: name and content are stored as punycode with the zone suffix, the write goes through the record manager, an SOA edit is bumped by the same rule, the PTR follows when asked, the edit is audited and the record comment is stored or carried along with a rename.

Creates a record through RecordManager, then logs it, stores its comment and syncs the PTR comment.

Resolves a user's avatar URL from an OAuth profile picture or Gravatar, per the interface.avatar_* settings.

Adds and removes users from groups and lists a group's members.

Creates, updates, deletes and lists user groups, with the view checks the group pages need.

Changes the logged-in user's own password after verifying the current one; LDAP users are refused.

Generates random passwords that satisfy the configured password policy.

Checks a password against the security.password_policy rules and reports the ones it fails.

Password reset by email: issues and rate-limits tokens, validates them and stores the new password.

Words a permission template delete outcome for the web flash messages.

The single guarded entry point for permission template writes.

Turns a user create or update request, keyed by the API field names, into the typed command UserManagementService takes. A value of the wrong shape is refused here with the same wording and refusal the service used to give.

Words a refused UserManagementService write for the user forms. The service's own message is the API wording; password policy, field length and external-auth password messages are the same on both sides and pass through.

Username recovery by email: rate-limits requests and mails the usernames registered to an address.

Writes the "client_ip:.. user:.. operation:.." audit lines. Every line starts with the same actor context; one method per event keeps the field names in one place.

The totals on the admin dashboard. Zone and record counts are null when they cannot be read, so the page still renders.

Resolves the interface language for the current request.

Builds Pagination objects and resolves the rows-per-page value within the allowed bounds.

Sends a Location header for the given URL, or a prepared response, and ends the request. The halt unwinds to the router the way the former exit ended the process, which keeps the redirect out of the way of anything that follows and leaves it observable to a test.

Validates controller request data against Symfony constraints.

Value object holding the search parameters the search page works with.

Renders the memory usage and elapsed time footer shown when misc.display_stats is on.

Builds absolute URLs for emails and redirects from the configured base URL.

Answers what the change-approval feature means for one user: whether it is on, how their edits to a zone are handled, which zones they review, and how many requests are waiting.

Words a ZoneChangeRequestService outcome for the web flash messages.

Writes the zone audit line for each change request event, then emails the reviewers of the zone when a request is filed and the requester when it is decided. Mail failures are logged and reported as false; nothing here throws to the caller, so a mail problem never blocks a request.

Emails a user when they gain or lose access to a zone.

What ZoneCreateService made of a batch: either a refusal that stopped the batch before any zone was tried, or one outcome per submitted name.

Words a refused ZoneManagementService::createZone() for the add-zone forms, and the warning about parent-zone records a created zone hides.

What ZoneCreateService made of one request: the created zone, or the refusal worded for the form.

What a zone creation form submitted, as ZoneCreateService takes it: the name as typed, the owner controls as posted, and the kind-specific options.

The zone creation flow shared by the add-zone forms, bulk registration and the secondary zone import: the name is normalised the same way, the owner controls are resolved by the same rules, the zone is created and audited the same way, and every refusal is worded for the form.

Assigns zones to groups and removes them; the group-based half of zone ownership.

Reads a submitted zone limit: empty clears the own limit (the configured default applies), a whole number of 0 or more sets it.

Web wording for zone limits on the user, group and add-zone pages.

Words a refused ZoneMetadataService write for the metadata editor.

Reads the owner and group fields of the add-zone forms and applies the shared ownership rules. The forms drop what the ownership mode disallows instead of rejecting it, and word the refusals in the user's language.

Reads the owner fields of a decoded zone creation body into the typed input ZoneCreateOwnershipResolver takes; a value of the wrong shape is refused with the same wording and status the resolver used to give.

Words a ZoneOwnershipGuard refusal for the zone ownership page.

Words a ZoneEditService save for the zone editor's flash message.

Words a ZoneSigningService outcome for the web pages that sign or unsign an existing zone.

Resolves the zone list's sort column, direction and reverse-zone filter from submitted values and the session.

Decides once per request which navigation entries the current user gets, so the two theme headers and the dashboard share one rule per entry.

Where a controller's pages go: the themed chrome and body in production (PageRenderer), a recorder in tests. A controller hands over the template and the parameters exactly as it built them.

Renders the shared page chrome (header, footer, Twig globals) around controller-rendered templates.

Decodes the zone editor's POST: the record[] rows with their trailing _complete marker, the checkbox encoding of "disabled", the form_complete marker at the end of the form, and the fields around the table.

Read access to settings by group and key.

Resolves which zones row a Poweradmin zone ID refers to.

DbCompat class provides compatibility methods for different database types.

Applies the pdns_db_name prefix to PowerDNS table names and validates ORDER BY, LIMIT and OFFSET inputs.

Reusable SQL fragments that derive zone-health flags (Disabled / No SOA) from the PowerDNS records table. Used by SQL-mode repositories to render status badges in the zone list without an extra round-trip.

Runtime exception carrying a message, a code and an array of extra details for API error responses.

Thrown when a referenced user group does not exist.

Thrown when a write would leave zones without an owner, carrying the zones it would strand so the caller can name them.

Thrown by a zone creation step once the backend zone exists, so the caller can roll back and remove the zone. The message is the user-facing failure text.

An API key row: name, secret, creator, expiry, disabled flag and its read-only, operation and zone scopes.

Immutable description of what an API key is allowed to do.

Application-wide constants.

A DNSSEC key of a zone: id, type (ksk/zsk/csk), size, algorithm, active flag, DNSKEY and DS records.

Numeric DNSSEC algorithm identifiers from the IANA registry and their display names.

PowerDNS DNSSEC algorithm names, the subset offered for new keys, and version-gating against the server.

Built-in PowerDNS domain metadata kind definitions.

Page arithmetic for a list: current page, page count, page-link window, and the SQL offset and limit.

Bounds and default for a usable page size; shared by the pagination and user preference services.

Maps a PowerDNS Authoritative Server version string to feature capability flags used by the UI to show, hide, or default behaviour appropriately.

Permission names and the record-type restrictions for client-level editors.

The seed data every fresh installation starts from: the perm_items table, the default permission templates, and the default user groups. The installer and the sql/poweradmin-*-db-structure.sql files (via composer sql:seed) both read it, so a new permission or template is added here only.

A comment on a record set (zone, name, type) with its author account, text and modification timestamp.

One record of a zone listing, as the export, template-save and console paths read it.

DNS record type names and the groups the UI and validators select from.

A parsed network for batch PTR creation: the address range to walk and the reverse name used to probe for its zone.

A pending change that can take super admin away from users, described so the repository can count who would still hold it once the change is written.

A user as seen by authentication: id, stored password hash and whether the account is LDAP-backed.

A user group as stored in user_groups.

One user's membership in a group, with the user columns the member list shows.

A user's MFA settings row: type (app or email), secret, recovery codes, verification data and timestamps.

One user_preferences row plus the list of allowed keys and the timezone validity rules.

A zone as seen by DNSSEC: its name and whether it is secured.

A filed change request: the actions a requester wants applied to a zone, who filed it, and how a reviewer decided it.

The row shapes stored inside a change request's actions. They are a data contract: requests filed by earlier versions are decoded by this class, so the keys and their types stay as they are.

One zone with its ownership, as read by ZoneReadRepositoryInterface::getZone().

A zone-to-group ownership row from zones_groups.

The first-letter filter on the forward zone list: '1' for a leading digit, a-z or '_', 'idn' for zones whose name starts with a punycode label, or 'all'.

One row of a zone list: the forward and reverse pages, the internal API list and the console listing.

ZoneType class represents the different types of zones in a DNS system.

A feature module: its routes, navigation items, capabilities and templates, enabled through configuration.

Who is acting in the current request: the session user on the web, the key owner on the API. Domain rules ask this instead of reading the session.

Exposes the most recent PowerDNS API error so domain checks can tell an outage from an empty backend.

Records or clears the most recent PowerDNS API error; the API client and backend provider write through this.

The audit events domain services record; the Application layer owns the line format and the actor context.

Capability probe telling callers which kind of DNS backend they hold.

Catalog zone membership reads and writes against the DNS backend.

Told about change request events so people can be notified. Implementations must not throw; a failed notification never undoes the event.

PowerDNS data access (domains, records, supermasters) over direct SQL or the PowerDNS API; Poweradmin-native tables stay on SQL.

DNSSEC operations for one zone.

Renders the account emails a preview tool can show; the Application layer owns the templates and their custom overrides.

Records login attempts and reports lockouts; the Application layer owns the storage and thresholds.

Delivers MFA email verification codes; the Application layer owns the template and transport.

Hashes and verifies user passwords; the Application layer owns the algorithm and cost settings.

Checks a password against the configured policy rules; the Application layer owns the configuration.

Merges the outbound HTTP proxy, when one applies to the URL, into a set of PHP stream context options.

Splits a hostname on the public suffix boundary, so that names under a multi-label suffix such as co.uk or com.pl are divided where registration actually happens rather than on the last dot.

Renders a string as a QR code for display in a page.

Records before/after snapshots of record and zone changes for the change log.

The per-record comment reads and writes the zone editor needs; the Application layer owns the storage.

Carries an edited record's comment over to its A/AAAA or PTR counterpart.

Record lookups by id, name or zone read from the DNS backend.

The search page's record half: matching records with their zone owner, paged and sorted, and the unpaged match count. Rows carry disabled as a bool.

Record add, edit and delete writes against the DNS backend.

A record write backend that sits behind a separate service which can refuse a write and say why (the PowerDNS API). Backends without one do not implement it.

Orders reverse zone names in PHP by the configured sort type.

Wildcard search over zones and records in the DNS backend.

SOA serial handling: whether PowerDNS bumps the serial itself and the zone serial policy metadata.

The request's session store. One implementation wraps PHP's own session, the other keeps the values in memory for tests and for request-scoped caches.

Supermaster (autoprimary) reads and writes against the DNS backend.

Time-based one-time passwords, as used by authenticator apps.

The request's unit of work: one transaction shared with every repository that writes through the same connection.

Tells PowerDNS that a zone written straight to its database changed, so a new zone is served at once and cached answers for the zone are dropped.

DNSSEC key lifecycle for a zone, plus the DS and DNSKEY records derived from its keys.

Zone lookups, listings, record counts and SOA health read from the DNS backend.

Rectifies a zone after its records change so the DNSSEC ordering data stays valid.

The search page's zone half: matching zones with their owners, paged and sorted, and the unpaged match count. Each backend keeps its own row shape.

Signing state of a zone: securing, unsecuring and reading whether it is signed.

Zone create, delete, kind, primary, account and AXFR-retrieve writes against the DNS backend.

Persistence for API keys.

The account rows the authenticators read while deciding a login.

Lookups on the domains table; implemented for SQL and for the API backend mode.

Persistence for the dynamic DNS update endpoint.

Persistence for the OIDC and SAML identity links that tie a provider subject to a local user.

Persistence for the login_attempts counters the authentication throttle reads and writes.

Persistence for password reset tokens and their rate-limit counters.

Persistence for permission templates and the permission items they bundle.

Persistence for RRset-level record comments; both backends implement it.

Comments linked to individual records through record_comment_links.

Zone-wide record listing, filtering, counting and RRset reads.

Single-record reads and existence checks within a zone.

Reads on the records table; implemented for SQL and for the API backend mode.

Persistence for admin-configured default TTLs per record type.

Builds the repositories a domain service needs on demand; the Application layer picks the SQL or API implementation for the configured backend.

Tracks which zone records a template application wrote, so a later application of the same template can remove exactly those records.

Account administration: listing, creating, updating and deleting users and moving their zones.

Persistence for the user agreement versions each user has accepted.

Write access to a user's stored password.

Read access to user groups and their membership by user.

Persistence for user group membership.

Persistence for user groups.

Creating, updating and deleting groups, plus the counts that guard a delete.

Read access to individual user accounts by id, name or email.

Persistence for per-user MFA settings.

The account rows the notification mailers address their messages to.

Read access to what a user may do: permissions, uberuser status, template grants and zone ownership.

Persistence for per-user interface preferences.

Persistence for user accounts and the zones they own.

Persistence for username recovery attempts and their rate-limit counters.

Resolves the owner whose username the PowerDNS account field mirrors.

Persistence for zone change requests. Lists come back newest first.

Persistence for group-based zone ownership.

Where a zone's metadata rows live: the domainmetadata table on the SQL backend, or the PowerDNS API (metadata plus zone-object properties) on the API backend. Rows are [['kind' => string, 'content' => string], ...].

Zone ownership reads and writes; one of the three roles ZoneRepositoryInterface combines.

Zone lookups, lists and counts; one of the three roles ZoneRepositoryInterface combines.

Zone reads and ownership writes; implemented for SQL and for the API backend mode.

Read access to zone SOA serials.

Persistence for zone templates (zone_templ), their records (zone_templ_records) and the zone -> template links kept in zones.zone_templ_id.

Tracks which zones are out of date against their template after the template changes.

Zone row, comment and metadata writes (plus the metadata read the editor pairs with them); one of the three roles ZoneRepositoryInterface combines.

Creates, regenerates, disables and deletes API keys and enforces the per-user key limit.

Outcome of an API key write: the saved key on success, otherwise the reason, its code and the refusal.

Permission gate for the public API. A facade over PermissionService so the API and the web UI share one oracle; group and visible-zone lookups read the user repository.

Checks a DDNS client's password (with login-attempt lockout) and which zones that user may update.

TOTP, email-code and recovery-code verification, MFA enrolment, QR code rendering and enforcement checks.

AES-256-CBC encryption for the password held in the session, keyed from the configured session_key.

Answers permission questions for a user from their template and group grants, cached per request.

Gates perm_templ assignment on user create/update API paths.

Gates what a permission template may contain.

Gates auth-critical fields on user self-edit API paths (#1327).

Pure rules for which requests a session gate (required MFA setup, user agreement) holds back while the user still has to complete it.

Catalogue of the login and user identity $_SESSION keys.

Promotes the half-authenticated pending session into a fully authenticated one.

Session-backed identity of the current user (id, username, auth method) and the session storage controllers use. Domain rules read the actor through ActorInterface instead.

Pure rules for what a user may change on the zone edit screens.

Builds the ownership index the zone lists and the search page use to decide per-row edit/delete controls and owner-column visibility.

Finds and repairs ownerless zones, masterless slave zones, orphaned records and missing or duplicate SOAs. One implementation per DNS backend.

Shapes check results and fix-all tallies the same way for every backend strategy.

Validator for AAAA DNS records

AFSDB record validator

Validator for ALIAS DNS records

Validator for APL (Address Prefix List) DNS records

Validator for A DNS records

BRID (Broadcast Remote ID) record validator

Validator for opaque RDATA stored as base64 in zone-file form (PowerDNS xfrBlob).

CAA record validator

CDNSKEY record validator

CDS (Child DS) record validator

CERT record validator

Validator for CNAME DNS records

Validator for CSYNC DNS records

Parser for DNS wire format (RFC 1035 section 3.3).

DHCID (Dynamic Host Configuration Identifier) record validator

Validator for DLV (DNSSEC Lookaside Validation) DNS records

DMARC record validator

DNAME record validator

DNSKEY record validator

DNS Violation Validator

Validator for DS (Delegation Signer) DNS records

Default DNS record validator for record types that don't have specific validation

Common DNS validation functions shared across record types

Validator for one record type; DnsValidatorRegistry picks the implementation.

Registry for DNS record validators

EUI48 record validator

EUI64 record validator

HHIT (HIP Hash Identity Tag) record validator

HINFO record validator

HTTPS record validator

The three dns.* settings that decide how strictly a hostname's labels and TLD are checked.

Hostname validation service

IP address validation service

IPSECKEY record validator

KEY record validator

KX Record Validator

L32 record validator

L64 record validator

LOC record validator

LP record validator

LUA record validator

MINFO Record Validator

MR (Mail Rename) record validator

MX Record Validator

NAPTR (Naming Authority Pointer) Record Validator

NID (Node Identifier) Record Validator

NSEC3PARAM record validator

NSEC3 record validator

NSEC record validator

NS Record Validator

OPENPGPKEY record validator

Validator for PTR (Pointer) DNS records

RESINFO (Resolver Information) record validator

RKEY (Resource KEY) record validator

RP (Responsible Person) record validator

RRSIG (Resource Record Signature) record validator for DNSSEC

SMIMEA (S/MIME Certificate Association) record validator

SOA record validator

SPF record validator

SRV record validator

SSHFP (SSH Fingerprint) record validator

SVCB record validator

String validation for DNS records

TKEY (Transaction KEY) record validator

TLSA (TLS Authentication) record validator

TSIG (Transaction SIGnature) record validator

DNS TTL validation service

TXT record validator

URI (Uniform Resource Identifier) Record Validator

WALLET record validator

ZONEMD (Message Digest for DNS Zones) Record Validator

Finds records that PowerDNS Auth 5.1.x would alter when they are written back through its REST API: it removes one level of backslash escaping from record content (PowerDNS issue 18159), so "a\b" is stored as "a\b" and "a\"b" is refused.

Creates PTR records for a whole IPv4 or IPv6 /64 network, optionally only where forward A/AAAA records exist.

Generates standard BIND zone files from DNS records.

Parses one CSV line of the bulk record form (name,type,content,prio,ttl[,disabled][,comment]) into a record.

The apex SOA a zone gets when no template supplies one, built from the dns.* settings.

Normalizes record content before saving; wraps TXT content in quotes when dns.txt_auto_quote is on.

Validates a record by dispatching to the validator for its type.

Validates a record before it is written.

Creates, updates and deletes zones for the web UI, including template records and DNSSEC setup.

Zone creation, update and deletion.

Splits a domain name into subdomain, domain and TLD parts.

Adds the matching A record in the managed forward zone when a PTR record is created in a reverse zone.

Helper functions for dynamic DNS updates

Runs a DDNS update: validates and authenticates it, picks the owning zone and syncs the A/AAAA records.

Validates a DDNS request's user agent, username, hostname and IP lists before any update is applied.

Replaces every record of one name and type with a new set: validate all, delete the old set, insert the new one.

Outcome of deleting a selection of records: how many went, and the reason for each one the backend refused. Rows that no longer exist are skipped silently and count for neither.

Outcome of deleting a record together with its reverse counterpart.

Deletes a record and, when asked and when reverse handling is on, the PTR of an A/AAAA record or the A/AAAA of a PTR record. A selection of records is deleted the same way, with each affected zone finalized once.

Service responsible for transforming DNS records for display purposes Implements the Single Responsibility Principle by focusing only on display transformations

Captures a record before and after an edit and writes the change to the zone audit log.

Creates, updates and deletes records for the web UI, with validation, logging and serial updates.

Record creation, update and deletion.

Finds the A or AAAA records of a forward zone whose addresses fall inside a given IPv4 range or IPv6 /64.

Record-type lists for the forward and reverse zone editors, filtered by config, DNSSEC and server support.

Outcome of a record write. Replaces the bool return plus MessageService side channel: callers read the reason, the refusal and the offending record part from here instead of the session.

Keeps PTR records in step with A/AAAA records: adds, updates and deletes the counterpart in the paired zone.

Resolves the default TTL for new records.

Reads and rewrites SOA records and bumps their serial.

SOA record and serial handling.

Creates, updates and deletes PowerDNS supermasters.

Outcome of a supermaster write. Callers read the reason, its code and the refusal from here instead of a message side channel.

Applies a zone template to an existing zone: removes the records an earlier application of that template wrote, writes and links the template's records, repoints the zone at the template and reconciles the sync state.

Outcome of a zone write (create, delete, metadata, owner or template change).

What the acting user may do with zone templates: which template a zone may be created from, who owns a template, which record types may be stored in one, and how far the linked-zone listings reach.

Which user groups a zone template is shared with. The owner shares with groups they belong to, a ueberuser with any group; members of a group see, apply and (with zone_templ_edit) edit the template.

Expands the [ZONE], [NS1], [SERIAL] style placeholders of zone template records.

Adding, editing and deleting the records of a zone template. Writes report their outcome instead of flashing it.

Validates zone template records before they are stored.

Facade over the zone template use cases, kept so existing callers keep one entry point: ZoneTemplateWriteService (templates and the default flag), ZoneTemplateRecordService (template records) and ZoneTemplateAccessPolicy (who may use or owns a template). Lookups and linked-zone listings read the repository directly. New code should depend on the specific service.

Outcome of a zone template write. Callers read the reason and the refusal from here instead of the session; a success may still carry a warning.

Creating, editing and deleting zone templates, saving a zone as a template, and the system-wide default template. Writes report their outcome instead of flashing it.

What a create-user request asks for, typed and independent of the wire format. The controllers build it from their own field names; the service hands it on to the repository with the password in its stored form.

Turns a submitted list of group references into distinct group entities

The last-super-admin rule for writes that take super admin away from users without touching their account: template contents, group membership, group deletion and a group's template. Each one decides and writes in one transaction holding the super admin rows, so two concurrent changes cannot both pass.

What a partial user update asks for: every field is null when the request left it alone. The controllers build it from their own field names; the service hands it on to the repository with the password in its stored form.

Decides whether a user must accept the current user-agreement version and records acceptances.

Domain service for user management operations

Reads and writes per-user preferences with a request cache and config-derived defaults.

Shapes raw user rows into the read format the API exposes

Resolves the timezone to display for a user: their preference, then misc.timezone, then UTC.

Simple validation result class following the Result pattern

Syntax checks for email addresses and digit-only strings.

Catalog zone membership.

Pure rules for the opt-in change approval workflow: whether a user's zone changes are written directly, filed as a change request, or refused, and who may review a request.

Outcome of a DnssecKeyService request, the key or keys it concerns, and the accepted values when a new key was refused as invalid.

Lists, adds, activates, deactivates and removes the DNSSEC keys of a zone the one way the web key pages and the API agree on: validate a new key against what the server offers, refuse changes when PowerDNS cannot be asked, has DNSSEC off or the zone is presigned, and audit what changed.

Turns a DNSSEC private key into the ISC (BIND "Private-key-format") text the PowerDNS API takes. The API reads no PEM; only pdnsutil import-zone-key-pem does.

Maps each reverse zone to the forward zones its PTR records point at, with a PTR count per forward zone.

Finds the records a new zone would hide in its closest existing parent zone.

Records in the closest parent zone that a new zone hides, because PowerDNS answers from the most specific zone.

Mirrors zone ownership into the PowerDNS account field.

Outcome of filing, approving, rejecting or cancelling a change request.

Files zone change requests and applies the reviewer's decision.

Counts the zones a user may see; the backend-specific query lives in the zone repository.

Resolves the user-owner and group-owner assignment for a new zone, applying the active zone_ownership_mode and permission rules. The API hands in the typed request input; the web forms hand in the owner and groups they parsed.

One row of the zone editor's record table as the caller wants it: the record it refers to and the values to store, already decoded from whatever form or request carried them.

One posted editor row that differs from the zone: the normalised row as it will be written and the log holding the stored state it replaces.

Saves the zone editor's record table: the edit gate, the stale-form check, the per-row diff and write, the record and zone comments, and the SOA serial bump that closes a save.

One submission of the zone editor's record table.

A user or group that a change would take past its zone limit.

Creates zones for the API with the same checks the web form applies. Failures come back as

message is the API wording, the code lets the web forms word it themselves.

Outcome of a ZoneMetadataService write, with the metadata kind and options the caller needs to word a refusal.

The zone metadata rules the editor and the API share: what a kind accepts, who may change it, what the active backend can store, and how a change is persisted and logged. Callers parse their input and word the refusals.

Blocks creating a zone that overlaps an existing zone owned by another user.

The last-owner rule: a zone keeps at least one owner of a kind the ownership mode allows. Every writer removes owners through here, so the check and the delete share one transaction and two concurrent removals cannot both pass.

Who owns which of a page of zones, resolved once so per-row controls do not query per zone. Ownership is direct (zones.owner) or through any group the user belongs to.

The owner choice a zone creation request made, as ZoneCreateOwnershipResolver reads it: the user owner may be omitted (the caller becomes owner), given as null (no user owner) or given as an id; the groups may be omitted or listed.

How many zones a user or group may own, and whether a change would exceed it.

Resolves the dns.zone_ownership_mode setting into ownership-side flags.

Why ZoneOwnershipGuard refused an owner removal. Callers word the code for their own audience; the mode tells them what kind of replacement to suggest.

Outcome of {ZoneCreateOwnershipResolver}: either a resolved owner/group assignment for the new zone, or an error with its refusal. The error carries a code so the web forms can word it themselves; the message is the API text.

How a zone editor save ended, with what the page needs to report it and, for a refused stale form, the rows to put back in front of the operator.

Outcome of a ZoneSigningService sign or unsign request plus the detail text callers may show.

Signs and unsigns zones the one way every entry point agrees on: refuse presigned zones and invalid zones, bump the SOA serial so secondaries notice, verify what PowerDNS reports afterwards, rectify, and audit.

Checks a zone is fit for DNSSEC signing and formats the reasons when it is not.

Static name helpers: reverse-zone detection, apex and in-zone tests, and stripping or restoring a zone suffix.

Converts domain names between punycode and Unicode for storage and display.

Flattens an API CryptoKey into the [id, type, key tag, algorithm, bits, active] row of the DNSSEC key table.

Splits the bulk-registration textarea into lowercase punycode domain names, one per line.

Domain name helpers: reverse-zone names, domain levels and second-level extraction.

IPv4/IPv6 arithmetic for reverse DNS: CIDR sizes, PTR names, reverse zone names and address display forms.

Casts an all-digit record id to int while leaving the API backend's encoded string ids untouched.

Splits stored SOA content into its seven named fields for display.

A short, non-reversible label for a secret token, so log lines about the same token can be matched without the logs holding a usable token.

Top-level domain validation against the bundled TLD list.

Parameters of one DDNS update call: credentials, hostname, IPv4 and IPv6 lists, dualstack flag and user agent.

A hostname that passed validation (full HostnameValidator when config is given, a syntax check otherwise).

Validated, de-duplicated IPv4 and IPv6 address lists parsed from a DDNS request's comma-separated fields.

Value object representing user information read from an LDAP entry

Value object representing OIDC user information

Encoded composite record identifier for API-mode records.

The user the web server or an authenticating proxy has already signed in.

Value object representing SAML user information

User details returned by an external login provider (LDAP, OIDC or SAML).

Sends JSON requests to the PowerDNS HTTP API with X-API-Key, retrying GETs once on transient failures.

Typed wrapper over the PowerDNS /api/v1 server endpoints: zones, RRsets, DNSSEC keys, metadata, TSIG, views.

QR codes rendered as SVG by bacon/bacon-qr-code.

TOTP backed by pragmarx/google2fa.

Checks the loaded settings array for invalid values (syslog, session timeout, theme, PowerDNS API, pdns_db_name).

Singleton that layers config/settings.php over config/settings.defaults.php and serves values by group and key.

Resolves the configured theme base path for on-disk checks.

Records that a database has been used with the API backend, so the SQL backend can refuse it.

Settles the canonical id of zone rows this application creates in API backend mode.

Maps the database settings block to the PDO connection arguments.

Creates and drops tables, indexes and foreign keys for the installer using per-driver SQL.

Re-runs a whole transaction the database rolled back because it lost a lock race.

PDO subclass that records executed queries for debug display.

Opens the PDO connection from the database credentials, building the DSN and SSL options per driver.

Transaction control over the request's PDO handle, the one the repositories write through.

Writes the PermissionCatalogue seed data into freshly created Poweradmin tables.

Ownership under a zone id collision in API backend mode.

Keeps one zones row per zone named after its PowerDNS domain under the SQL backend.

Sink for audit lines: hands each one to the syslog logger and, when database logging is on, to the log_users, log_zones, log_groups or log_api table.

PSR-3 decorator that tags every log call with the owning class's short name in the classname context key.

Writes API events to the log_api table and queries, filters and prunes them for the API log page.

Writes group events to the log_groups table and queries them, joined to user_groups, for the group log page.

Writes user events to the log_users table and queries them with filters for the user log page.

Writes zone events to the log_zones table and queries them by domain or filter, with SQL and API-backend joins.

Fits an audit message into the log_*.event columns, which are varchar(2048) on every database.

Output sink for the PSR-3 Logger.

PSR-3 logger that applies the logging.level threshold, fills {placeholders} and passes lines to a log handler.

Log handler that formats a line with DEFAULT_LOG_FORMAT and sends it to PHP's error_log (the SAPI log).

Writes before/after record and zone snapshots to log_record_changes, grouped into log_changesets rows.

PSR-3 logger that writes every message to syslog under the configured identity and facility.

Collects the gauges behind the /api/metrics endpoint: counts about Poweradmin itself, never keyed by zone or user name, so every metric has a handful of series at most.

Renders metrics in the Prometheus text exposition format 0.0.4.

The HTTP(S)_PROXY / NO_PROXY lookup of ProxyContext behind the port, for services that take the proxy as a dependency.

Public suffix lookups backed by the IANA list in data/public_suffix_list.dat.

Resolves HTTP(S)_PROXY / NO_PROXY environment variables into stream-context options usable by PHP's HTTP wrapper. PHP's stream wrapper does not pick up these variables on its own, so each call site needs to opt in explicitly.

Finds the Poweradmin user a PowerDNS account value names, for zones that arrive without an owner (an autoprimary sets the account from its own configuration).

Domain lookups for the API backend mode, read through PowerDNS.

Dynamic DNS persistence for the API backend mode.

Record comment persistence for the API backend mode.

Record reads for the API backend mode, served from PowerDNS RRsets.

Record search over the PowerDNS API, enriched with the zone owner from Poweradmin's zones table and filtered, sorted and paged in memory.

Shared parts of the API-mode searches: query preprocessing that mirrors BaseSearch, and the ownership lookups against Poweradmin's own zones table.

Zone metadata behind the PowerDNS API: metadata kinds through the metadata endpoints, and the kinds PowerDNS exposes as zone-object properties through a zone update.

API-backend zone repository; reads zone state through PowerDNS and ownership from zones and zones_groups.

Zone search over the PowerDNS API, enriched with owners and comments from Poweradmin's zones table and filtered, sorted and paged in memory.

Shared query building for the record and zone searches: IDN matching and reverse IP search strings.

SQL persistence for API keys in the api_keys table and their zone scopes in api_key_zones.

SQL persistence for the oidc_user_links and saml_user_links tables.

SQL persistence for the authentication throttle counters in login_attempts.

SQL persistence for password reset tokens and their rate-limit counters in password_reset_tokens.

SQL persistence for permission templates in perm_templ and their perm_items links in perm_templ_items.

SQL persistence for record comments in the PowerDNS comments table, linked to records via record_comment_links.

SQL persistence for per-record-type default TTLs in the record_type_defaults table.

SQL persistence for records_zone_templ (numeric ids) and records_zone_templ_api (encoded ids).

SQL persistence for accepted user agreement versions in the user_agreements table.

SQL persistence for group membership rows in the user_group_members table.

SQL persistence for user groups in the user_groups table, with member and zone counts.

SQL persistence for per-user MFA settings in the user_mfa table.

SQL persistence for per-user settings in the user_preferences table.

SQL persistence for accounts in the users table, with permission lookups through perm_templ and perm_items.

SQL persistence for username recovery attempts and their rate-limit counters in username_recovery_requests.

Reads the oldest direct owner of a zone from the native zones table.

SQL persistence for zone_change_requests, a Poweradmin-native table that is never prefixed and is shared by the SQL and API backends. Until the 4.6.0 schema update creates it, reads find nothing and writes fail.

SQL persistence for zone-to-group links in zones_groups; joins domains, or the zones table under the API backend.

Zone metadata in the PowerDNS domainmetadata table.

SQL zone repository over the PowerDNS domains and records tables plus the zones and zones_groups ownership tables.

SQL persistence for zone templates in zone_templ and their records in zone_templ_records.

Tracks which zones are out of date against their template in the zone_template_sync table.

Runs the record search page query with grouping, comments, sorting and pagination.

Domain lookups on the domains table.

Dynamic DNS persistence on the records table.

Record reads on the records table.

Runs the zone search page query, counting and fetching the domains that match the search string.

PowerDNS REST API-based DNS backend provider.

Rewrites API key zone scopes from zones row ids to canonical zone ids, once.

The backend-independent half of a consistency checker: zone ownership lives in the Poweradmin-native zones table under every backend, and the fix actions the consistency page posts map onto the same repairs whichever backend runs them.

Consistency checks for the API backend: zone and record state comes from the PowerDNS API, ownership from the Poweradmin-native zones tables.

Consistency checks against the PowerDNS tables in the local database.

Writes a zone owner into the Poweradmin-native zones table. Ownership lives there under both backends, so the SQL and API strategies share this repair.

DnssecProviderInterface that manages zone keys, DS/DNSKEY records and rectification through the PowerDNS API.

Queues per-page flash messages in the session and renders the bare-HTML fatal error page.

Null Object implementation of DnssecProviderInterface Used when PowerDNS API is not configured or DNSSEC is disabled

SQL backend with a PowerDNS API configured: flushes through the API, which also adds a new zone to the PowerDNS zone cache (PowerDNS 4.6 and later).

DnsBackendProviderInterface over direct SQL on the PowerDNS tables.

Picks the light/dark stylesheet from the style cookie or config, limited to what the theme's style directory ships.

Resolves the Twig compiled-template cache directory, creating it or falling back to uncached rendering.

Synchronizes zone metadata between the PowerDNS API and the local zones table.

Tracks the most recent PowerDNS API error so the UI can surface it.

A session held in memory: what a test injects, and what a request without a session (the public API) uses as a request-scoped cache.

$_SESSION keys owned by the authentication flows: MFA, the OIDC and SAML logout round trips, and password and username recovery.

A flash message (text plus Bootstrap alert type) kept in the session across a redirect.

Keeps submitted form data in the session so a failed request can refill the form.

Sets, reads and resets the MFA pending/verified state in the session.

PHP's own session: $SESSION plus the session*() lifecycle functions.

The actor of a web request: whoever the session says is logged in.

Stores the login message in the session and clears auth and MFA keys on logout.

Prefixes CSV cell values that start with a formula trigger (=, +, -, @, tab, CR, LF) with a quote.

DependencyCheck class verifies the availability of required PHP extensions.

Resolves the client IP from REMOTE_ADDR, honoring forwarded headers only from private or trusted proxy peers.

LanguageCode class is used for retrieving language names based on their codes.

Detects the HTTP protocol (http/https) from server environment.

In-memory sorting, filtering, and pagination for datasets.

ORDER BY clauses and a PHP comparator that sort reverse zones by network hierarchy (10., 172., 192.168.).

Picks natural or hierarchical reverse zone sorting per the configured sort type, in SQL or in PHP.

Per-database ORDER BY clauses that sort zone and record names naturally instead of lexically, and the ORDER BY of API lists sorted in SQL.

An explicit list of proxy addresses. Unlike IpAddressRetriever's peer check, it trusts nothing implicitly: private and loopback addresses match only when listed.

Reads and sanitizes the request User-Agent for logging and bot detection.

Twig functions for record and zone type badge classes, zone type labels and the autoprimaries wording.

Twig function can() that asks the injected permission checker whether the current user holds a permission.

GET /zones/{id}/export/csv - downloads the zone's records as a CSV file.

Module registration for the CSV zone export route and its zone-page action button.

/api/internal/dns-wizard: validates and previews wizard input for the record form.

Renders the form for one wizard at /zones/{id}/wizard/{type} and creates the records it builds.

Renders the wizard picker at /zones/{id}/wizard.

Module registration for the DMARC, SPF, DKIM, CAA, TLSA and SRV record wizards under /zones/{id}/wizard.

Shared validation, TXT quoting and record assembly for the record wizards; each wizard fills in its type.

Builds CAA records naming the certificate authorities allowed to issue for a domain.

Builds the DKIM public-key TXT record at ._domainkey.; the key itself comes from the mail server.

Builds the DMARC policy TXT record published at _dmarc..

Builds an SPF TXT record and warns when it exceeds the RFC 7208 lookup limit.

Builds SRV records giving the host and port of a service.

Builds TLSA records at _port._protocol.hostname for DANE; the zone must be DNSSEC-signed.

Lookup of the available record wizards by type.

GET /tools/email-previews - renders the email templates in light and dark mode for ueberusers.

Module registration for the /tools/email-previews page and its tools menu entry.

Renders each email template with sample data, in light and forced dark mode, for the preview page.

/rdap and /zones/{id}/rdap - looks up a domain's RDAP record and shows the result.

Module registration for the RDAP lookup page and its zone-page action.

RDAP lookups: picks the server for a TLD from data/rdap_servers.php, queries it and formats the reply.

Imports a zone from a live primary by creating a secondary, triggering an AXFR pull, and offering a one-click conversion to a primary zone once the records have transferred. API-backend only (see the module class).

Imports a zone from a live primary server by creating a secondary zone, pulling it over AXFR, and converting it to a primary once the data lands.

/whois and /zones/{id}/whois - looks up a domain's WHOIS record and shows the result.

WHOIS lookups over port 43 using the per-TLD server list in data/whois_servers.php.

Module registration for the WHOIS lookup page and its zone-page action.

GET /zones/{id}/export/zonefile - downloads the zone in BIND format, from the API or the records table.

The /tools/zone-import page: uploads a BIND zone file, previews the parsed records and creates the zone.

Session keys the zone import module keeps between its preview and confirm steps.

Parses BIND zone file text into records, handling $ORIGIN, $TTL and multi-line values.

One resource record parsed from an uploaded zone file.

Result of parsing a BIND zone file: origin, default TTL, records and parser warnings.

Module registration for the zone file import page and the per-zone BIND export route.

Holds the Poweradmin release version constant.