Adds internal/tmpl with Materialize (template placeholder -> zone name) and
Parameterize (zone name -> placeholder, the inverse used by the
template-from-zone snapshot). service.resolve now materializes the template
against DomainRef.ZoneName before diffing, so one template can be reused
across domains. LoadDomainFull (source query + hand-edited sqlc output, since
sqlc is not installed) now also selects zone_name to populate it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
LoadDomain requires a template, so a zone without one could never be
viewed or snapshotted. Adds a template-free path: store.LoadZone /
service.ZoneRef / DomainService.ZoneRecords read a zone's live records
straight from the provider (no diff, no template). GET
/domains/{did}/records exposes read-only viewing; POST
/domains/{did}/template-from-zone snapshots only managed record types
(NS/SOA excluded) into a new template and auto-attaches it to the domain.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
Task 5 Фазы 3: GET/PUT /schedule (дефолт при отсутствии строки, валидация
interval>=60), POST/GET/DELETE /channels (секрет шифруется Cipher, никогда
не возвращается в ответах), POST /channels/{cid}/test через узкий
TestSender-интерфейс (200/502 без утечки секрета), GET /domains/{did}/history
(сначала GetDomain для project-scoping, затем ListCheckRuns — иначе IDOR
через check_runs, который сам по себе не scoped по project).
Добавлены store.GetDomain (обёртка над существующим sqlc-запросом) и
store.ListCheckRuns (новый запрос + sqlc regen) для поддержки истории.