-- +brant Up CREATE TABLE space ( id SERIAL PRIMARY KEY, owner TEXT NOT NULL, name TEXT NOT NULL, created TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT uq_space_owner_name UNIQUE (owner, name) ); CREATE TABLE document_id ( doc_id TEXT PRIMARY KEY, space_id INTEGER NOT NULL REFERENCES space(id) ON DELETE CASCADE, path TEXT NOT NULL, updated_rev TEXT NOT NULL ); CREATE TABLE proposal ( id SERIAL PRIMARY KEY, space_id INTEGER NOT NULL REFERENCES space(id) ON DELETE CASCADE, title TEXT NOT NULL, rationale TEXT, base_rev TEXT NOT NULL, branch TEXT NOT NULL, state TEXT NOT NULL, approval TEXT, merged_rev TEXT, agent TEXT NOT NULL, agent_session TEXT NOT NULL, created TIMESTAMPTZ NOT NULL DEFAULT now(), resolved TIMESTAMPTZ, CONSTRAINT ck_proposal_state CHECK (state IN ('open', 'merged', 'rejected')), CONSTRAINT ck_proposal_approval CHECK (approval IS NULL OR approval IN ('human', 'policy')), CONSTRAINT ck_proposal_merged CHECK ((state = 'merged') = (approval IS NOT NULL)), CONSTRAINT ck_proposal_merged_rev CHECK ((state = 'merged') = (merged_rev IS NOT NULL)), CONSTRAINT ck_proposal_resolved CHECK ((state = 'open') = (resolved IS NULL)), CONSTRAINT ck_proposal_provenance CHECK (length(agent) > 0 AND length(agent_session) > 0) ); CREATE INDEX ix_proposal_state_created ON proposal (state, created DESC); CREATE TABLE agent_token ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, token_hash BYTEA NOT NULL UNIQUE, created TIMESTAMPTZ NOT NULL DEFAULT now(), revoked TIMESTAMPTZ ); CREATE TABLE index_stamp ( space_id INTEGER PRIMARY KEY REFERENCES space(id) ON DELETE CASCADE, rev TEXT NOT NULL, indexed_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE digest_mark ( owner TEXT PRIMARY KEY, seen_at TIMESTAMPTZ NOT NULL ); -- +brant Down DROP TABLE digest_mark; DROP TABLE index_stamp; DROP TABLE agent_token; DROP TABLE proposal; DROP TABLE document_id; DROP TABLE space;