Adding migrations and lot of work. Starting work on the demo scope
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
-- Level-local achievements and normalized document reveal requirements.
|
||||
-- Requirements live on boards so they clone with immutable template versions;
|
||||
-- earned/seen state lives on the mutable level instance.
|
||||
|
||||
ALTER TABLE osint.levels
|
||||
ADD CONSTRAINT levels_id_board_unique UNIQUE (id,board_id);
|
||||
|
||||
CREATE TABLE osint.level_flags (
|
||||
level_id UUID NOT NULL,
|
||||
board_id UUID NOT NULL,
|
||||
flag_key TEXT NOT NULL CHECK (flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
|
||||
earned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (level_id,flag_key),
|
||||
FOREIGN KEY (level_id,board_id) REFERENCES osint.levels(id,board_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX level_flags_board_idx ON osint.level_flags (board_id,flag_key);
|
||||
|
||||
CREATE TABLE osint.document_flag_requirements (
|
||||
board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
|
||||
document_exhibit_id UUID NOT NULL REFERENCES osint.document_exhibits(exhibit_id) ON DELETE CASCADE,
|
||||
flag_key TEXT NOT NULL CHECK (flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
|
||||
PRIMARY KEY (document_exhibit_id,flag_key),
|
||||
FOREIGN KEY (board_id,document_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX document_flag_requirements_board_idx ON osint.document_flag_requirements (board_id,flag_key);
|
||||
|
||||
CREATE TABLE osint.level_seen_documents (
|
||||
level_id UUID NOT NULL,
|
||||
board_id UUID NOT NULL,
|
||||
document_exhibit_id UUID NOT NULL REFERENCES osint.document_exhibits(exhibit_id) ON DELETE CASCADE,
|
||||
seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (level_id,document_exhibit_id),
|
||||
FOREIGN KEY (level_id,board_id) REFERENCES osint.levels(id,board_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (board_id,document_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
COMMENT ON TABLE osint.level_flags IS 'Boolean achievements earned within one mutable level instance.';
|
||||
COMMENT ON TABLE osint.document_flag_requirements IS 'All listed flags must be earned before a document is included in the play-mode level payload.';
|
||||
COMMENT ON TABLE osint.level_seen_documents IS 'Documents whose first-arrival animation has already been acknowledged for this level.';
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Achievements: the playthrough case-state. Boolean facts earned by a player, each
|
||||
-- remembering the story node that awarded it. This is the NARRATIVE scope the phone
|
||||
-- gate, node-enable requirements, and gates read; level-local flags (025) promote up
|
||||
-- into it when a level node's achievement fires. A fact is true once (PK on player +
|
||||
-- key); the awarding node is provenance and is nullable (New Game / manual grants).
|
||||
|
||||
CREATE TABLE osint.achievements (
|
||||
playthrough_id UUID NOT NULL REFERENCES osint.playthroughs(id) ON DELETE CASCADE,
|
||||
flag_key TEXT NOT NULL CHECK (flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
|
||||
awarded_by_node_id UUID REFERENCES osint.story_nodes(id) ON DELETE SET NULL,
|
||||
earned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (playthrough_id, flag_key)
|
||||
);
|
||||
CREATE INDEX achievements_playthrough_idx ON osint.achievements (playthrough_id);
|
||||
|
||||
COMMENT ON TABLE osint.achievements IS 'Boolean achievements earned by a player (playthrough), each remembering the awarding story node. The narrative case-state that gates the phone, node-enable requirements, and story gates.';
|
||||
@@ -0,0 +1,79 @@
|
||||
-- Data-defined evidence recognition for player-uploaded sources. Text extraction
|
||||
-- belongs to the immutable asset; matching rules belong to a clonable board;
|
||||
-- evaluations and awarded flags belong to the mutable level instance.
|
||||
|
||||
CREATE TABLE osint.asset_text_extractions (
|
||||
id UUID PRIMARY KEY,
|
||||
asset_id UUID NOT NULL REFERENCES osint.assets(id) ON DELETE CASCADE,
|
||||
extractor TEXT NOT NULL,
|
||||
extractor_version TEXT NOT NULL,
|
||||
language TEXT NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('succeeded','unsupported','failed')),
|
||||
extracted_text TEXT NOT NULL DEFAULT '',
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (asset_id,extractor,extractor_version,language)
|
||||
);
|
||||
CREATE INDEX asset_text_extractions_asset_idx ON osint.asset_text_extractions (asset_id,created_at DESC);
|
||||
|
||||
CREATE TABLE osint.evidence_match_rules (
|
||||
id UUID PRIMARY KEY,
|
||||
board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
|
||||
origin_rule_id UUID REFERENCES osint.evidence_match_rules(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
flag_key TEXT NOT NULL CHECK (flag_key ~ '^[a-z][a-z0-9_.-]{0,63}$'),
|
||||
matcher_version TEXT NOT NULL DEFAULT 'char_trigram_v1' CHECK (matcher_version = 'char_trigram_v1'),
|
||||
minimum_anchor_matches SMALLINT NOT NULL DEFAULT 1 CHECK (minimum_anchor_matches > 0),
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (board_id,id),
|
||||
UNIQUE (board_id,name)
|
||||
);
|
||||
CREATE INDEX evidence_match_rules_board_flag_idx ON osint.evidence_match_rules (board_id,flag_key) WHERE enabled;
|
||||
|
||||
CREATE TABLE osint.evidence_match_anchors (
|
||||
id UUID PRIMARY KEY,
|
||||
rule_id UUID NOT NULL REFERENCES osint.evidence_match_rules(id) ON DELETE CASCADE,
|
||||
phrase_text TEXT NOT NULL CHECK (char_length(btrim(phrase_text)) >= 12),
|
||||
minimum_similarity NUMERIC(4,3) NOT NULL DEFAULT 0.720 CHECK (minimum_similarity >= 0.500 AND minimum_similarity <= 1),
|
||||
sort_order SMALLINT NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
|
||||
UNIQUE (rule_id,sort_order)
|
||||
);
|
||||
|
||||
CREATE TABLE osint.evidence_match_evaluations (
|
||||
id UUID PRIMARY KEY,
|
||||
level_id UUID NOT NULL,
|
||||
board_id UUID NOT NULL,
|
||||
document_exhibit_id UUID NOT NULL REFERENCES osint.document_exhibits(exhibit_id) ON DELETE CASCADE,
|
||||
extraction_id UUID NOT NULL REFERENCES osint.asset_text_extractions(id) ON DELETE CASCADE,
|
||||
rule_id UUID NOT NULL,
|
||||
matched BOOLEAN NOT NULL,
|
||||
matched_anchor_count SMALLINT NOT NULL CHECK (matched_anchor_count >= 0),
|
||||
score NUMERIC(4,3) NOT NULL CHECK (score >= 0 AND score <= 1),
|
||||
evaluated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
FOREIGN KEY (level_id,board_id) REFERENCES osint.levels(id,board_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (board_id,document_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (board_id,rule_id) REFERENCES osint.evidence_match_rules(board_id,id) ON DELETE CASCADE,
|
||||
UNIQUE (level_id,document_exhibit_id,rule_id)
|
||||
);
|
||||
CREATE INDEX evidence_match_evaluations_level_idx ON osint.evidence_match_evaluations (level_id,evaluated_at DESC);
|
||||
|
||||
CREATE TABLE osint.evidence_match_anchor_evaluations (
|
||||
evaluation_id UUID NOT NULL REFERENCES osint.evidence_match_evaluations(id) ON DELETE CASCADE,
|
||||
anchor_id UUID NOT NULL REFERENCES osint.evidence_match_anchors(id) ON DELETE CASCADE,
|
||||
similarity NUMERIC(4,3) NOT NULL CHECK (similarity >= 0 AND similarity <= 1),
|
||||
matched BOOLEAN NOT NULL,
|
||||
matched_text TEXT NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (evaluation_id,anchor_id)
|
||||
);
|
||||
|
||||
ALTER TABLE osint.level_flags
|
||||
ADD COLUMN awarded_by_evidence_match_id UUID REFERENCES osint.evidence_match_evaluations(id) ON DELETE SET NULL;
|
||||
|
||||
COMMENT ON TABLE osint.asset_text_extractions IS 'Cached OCR or direct-text extraction for one immutable uploaded asset.';
|
||||
COMMENT ON TABLE osint.evidence_match_rules IS 'Clonable level-authored rule that awards a flag when enough distinctive text anchors match an uploaded source.';
|
||||
COMMENT ON TABLE osint.evidence_match_anchors IS 'Alternative or cumulative reference passages used by one evidence match rule.';
|
||||
COMMENT ON TABLE osint.evidence_match_evaluations IS 'Auditable result of applying one board rule to one player-uploaded document.';
|
||||
COMMENT ON TABLE osint.evidence_match_anchor_evaluations IS 'Per-anchor fuzzy score and best normalized text window for an evidence evaluation.';
|
||||
Reference in New Issue
Block a user