feat(db): Phase 1 — DB-Schema, goose-Migrations, GORM-Models

Initialer Schema-Set (8 Migrationen, 13 Tabellen) für EdgeGuard v1:
users + audit_log + system_settings, ha_nodes, backends/domains/
routing_rules/tls_certs, forward_proxy_acls, wireguard_peers,
firewall_rules, dns_zones/dns_records, licenses. Migrations liegen
in internal/database/migrations/ (analog mail-gateway) und werden
per //go:embed ins Binary gepackt — keine separate SQL-Dateien im
.deb. ValidateMigrations + Test schützen vor Duplicate-Versionen
(mail-gateway 2026-05-08-Vorfall). GORM-Models für alle Tabellen,
sensible Felder (password_hash, private_key_enc) sind json:"-".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-08 23:44:44 +02:00
parent 9f75eec756
commit b307a7b1f7
29 changed files with 900 additions and 27 deletions

View File

@@ -0,0 +1,38 @@
-- +goose Up
-- +goose StatementBegin
-- License state cache. The license-leader (KeyDB-locked, see
-- architecture.md §12.1) calls https://license.netcell-it.com and
-- mirrors the result here. Every node reads from this table for its
-- "is the license valid?" check; the KeyDB key cluster:license-status
-- is just the in-flight TTL cache layered on top.
--
-- payload holds the verbatim verify-response (limits, feature flags,
-- expiry). active_domains_at_verify is the value that was sent to the
-- license server — kept for audit / re-issue (so we can prove what
-- we reported on a given day).
CREATE TABLE IF NOT EXISTS licenses (
id BIGSERIAL PRIMARY KEY,
license_key TEXT NOT NULL,
status TEXT NOT NULL,
valid_until TIMESTAMPTZ,
last_verified_at TIMESTAMPTZ,
last_verified_node TEXT,
active_domains_at_verify INTEGER,
payload JSONB,
last_error TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT licenses_key_unique UNIQUE (license_key),
CONSTRAINT licenses_status_check CHECK (status IN ('trial', 'active', 'expired', 'invalid', 'unknown'))
);
CREATE INDEX IF NOT EXISTS idx_licenses_valid_until ON licenses (valid_until);
CREATE INDEX IF NOT EXISTS idx_licenses_status ON licenses (status);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS licenses;
-- +goose StatementEnd