-- Initial tomswallapi schema: fleet-global objects + per-device layer.
-- See DESIGN.md (tomswall repo) for the model this implements.

-- Global settings: a single row of fleet-wide defaults.
CREATE TABLE settings (
    id             BOOLEAN PRIMARY KEY DEFAULT true CHECK (id),  -- singleton
    address_family TEXT    NOT NULL DEFAULT 'inet',
    log_level      TEXT    NOT NULL DEFAULT 'info',
    ip_forwarding  BOOLEAN NOT NULL DEFAULT true,
    table_name     TEXT    NOT NULL DEFAULT 'tomswall',
    default_resolver JSONB NOT NULL DEFAULT '[]'::jsonb  -- ["10.0.0.53"] or "system"
);
INSERT INTO settings (id) VALUES (true);

-- Routing domains. enforce_on_routers toggles defense-in-depth vs transparent transit.
CREATE TABLE fabrics (
    name               TEXT PRIMARY KEY,
    enforce_on_routers BOOLEAN NOT NULL DEFAULT false,
    description        TEXT NOT NULL DEFAULT ''
);

-- Fleet-global zones. subnets is a list of CIDRs. parent gives subzone nesting.
CREATE TABLE zones (
    name    TEXT PRIMARY KEY,
    type    TEXT NOT NULL DEFAULT 'ip',        -- ip | ip6 | firewall
    subnets JSONB NOT NULL DEFAULT '[]'::jsonb,
    parent  TEXT REFERENCES zones(name) ON DELETE RESTRICT
);

-- Address groups materialize nftables named sets. type drives population source.
CREATE TABLE address_groups (
    name         TEXT PRIMARY KEY,
    type         TEXT NOT NULL CHECK (type IN ('static', 'dns', 'asn')),
    members      JSONB NOT NULL DEFAULT '[]'::jsonb,  -- static: CIDRs; dns: FQDNs; asn: ASN numbers
    refresh      TEXT NOT NULL DEFAULT '',            -- asn: cache TTL (e.g. 24h); dns: honor_ttl
    description  TEXT NOT NULL DEFAULT ''
);

-- Reusable port+proto combos.
CREATE TABLE portgroups (
    name  TEXT PRIMARY KEY,
    proto TEXT NOT NULL,
    ports JSONB NOT NULL DEFAULT '[]'::jsonb
);

-- Default zone-to-zone policies. priority orders evaluation (first match wins).
CREATE TABLE policies (
    id       BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    priority INT NOT NULL DEFAULT 0,
    source   TEXT NOT NULL,
    dest     TEXT NOT NULL,
    action   TEXT NOT NULL,
    log      TEXT NOT NULL DEFAULT ''
);

-- Fleet-global intents. source/dest use the shorewall-style element list
-- (bare zone, or zone:+ipset / zone:&fqdn). Stored as JSONB element arrays.
CREATE TABLE rules (
    id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    priority  INT NOT NULL DEFAULT 0,
    action    TEXT NOT NULL,
    source    JSONB NOT NULL DEFAULT '[]'::jsonb,  -- ["loc", "net:+asn_cloudflare"]
    dest      JSONB NOT NULL DEFAULT '[]'::jsonb,
    proto     TEXT NOT NULL DEFAULT '',
    portgroup TEXT REFERENCES portgroups(name) ON DELETE RESTRICT,
    ports     JSONB NOT NULL DEFAULT '[]'::jsonb,
    log       TEXT NOT NULL DEFAULT '',
    comment   TEXT NOT NULL DEFAULT ''
);

-- Devices in the fleet.
CREATE TABLE devices (
    name     TEXT PRIMARY KEY,
    class    TEXT NOT NULL CHECK (class IN ('router', 'firewall')),
    fabric   TEXT REFERENCES fabrics(name) ON DELETE SET NULL,
    resolver JSONB NOT NULL DEFAULT '[]'::jsonb,   -- per-device DNS resolver override
    settings JSONB NOT NULL DEFAULT '{}'::jsonb,   -- per-device settings overrides
    reported_generation BIGINT NOT NULL DEFAULT 0, -- last generation the agent applied
    last_seen TIMESTAMPTZ
);

-- The per-device zone->interface binding table (the only host-specific object).
CREATE TABLE bindings (
    device     TEXT NOT NULL REFERENCES devices(name) ON DELETE CASCADE,
    zone       TEXT NOT NULL REFERENCES zones(name) ON DELETE CASCADE,
    interfaces JSONB NOT NULL DEFAULT '[]'::jsonb,  -- ["eth1"] or ["bond0.40"]
    PRIMARY KEY (device, zone)
);

-- Monotonic generation counter bumped on any config-affecting change.
CREATE TABLE generation (
    id      BOOLEAN PRIMARY KEY DEFAULT true CHECK (id),  -- singleton
    current BIGINT NOT NULL DEFAULT 1
);
INSERT INTO generation (id) VALUES (true);
