The domains list had no way to narrow itself down, so an operator with
dozens of zones had to scan the whole table to find the drifted ones.
Add two client-side filters above the table (the full list already
arrives in one request, so server-side filtering would only add contract
surface). The status filter compares against the same derived value the
row's badge renders — a domain with no template shows "без шаблона" and
must not match "drift" just because it kept a stale last_check_status
from before its template was detached, so that derivation lives in one
function used by both.
Sorting is now decided in the store: ListDomains orders by zone_name
instead of created_at, so every consumer of the list gets the same order
and the filters never reorder anything.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yr8frsaxBgab1Aa7yfPuU
handleCheck's error branch wrote last_check_status via an id-only UPDATE, so
an authenticated caller's own valid project id paired with a foreign domain
id in the URL could flip a stranger's domain to "error" even though Check
itself is project-scoped and would 404/error out first. Add project_id to
the WHERE clause (queries/domains.sql + generated db/domains.sql.go), thread
projectID through Store/TenantStore/SchedStore SetDomainStatus, and pass pid
from context at both call sites in handleCheck plus the scheduler.
Also collapse checkDomain's inline status derivation in scheduler.go into a
call to service.DeriveStatus, the same helper handleCheck already uses, so
there's a single source of truth for "drift vs in_sync" instead of two
copies that could drift apart.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
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