---
type: pointer
title: 现有数据库字典
summary: 123 张现有表的字段、键与查询索引；SQL 仍以 backend/database/schema.sql 为唯一来源
updated: 2026-10-08
---

# 现有数据库字典

2026-10-08 对 `4489b400` 的 [schema.sql](../../../../backend/database/schema.sql) 静态核对，共 123 张表。**这是字段词典，不是第二份建表脚本，也未验证正在运行的数据库与该基线完全一致。** 所有现有字段按原 SQL 摘录约束，不在文档中补造已存在的外键。业务设计见[数据库设计](09-全站页面数据库设计.md)。

存量表数量不决定目标设计，不要求继续扩建所有领域；是否保留/合并/退役以当前页面、后台消费者和数据迁移证据决定。

字段表中保留类型、默认值和行内约束；表级键、CHECK、外键及索引在字段后列出。SQL 注释和模型/服务中的校验不等同于数据库约束。

## identity_users

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `username` | `VARCHAR(64) NOT NULL UNIQUE` |
| `email` | `VARCHAR(254) UNIQUE` |
| `github_user_id` | `VARCHAR(32) UNIQUE` |
| `password_hash` | `TEXT` |
| `avatar_data` | `BYTEA` |
| `avatar_sha256` | `BYTEA` |
| `credential_version` | `INTEGER NOT NULL DEFAULT 1 CONSTRAINT identity_users_credential_version_check CHECK (credential_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT identity_users_avatar_check CHECK ( (avatar_data IS NULL AND avatar_sha256 IS NULL) OR (avatar_data IS NOT NULL AND avatar_sha256 IS NOT NULL AND octet_length(avatar_data) BETWEEN 1 AND 262144 AND octet_length(avatar_sha256) = 32) )`

## identity_sessions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `user_id` | `UUID NOT NULL REFERENCES identity_users(id) ON DELETE CASCADE` |
| `token_digest` | `BYTEA NOT NULL UNIQUE CONSTRAINT identity_sessions_token_length CHECK (octet_length(token_digest) = 32)` |
| `csrf_digest` | `BYTEA NOT NULL CONSTRAINT identity_sessions_csrf_length CHECK (octet_length(csrf_digest) = 32)` |
| `credential_version` | `INTEGER NOT NULL CONSTRAINT identity_sessions_credential_version CHECK (credential_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `expires_at` | `TIMESTAMPTZ NOT NULL CONSTRAINT identity_sessions_expiry CHECK (expires_at > created_at)` |
| `revoked_at` | `TIMESTAMPTZ` |
| `revoked_reason` | `VARCHAR(32)` |

键与查询约束（现状）：

- `CONSTRAINT identity_sessions_revocation CHECK ( (revoked_at IS NULL AND revoked_reason IS NULL) OR (revoked_at IS NOT NULL AND revoked_reason IS NOT NULL) )`
- `CREATE INDEX identity_sessions_user_id_idx ON identity_sessions(user_id);`
- `CREATE INDEX identity_sessions_active_expiry_idx ON identity_sessions(expires_at) WHERE revoked_at IS NULL;`

## monitor_topics

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `name` | `VARCHAR(80) NOT NULL CHECK (char_length(name) BETWEEN 1 AND 80)` |
| `status` | `VARCHAR(16) NOT NULL DEFAULT 'paused' CHECK (status IN ('paused', 'active', 'archived'))` |
| `readiness_status` | `VARCHAR(32) NOT NULL DEFAULT 'pending_source_selection' CHECK ( readiness_status IN ( 'pending_source_selection', 'pending_source_readiness', 'ready' ) )` |
| `current_version` | `INTEGER NOT NULL DEFAULT 1 CHECK (current_version >= 1)` |
| `collection_interval_seconds` | `INTEGER NOT NULL DEFAULT 3600 CHECK ( collection_interval_seconds BETWEEN 600 AND 86400 )` |
| `report_time` | `TIME WITHOUT TIME ZONE NOT NULL DEFAULT '08:00:00'` |
| `report_timezone` | `VARCHAR(64) NOT NULL DEFAULT 'Asia/Shanghai' CHECK ( report_timezone = 'Asia/Shanghai' )` |
| `weekly_report_enabled` | `BOOLEAN NOT NULL DEFAULT TRUE` |
| `notification_target_names` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK ( jsonb_typeof(notification_target_names) = 'array' )` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT monitor_topics_owner_id_key UNIQUE (owner_id, id)`
- `CREATE INDEX monitor_topics_owner_updated_idx ON monitor_topics (owner_id, updated_at);`

## monitor_topic_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `topic_id` | `UUID NOT NULL REFERENCES monitor_topics (id) ON DELETE CASCADE` |
| `version` | `INTEGER NOT NULL CHECK (version >= 1)` |
| `created_by` | `UUID NOT NULL` |
| `match_any` | `JSONB NOT NULL CHECK (jsonb_typeof(match_any) = 'array')` |
| `match_all` | `JSONB NOT NULL CHECK (jsonb_typeof(match_all) = 'array')` |
| `exclude` | `JSONB NOT NULL CHECK (jsonb_typeof(exclude) = 'array')` |
| `source_keys` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK (jsonb_typeof(source_keys) = 'array')` |
| `editorial_profile_ids` | `JSONB NOT NULL DEFAULT '[]'::jsonb CONSTRAINT monitor_topic_versions_editorial_profiles_check CHECK ( jsonb_typeof(editorial_profile_ids) = 'array' AND jsonb_array_length(editorial_profile_ids) <= 32 )` |
| `collection_interval_seconds` | `INTEGER NOT NULL DEFAULT 3600 CHECK ( collection_interval_seconds BETWEEN 600 AND 86400 )` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (topic_id, version)`
- `CREATE INDEX monitor_topic_versions_created_by_idx ON monitor_topic_versions (created_by);`

## monitor_topic_status_events

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_sequence` | `INTEGER NOT NULL` |
| `topic_rule_version` | `INTEGER NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `reason` | `VARCHAR(32) NOT NULL` |
| `occurred_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT monitor_topic_status_events_owner_topic_sequence_key UNIQUE (owner_id, topic_id, event_sequence)`
- `CONSTRAINT monitor_topic_status_events_sequence_check CHECK (event_sequence >= 1)`
- `CONSTRAINT monitor_topic_status_events_rule_version_check CHECK (topic_rule_version >= 1)`
- `CONSTRAINT monitor_topic_status_events_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT monitor_topic_status_events_rule_version_fkey FOREIGN KEY (topic_id, topic_rule_version) REFERENCES monitor_topic_versions (topic_id, version) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED`
- `CONSTRAINT monitor_topic_status_events_status_reason_check CHECK ( (status = 'paused' AND reason IN ('created', 'cloned', 'paused', 'source_selection')) OR (status = 'active' AND reason = 'resumed') OR (status = 'archived' AND reason = 'archived') )`
- `CREATE INDEX monitor_topic_status_events_timeline_idx ON monitor_topic_status_events (owner_id, topic_id, occurred_at, event_sequence);`

## monitor_schedules

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK ( source_key ~ '^[a-z][a-z0-9_-]{0,63}$' )` |
| `capability` | `VARCHAR(32) NOT NULL CHECK ( capability IN ('search', 'author_posts', 'comments', 'replies', 'page_content', 'hotlist') )` |
| `interval_seconds` | `INTEGER NOT NULL CHECK ( interval_seconds BETWEEN 600 AND 86400 )` |
| `next_run_at` | `TIMESTAMPTZ NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL DEFAULT FALSE` |
| `last_job_id` | `UUID` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT monitor_schedules_owner_topic_source_capability_key PRIMARY KEY ( owner_id, topic_id, source_key, capability )`
- `CONSTRAINT monitor_schedules_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CREATE INDEX monitor_schedules_enabled_next_run_idx ON monitor_schedules (enabled, next_run_at);`

## followed_accounts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK (length(source_key) BETWEEN 1 AND 64)` |
| `external_id` | `VARCHAR(256) NOT NULL CHECK (length(external_id) BETWEEN 1 AND 256)` |
| `display_name` | `VARCHAR(256) CHECK ( display_name IS NULL OR length(display_name) BETWEEN 1 AND 256 )` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT followed_accounts_owner_source_identity_key UNIQUE (owner_id, source_key, external_id)`
- `CONSTRAINT followed_accounts_owner_id_key UNIQUE (owner_id, id)`
- `CREATE INDEX followed_accounts_owner_created_idx ON followed_accounts (owner_id, created_at, id);`

## followed_account_aliases

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `account_id` | `UUID NOT NULL` |
| `alias_value` | `VARCHAR(128) NOT NULL CHECK (length(alias_value) BETWEEN 1 AND 128)` |
| `first_seen_at` | `TIMESTAMPTZ NOT NULL` |
| `last_seen_at` | `TIMESTAMPTZ NOT NULL CHECK (last_seen_at >= first_seen_at)` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, account_id, alias_value)`
- `CONSTRAINT followed_account_aliases_owner_account_fkey FOREIGN KEY (owner_id, account_id) REFERENCES followed_accounts (owner_id, id) ON DELETE CASCADE`
- `CREATE INDEX followed_account_aliases_owner_value_idx ON followed_account_aliases (owner_id, alias_value);`

## codex_reset_monitors

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `projection_epoch` | `INTEGER NOT NULL` |
| `scan_revision` | `INTEGER NOT NULL` |
| `since_id` | `VARCHAR(19)` |
| `hot_until` | `TIMESTAMPTZ` |
| `last_attempt_at` | `TIMESTAMPTZ` |
| `last_collected_at` | `TIMESTAMPTZ` |
| `last_verified_at` | `TIMESTAMPTZ` |
| `history_from` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT codex_reset_monitors_owner_id_key UNIQUE(owner_id,id)`
- `CONSTRAINT codex_reset_monitors_owner_key UNIQUE(owner_id)`
- `CONSTRAINT codex_reset_monitors_versions_check CHECK(revision>=1 AND configuration_version>=1 AND projection_epoch>=1 AND scan_revision>=1)`

## codex_reset_monitor_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `version` | `INTEGER NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY(owner_id,monitor_id,version)`
- `CONSTRAINT codex_reset_monitor_versions_monitor_fkey FOREIGN KEY(owner_id,monitor_id) REFERENCES codex_reset_monitors(owner_id,id) ON DELETE CASCADE`
- `CONSTRAINT codex_reset_monitor_versions_configuration_check CHECK(version>=1 AND jsonb_typeof(configuration)='object')`

## codex_reset_scan_gaps

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `query` | `VARCHAR(512) NOT NULL` |
| `next_token` | `VARCHAR(2048)` |
| `stop_at_id` | `VARCHAR(19)` |
| `before_id` | `VARCHAR(19)` |
| `starts_at` | `TIMESTAMPTZ` |
| `ends_at` | `TIMESTAMPTZ` |
| `state` | `VARCHAR(16) NOT NULL` |
| `failure_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT codex_reset_scan_gaps_version_fkey FOREIGN KEY(owner_id,monitor_id,configuration_version) REFERENCES codex_reset_monitor_versions(owner_id,monitor_id,version) ON DELETE CASCADE`
- `CONSTRAINT codex_reset_scan_gaps_state_check CHECK(state IN ('pending','held','complete'))`
- `CONSTRAINT codex_reset_scan_gaps_bounds_check CHECK(starts_at IS NULL AND ends_at IS NULL OR starts_at<ends_at)`
- `CREATE INDEX codex_reset_scan_gaps_monitor_idx ON codex_reset_scan_gaps(owner_id,monitor_id,state,created_at);`

## codex_reset_posts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `external_id` | `VARCHAR(19) NOT NULL` |
| `published_at` | `TIMESTAMPTZ NOT NULL` |
| `source_input` | `JSONB NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `translation_zh` | `TEXT` |
| `context` | `JSONB NOT NULL` |
| `processed_at` | `TIMESTAMPTZ` |
| `needs_review` | `BOOLEAN NOT NULL` |
| `reviewed` | `BOOLEAN NOT NULL` |
| `skipped` | `BOOLEAN NOT NULL` |
| `review_version` | `INTEGER NOT NULL` |
| `failure_count` | `INTEGER NOT NULL` |
| `failure_code` | `VARCHAR(64)` |
| `outage` | `JSONB` |
| `activity` | `JSONB` |
| `collected_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT codex_reset_posts_owner_monitor_id_key UNIQUE(owner_id,monitor_id,id)`
- `CONSTRAINT codex_reset_posts_external_key UNIQUE(owner_id,monitor_id,external_id)`
- `CONSTRAINT codex_reset_posts_version_fkey FOREIGN KEY(owner_id,monitor_id,configuration_version) REFERENCES codex_reset_monitor_versions(owner_id,monitor_id,version)`
- `CONSTRAINT codex_reset_posts_input_check CHECK(octet_length(input_fingerprint)=32 AND review_version>=1 AND failure_count>=0)`
- `CONSTRAINT codex_reset_posts_source_check CHECK(external_id ~ '^[0-9]{1,19}$' AND jsonb_typeof(source_input)='object')`
- `CREATE INDEX codex_reset_posts_pending_idx ON codex_reset_posts(owner_id,monitor_id,published_at,external_id);`

## codex_reset_events

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `id` | `VARCHAR(128) NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `manual_version` | `INTEGER NOT NULL` |
| `withdrawn` | `BOOLEAN NOT NULL` |
| `in_progress` | `BOOLEAN NOT NULL` |
| `kind_explicit` | `BOOLEAN NOT NULL` |
| `time_inferred` | `BOOLEAN NOT NULL` |
| `schedule` | `JSONB` |
| `estimate` | `JSONB` |
| `scope` | `JSONB NOT NULL` |
| `reported_at` | `TIMESTAMPTZ` |
| `confirmed_at` | `TIMESTAMPTZ` |
| `occurred_on` | `DATE` |
| `confirmation_basis` | `VARCHAR(16)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY(owner_id,monitor_id,id)`
- `CONSTRAINT codex_reset_events_monitor_fkey FOREIGN KEY(owner_id,monitor_id) REFERENCES codex_reset_monitors(owner_id,id)`
- `CONSTRAINT codex_reset_events_state_check CHECK(kind IN ('direct_reset','reset_credit') AND status IN ('announced','confirmed'))`
- `CONSTRAINT codex_reset_events_revision_check CHECK(revision>=1 AND manual_version>=0)`
- `CONSTRAINT codex_reset_events_basis_check CHECK(confirmation_basis IS NULL OR confirmation_basis IN ('source_post','receipt_review'))`
- `CREATE INDEX codex_reset_events_timeline_idx ON codex_reset_events(owner_id,monitor_id,created_at);`

## codex_reset_event_posts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `event_id` | `VARCHAR(128) NOT NULL` |
| `post_id` | `UUID NOT NULL` |
| `action` | `VARCHAR(16) NOT NULL` |
| `stage` | `VARCHAR(32) NOT NULL` |
| `excerpt` | `TEXT NOT NULL` |
| `excerpt_zh` | `TEXT NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY(owner_id,monitor_id,event_id,post_id)`
- `CONSTRAINT codex_reset_event_posts_event_fkey FOREIGN KEY(owner_id,monitor_id,event_id) REFERENCES codex_reset_events(owner_id,monitor_id,id)`
- `CONSTRAINT codex_reset_event_posts_post_fkey FOREIGN KEY(owner_id,monitor_id,post_id) REFERENCES codex_reset_posts(owner_id,monitor_id,id)`
- `CONSTRAINT codex_reset_event_posts_action_check CHECK(action IN ('announce','progress','confirm','amend','withdraw'))`

## codex_reset_reviews

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `entity_kind` | `VARCHAR(16) NOT NULL` |
| `entity_id` | `VARCHAR(128) NOT NULL` |
| `action` | `VARCHAR(32) NOT NULL` |
| `actor` | `VARCHAR(128) NOT NULL` |
| `reason` | `TEXT NOT NULL` |
| `before` | `JSONB NOT NULL` |
| `after` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT codex_reset_reviews_monitor_fkey FOREIGN KEY(owner_id,monitor_id) REFERENCES codex_reset_monitors(owner_id,id)`
- `CONSTRAINT codex_reset_reviews_operation_key UNIQUE(owner_id,monitor_id,operation_id)`
- `CONSTRAINT codex_reset_reviews_input_check CHECK(octet_length(input_fingerprint)=32 AND length(reason) BETWEEN 1 AND 1000)`

## source_connections

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK ( source_key ~ '^[a-z][a-z0-9_-]{0,63}$' )` |
| `status` | `VARCHAR(16) NOT NULL CHECK (status IN ('active', 'disabled'))` |
| `current_version` | `INTEGER NOT NULL DEFAULT 1 CHECK (current_version >= 1)` |
| `safety_stop_reason` | `VARCHAR(32) CHECK (safety_stop_reason IN ('authentication_required', 'rate_limited'))` |
| `safety_trigger_job_id` | `UUID` |
| `safety_stopped_at` | `TIMESTAMPTZ` |
| `safety_stopped_version` | `INTEGER CHECK (safety_stopped_version >= 1)` |
| `safety_events` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK (jsonb_typeof(safety_events) = 'array')` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT source_connections_safety_stop_complete_check CHECK ( (safety_stop_reason IS NULL AND safety_trigger_job_id IS NULL AND safety_stopped_at IS NULL AND safety_stopped_version IS NULL) OR (source_key = 'bilibili' AND status = 'disabled' AND safety_stop_reason IS NOT NULL AND safety_trigger_job_id IS NOT NULL AND safety_stopped_at IS NOT NULL AND safety_stopped_version IS NOT NULL) )`
- `CONSTRAINT source_connections_owner_source_key UNIQUE (owner_id, source_key)`
- `CONSTRAINT source_connections_owner_id_key UNIQUE (owner_id, id)`
- `ALTER TABLE source_connections ADD CONSTRAINT source_connections_current_version_fkey FOREIGN KEY (owner_id, id, current_version) REFERENCES source_connection_versions (owner_id, connection_id, version) DEFERRABLE INITIALLY DEFERRED;`

## source_connection_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `connection_id` | `UUID NOT NULL` |
| `version` | `INTEGER NOT NULL CHECK (version >= 1)` |
| `owner_id` | `UUID NOT NULL` |
| `auth_kind` | `VARCHAR(32) NOT NULL DEFAULT 'server_credential' CHECK ( auth_kind IN ('none', 'server_credential', 'browser_state') )` |
| `secret_ref` | `VARCHAR(256)` |
| `config` | `JSONB NOT NULL DEFAULT '{}'::jsonb` |
| `execution_policy` | `JSONB` |
| `created_by` | `UUID NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (connection_id, version)`
- `CONSTRAINT source_connection_versions_auth_secret_check CHECK ( (auth_kind = 'none' AND secret_ref IS NULL) OR ( auth_kind = 'server_credential' AND secret_ref IS NOT NULL AND secret_ref ~ '^[A-Za-z][A-Za-z0-9+.-]*:[A-Za-z0-9_./:-]+$' ) OR ( auth_kind = 'browser_state' AND secret_ref IS NOT NULL AND secret_ref = 'browser-state:' \|\| replace(owner_id::text, '-', '') \|\| '/' \|\| replace(connection_id::text, '-', '') \|\| '/' \|\| version::text ) )`
- `CONSTRAINT source_connection_versions_config_object_check CHECK ( jsonb_typeof(config) = 'object' )`
- `CONSTRAINT source_connection_versions_config_keys_check CHECK ( config - 'feed_url' - 'feed_url_template' - 'base_url' - 'engines' - 'allowed_hosts' - 'comment_scan' = '{}'::jsonb )`
- `CONSTRAINT source_connection_versions_comment_scan_keys_check CHECK ( NOT (config ? 'comment_scan') OR ( jsonb_typeof(config -> 'comment_scan') = 'object' AND (config -> 'comment_scan') - 'candidate_age_seconds' - 'refresh_interval_seconds' - 'max_posts_per_topic' - 'page_size' - 'max_pages' - 'max_requests' - 'max_seconds' - 'first_level_limit' - 'replies_per_thread_limit' = '{}'::jsonb ) )`
- `CONSTRAINT source_connection_versions_execution_policy_object_check CHECK ( execution_policy IS NULL OR jsonb_typeof(execution_policy) = 'object' )`
- `CONSTRAINT source_connection_versions_execution_policy_keys_check CHECK ( execution_policy IS NULL OR execution_policy - 'min_interval_seconds' - 'quiet_windows' - 'max_queries' - 'max_items_per_query' - 'max_requests' - 'max_seconds' - 'hard_timeout_seconds' - 'max_concurrency' - 'enabled' = '{}'::jsonb )`
- `CONSTRAINT source_connection_versions_owner_connection_version_key UNIQUE (owner_id, connection_id, version)`
- `CONSTRAINT source_connection_versions_owner_connection_fkey FOREIGN KEY (owner_id, connection_id) REFERENCES source_connections (owner_id, id) ON DELETE CASCADE`
- `CREATE INDEX source_connection_versions_created_by_idx ON source_connection_versions (created_by);`

## source_capability_evidence

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `operation_id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `connection_id` | `UUID NOT NULL` |
| `connection_version` | `INTEGER NOT NULL CHECK (connection_version >= 1)` |
| `capability` | `VARCHAR(32) NOT NULL CHECK ( capability IN ('search', 'author_posts', 'comments', 'replies', 'page_content', 'hotlist') )` |
| `entry_point` | `VARCHAR(16) NOT NULL CHECK ( entry_point IN ('manual', 'scheduled') )` |
| `kind` | `VARCHAR(32) NOT NULL CHECK (kind IN ('probe', 'persisted_read'))` |
| `outcome` | `VARCHAR(16) NOT NULL CHECK (outcome IN ('succeeded', 'failed'))` |
| `stop_reason` | `VARCHAR(32) CHECK ( stop_reason IS NULL OR stop_reason IN ( 'end_of_results', 'source_empty', 'rate_limited', 'authentication_required', 'access_denied', 'not_found', 'unsupported', 'cancelled', 'budget_exhausted', 'upstream_error', 'protocol_error' ) )` |
| `resource_ref` | `VARCHAR(512)` |
| `component_name` | `VARCHAR(128) NOT NULL` |
| `component_version` | `VARCHAR(64) NOT NULL` |
| `observed_at` | `TIMESTAMPTZ NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT source_capability_evidence_owner_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT source_capability_evidence_connection_version_fkey FOREIGN KEY (owner_id, connection_id, connection_version) REFERENCES source_connection_versions (owner_id, connection_id, version) ON DELETE CASCADE`
- `CHECK ( (outcome = 'succeeded' AND stop_reason IS NULL) OR (outcome = 'failed' AND stop_reason IS NOT NULL) )`
- `CHECK (kind <> 'probe' OR resource_ref IS NULL)`
- `CHECK ( kind <> 'persisted_read' OR outcome <> 'succeeded' OR resource_ref IS NOT NULL )`
- `CREATE INDEX source_capability_evidence_latest_idx ON source_capability_evidence ( owner_id, connection_id, connection_version, capability, entry_point, observed_at );`

## editorial_source_profiles

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `name` | `VARCHAR(128) NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL` |
| `current_version` | `INTEGER NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `cursor` | `JSONB NOT NULL` |
| `health` | `VARCHAR(16) NOT NULL` |
| `failure_count` | `INTEGER NOT NULL` |
| `last_failure_code` | `VARCHAR(64)` |
| `last_fetch_at` | `TIMESTAMPTZ` |
| `last_ok_at` | `TIMESTAMPTZ` |
| `next_fetch_at` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT editorial_profiles_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT editorial_profiles_source_key UNIQUE (owner_id, source_key)`
- `CONSTRAINT editorial_profiles_source_key_check CHECK (source_key ~ '^ed_[a-z_]+_[a-f0-9]{32}$')`
- `CONSTRAINT editorial_profiles_counters_check CHECK (current_version >= 1 AND revision >= 1 AND failure_count >= 0)`
- `CONSTRAINT editorial_profiles_health_check CHECK (health IN ('unknown','ok','degraded','failing'))`
- `CONSTRAINT editorial_profiles_cursor_check CHECK (jsonb_typeof(cursor) = 'object')`
- `CREATE INDEX editorial_profiles_due_idx ON editorial_source_profiles (enabled, next_fetch_at);`
- `ALTER TABLE editorial_source_profiles ADD CONSTRAINT editorial_profiles_current_version_fkey FOREIGN KEY (owner_id, id, current_version) REFERENCES editorial_source_profile_versions (owner_id, profile_id, version) DEFERRABLE INITIALLY DEFERRED;`

## editorial_source_profile_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `profile_id` | `UUID NOT NULL` |
| `version` | `INTEGER NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `participation_mode` | `VARCHAR(16) NOT NULL` |
| `tier` | `VARCHAR(8) NOT NULL` |
| `first_party` | `BOOLEAN NOT NULL` |
| `connection_id` | `UUID NOT NULL` |
| `connection_version` | `INTEGER NOT NULL` |
| `policy_version` | `INTEGER NOT NULL` |
| `interval_minutes` | `INTEGER NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (profile_id, version)`
- `CONSTRAINT editorial_versions_owner_key UNIQUE (owner_id, profile_id, version)`
- `CONSTRAINT editorial_versions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT editorial_versions_profile_fkey FOREIGN KEY(owner_id, profile_id) REFERENCES editorial_source_profiles (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT editorial_versions_connection_fkey FOREIGN KEY(owner_id, connection_id, connection_version) REFERENCES source_connection_versions (owner_id, connection_id, version)`
- `CONSTRAINT editorial_versions_kind_check CHECK (kind IN ('rss','web_list','json_list','x_search','mp_account','external'))`
- `CONSTRAINT editorial_versions_participation_check CHECK (participation_mode IN ('editorial','hot_signal','isolated') AND tier IN ('T1','T1_5','T2','T3'))`
- `CONSTRAINT editorial_versions_numbers_check CHECK (octet_length(input_hash) = 32 AND version >= 1 AND policy_version >= 1 AND connection_version >= 1 AND interval_minutes BETWEEN 1 AND 360)`
- `CONSTRAINT editorial_versions_configuration_check CHECK (jsonb_typeof(configuration) = 'object')`

## source_access_policies

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')` |
| `capability` | `VARCHAR(32) NOT NULL CHECK ( capability IN ('search', 'author_posts', 'comments', 'replies', 'page_content', 'hotlist') )` |
| `status` | `VARCHAR(16) NOT NULL CHECK (status IN ('pending', 'approved', 'blocked'))` |
| `enabled` | `BOOLEAN NOT NULL DEFAULT false` |
| `access_basis` | `VARCHAR(32) CHECK ( access_basis IS NULL OR access_basis IN ( 'official_api', 'authorized_feed', 'written_permission', 'manual_import', 'public_web' ) )` |
| `terms_reference` | `VARCHAR(512)` |
| `processing_purpose` | `VARCHAR(256) NOT NULL` |
| `component_name` | `VARCHAR(128)` |
| `component_version` | `VARCHAR(64)` |
| `component_license` | `VARCHAR(128)` |
| `field_purposes` | `JSONB NOT NULL DEFAULT '{}'::jsonb CHECK (jsonb_typeof(field_purposes) = 'object')` |
| `reviewed_at` | `TIMESTAMPTZ` |
| `review_expires_at` | `TIMESTAMPTZ` |
| `policy_version` | `INTEGER NOT NULL DEFAULT 1 CHECK (policy_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT source_access_policies_owner_source_capability_key UNIQUE (owner_id, source_key, capability)`
- `CONSTRAINT source_access_policies_owner_id_id_key UNIQUE (owner_id, id)`
- `CHECK (NOT enabled OR status = 'approved')`
- `CHECK ( status <> 'approved' OR ( access_basis IS NOT NULL AND terms_reference IS NOT NULL AND component_name IS NOT NULL AND component_version IS NOT NULL AND component_license IS NOT NULL AND reviewed_at IS NOT NULL AND field_purposes <> '{}'::jsonb ) )`
- `CHECK ( review_expires_at IS NULL OR (reviewed_at IS NOT NULL AND review_expires_at > reviewed_at) )`

## evidence_retention_policies

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_policy_id` | `UUID NOT NULL` |
| `source_policy_version` | `INTEGER NOT NULL CHECK (source_policy_version >= 1)` |
| `data_class` | `VARCHAR(16) NOT NULL CHECK (data_class IN ('structured', 'raw', 'media'))` |
| `requested_days` | `INTEGER NOT NULL CHECK (requested_days BETWEEN 0 AND 3650)` |
| `source_max_days` | `INTEGER CHECK (source_max_days BETWEEN 0 AND 3650)` |
| `effective_days` | `INTEGER NOT NULL` |
| `policy_version` | `INTEGER NOT NULL DEFAULT 1 CHECK (policy_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT evidence_retention_policies_owner_source_class_key UNIQUE (owner_id, source_policy_id, data_class)`
- `CONSTRAINT evidence_retention_policies_owner_id_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT evidence_retention_policies_owner_source_policy_fkey FOREIGN KEY (owner_id, source_policy_id) REFERENCES source_access_policies (owner_id, id) ON DELETE CASCADE`
- `CHECK ( effective_days = CASE WHEN source_max_days IS NULL THEN requested_days ELSE LEAST(requested_days, source_max_days) END )`

## evidence_resources

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `resource_type` | `VARCHAR(64) NOT NULL CHECK ( resource_type ~ '^[a-z][a-z0-9_]{0,63}$' )` |
| `resource_id` | `UUID NOT NULL` |
| `source_policy_id` | `UUID NOT NULL` |
| `source_policy_version` | `INTEGER NOT NULL CHECK (source_policy_version >= 1)` |
| `retention_policy_id` | `UUID NOT NULL` |
| `retention_policy_version` | `INTEGER NOT NULL CHECK (retention_policy_version >= 1)` |
| `data_class` | `VARCHAR(16) NOT NULL CHECK (data_class IN ('structured', 'raw', 'media'))` |
| `collected_at` | `TIMESTAMPTZ NOT NULL` |
| `expires_at` | `TIMESTAMPTZ NOT NULL CHECK (expires_at >= collected_at)` |
| `cleanup_targets` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK ( jsonb_typeof(cleanup_targets) = 'array' )` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT evidence_resources_owner_type_resource_key UNIQUE (owner_id, resource_type, resource_id)`
- `CONSTRAINT evidence_resources_owner_id_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT evidence_resources_owner_source_policy_fkey FOREIGN KEY (owner_id, source_policy_id) REFERENCES source_access_policies (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT evidence_resources_owner_retention_policy_fkey FOREIGN KEY (owner_id, retention_policy_id) REFERENCES evidence_retention_policies (owner_id, id) ON DELETE RESTRICT`
- `CREATE INDEX evidence_resources_expiry_idx ON evidence_resources (expires_at);`

## evidence_deletions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `resource_record_id` | `UUID NOT NULL` |
| `reason` | `VARCHAR(32) NOT NULL CHECK ( reason IN ( 'user_request', 'retention_expired', 'authorization_revoked', 'source_deleted' ) )` |
| `status` | `VARCHAR(16) NOT NULL CHECK (status IN ('pending', 'completed', 'failed'))` |
| `requested_at` | `TIMESTAMPTZ NOT NULL` |
| `cleanup_due_at` | `TIMESTAMPTZ NOT NULL CHECK (cleanup_due_at >= requested_at)` |
| `completed_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT evidence_deletions_owner_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT evidence_deletions_owner_resource_key UNIQUE (owner_id, resource_record_id)`
- `CONSTRAINT evidence_deletions_owner_resource_fkey FOREIGN KEY (owner_id, resource_record_id) REFERENCES evidence_resources (owner_id, id) ON DELETE CASCADE`
- `CHECK ((status = 'completed') = (completed_at IS NOT NULL))`
- `CREATE INDEX evidence_deletions_status_due_idx ON evidence_deletions (status, cleanup_due_at);`

## evidence_cleanup_targets

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `deletion_id` | `UUID NOT NULL REFERENCES evidence_deletions (id) ON DELETE CASCADE` |
| `target_kind` | `VARCHAR(32) NOT NULL CHECK ( target_kind IN ( 'redis_cache', 'minio_object', 'postgres_content_observation' ) )` |
| `target_reference` | `VARCHAR(1024) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL CHECK ( status IN ('pending', 'processing', 'failed', 'succeeded') )` |
| `attempt_count` | `INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count BETWEEN 0 AND 6)` |
| `next_attempt_at` | `TIMESTAMPTZ` |
| `lease_token` | `UUID` |
| `lease_expires_at` | `TIMESTAMPTZ` |
| `last_error_code` | `VARCHAR(128)` |
| `completed_at` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT evidence_cleanup_targets_deletion_kind_reference_key UNIQUE (deletion_id, target_kind, target_reference)`
- `CHECK ( target_kind <> 'postgres_content_observation' OR target_reference ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' )`
- `CHECK ( (status = 'processing') = (lease_token IS NOT NULL AND lease_expires_at IS NOT NULL) )`
- `CHECK ((status = 'succeeded') = (completed_at IS NOT NULL))`
- `CREATE INDEX evidence_cleanup_targets_claim_idx ON evidence_cleanup_targets (status, next_attempt_at);`

## resource_budget_policies

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `budget_key` | `VARCHAR(128) NOT NULL CHECK ( budget_key ~ '^[a-z][a-z0-9_.:-]{0,127}$' )` |
| `metric` | `VARCHAR(32) NOT NULL CHECK ( metric IN ('network_request', 'collector_call', 'analysis_attempt', 'concurrency_slot', 'x_api_usd_micros', 'provider_cny_micros', 'provider_usd_micros') )` |
| `scope_kind` | `VARCHAR(32) NOT NULL CHECK ( scope_kind IN ('global', 'source', 'connection', 'job') )` |
| `scope_reference` | `VARCHAR(128)` |
| `limit_units` | `BIGINT NOT NULL CHECK (limit_units > 0)` |
| `window_seconds` | `BIGINT NOT NULL CHECK (window_seconds > 0)` |
| `window_anchor_at` | `TIMESTAMPTZ NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL` |
| `policy_version` | `BIGINT NOT NULL DEFAULT 1 CHECK (policy_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT resource_budget_policies_owner_key UNIQUE (owner_id, budget_key)`
- `CONSTRAINT resource_budget_policies_owner_id_key UNIQUE (owner_id, id)`
- `CHECK ( (scope_kind = 'global' AND scope_reference IS NULL) OR ( scope_kind <> 'global' AND scope_reference ~ '^[a-z0-9][a-z0-9_.:-]{0,127}$' ) )`
- `CONSTRAINT resource_budget_policies_x_source_check CHECK (metric <> 'x_api_usd_micros' OR scope_kind <> 'source' OR scope_reference = 'x')`
- `CREATE UNIQUE INDEX resource_budget_policies_source_window_key ON resource_budget_policies (owner_id, scope_reference, metric, window_seconds, window_anchor_at) WHERE scope_kind = 'source';`

## resource_budget_windows

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `budget_policy_id` | `UUID NOT NULL` |
| `budget_mode` | `VARCHAR(32) NOT NULL CHECK ( budget_mode IN ('cumulative', 'concurrent') )` |
| `window_start` | `TIMESTAMPTZ NOT NULL` |
| `window_end` | `TIMESTAMPTZ NOT NULL CHECK (window_end > window_start)` |
| `used_units` | `BIGINT NOT NULL DEFAULT 0 CHECK (used_units >= 0)` |
| `reserved_units` | `BIGINT NOT NULL DEFAULT 0 CHECK (reserved_units >= 0)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT resource_budget_windows_policy_start_key UNIQUE (owner_id, budget_policy_id, window_start)`
- `CONSTRAINT resource_budget_windows_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT resource_budget_windows_owner_policy_fkey FOREIGN KEY (owner_id, budget_policy_id) REFERENCES resource_budget_policies (owner_id, id) ON DELETE CASCADE`
- `CHECK (budget_mode = 'cumulative' OR used_units = 0)`
- `CREATE INDEX resource_budget_windows_lookup_idx ON resource_budget_windows (owner_id, budget_policy_id, window_end);`

## resource_budget_reservations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `reservation_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `budget_policy_id` | `UUID NOT NULL` |
| `budget_window_id` | `UUID NOT NULL` |
| `policy_version` | `BIGINT NOT NULL CHECK (policy_version >= 1)` |
| `limit_units` | `BIGINT NOT NULL CHECK (limit_units > 0)` |
| `metric` | `VARCHAR(32) NOT NULL CHECK ( metric IN ('network_request', 'collector_call', 'analysis_attempt', 'concurrency_slot', 'x_api_usd_micros', 'provider_cny_micros', 'provider_usd_micros') )` |
| `budget_mode` | `VARCHAR(32) NOT NULL CHECK ( budget_mode IN ('cumulative', 'concurrent') )` |
| `requested_units` | `BIGINT NOT NULL CHECK (requested_units > 0)` |
| `actual_units` | `BIGINT` |
| `released_units` | `BIGINT` |
| `remaining_units_after` | `BIGINT NOT NULL CHECK (remaining_units_after >= 0)` |
| `context_fingerprint` | `BYTEA NOT NULL CHECK (octet_length(context_fingerprint) = 32)` |
| `status` | `VARCHAR(32) NOT NULL DEFAULT 'reserved' CHECK ( status IN ('reserved', 'settled') )` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `settled_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT resource_budget_reservations_owner_reservation_policy_key UNIQUE (owner_id, reservation_id, budget_policy_id)`
- `CONSTRAINT resource_budget_reservations_owner_policy_fkey FOREIGN KEY (owner_id, budget_policy_id) REFERENCES resource_budget_policies (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT resource_budget_reservations_owner_window_fkey FOREIGN KEY (owner_id, budget_window_id) REFERENCES resource_budget_windows (owner_id, id) ON DELETE CASCADE`
- `CHECK ( (status = 'reserved' AND actual_units IS NULL AND released_units IS NULL AND settled_at IS NULL) OR (status = 'settled' AND actual_units IS NOT NULL AND released_units IS NOT NULL AND settled_at IS NOT NULL) )`
- `CHECK ( actual_units IS NULL OR (actual_units >= 0 AND (actual_units <= requested_units OR metric IN ('provider_cny_micros', 'provider_usd_micros'))) )`
- `CHECK ( released_units IS NULL OR (released_units >= 0 AND released_units <= requested_units) )`
- `CHECK ( status = 'reserved' OR (budget_mode = 'cumulative' AND actual_units + released_units = GREATEST(requested_units, actual_units)) OR (budget_mode = 'concurrent' AND released_units = requested_units) )`
- `CREATE INDEX resource_budget_reservations_lookup_idx ON resource_budget_reservations (owner_id, reservation_id);`

## resource_component_policies

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `component_key` | `VARCHAR(128) NOT NULL CHECK ( component_key ~ '^[a-z][a-z0-9_.:-]{0,127}$' )` |
| `component_version` | `VARCHAR(128) NOT NULL CHECK (component_version <> '')` |
| `upstream_revision` | `VARCHAR(40)` |
| `patched_revision` | `VARCHAR(40)` |
| `cost_class` | `VARCHAR(32) NOT NULL CHECK ( cost_class IN ('local', 'zero_price', 'free_credit', 'paid', 'unknown') )` |
| `enabled_for_core` | `BOOLEAN NOT NULL` |
| `terms_reference` | `VARCHAR(512) NOT NULL CHECK (terms_reference <> '')` |
| `reviewed_at` | `TIMESTAMPTZ NOT NULL` |
| `policy_version` | `BIGINT NOT NULL DEFAULT 1 CHECK (policy_version >= 1)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT resource_component_policies_owner_component_key UNIQUE (owner_id, component_key)`
- `CONSTRAINT resource_component_policies_owner_id_key UNIQUE (owner_id, id)`
- `CHECK (NOT enabled_for_core OR cost_class IN ('local', 'zero_price'))`
- `CONSTRAINT resource_component_policies_revision_pair_check CHECK ( (upstream_revision IS NULL AND patched_revision IS NULL) OR (upstream_revision IS NOT NULL AND patched_revision IS NOT NULL AND upstream_revision ~ '^[0-9a-f]{40}$' AND patched_revision ~ '^[0-9a-f]{40}$') )`

## resource_usage_attempts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `attempt_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `component_policy_id` | `UUID NOT NULL` |
| `component_version` | `VARCHAR(128) NOT NULL CHECK (component_version <> '')` |
| `usage_kind` | `VARCHAR(32) NOT NULL CHECK ( usage_kind IN ('network_request', 'collector_call', 'analysis_attempt') )` |
| `stage` | `VARCHAR(128) NOT NULL CHECK (stage ~ '^[a-z][a-z0-9_.:-]{0,127}$')` |
| `outcome` | `VARCHAR(32) NOT NULL DEFAULT 'started' CHECK ( outcome IN ('started', 'succeeded', 'failed', 'filtered', 'empty') )` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `finished_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT resource_usage_attempts_owner_attempt_key UNIQUE (owner_id, attempt_id)`
- `CONSTRAINT resource_usage_attempts_owner_policy_fkey FOREIGN KEY (owner_id, component_policy_id) REFERENCES resource_component_policies (owner_id, id) ON DELETE CASCADE`
- `CHECK ( (outcome = 'started' AND finished_at IS NULL) OR (outcome <> 'started' AND finished_at IS NOT NULL) )`
- `CHECK (finished_at IS NULL OR finished_at >= started_at)`
- `CREATE INDEX resource_usage_attempts_operation_idx ON resource_usage_attempts (owner_id, operation_id, started_at);`

## jobs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(64) NOT NULL CHECK (kind ~ '^[a-z][a-z0-9_.-]{0,63}$')` |
| `configuration_ref` | `VARCHAR(128) NOT NULL CHECK (configuration_ref ~ '^[a-z0-9][a-z0-9_.:-]{0,127}$')` |
| `configuration_version` | `BIGINT NOT NULL CHECK (configuration_version >= 1)` |
| `source_key` | `VARCHAR(64)` |
| `source_capability` | `VARCHAR(32)` |
| `upstream_revision` | `VARCHAR(40)` |
| `patched_revision` | `VARCHAR(40)` |
| `adapter_version` | `VARCHAR(128)` |
| `scope` | `JSONB NOT NULL CHECK (jsonb_typeof(scope) = 'object')` |
| `request_fingerprint` | `BYTEA NOT NULL CHECK (octet_length(request_fingerprint) = 32)` |
| `status` | `VARCHAR(32) NOT NULL DEFAULT 'queued' CHECK ( status IN ( 'queued', 'running', 'succeeded', 'partially_succeeded', 'failed', 'cancelled' ) )` |
| `lease_owner` | `VARCHAR(128)` |
| `lease_epoch` | `BIGINT NOT NULL DEFAULT 0 CHECK (lease_epoch >= 0)` |
| `lease_expires_at` | `TIMESTAMPTZ` |
| `checkpoint_sequence` | `BIGINT NOT NULL DEFAULT 0 CHECK (checkpoint_sequence >= 0)` |
| `checkpoint` | `JSONB NOT NULL DEFAULT '{}'::jsonb CHECK (jsonb_typeof(checkpoint) = 'object')` |
| `progress_stage` | `VARCHAR(32)` |
| `requests_sent` | `BIGINT NOT NULL DEFAULT 0 CHECK (requests_sent >= 0)` |
| `items_saved` | `BIGINT NOT NULL DEFAULT 0 CHECK (items_saved >= 0)` |
| `progress_updated_at` | `TIMESTAMPTZ` |
| `cancel_requested_at` | `TIMESTAMPTZ` |
| `cancel_deadline_at` | `TIMESTAMPTZ` |
| `scheduled_for_at` | `TIMESTAMPTZ` |
| `started_at` | `TIMESTAMPTZ` |
| `collection_cycle_no` | `BIGINT NOT NULL DEFAULT 0` |
| `collection_cycle_started_at` | `TIMESTAMPTZ` |
| `collection_cycle_requests_sent` | `BIGINT NOT NULL DEFAULT 0` |
| `completed_at` | `TIMESTAMPTZ` |
| `defer_reason` | `VARCHAR(128)` |
| `next_run_at` | `TIMESTAMPTZ` |
| `retry_count` | `BIGINT NOT NULL DEFAULT 0 CHECK (retry_count >= 0)` |
| `last_error_code` | `VARCHAR(128)` |
| `last_error_category` | `VARCHAR(32)` |
| `last_error_at` | `TIMESTAMPTZ` |
| `next_action` | `VARCHAR(512)` |
| `manual_retry_allowed` | `BOOLEAN NOT NULL DEFAULT FALSE` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT jobs_owner_kind_operation_key UNIQUE (owner_id, kind, operation_id)`
- `CONSTRAINT jobs_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT jobs_mediacrawler_version_evidence_check CHECK ( (upstream_revision IS NULL AND patched_revision IS NULL AND adapter_version IS NULL) OR (upstream_revision IS NOT NULL AND patched_revision IS NOT NULL AND upstream_revision ~ '^[0-9a-f]{40}$' AND patched_revision ~ '^[0-9a-f]{40}$' AND adapter_version IS NOT NULL AND adapter_version <> '') )`
- `CHECK ( (source_key IS NULL AND source_capability IS NULL) OR ( source_key IS NOT NULL AND source_capability IS NOT NULL AND source_key ~ '^[a-z][a-z0-9_-]{0,63}$' AND source_capability IN ( 'search', 'author_posts', 'comments', 'replies', 'page_content', 'hotlist' ) ) )`
- `CHECK ( (lease_owner IS NULL AND lease_expires_at IS NULL) OR (lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL) )`
- `CHECK (status = 'running' OR (lease_owner IS NULL AND lease_expires_at IS NULL))`
- `CHECK (progress_stage IS NULL OR progress_stage IN ('request', 'parse', 'save', 'analysis'))`
- `CHECK ( ( progress_stage IS NULL AND progress_updated_at IS NULL AND requests_sent = 0 AND items_saved = 0 ) OR (progress_stage IS NOT NULL AND progress_updated_at IS NOT NULL) )`
- `CHECK (progress_updated_at IS NULL OR progress_updated_at >= created_at)`
- `CONSTRAINT jobs_collection_cycle_check CHECK ( (collection_cycle_no = 0 AND collection_cycle_started_at IS NULL AND collection_cycle_requests_sent = 0) OR (collection_cycle_no >= 1 AND collection_cycle_started_at IS NOT NULL AND collection_cycle_requests_sent >= 0 AND collection_cycle_requests_sent <= requests_sent) )`
- `CHECK ( (cancel_requested_at IS NULL AND cancel_deadline_at IS NULL) OR ( cancel_requested_at IS NOT NULL AND status IN ('running', 'cancelled') AND (cancel_deadline_at IS NULL OR cancel_deadline_at >= cancel_requested_at) ) )`
- `CHECK ( completed_at IS NULL OR status IN ('succeeded', 'partially_succeeded', 'failed', 'cancelled') )`
- `CHECK ( (defer_reason IS NULL AND next_run_at IS NULL) OR ( status = 'queued' AND defer_reason IS NOT NULL AND next_run_at IS NOT NULL AND defer_reason ~ '^[a-z][a-z0-9_.:-]{0,127}$' ) )`
- `CHECK (next_run_at IS NULL OR next_run_at >= created_at)`
- `CHECK ( ( last_error_code IS NULL AND last_error_category IS NULL AND last_error_at IS NULL AND next_action IS NULL ) OR ( last_error_code ~ '^[a-z][a-z0-9_.:-]{0,127}$' AND last_error_category IN ( 'transient', 'rate_limited', 'authentication_required', 'permission_denied', 'invalid_response', 'parse_error', 'invalid_input', 'configuration_unavailable' ) AND last_error_at IS NOT NULL AND next_action IS NOT NULL ) )`
- `CREATE INDEX jobs_runnable_idx ON jobs (status, lease_expires_at);`

## editorial_source_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `profile_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `profile_revision` | `INTEGER NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `prepared_page` | `JSONB` |
| `found` | `INTEGER DEFAULT 0 NOT NULL` |
| `created` | `INTEGER DEFAULT 0 NOT NULL` |
| `revised` | `INTEGER DEFAULT 0 NOT NULL` |
| `failure_code` | `VARCHAR(64)` |
| `review_audit` | `JSONB` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT editorial_source_runs_operation_key UNIQUE (owner_id, profile_id, operation_id)`
- `CONSTRAINT editorial_source_runs_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT editorial_source_runs_version_fkey FOREIGN KEY(owner_id, profile_id, configuration_version) REFERENCES editorial_source_profile_versions (owner_id, profile_id, version)`
- `CONSTRAINT editorial_source_runs_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT editorial_source_runs_status_check CHECK (status IN ('running','staged','succeeded','partial','unknown','failed','blocked','cancelled'))`
- `CONSTRAINT editorial_source_runs_input_check CHECK (octet_length(input_hash) = 32 AND configuration_version >= 1 AND profile_revision >= 1)`
- `CONSTRAINT editorial_source_runs_counts_check CHECK (found >= 0 AND created >= 0 AND revised >= 0)`
- `CONSTRAINT editorial_source_runs_page_check CHECK (prepared_page IS NULL OR (jsonb_typeof(prepared_page) = 'object' AND octet_length(prepared_page::text) <= 8388608))`
- `CONSTRAINT editorial_source_runs_review_check CHECK (review_audit IS NULL OR jsonb_typeof(review_audit) = 'object')`
- `CREATE INDEX editorial_runs_profile_status_idx ON editorial_source_runs (owner_id, profile_id, status);`

## editorial_source_icons

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `profile_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `profile_revision` | `INTEGER NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `source_url` | `TEXT` |
| `media_refs` | `JSONB NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `failure_code` | `VARCHAR(64)` |
| `checked_at` | `TIMESTAMPTZ` |
| `next_retry_at` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, profile_id)`
- `CONSTRAINT editorial_source_icons_version_fkey FOREIGN KEY (owner_id, profile_id, configuration_version) REFERENCES editorial_source_profile_versions (owner_id, profile_id, version)`
- `CONSTRAINT editorial_source_icons_job_fkey FOREIGN KEY (job_id) REFERENCES jobs (id)`
- `CONSTRAINT editorial_source_icons_version_check CHECK (configuration_version >= 1 AND profile_revision >= 1)`
- `CONSTRAINT editorial_source_icons_hash_check CHECK (octet_length(input_hash) = 32)`
- `CONSTRAINT editorial_source_icons_status_check CHECK (status IN ('ready','missing','blocked','unknown','running'))`
- `CONSTRAINT editorial_source_icons_media_check CHECK (jsonb_typeof(media_refs) = 'array' AND octet_length(media_refs::text) <= 65536)`
- `CONSTRAINT editorial_source_icons_ready_check CHECK (status <> 'ready' OR (source_url IS NOT NULL AND jsonb_array_length(media_refs) = 2))`

## provenance_manifests

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `result_kind` | `VARCHAR(64) NOT NULL CHECK ( result_kind ~ '^[a-z][a-z0-9_.:-]{0,63}$' )` |
| `method_key` | `VARCHAR(128) NOT NULL CHECK ( method_key ~ '^[a-z][a-z0-9_.:-]{0,127}$' )` |
| `method_version` | `VARCHAR(128) NOT NULL CHECK ( method_version ~ '^[a-z0-9][a-z0-9_.:-]{0,127}$' )` |
| `method_parameters` | `JSONB NOT NULL CHECK (jsonb_typeof(method_parameters) = 'object')` |
| `manifest_fingerprint` | `BYTEA NOT NULL CHECK (octet_length(manifest_fingerprint) = 32)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT provenance_manifests_owner_id_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT provenance_manifests_owner_job_result_key UNIQUE (owner_id, job_id, result_kind)`
- `CONSTRAINT provenance_manifests_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE CASCADE`

## provenance_manifest_inputs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `manifest_id` | `UUID NOT NULL` |
| `role` | `VARCHAR(16) NOT NULL CHECK (role IN ('subject', 'reference'))` |
| `resource_record_id` | `UUID NOT NULL` |
| `snapshot_ref` | `VARCHAR(128) NOT NULL CHECK ( snapshot_ref ~ '^[a-z0-9][a-z0-9_.:-]{0,127}$' )` |
| `ordinal` | `INTEGER NOT NULL CHECK (ordinal >= 0)` |

键与查询约束（现状）：

- `CONSTRAINT provenance_manifest_inputs_role_ordinal_key UNIQUE (manifest_id, role, ordinal)`
- `CONSTRAINT provenance_manifest_inputs_resource_snapshot_key UNIQUE (manifest_id, role, resource_record_id, snapshot_ref)`
- `CONSTRAINT provenance_manifest_inputs_owner_manifest_fkey FOREIGN KEY (owner_id, manifest_id) REFERENCES provenance_manifests (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT provenance_manifest_inputs_owner_resource_fkey FOREIGN KEY (owner_id, resource_record_id) REFERENCES evidence_resources (owner_id, id)`
- `CREATE INDEX provenance_manifest_inputs_manifest_idx ON provenance_manifest_inputs (manifest_id, role, ordinal);`

## coverage_windows

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CONSTRAINT coverage_windows_source_check CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')` |
| `capability` | `VARCHAR(32) NOT NULL CONSTRAINT coverage_windows_capability_check CHECK (capability IN ('search', 'author_posts', 'comments', 'replies'))` |
| `target_hash` | `BYTEA NOT NULL CONSTRAINT coverage_windows_target_hash_check CHECK (octet_length(target_hash) = 32)` |
| `sort_key` | `VARCHAR(16) NOT NULL CONSTRAINT coverage_windows_sort_check CHECK (sort_key IN ('latest', 'top'))` |
| `rule_version` | `BIGINT NOT NULL CONSTRAINT coverage_windows_rule_version_check CHECK (rule_version >= 1)` |
| `starts_at` | `TIMESTAMPTZ NOT NULL` |
| `ends_at` | `TIMESTAMPTZ NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL DEFAULT 'pending' CONSTRAINT coverage_windows_status_check CHECK (status IN ('pending', 'running', 'confirmed', 'partial'))` |
| `stop_reason` | `VARCHAR(64)` |
| `last_job_id` | `UUID` |
| `checkpoint_sequence` | `BIGINT NOT NULL DEFAULT 0 CONSTRAINT coverage_windows_checkpoint_check CHECK (checkpoint_sequence >= 0)` |
| `page_count` | `BIGINT NOT NULL DEFAULT 0 CONSTRAINT coverage_windows_page_count_check CHECK (page_count >= 0)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CONSTRAINT coverage_windows_updated_at_check CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT coverage_windows_scope_range_key UNIQUE ( owner_id, source_key, capability, target_hash, sort_key, rule_version, starts_at, ends_at )`
- `CONSTRAINT coverage_windows_owner_job_fkey FOREIGN KEY (owner_id, last_job_id) REFERENCES jobs (owner_id, id) ON DELETE SET NULL (last_job_id)`
- `CONSTRAINT coverage_windows_range_check CHECK (starts_at < ends_at)`
- `CONSTRAINT coverage_windows_reason_check CHECK ( (status = 'partial' AND stop_reason ~ '^[a-z][a-z0-9_]{0,63}$') OR (status <> 'partial' AND stop_reason IS NULL) )`

## collection_due_windows

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `schedule_key` | `UUID NOT NULL` |
| `topic_id` | `UUID` |
| `source_key` | `VARCHAR(64) NOT NULL CONSTRAINT collection_due_windows_source_check CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')` |
| `capability` | `VARCHAR(32) NOT NULL CONSTRAINT collection_due_windows_capability_check CHECK (capability IN ('search', 'author_posts', 'comments', 'replies', 'page_content', 'hotlist'))` |
| `due_at` | `TIMESTAMPTZ NOT NULL` |
| `window_start` | `TIMESTAMPTZ NOT NULL` |
| `window_end` | `TIMESTAMPTZ NOT NULL` |
| `connection_version` | `BIGINT CONSTRAINT collection_due_windows_version_check CHECK (connection_version >= 1)` |
| `policy_snapshot` | `JSONB CONSTRAINT collection_due_windows_policy_object_check CHECK (policy_snapshot IS NULL OR jsonb_typeof(policy_snapshot) = 'object')` |
| `admission_state` | `VARCHAR(16) NOT NULL DEFAULT 'pending' CONSTRAINT collection_due_windows_state_check CHECK (admission_state IN ('pending', 'accepted', 'skipped', 'missed'))` |
| `reason` | `VARCHAR(64)` |
| `operation_id` | `UUID` |
| `job_id` | `UUID` |
| `recorded_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT collection_due_windows_owner_schedule_due_key UNIQUE (owner_id, schedule_key, due_at)`
- `CONSTRAINT collection_due_windows_owner_job_key UNIQUE (owner_id, job_id)`
- `CONSTRAINT collection_due_windows_owner_job_source_operation_key UNIQUE (owner_id, job_id, source_key, operation_id)`
- `CONSTRAINT collection_due_windows_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) DEFERRABLE INITIALLY DEFERRED`
- `CONSTRAINT collection_due_windows_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) DEFERRABLE INITIALLY DEFERRED`
- `CONSTRAINT collection_due_windows_range_check CHECK (window_start < window_end AND window_end <= due_at)`
- `CONSTRAINT collection_due_windows_admission_pair_check CHECK ( (admission_state = 'pending' AND reason IS NULL AND operation_id IS NULL AND job_id IS NULL) OR (admission_state = 'accepted' AND reason IS NULL AND operation_id IS NOT NULL AND job_id IS NOT NULL) OR (admission_state = 'skipped' AND reason IS NOT NULL AND reason IN ('quiet', 'disabled', 'rate_limited', 'budget') AND operation_id IS NULL AND job_id IS NULL) OR (admission_state = 'missed' AND reason IS NOT NULL AND reason = 'scheduler_interrupted' AND operation_id IS NULL AND job_id IS NULL) )`
- `CREATE INDEX collection_due_windows_owner_due_idx ON collection_due_windows (owner_id, due_at);`

## job_stage_attempts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `stage` | `VARCHAR(32) NOT NULL CHECK (stage IN ('request', 'parse', 'save', 'analysis'))` |
| `attempt_sequence` | `BIGINT NOT NULL CHECK (attempt_sequence >= 1)` |
| `outcome` | `VARCHAR(32) NOT NULL DEFAULT 'started' CHECK ( outcome IN ( 'started', 'succeeded', 'partially_succeeded', 'failed', 'delayed', 'cancelled' ) )` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `finished_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT job_stage_attempts_job_stage_sequence_key UNIQUE (job_id, stage, attempt_sequence)`
- `CONSTRAINT job_stage_attempts_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE CASCADE`
- `CHECK ( (outcome = 'started' AND finished_at IS NULL) OR (outcome <> 'started' AND finished_at IS NOT NULL) )`
- `CHECK (finished_at IS NULL OR finished_at >= started_at)`
- `CREATE INDEX job_stage_attempts_owner_started_idx ON job_stage_attempts (owner_id, started_at);`
- `CREATE INDEX job_stage_attempts_job_stage_idx ON job_stage_attempts (job_id, stage, attempt_sequence);`

## outbox_messages

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `aggregate_id` | `UUID NOT NULL REFERENCES jobs (id) ON DELETE CASCADE` |
| `topic` | `VARCHAR(128) NOT NULL` |
| `message_key` | `UUID NOT NULL` |
| `event_type` | `VARCHAR(64) NOT NULL` |
| `dispatch_sequence` | `BIGINT NOT NULL CHECK (dispatch_sequence >= 1)` |
| `payload` | `JSONB NOT NULL CHECK (jsonb_typeof(payload) = 'object')` |
| `available_at` | `TIMESTAMPTZ NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `published_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT outbox_messages_aggregate_dispatch_key UNIQUE (aggregate_id, dispatch_sequence)`
- `CHECK (published_at IS NULL OR published_at >= created_at)`
- `CREATE INDEX outbox_messages_unpublished_idx ON outbox_messages (available_at) WHERE published_at IS NULL;`

## job_attempts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `job_id` | `UUID NOT NULL REFERENCES jobs (id) ON DELETE CASCADE` |
| `lease_epoch` | `BIGINT NOT NULL CHECK (lease_epoch >= 1)` |
| `collection_cycle_no` | `BIGINT NOT NULL CHECK (collection_cycle_no >= 1)` |
| `worker_id` | `VARCHAR(128) NOT NULL` |
| `queued_at` | `TIMESTAMPTZ NOT NULL` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `lease_expires_at` | `TIMESTAMPTZ NOT NULL CHECK (lease_expires_at > started_at)` |
| `finished_at` | `TIMESTAMPTZ` |
| `outcome` | `VARCHAR(32)` |

键与查询约束（现状）：

- `CONSTRAINT job_attempts_job_epoch_key UNIQUE (job_id, lease_epoch)`
- `CHECK (queued_at <= started_at)`
- `CHECK ( (finished_at IS NULL AND outcome IS NULL) OR (finished_at IS NOT NULL AND outcome IS NOT NULL) )`
- `CHECK (finished_at IS NULL OR finished_at >= started_at)`
- `CHECK ( outcome IS NULL OR outcome IN ('expired', 'succeeded', 'cancelled', 'delayed', 'failed') )`

## processed_messages

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `job_id` | `UUID NOT NULL REFERENCES jobs (id) ON DELETE CASCADE` |
| `topic` | `VARCHAR(128) NOT NULL` |
| `partition` | `INTEGER NOT NULL CHECK (partition >= 0)` |
| `message_offset` | `BIGINT NOT NULL CHECK (message_offset >= 0)` |
| `processed_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT processed_messages_topic_partition_offset_key UNIQUE (topic, partition, message_offset)`

## ai_calls

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `job_id` | `UUID` |
| `purpose` | `VARCHAR(128) NOT NULL CHECK (purpose <> '')` |
| `provider` | `VARCHAR(64) NOT NULL CHECK (provider <> '')` |
| `model` | `VARCHAR(128) NOT NULL CHECK (model <> '')` |
| `prompt_version` | `VARCHAR(128) NOT NULL CHECK (prompt_version <> '')` |
| `input_fingerprint` | `BYTEA NOT NULL CHECK (octet_length(input_fingerprint) = 32)` |
| `status` | `VARCHAR(16) NOT NULL CHECK (status IN ('running', 'unknown', 'succeeded', 'failed'))` |
| `failure_code` | `VARCHAR(32) CHECK ( failure_code IN ( 'rate_limited', 'unavailable', 'timeout', 'invalid_output', 'output_truncated', 'failed' ) )` |
| `input_tokens` | `BIGINT NOT NULL CHECK (input_tokens >= 0)` |
| `cached_input_tokens` | `BIGINT NOT NULL CHECK (cached_input_tokens >= 0)` |
| `output_tokens` | `BIGINT NOT NULL CHECK (output_tokens >= 0)` |
| `reasoning_output_tokens` | `BIGINT NOT NULL CHECK (reasoning_output_tokens >= 0)` |
| `duration_ms` | `BIGINT NOT NULL CHECK (duration_ms >= 0)` |
| `model_key` | `VARCHAR(64)` |
| `routing_version` | `BIGINT` |
| `routing_hash` | `BYTEA` |
| `currency` | `VARCHAR(3)` |
| `cost_estimate_micros` | `BIGINT` |
| `cost_actual_micros` | `BIGINT` |
| `cost_cap_micros` | `BIGINT` |
| `execution_epoch` | `BIGINT` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT ai_calls_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT ai_calls_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT ai_calls_routing_version_check CHECK (routing_version IS NULL OR routing_version >= 0)`
- `CONSTRAINT ai_calls_execution_epoch_check CHECK (execution_epoch IS NULL OR execution_epoch >= 1)`
- `CONSTRAINT ai_calls_routing_hash_check CHECK (routing_hash IS NULL OR octet_length(routing_hash) = 32)`
- `CONSTRAINT ai_calls_currency_check CHECK (currency IS NULL OR currency IN ('USD', 'CNY'))`
- `CONSTRAINT ai_calls_cost_check CHECK ( (cost_estimate_micros IS NULL OR cost_estimate_micros >= 0) AND (cost_actual_micros IS NULL OR cost_actual_micros >= 0) AND (cost_cap_micros IS NULL OR cost_cap_micros >= 0) )`
- `CONSTRAINT ai_calls_status_failure_check CHECK ( (status IN ('running', 'succeeded') AND failure_code IS NULL) OR (status IN ('unknown', 'failed') AND failure_code IS NOT NULL) )`
- `CREATE INDEX ai_calls_owner_created_idx ON ai_calls (owner_id, created_at);`

## codex_reset_recognitions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `monitor_id` | `UUID NOT NULL` |
| `post_id` | `UUID NOT NULL` |
| `configuration_version` | `INTEGER NOT NULL` |
| `projection_epoch` | `INTEGER NOT NULL` |
| `review_version` | `INTEGER NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `ai_call_id` | `UUID` |
| `status` | `VARCHAR(16) NOT NULL` |
| `recognition` | `JSONB NOT NULL` |
| `held` | `JSONB NOT NULL` |
| `notifications` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT codex_reset_recognitions_post_fkey FOREIGN KEY(owner_id,monitor_id,post_id) REFERENCES codex_reset_posts(owner_id,monitor_id,id)`
- `CONSTRAINT codex_reset_recognitions_ai_call_fkey FOREIGN KEY(owner_id,ai_call_id) REFERENCES ai_calls(owner_id,id)`
- `CONSTRAINT codex_reset_recognitions_status_check CHECK(status IN ('applied','held','stale','failed','running','unknown') AND octet_length(input_fingerprint)=32)`
- `CONSTRAINT codex_reset_recognitions_json_check CHECK(jsonb_typeof(recognition)='object' AND jsonb_typeof(held)='array' AND jsonb_typeof(notifications)='array')`
- `CREATE INDEX codex_reset_recognitions_post_idx ON codex_reset_recognitions(owner_id,monitor_id,post_id,created_at);`

## ai_capability_configurations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `version` | `INTEGER NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `overrides` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, version)`
- `CONSTRAINT ai_capability_configurations_owner_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT ai_capability_configurations_version_check CHECK (version >= 1)`
- `CONSTRAINT ai_capability_configurations_hash_check CHECK (octet_length(input_hash) = 32)`
- `CONSTRAINT ai_capability_configurations_overrides_check CHECK ( jsonb_typeof(overrides) = 'object' AND octet_length(overrides::text) <= 4096 )`

## content_records

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK ( source_key ~ '^[a-z][a-z0-9_-]{0,63}$' )` |
| `object_type` | `VARCHAR(16) NOT NULL CHECK ( object_type IN ('post', 'comment', 'webpage') )` |
| `native_scope` | `VARCHAR(512) CHECK (native_scope IS NULL OR native_scope <> '')` |
| `external_id` | `VARCHAR(512) NOT NULL CHECK (external_id <> '')` |
| `identity_basis` | `VARCHAR(16) CONSTRAINT content_records_identity_basis_check CHECK (identity_basis IN ('guid', 'url_fallback'))` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT content_records_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_records_owner_id_source_key UNIQUE (owner_id, id, source_key)`
- `CONSTRAINT content_records_source_identity_key UNIQUE NULLS NOT DISTINCT ( owner_id, source_key, object_type, native_scope, external_id )`
- `CREATE INDEX content_records_owner_id_idx ON content_records (owner_id, id);`

## content_native_identities

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `platform` | `VARCHAR(32) NOT NULL` |
| `object_type` | `VARCHAR(16) NOT NULL` |
| `namespace` | `VARCHAR(64) NOT NULL` |
| `native_id` | `VARCHAR(128) NOT NULL` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT content_native_identities_native_key UNIQUE (owner_id, platform, object_type, namespace, native_id)`
- `CONSTRAINT content_native_identities_content_fkey FOREIGN KEY(owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_native_identities_namespace_check CHECK (platform = 'threads' AND object_type = 'post' AND namespace = 'threads_shortcode')`
- `CONSTRAINT content_native_identities_id_check CHECK (native_id ~ '^[A-Za-z0-9_-]{1,128}$')`

## content_discoveries

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `first_observed_at` | `TIMESTAMPTZ NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT content_discoveries_owner_content_job_key UNIQUE (owner_id, content_id, job_id)`
- `CONSTRAINT content_discoveries_owner_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_discoveries_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE RESTRICT`
- `CREATE INDEX content_discoveries_content_idx ON content_discoveries (owner_id, content_id);`

## hotlist_snapshots

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')` |
| `job_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `observed_at` | `TIMESTAMPTZ NOT NULL` |
| `entry_count` | `INTEGER NOT NULL CHECK (entry_count >= 0 AND entry_count <= 100)` |

键与查询约束（现状）：

- `CONSTRAINT hotlist_snapshots_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT hotlist_snapshots_owner_job_key UNIQUE (owner_id, job_id)`
- `CONSTRAINT hotlist_snapshots_owner_source_operation_key UNIQUE (owner_id, source_key, operation_id)`
- `CONSTRAINT hotlist_snapshots_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT hotlist_snapshots_owner_due_identity_fkey FOREIGN KEY (owner_id, job_id, source_key, operation_id) REFERENCES collection_due_windows (owner_id, job_id, source_key, operation_id) ON DELETE RESTRICT`
- `CREATE INDEX hotlist_snapshots_latest_idx ON hotlist_snapshots (owner_id, source_key, observed_at DESC, id DESC);`

## hotlist_entries

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `snapshot_id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `rank` | `INTEGER NOT NULL CHECK (rank BETWEEN 1 AND 100)` |
| `title` | `VARCHAR(2000) NOT NULL CHECK (title <> '')` |
| `url` | `VARCHAR(2048) NOT NULL CHECK (url ~ '^https?://')` |
| `summary` | `TEXT` |
| `heat` | `VARCHAR(256)` |
| `published_at` | `TIMESTAMPTZ` |
| `content_id` | `UUID` |
| `matched_topic_names` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK (jsonb_typeof(matched_topic_names) = 'array')` |
| `matched_topic_ids` | `JSONB NOT NULL DEFAULT '[]'::jsonb CHECK (jsonb_typeof(matched_topic_ids) = 'array')` |

键与查询约束（现状）：

- `CONSTRAINT hotlist_entries_snapshot_rank_key PRIMARY KEY (snapshot_id, rank)`
- `CONSTRAINT hotlist_entries_owner_snapshot_fkey FOREIGN KEY (owner_id, snapshot_id) REFERENCES hotlist_snapshots (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT hotlist_entries_owner_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE SET NULL (content_id)`

## content_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `fingerprint` | `BYTEA NOT NULL CHECK (octet_length(fingerprint) = 32)` |
| `text_scope` | `VARCHAR(16) NOT NULL CHECK ( text_scope IN ('full', 'summary', 'truncated', 'media_only') )` |
| `text_origin` | `VARCHAR(32) NOT NULL CHECK ( text_origin IN ('source', 'machine_extracted') )` |
| `text_origin_ref` | `VARCHAR(512)` |
| `title` | `VARCHAR(2000)` |
| `body` | `TEXT` |
| `truncation_reason` | `VARCHAR(32)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT content_versions_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_versions_owner_content_id_key UNIQUE (owner_id, content_id, id)`
- `CONSTRAINT content_versions_owner_content_fingerprint_key UNIQUE (owner_id, content_id, fingerprint)`
- `CONSTRAINT content_versions_owner_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_versions_origin_ref_check CHECK ( (text_origin = 'source' AND text_origin_ref IS NULL) OR ( text_origin = 'machine_extracted' AND text_origin_ref IS NOT NULL AND text_origin_ref <> '' ) )`
- `CONSTRAINT content_versions_text_length_check CHECK ( (title IS NULL OR char_length(title) BETWEEN 1 AND 2000) AND (body IS NULL OR char_length(body) BETWEEN 1 AND 100000) )`
- `CONSTRAINT content_versions_scope_content_check CHECK ( ( text_scope = 'media_only' AND title IS NULL AND body IS NULL AND truncation_reason IS NULL AND text_origin = 'source' ) OR ( text_scope IN ('full', 'summary') AND (title IS NOT NULL OR body IS NOT NULL) AND truncation_reason IS NULL ) OR ( text_scope = 'truncated' AND (title IS NOT NULL OR body IS NOT NULL) AND truncation_reason IN ('source_limit', 'collector_limit') ) )`
- `CREATE INDEX content_versions_content_idx ON content_versions (owner_id, content_id, created_at, id);`

## content_version_relations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `relation_type` | `VARCHAR(16) NOT NULL CHECK ( relation_type IN ('quote', 'repost') )` |
| `target_native_scope` | `VARCHAR(512) CHECK ( target_native_scope IS NULL OR target_native_scope <> '' )` |
| `target_external_id` | `VARCHAR(512) NOT NULL CHECK ( target_external_id <> '' )` |
| `target_author_external_id` | `VARCHAR(512) CHECK ( target_author_external_id IS NULL OR target_author_external_id <> '' )` |

键与查询约束（现状）：

- `CONSTRAINT content_version_relations_target_key UNIQUE NULLS NOT DISTINCT ( owner_id, content_version_id, relation_type, target_native_scope, target_external_id )`
- `CONSTRAINT content_version_relations_owner_version_fkey FOREIGN KEY (owner_id, content_version_id) REFERENCES content_versions (owner_id, id) ON DELETE CASCADE`
- `CREATE INDEX content_version_relations_version_idx ON content_version_relations ( owner_id, content_version_id, relation_type, id );`

## content_observations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `source_operation_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64)` |
| `source_native_scope` | `VARCHAR(512)` |
| `source_external_id` | `VARCHAR(512)` |
| `source_identity_basis` | `VARCHAR(16)` |
| `editorial_profile_id` | `UUID` |
| `native_identity_proof` | `JSONB` |
| `input_basis` | `VARCHAR(32)` |
| `content_version_id` | `UUID` |
| `observed_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `received_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `published_at` | `TIMESTAMP WITH TIME ZONE` |
| `published_at_fractional_digits` | `SMALLINT` |
| `canonical_url` | `VARCHAR(2048)` |
| `final_url` | `VARCHAR(2048)` |
| `author_external_id` | `VARCHAR(512)` |
| `author_name` | `VARCHAR(256)` |
| `like_count` | `BIGINT` |
| `comment_count` | `BIGINT` |
| `repost_count` | `BIGINT` |
| `view_count` | `BIGINT` |
| `play_count` | `BIGINT` |
| `danmaku_count` | `BIGINT` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT content_observations_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_observations_owner_identity_version_key UNIQUE (owner_id, id, content_id, content_version_id)`
- `CONSTRAINT content_observations_source_context_key UNIQUE (owner_id, id, content_id, content_version_id, source_key)`
- `CONSTRAINT content_observations_input_basis_check CHECK (input_basis IS NULL OR input_basis IN ('source_v1', 'observations_v1'))`
- `CONSTRAINT content_observations_provenance_check CHECK ((input_basis IS NULL AND source_key IS NULL AND source_native_scope IS NULL AND source_external_id IS NULL AND source_identity_basis IS NULL AND editorial_profile_id IS NULL AND native_identity_proof IS NULL) OR (input_basis IS NOT NULL AND source_key IS NOT NULL AND source_external_id IS NOT NULL AND source_identity_basis IS NOT NULL AND source_key ~ '^[a-z][a-z0-9_-]{0,63}$' AND source_external_id <> '' AND source_identity_basis IN ('guid', 'url_fallback')))`
- `CONSTRAINT content_observations_proof_check CHECK (native_identity_proof IS NULL OR (jsonb_typeof(native_identity_proof) = 'object' AND octet_length(native_identity_proof::text) <= 8192))`
- `CONSTRAINT content_observations_owner_content_fkey FOREIGN KEY(owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_observations_owner_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT content_observations_owner_content_version_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE RESTRICT`
- `CONSTRAINT content_observations_owner_content_operation_key UNIQUE (owner_id, content_id, source_operation_id)`
- `CONSTRAINT content_observations_received_at_check CHECK (received_at >= observed_at)`
- `CONSTRAINT content_observations_canonical_url_check CHECK (canonical_url IS NULL OR canonical_url ~ '^https?://')`
- `CONSTRAINT content_observations_final_url_check CHECK (final_url IS NULL OR final_url ~ '^https?://')`
- `CONSTRAINT content_observations_author_check CHECK (author_external_id IS NULL OR author_external_id <> '')`
- `CONSTRAINT content_observations_author_name_check CHECK (author_name IS NULL OR author_name <> '')`
- `CONSTRAINT content_observations_published_precision_check CHECK ((published_at IS NULL AND published_at_fractional_digits IS NULL) OR (published_at IS NOT NULL AND published_at_fractional_digits BETWEEN 0 AND 6))`
- `CONSTRAINT content_observations_metrics_check CHECK ((like_count IS NULL OR like_count >= 0) AND (comment_count IS NULL OR comment_count >= 0) AND (repost_count IS NULL OR repost_count >= 0) AND (view_count IS NULL OR view_count >= 0) AND (play_count IS NULL OR play_count >= 0) AND (danmaku_count IS NULL OR danmaku_count >= 0))`
- `CREATE INDEX content_observations_latest_idx ON content_observations (owner_id, content_id, observed_at, received_at, id);`

## editorial_source_material_receipts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `profile_id` | `UUID NOT NULL` |
| `identity_key` | `VARCHAR(512) NOT NULL` |
| `material_hash` | `BYTEA NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `observation_id` | `UUID` |
| `run_id` | `UUID NOT NULL` |
| `body_status` | `VARCHAR(16) NOT NULL` |
| `body_retry_count` | `INTEGER NOT NULL` |
| `first_import` | `BOOLEAN NOT NULL` |
| `detail_title` | `VARCHAR(2000)` |
| `published_at` | `TIMESTAMP WITH TIME ZONE` |
| `source_updated_at` | `TIMESTAMP WITH TIME ZONE` |
| `next_body_retry_at` | `TIMESTAMP WITH TIME ZONE` |
| `metadata` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, profile_id, identity_key)`
- `CONSTRAINT editorial_materials_profile_fkey FOREIGN KEY(owner_id, profile_id) REFERENCES editorial_source_profiles (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT editorial_materials_content_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id)`
- `CONSTRAINT editorial_materials_run_fkey FOREIGN KEY(owner_id, run_id) REFERENCES editorial_source_runs (owner_id, id)`
- `CONSTRAINT editorial_materials_observation_fkey FOREIGN KEY(owner_id, observation_id) REFERENCES content_observations (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT editorial_materials_numbers_check CHECK (octet_length(material_hash) = 32 AND body_retry_count BETWEEN 0 AND 3)`
- `CONSTRAINT editorial_materials_body_check CHECK (body_status IN ('ok','pending','none'))`
- `CONSTRAINT editorial_materials_metadata_check CHECK (jsonb_typeof(metadata) = 'object')`

## content_observation_inputs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `output_observation_id` | `UUID NOT NULL` |
| `input_observation_id` | `UUID NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, output_observation_id, input_observation_id)`
- `CONSTRAINT content_observation_inputs_output_fkey FOREIGN KEY(owner_id, output_observation_id) REFERENCES content_observations (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_observation_inputs_input_fkey FOREIGN KEY(owner_id, input_observation_id) REFERENCES content_observations (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT content_observation_inputs_not_self_check CHECK (output_observation_id <> input_observation_id)`

## content_version_inputs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `observation_id` | `UUID NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_version_id, observation_id)`
- `CONSTRAINT content_version_inputs_version_fkey FOREIGN KEY (owner_id, content_version_id) REFERENCES content_versions (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_version_inputs_observation_fkey FOREIGN KEY (owner_id, observation_id) REFERENCES content_observations (owner_id, id) ON DELETE RESTRICT`

## content_topic_matches

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `topic_rule_version` | `INTEGER NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `profile_id` | `UUID NOT NULL` |
| `profile_configuration_version` | `INTEGER NOT NULL` |
| `observation_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `connection_id` | `UUID NOT NULL` |
| `connection_version` | `INTEGER NOT NULL` |
| `policy_version` | `INTEGER NOT NULL` |
| `input_observation_ids` | `JSONB NOT NULL` |
| `matched_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT content_topic_matches_frozen_key UNIQUE (owner_id, topic_id, topic_rule_version, content_version_id, profile_id, profile_configuration_version)`
- `CONSTRAINT content_topic_matches_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_topic_matches_topic_rule_fkey FOREIGN KEY (topic_id, topic_rule_version) REFERENCES monitor_topic_versions (topic_id, version) ON DELETE CASCADE`
- `CONSTRAINT content_topic_matches_content_version_fkey FOREIGN KEY (owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_topic_matches_observation_fkey FOREIGN KEY (owner_id, observation_id, content_id, content_version_id) REFERENCES content_observations (owner_id, id, content_id, content_version_id) ON DELETE CASCADE`
- `CONSTRAINT content_topic_matches_profile_version_fkey FOREIGN KEY (owner_id, profile_id, profile_configuration_version) REFERENCES editorial_source_profile_versions (owner_id, profile_id, version)`
- `CONSTRAINT content_topic_matches_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT content_topic_matches_connection_fkey FOREIGN KEY (owner_id, connection_id, connection_version) REFERENCES source_connection_versions (owner_id, connection_id, version)`
- `CONSTRAINT content_topic_matches_versions_check CHECK (topic_rule_version >= 1 AND profile_configuration_version >= 1 AND connection_version >= 1 AND policy_version >= 1)`
- `CONSTRAINT content_topic_matches_inputs_check CHECK (jsonb_typeof(input_observation_ids) = 'array' AND jsonb_array_length(input_observation_ids) BETWEEN 1 AND 32)`
- `CREATE INDEX content_topic_matches_topic_idx ON content_topic_matches (owner_id, topic_id, matched_at);`

## content_threads

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `post_content_id` | `UUID NOT NULL` |
| `root_content_id` | `UUID` |
| `parent_content_id` | `UUID` |
| `reply_target_content_id` | `UUID` |
| `parent_relation_status` | `VARCHAR(16) NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_id)`
- `CONSTRAINT content_threads_owner_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_threads_owner_post_fkey FOREIGN KEY (owner_id, post_content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_threads_owner_root_fkey FOREIGN KEY (owner_id, root_content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_threads_owner_parent_fkey FOREIGN KEY (owner_id, parent_content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_threads_owner_reply_target_fkey FOREIGN KEY (owner_id, reply_target_content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_threads_distinct_check CHECK ( content_id <> post_content_id AND (parent_content_id IS NULL OR parent_content_id <> content_id) AND (reply_target_content_id IS NULL OR reply_target_content_id <> content_id) AND ( (parent_content_id IS NULL AND root_content_id IS NOT NULL AND root_content_id = content_id AND reply_target_content_id IS NULL AND parent_relation_status = 'root') OR (parent_content_id IS NOT NULL AND (root_content_id IS NULL OR root_content_id <> content_id) AND parent_relation_status IN ('observed', 'unavailable', 'unresolved')) ) )`
- `CREATE INDEX content_threads_post_idx ON content_threads (owner_id, post_content_id, content_id);`

## content_visibility_observations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `source_operation_id` | `UUID NOT NULL` |
| `observed_at` | `TIMESTAMPTZ NOT NULL` |
| `received_at` | `TIMESTAMPTZ NOT NULL CHECK (received_at >= observed_at)` |
| `status` | `VARCHAR(32) NOT NULL` |
| `basis` | `VARCHAR(32) NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT content_visibility_observations_owner_content_operation_key UNIQUE (owner_id, content_id, source_operation_id)`
- `CONSTRAINT content_visibility_observations_owner_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_visibility_observations_owner_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT content_visibility_observations_status_basis_check CHECK ( (status = 'visible' AND basis = 'content_returned') OR ( status = 'deleted' AND basis IN ('source_tombstone', 'http_gone') ) OR ( status = 'restricted' AND basis IN ('access_denied', 'authentication_required') ) OR ( status = 'transient_failure' AND basis IN ('timeout', 'rate_limited', 'upstream_error') ) OR ( status = 'unknown' AND basis IN ('not_found', 'protocol_error') ) )`
- `CREATE INDEX content_visibility_observations_latest_idx ON content_visibility_observations ( owner_id, content_id, observed_at, received_at, id );`

## content_rendered_materials

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `body_format` | `VARCHAR(16) NOT NULL` |
| `body` | `TEXT NOT NULL` |
| `media` | `JSONB NOT NULL` |
| `representation_hash` | `BYTEA NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_version_id)`
- `CONSTRAINT content_rendered_materials_version_fkey FOREIGN KEY (owner_id, content_id, content_version_id) REFERENCES content_versions(owner_id, content_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_rendered_materials_format_check CHECK (body_format IN ('text','html','markdown'))`
- `CONSTRAINT content_rendered_materials_body_check CHECK (char_length(body) <= 500000)`
- `CONSTRAINT content_rendered_materials_media_check CHECK (jsonb_typeof(media) = 'array' AND jsonb_array_length(media) <= 64 AND octet_length(media::text) <= 65536)`
- `CONSTRAINT content_rendered_materials_hash_check CHECK (octet_length(representation_hash) = 32 AND octet_length(input_hash) = 32)`

## analysis_prompt_activations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `prompt_version` | `VARCHAR(128) PRIMARY KEY CONSTRAINT analysis_prompt_activations_version_check CHECK (prompt_version <> '')` |
| `activated_at` | `TIMESTAMPTZ NOT NULL` |

## analysis_prompt_runtime_sessions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `prompt_version` | `VARCHAR(128) NOT NULL CONSTRAINT analysis_prompt_runtime_sessions_version_check CHECK (prompt_version <> '')` |
| `ai_enabled` | `BOOLEAN NOT NULL` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `last_seen_at` | `TIMESTAMPTZ NOT NULL` |
| `stopped_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT analysis_prompt_runtime_sessions_last_seen_check CHECK (last_seen_at >= started_at)`
- `CONSTRAINT analysis_prompt_runtime_sessions_stopped_check CHECK (stopped_at IS NULL OR stopped_at >= last_seen_at)`
- `CREATE INDEX analysis_prompt_runtime_sessions_version_started_idx ON analysis_prompt_runtime_sessions (prompt_version, started_at);`

## content_annotations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `topic_rule_version` | `INTEGER NOT NULL` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `input_manifest` | `JSONB` |
| `input_signature` | `VARCHAR(64) DEFAULT 'legacy' NOT NULL` |
| `relevant` | `BOOLEAN` |
| `relevance_reason` | `VARCHAR(500)` |
| `sentiment` | `VARCHAR(16)` |
| `summary` | `VARCHAR(60)` |
| `viewpoints` | `JSONB DEFAULT '[]'::jsonb NOT NULL` |
| `ai_call_id` | `UUID` |
| `status` | `VARCHAR(16) NOT NULL` |
| `result_state` | `VARCHAR(16) NOT NULL` |
| `error_code` | `VARCHAR(64)` |
| `diagnostic_history` | `JSONB DEFAULT '[]'::jsonb NOT NULL` |
| `first_valid_at` | `TIMESTAMP WITH TIME ZONE` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT content_annotations_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_annotations_owner_version_topic_rule_prompt_key UNIQUE (owner_id, content_version_id, topic_id, topic_rule_version, prompt_version, input_signature)`
- `CONSTRAINT content_annotations_owner_content_version_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_annotations_owner_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT content_annotations_topic_rule_version_fkey FOREIGN KEY(topic_id, topic_rule_version) REFERENCES monitor_topic_versions (topic_id, version) ON DELETE CASCADE`
- `CONSTRAINT content_annotations_owner_ai_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT content_annotations_rule_version_check CHECK (topic_rule_version >= 1)`
- `CONSTRAINT content_annotations_prompt_version_check CHECK (prompt_version <> '')`
- `CONSTRAINT content_annotations_input_manifest_check CHECK ((input_manifest IS NULL AND input_signature = 'legacy') OR (input_manifest IS NOT NULL AND jsonb_typeof(input_manifest) = 'object' AND octet_length(input_manifest::text) <= 262144 AND input_signature ~ '^[0-9a-f]{64}$'))`
- `CONSTRAINT content_annotations_sentiment_check CHECK (sentiment IS NULL OR sentiment IN ('positive', 'neutral', 'negative'))`
- `CONSTRAINT content_annotations_viewpoints_check CHECK (jsonb_typeof(viewpoints) = 'array' AND jsonb_array_length(viewpoints) <= 5)`
- `CONSTRAINT content_annotations_diagnostic_history_check CHECK (jsonb_typeof(diagnostic_history) = 'array')`
- `CONSTRAINT content_annotations_status_check CHECK (status IN ('annotated', 'unanalyzed'))`
- `CONSTRAINT content_annotations_output_status_check CHECK ((status = 'annotated' AND result_state = 'valid' AND relevant IS NOT NULL AND relevance_reason IS NOT NULL AND btrim(relevance_reason) <> '' AND summary IS NOT NULL AND btrim(summary) <> '' AND ai_call_id IS NOT NULL AND error_code IS NULL AND ((relevant AND sentiment IS NOT NULL) OR (NOT relevant AND sentiment IS NULL))) OR (status = 'unanalyzed' AND result_state IN ('pending', 'failed', 'invalid') AND relevant IS NULL AND relevance_reason IS NULL AND sentiment IS NULL AND summary IS NULL AND viewpoints = '[]'::jsonb AND ((result_state = 'pending' AND ai_call_id IS NULL AND error_code IS NULL) OR (result_state IN ('failed', 'invalid') AND ai_call_id IS NOT NULL AND error_code IS NOT NULL AND btrim(error_code) <> ''))))`
- `CONSTRAINT content_annotations_updated_at_check CHECK (created_at <= updated_at)`
- `CONSTRAINT content_annotations_first_valid_at_check CHECK ((result_state = 'valid') = (first_valid_at IS NOT NULL))`
- `CREATE INDEX content_annotations_content_idx ON content_annotations (owner_id, content_id, created_at);`
- `CREATE INDEX content_annotations_topic_created_idx ON content_annotations (owner_id, topic_id, created_at);`

## editorial_sources

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `scan_cursor` | `UUID` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, source_key)`
- `CONSTRAINT editorial_sources_revision_check CHECK (revision >= 1)`

## editorial_source_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, source_key, revision)`
- `CONSTRAINT editorial_source_versions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT editorial_source_versions_source_fkey FOREIGN KEY (owner_id, source_key) REFERENCES editorial_sources (owner_id, source_key) ON DELETE CASCADE`
- `CONSTRAINT editorial_source_versions_input_check CHECK (revision >= 1 AND octet_length(input_fingerprint) = 32)`
- `CONSTRAINT editorial_source_versions_configuration_check CHECK (jsonb_typeof(configuration) = 'object')`

## editorial_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `source_revision` | `INTEGER NOT NULL` |
| `job_id` | `UUID` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `request_fingerprint` | `BYTEA NOT NULL` |
| `input_manifest` | `JSONB NOT NULL` |
| `stages` | `VARCHAR(16) NOT NULL` |
| `manual_version` | `INTEGER NOT NULL` |
| `execution_token` | `UUID` |
| `status` | `VARCHAR(16) NOT NULL` |
| `result` | `JSONB` |
| `failure_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT editorial_runs_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT editorial_runs_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT editorial_runs_content_version_fkey FOREIGN KEY (owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE CASCADE`
- `CONSTRAINT editorial_runs_source_version_fkey FOREIGN KEY (owner_id, source_key, source_revision) REFERENCES editorial_source_versions (owner_id, source_key, revision)`
- `CONSTRAINT editorial_runs_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT editorial_runs_status_check CHECK (status IN ('queued','running','complete','blocked','failed','unknown','stale'))`
- `CONSTRAINT editorial_runs_options_check CHECK (stages IN ('selection','all') AND manual_version >= 0)`
- `CONSTRAINT editorial_runs_input_check CHECK (octet_length(input_fingerprint) = 32 AND length(prompt_version) > 0)`
- `CONSTRAINT editorial_runs_result_check CHECK (result IS NULL OR jsonb_typeof(result) = 'object')`
- `CREATE INDEX editorial_runs_owner_content_created_idx ON editorial_runs (owner_id, content_id, created_at);`

## editorial_stages

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `run_id` | `UUID NOT NULL` |
| `stage_key` | `VARCHAR(64) NOT NULL` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `output` | `JSONB` |
| `ai_call_id` | `UUID` |
| `failure_code` | `VARCHAR(64)` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `completed_at` | `TIMESTAMPTZ` |

键与查询约束（现状）：

- `CONSTRAINT editorial_stages_run_key UNIQUE (owner_id, run_id, stage_key)`
- `CONSTRAINT editorial_stages_run_fkey FOREIGN KEY (owner_id, run_id) REFERENCES editorial_runs (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT editorial_stages_ai_call_fkey FOREIGN KEY (owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT editorial_stages_status_check CHECK (status IN ('running','succeeded','failed','unknown'))`
- `CONSTRAINT editorial_stages_input_check CHECK (octet_length(input_fingerprint) = 32)`
- `CONSTRAINT editorial_stages_output_check CHECK (output IS NULL OR jsonb_typeof(output) = 'object')`
- `CONSTRAINT editorial_stages_success_check CHECK (status <> 'succeeded' OR output IS NOT NULL)`

## editorial_overrides

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `run_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `before` | `JSONB` |
| `after` | `JSONB NOT NULL` |
| `reason` | `TEXT NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT editorial_overrides_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT editorial_overrides_run_fkey FOREIGN KEY (owner_id, run_id) REFERENCES editorial_runs (owner_id, id)`
- `CONSTRAINT editorial_overrides_input_check CHECK (revision >= 1 AND octet_length(input_fingerprint) = 32)`
- `CONSTRAINT editorial_overrides_reason_check CHECK (length(reason) BETWEEN 1 AND 1000)`

## editorial_content_states

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `current_run_id` | `UUID NOT NULL` |
| `manual_version` | `INTEGER NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_id)`
- `CONSTRAINT editorial_content_states_content_fkey FOREIGN KEY (owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT editorial_content_states_current_run_fkey FOREIGN KEY (owner_id, current_run_id) REFERENCES editorial_runs (owner_id, id)`
- `CONSTRAINT editorial_content_states_manual_check CHECK (manual_version >= 0)`

## analysis_selectbench_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `gold_fingerprint` | `BYTEA NOT NULL` |
| `label` | `VARCHAR(200) NOT NULL` |
| `prompt_version` | `VARCHAR(100) NOT NULL` |
| `split` | `VARCHAR(64)` |
| `seed` | `INTEGER` |
| `sample_size` | `INTEGER NOT NULL` |
| `models` | `JSONB NOT NULL` |
| `summary` | `JSONB NOT NULL` |
| `imported_by` | `UUID NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT analysis_selectbench_runs_scope_key UNIQUE (owner_id, id)`
- `CONSTRAINT analysis_selectbench_runs_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT analysis_selectbench_runs_input_check CHECK (octet_length(input_fingerprint)=32 AND octet_length(gold_fingerprint)=32 AND sample_size BETWEEN 1 AND 5000 AND jsonb_typeof(models)='array' AND jsonb_typeof(summary)='object')`

## analysis_selectbench_results

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `run_id` | `UUID NOT NULL` |
| `model` | `VARCHAR(200) NOT NULL` |
| `case_id` | `VARCHAR(200) NOT NULL` |
| `title` | `VARCHAR(500) NOT NULL` |
| `stratum` | `VARCHAR(128)` |
| `gold` | `VARCHAR(8) NOT NULL` |
| `decision` | `VARCHAR(8)` |
| `score` | `FLOAT` |
| `relevance` | `VARCHAR(128)` |
| `category` | `VARCHAR(128)` |
| `reason` | `VARCHAR(2000)` |
| `error_code` | `VARCHAR(64)` |
| `ai_call_id` | `UUID` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT analysis_selectbench_results_run_fkey FOREIGN KEY(owner_id, run_id) REFERENCES analysis_selectbench_runs (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT analysis_selectbench_results_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT analysis_selectbench_results_case_key UNIQUE (owner_id, run_id, model, case_id)`
- `CONSTRAINT analysis_selectbench_results_decision_check CHECK (gold IN ('select','reject','either') AND (decision IS NULL OR decision IN ('select','reject')) AND (score IS NULL OR score BETWEEN 0 AND 100))`

## content_translation_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `policy_revision` | `INTEGER NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `request_fingerprint` | `VARCHAR(64) NOT NULL` |
| `reference` | `JSONB NOT NULL` |
| `source_format` | `VARCHAR(16) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `body_html` | `TEXT` |
| `translated_segments` | `INTEGER NOT NULL` |
| `total_segments` | `INTEGER NOT NULL` |
| `complete` | `BOOLEAN NOT NULL` |
| `failure_code` | `VARCHAR(80)` |
| `reason` | `TEXT NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT content_translation_runs_owner_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_translation_runs_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT content_translation_runs_revision_key UNIQUE (owner_id, content_id, content_version_id, policy_revision, revision)`
- `CONSTRAINT content_translation_runs_content_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id)`
- `CONSTRAINT content_translation_runs_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT content_translation_runs_status_check CHECK (status IN ('queued','running','complete','partial','unknown','failed','stale'))`
- `CONSTRAINT content_translation_runs_version_check CHECK (source_format IN ('text','html','markdown') AND revision >= 1 AND policy_revision >= 1)`
- `CONSTRAINT content_translation_runs_input_check CHECK (length(input_fingerprint)=64 AND length(request_fingerprint)=64 AND jsonb_typeof(reference)='object')`
- `CONSTRAINT content_translation_runs_counts_check CHECK (translated_segments >= 0 AND translated_segments <= total_segments)`
- `CONSTRAINT content_translation_runs_result_check CHECK (status NOT IN ('complete','partial') OR body_html IS NOT NULL)`

## content_translation_batches

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `run_id` | `UUID NOT NULL` |
| `ordinal` | `INTEGER NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `ai_call_id` | `UUID` |
| `answers` | `JSONB` |
| `failure_code` | `VARCHAR(80)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (run_id, ordinal)`
- `CONSTRAINT content_translation_batches_run_fkey FOREIGN KEY(owner_id, run_id) REFERENCES content_translation_runs (owner_id, id)`
- `CONSTRAINT content_translation_batches_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT content_translation_batches_status_check CHECK (status IN ('running','succeeded','unknown','failed') AND ordinal >= 0)`
- `CONSTRAINT content_translation_batches_answers_check CHECK (answers IS NULL OR jsonb_typeof(answers)='array')`

## events

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `revision` | `INTEGER NOT NULL DEFAULT 1 CHECK (revision >= 1)` |
| `title` | `VARCHAR(200) NOT NULL CHECK (btrim(title) <> '')` |
| `summary` | `TEXT NOT NULL CHECK (btrim(summary) <> '')` |
| `first_seen_at` | `TIMESTAMPTZ NOT NULL` |
| `first_seen_basis` | `VARCHAR(16) NOT NULL CHECK (first_seen_basis IN ('published', 'discovered'))` |
| `status` | `VARCHAR(16) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'merged'))` |
| `merged_into_id` | `UUID` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL CHECK (updated_at >= created_at)` |

键与查询约束（现状）：

- `CONSTRAINT events_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT events_owner_topic_id_key UNIQUE (owner_id, topic_id, id)`
- `CONSTRAINT events_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT events_merged_into_fkey FOREIGN KEY (owner_id, topic_id, merged_into_id) REFERENCES events (owner_id, topic_id, id)`
- `CONSTRAINT events_merge_state_check CHECK ( (status = 'active' AND merged_into_id IS NULL) OR (status = 'merged' AND merged_into_id IS NOT NULL AND merged_into_id <> id) )`
- `CREATE INDEX events_owner_topic_seen_idx ON events (owner_id, topic_id, first_seen_at DESC, id);`

## event_members

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `observation_id` | `UUID` |
| `observation_source_key` | `VARCHAR(64)` |
| `input_manifest` | `JSONB` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `representative_comment_id` | `UUID` |
| `representative_comment_observation_id` | `UUID` |
| `added_revision` | `INTEGER NOT NULL` |
| `removed_revision` | `INTEGER` |
| `assignment_origin` | `VARCHAR(16) NOT NULL` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_members_input_manifest_check CHECK (input_manifest IS NULL OR jsonb_typeof(input_manifest)='object')`
- `CONSTRAINT event_members_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_members_content_version_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_members_observation_identity_fkey FOREIGN KEY(owner_id, observation_id, content_id, content_version_id) REFERENCES content_observations (owner_id, id, content_id, content_version_id) ON DELETE RESTRICT`
- `CONSTRAINT event_members_observation_source_check CHECK (observation_source_key IS NULL OR observation_source_key=source_key)`
- `CONSTRAINT event_members_observation_source_fkey FOREIGN KEY(owner_id, observation_id, content_id, content_version_id, observation_source_key) REFERENCES content_observations (owner_id, id, content_id, content_version_id, source_key) ON DELETE RESTRICT`
- `CONSTRAINT event_members_comment_fkey FOREIGN KEY(owner_id, representative_comment_id) REFERENCES content_records (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_members_comment_observation_fkey FOREIGN KEY(owner_id, representative_comment_observation_id) REFERENCES content_observations (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_members_revision_key UNIQUE (owner_id, topic_id, event_id, content_id, added_revision)`
- `CONSTRAINT event_members_scope_id_key UNIQUE (owner_id, topic_id, event_id, id)`
- `CONSTRAINT event_members_added_revision_check CHECK (added_revision >= 1)`
- `CONSTRAINT event_members_removed_revision_check CHECK (removed_revision IS NULL OR removed_revision > added_revision)`
- `CONSTRAINT event_members_origin_check CHECK (assignment_origin IN ('model', 'manual'))`
- `CONSTRAINT event_members_source_key_check CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')`
- `CREATE INDEX event_members_event_current_idx ON event_members (owner_id, event_id) WHERE removed_revision IS NULL;`
- `CREATE UNIQUE INDEX event_members_one_current_assignment_idx ON event_members (owner_id, topic_id, content_id) WHERE removed_revision IS NULL;`

## event_candidates

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `member_version_ids` | `JSONB NOT NULL` |
| `input_manifest` | `JSONB` |
| `expected_event_revisions` | `JSONB DEFAULT '{}'::jsonb NOT NULL` |
| `window_start` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `window_end` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `status` | `VARCHAR(16) DEFAULT 'pending' NOT NULL` |
| `ai_call_id` | `UUID` |
| `job_id` | `UUID` |
| `event_id` | `UUID` |
| `error_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_candidates_fingerprint_key UNIQUE (owner_id, topic_id, input_fingerprint)`
- `CONSTRAINT event_candidates_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT event_candidates_owner_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_candidates_ai_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT event_candidates_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT event_candidates_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id)`
- `CONSTRAINT event_candidates_fingerprint_length_check CHECK (octet_length(input_fingerprint) = 32)`
- `CONSTRAINT event_candidates_members_check CHECK (jsonb_typeof(member_version_ids) = 'array' AND jsonb_array_length(member_version_ids) BETWEEN 1 AND 20)`
- `CONSTRAINT event_candidates_revisions_check CHECK (jsonb_typeof(expected_event_revisions) = 'object')`
- `CONSTRAINT event_candidates_input_manifest_check CHECK (input_manifest IS NULL OR jsonb_typeof(input_manifest) = 'object')`
- `CONSTRAINT event_candidates_window_check CHECK (window_end > window_start)`
- `CONSTRAINT event_candidates_prompt_check CHECK (prompt_version <> '')`
- `CONSTRAINT event_candidates_status_check CHECK (status IN ('pending', 'confirmed', 'rejected', 'failed'))`
- `CONSTRAINT event_candidates_updated_at_check CHECK (updated_at >= created_at)`
- `CONSTRAINT event_candidates_result_check CHECK ((status = 'pending' AND event_id IS NULL) OR (status = 'confirmed' AND event_id IS NOT NULL AND ai_call_id IS NOT NULL AND error_code IS NULL) OR (status = 'rejected' AND event_id IS NULL AND ai_call_id IS NOT NULL AND error_code IS NULL) OR (status = 'failed' AND event_id IS NULL AND error_code IS NOT NULL))`
- `CREATE INDEX event_candidates_pending_idx ON event_candidates (status, owner_id, topic_id, created_at);`

## event_facts

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `title` | `VARCHAR(200) NOT NULL` |
| `summary` | `TEXT NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `merged_into_id` | `UUID` |
| `frame` | `JSONB` |
| `first_seen_at` | `TIMESTAMPTZ NOT NULL` |
| `first_seen_basis` | `VARCHAR(16) NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_facts_scope_id_key UNIQUE (owner_id, topic_id, id)`
- `CONSTRAINT event_facts_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_facts_merged_into_fkey FOREIGN KEY(owner_id, topic_id, merged_into_id) REFERENCES event_facts (owner_id, topic_id, id)`
- `CONSTRAINT event_facts_revision_check CHECK (revision >= 1)`
- `CONSTRAINT event_facts_title_check CHECK (btrim(title) <> '')`
- `CONSTRAINT event_facts_summary_check CHECK (btrim(summary) <> '')`
- `CONSTRAINT event_facts_status_check CHECK (status IN ('confirmed','unreviewed','merged'))`
- `CONSTRAINT event_facts_merge_check CHECK ((status = 'merged' AND merged_into_id IS NOT NULL AND merged_into_id <> id) OR (status <> 'merged' AND merged_into_id IS NULL))`
- `CONSTRAINT event_facts_time_check CHECK (first_seen_basis IN ('published','discovered'))`
- `CONSTRAINT event_facts_frame_check CHECK (frame IS NULL OR jsonb_typeof(frame) = 'object')`
- `CONSTRAINT event_facts_updated_check CHECK (updated_at >= created_at)`

## event_fact_assignments

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `fact_id` | `UUID NOT NULL` |
| `root_fact_id` | `UUID` |
| `relation` | `VARCHAR(16) NOT NULL` |
| `added_revision` | `INTEGER NOT NULL` |
| `removed_revision` | `INTEGER` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_fact_assignments_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_fact_assignments_fact_fkey FOREIGN KEY(owner_id, topic_id, fact_id) REFERENCES event_facts (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_fact_assignments_root_fkey FOREIGN KEY(owner_id, topic_id, root_fact_id) REFERENCES event_facts (owner_id, topic_id, id)`
- `CONSTRAINT event_fact_assignments_revision_key UNIQUE (owner_id, event_id, fact_id, added_revision)`
- `CONSTRAINT event_fact_assignments_added_check CHECK (added_revision >= 1)`
- `CONSTRAINT event_fact_assignments_removed_check CHECK (removed_revision IS NULL OR removed_revision > added_revision)`
- `CONSTRAINT event_fact_assignments_relation_check CHECK (relation IN ('root','development','background','roundup','unreviewed'))`
- `CONSTRAINT event_fact_assignments_root_check CHECK ((relation IN ('development','background') AND root_fact_id IS NOT NULL AND root_fact_id <> fact_id) OR (relation IN ('root','roundup','unreviewed') AND root_fact_id IS NULL))`
- `CREATE UNIQUE INDEX event_fact_assignments_current_fact_idx ON event_fact_assignments (owner_id, topic_id, fact_id) WHERE removed_revision IS NULL;`
- `CREATE UNIQUE INDEX event_fact_assignments_current_root_idx ON event_fact_assignments (owner_id, event_id) WHERE removed_revision IS NULL AND relation IN ('root','roundup');`

## event_fact_members

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `fact_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `event_member_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `role` | `VARCHAR(16) NOT NULL` |
| `assignment_origin` | `VARCHAR(16) NOT NULL` |
| `added_revision` | `INTEGER NOT NULL` |
| `removed_revision` | `INTEGER` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_fact_members_fact_fkey FOREIGN KEY(owner_id, topic_id, fact_id) REFERENCES event_facts (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_fact_members_member_fkey FOREIGN KEY(owner_id, topic_id, event_id, event_member_id) REFERENCES event_members (owner_id, topic_id, event_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_fact_members_content_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_fact_members_history_key UNIQUE (owner_id, fact_id, event_member_id)`
- `CONSTRAINT event_fact_members_role_check CHECK (role IN ('primary','report','mention'))`
- `CONSTRAINT event_fact_members_origin_check CHECK (assignment_origin IN ('model','manual','legacy'))`
- `CONSTRAINT event_fact_members_added_check CHECK (added_revision >= 1)`
- `CONSTRAINT event_fact_members_removed_check CHECK (removed_revision IS NULL OR removed_revision > added_revision)`
- `CREATE UNIQUE INDEX event_fact_members_current_content_idx ON event_fact_members (owner_id, topic_id, content_id) WHERE removed_revision IS NULL;`
- `CREATE UNIQUE INDEX event_fact_members_current_primary_idx ON event_fact_members (owner_id, fact_id) WHERE removed_revision IS NULL AND role = 'primary';`

## event_grouping_overrides

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `mode` | `VARCHAR(24) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `reason` | `VARCHAR(2000) NOT NULL` |
| `actor_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, topic_id, content_id)`
- `CONSTRAINT event_grouping_overrides_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_grouping_overrides_content_fkey FOREIGN KEY(owner_id, content_id) REFERENCES content_records (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_grouping_overrides_mode_check CHECK (mode IN ('standalone','manual','regroup_pending'))`
- `CONSTRAINT event_grouping_overrides_revision_check CHECK (revision >= 1)`
- `CONSTRAINT event_grouping_overrides_reason_check CHECK (btrim(reason) <> '')`

## event_revision_operations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(24) NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `actor_id` | `UUID NOT NULL` |
| `reason` | `VARCHAR(2000) NOT NULL` |
| `before_state` | `JSONB NOT NULL` |
| `after_state` | `JSONB NOT NULL` |
| `result` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_revision_operations_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT event_revision_operations_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_revision_operations_hash_check CHECK (octet_length(input_fingerprint) = 32)`
- `CONSTRAINT event_revision_operations_kind_check CHECK (kind IN ('merge','split','move','detach','merge_facts','regroup','create_fact'))`
- `CONSTRAINT event_revision_operations_reason_check CHECK (btrim(reason) <> '')`
- `CONSTRAINT event_revision_operations_json_check CHECK (jsonb_typeof(before_state) = 'object' AND jsonb_typeof(after_state) = 'object' AND jsonb_typeof(result) = 'object')`

## event_derived_contents

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_revision` | `INTEGER NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `title` | `VARCHAR(200)` |
| `summary` | `TEXT` |
| `latest_progress` | `VARCHAR(2000)` |
| `ai_call_id` | `UUID` |
| `job_id` | `UUID` |
| `error_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, event_id)`
- `CONSTRAINT event_derived_contents_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_derived_contents_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT event_derived_contents_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT event_derived_contents_revision_check CHECK (event_revision >= 1)`
- `CONSTRAINT event_derived_contents_hash_check CHECK (octet_length(input_fingerprint) = 32)`
- `CONSTRAINT event_derived_contents_status_check CHECK (status IN ('pending','valid','failed','stale'))`
- `CONSTRAINT event_derived_contents_text_check CHECK ((status = 'valid' AND title IS NOT NULL AND summary IS NOT NULL) OR (status <> 'valid' AND title IS NULL AND summary IS NULL AND latest_progress IS NULL))`

## event_grouping_assessments

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `candidate_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `input_snapshot` | `JSONB NOT NULL` |
| `decisions` | `JSONB NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `confidence` | `FLOAT` |
| `ai_call_id` | `UUID` |
| `error_code` | `VARCHAR(64)` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_grouping_assessments_candidate_fkey FOREIGN KEY(owner_id, candidate_id) REFERENCES event_candidates (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_grouping_assessments_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_grouping_assessments_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT event_grouping_assessments_input_key UNIQUE (owner_id, candidate_id, input_fingerprint)`
- `CONSTRAINT event_grouping_assessments_hash_check CHECK (octet_length(input_fingerprint) = 32)`
- `CONSTRAINT event_grouping_assessments_status_check CHECK (status IN ('pending','valid','degraded','stale','failed'))`
- `CONSTRAINT event_grouping_assessments_json_check CHECK (jsonb_typeof(input_snapshot) = 'object' AND jsonb_typeof(decisions) = 'array')`
- `CONSTRAINT event_grouping_assessments_confidence_check CHECK (confidence IS NULL OR confidence BETWEEN 0 AND 1)`

## event_attention_sources

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `selector_kind` | `VARCHAR(24) NOT NULL` |
| `selector_ref` | `VARCHAR(256) NOT NULL` |
| `name` | `VARCHAR(200) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `mode` | `VARCHAR(16) NOT NULL` |
| `group_key` | `VARCHAR(128)` |
| `owner_entity_key` | `VARCHAR(128)` |
| `first_party` | `BOOLEAN NOT NULL` |
| `tier` | `VARCHAR(8)` |
| `scheduled` | `BOOLEAN NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL` |
| `interval_seconds` | `INTEGER NOT NULL` |
| `last_successful_fetch_at` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_attention_sources_scope_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT event_attention_sources_selector_key UNIQUE (owner_id, source_key, selector_kind, selector_ref)`
- `CONSTRAINT event_attention_sources_source_check CHECK (source_key ~ '^[a-z][a-z0-9_-]{0,63}$')`
- `CONSTRAINT event_attention_sources_selector_check CHECK (selector_kind IN ('source','author','native_scope','canonical_host'))`
- `CONSTRAINT event_attention_sources_identity_check CHECK (btrim(selector_ref) <> '' AND btrim(name) <> '')`
- `CONSTRAINT event_attention_sources_mode_check CHECK (mode IN ('editorial','signal','isolated'))`
- `CONSTRAINT event_attention_sources_revision_check CHECK (revision >= 1 AND interval_seconds >= 300)`
- `CONSTRAINT event_attention_sources_tier_check CHECK (tier IS NULL OR tier IN ('T1','T1_5','T2'))`
- `CONSTRAINT event_attention_sources_updated_check CHECK (updated_at >= created_at)`

## event_attention_signals

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `fact_id` | `UUID` |
| `source_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `observation_id` | `UUID` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `source_time` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `time_basis` | `VARCHAR(16) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_attention_signals_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_attention_signals_source_fkey FOREIGN KEY(owner_id, source_id) REFERENCES event_attention_sources (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_attention_signals_fact_fkey FOREIGN KEY(owner_id, topic_id, fact_id) REFERENCES event_facts (owner_id, topic_id, id)`
- `CONSTRAINT event_attention_signals_content_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_attention_signals_observation_fkey FOREIGN KEY(owner_id, observation_id) REFERENCES content_observations (owner_id, id) ON DELETE RESTRICT`
- `CONSTRAINT event_attention_signals_input_key UNIQUE (owner_id, topic_id, event_id, content_id, content_version_id, observation_id)`
- `CONSTRAINT event_attention_signals_kind_check CHECK (kind IN ('editorial','discussion','native'))`
- `CONSTRAINT event_attention_signals_time_check CHECK (time_basis IN ('published','discovered'))`
- `CONSTRAINT event_attention_signals_status_check CHECK (status IN ('active','withdrawn'))`
- `CREATE INDEX event_attention_signals_window_idx ON event_attention_signals (owner_id, event_id, source_time);`

## event_attention_snapshots

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `event_id` | `UUID NOT NULL` |
| `event_revision` | `INTEGER NOT NULL` |
| `window_end` | `TIMESTAMPTZ NOT NULL` |
| `formula_version` | `VARCHAR(128) NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `input_manifest` | `JSONB NOT NULL` |
| `result` | `JSONB NOT NULL` |
| `complete` | `BOOLEAN NOT NULL` |
| `computed_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_attention_snapshots_event_fkey FOREIGN KEY(owner_id, topic_id, event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_attention_snapshots_input_key UNIQUE (owner_id, event_id, event_revision, window_end, formula_version, input_fingerprint)`
- `CONSTRAINT event_attention_snapshots_revision_check CHECK (event_revision >= 1 AND octet_length(input_fingerprint) = 32)`
- `CONSTRAINT event_attention_snapshots_json_check CHECK (jsonb_typeof(input_manifest) = 'object' AND jsonb_typeof(result) = 'object')`
- `CREATE INDEX event_attention_snapshots_latest_idx ON event_attention_snapshots (owner_id, event_id, window_end, computed_at);`

## event_story_links

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `first_event_id` | `UUID NOT NULL` |
| `second_event_id` | `UUID NOT NULL` |
| `first_revision` | `INTEGER NOT NULL` |
| `second_revision` | `INTEGER NOT NULL` |
| `evidence` | `JSONB NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, first_event_id, second_event_id)`
- `CONSTRAINT event_story_links_first_fkey FOREIGN KEY(owner_id, topic_id, first_event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_story_links_second_fkey FOREIGN KEY(owner_id, topic_id, second_event_id) REFERENCES events (owner_id, topic_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_story_links_order_check CHECK (first_event_id < second_event_id)`
- `CONSTRAINT event_story_links_revision_check CHECK (first_revision >= 1 AND second_revision >= 1)`
- `CONSTRAINT event_story_links_evidence_check CHECK (jsonb_typeof(evidence)='array' AND jsonb_array_length(evidence) BETWEEN 2 AND 20)`
- `CREATE INDEX event_story_links_second_idx ON event_story_links (owner_id, topic_id, second_event_id);`

## event_content_embeddings

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `model` | `VARCHAR(128) NOT NULL` |
| `requested_dimensions` | `INTEGER NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `dimensions` | `INTEGER` |
| `vector` | `JSONB` |
| `ai_call_id` | `UUID` |
| `job_id` | `UUID` |
| `error_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT event_content_embeddings_scope_key UNIQUE (owner_id, id)`
- `CONSTRAINT event_content_embeddings_input_key UNIQUE (owner_id, content_version_id, model, requested_dimensions, input_fingerprint)`
- `CONSTRAINT event_content_embeddings_version_fkey FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id) ON DELETE CASCADE`
- `CONSTRAINT event_content_embeddings_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT event_content_embeddings_call_fkey FOREIGN KEY(owner_id, ai_call_id) REFERENCES ai_calls (owner_id, id)`
- `CONSTRAINT event_content_embeddings_input_check CHECK (requested_dimensions BETWEEN 0 AND 3072 AND octet_length(input_fingerprint)=32)`
- `CONSTRAINT event_content_embeddings_status_check CHECK (status IN ('pending','running','response_saved','valid','failed','unknown','stale'))`
- `CONSTRAINT event_content_embeddings_vector_check CHECK ((status IN ('valid','response_saved') AND dimensions BETWEEN 1 AND 3072 AND vector IS NOT NULL AND jsonb_typeof(vector)='array' AND jsonb_array_length(vector)=dimensions AND ai_call_id IS NOT NULL) OR (status NOT IN ('valid','response_saved') AND dimensions IS NULL AND vector IS NULL))`

## reports

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL CHECK (kind IN ('daily', 'weekly'))` |
| `window_start` | `TIMESTAMPTZ NOT NULL` |
| `window_end` | `TIMESTAMPTZ NOT NULL` |
| `cutoff_at` | `TIMESTAMPTZ NOT NULL` |
| `version` | `INTEGER NOT NULL CHECK (version >= 1)` |
| `status` | `VARCHAR(16) NOT NULL CHECK (status IN ('draft', 'final'))` |
| `generator` | `VARCHAR(16) NOT NULL CHECK (generator IN ('template', 'model'))` |
| `input_manifest` | `JSONB NOT NULL CHECK (jsonb_typeof(input_manifest) = 'object')` |
| `data` | `JSONB NOT NULL CHECK (jsonb_typeof(data) = 'object')` |
| `body_markdown` | `TEXT NOT NULL CHECK (body_markdown <> '')` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT reports_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT reports_owner_topic_kind_window_version_key UNIQUE (owner_id, topic_id, kind, window_start, version)`
- `CONSTRAINT reports_owner_topic_fkey FOREIGN KEY (owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT reports_window_check CHECK (window_start < window_end)`
- `CONSTRAINT reports_cutoff_check CHECK (cutoff_at >= window_end)`
- `CONSTRAINT reports_created_cutoff_check CHECK (created_at >= cutoff_at)`
- `CREATE INDEX reports_owner_topic_window_idx ON reports (owner_id, topic_id, kind, window_start, status);`

## report_editions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `actor_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `period_key` | `VARCHAR(10) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `window_start` | `TIMESTAMPTZ NOT NULL` |
| `window_end` | `TIMESTAMPTZ NOT NULL` |
| `cutoff_at` | `TIMESTAMPTZ NOT NULL` |
| `job_id` | `UUID` |
| `prompt_version` | `VARCHAR(128) NOT NULL` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `request_fingerprint` | `VARCHAR(64) NOT NULL` |
| `input_snapshot` | `JSONB NOT NULL` |
| `repeats_suppressed` | `INTEGER NOT NULL` |
| `daily_editions_covered` | `INTEGER NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `generator` | `VARCHAR(16) NOT NULL` |
| `content` | `JSONB` |
| `body_markdown` | `TEXT` |
| `ai_call_id` | `UUID` |
| `failure_code` | `VARCHAR(80)` |
| `reason` | `TEXT NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT report_editions_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT report_editions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT report_editions_revision_key UNIQUE (owner_id, kind, period_key, revision)`
- `CONSTRAINT report_editions_job_fkey FOREIGN KEY (owner_id, job_id) REFERENCES jobs(owner_id, id)`
- `CONSTRAINT report_editions_ai_call_fkey FOREIGN KEY (owner_id, ai_call_id) REFERENCES ai_calls(owner_id, id)`
- `CONSTRAINT report_editions_kind_revision_check CHECK (kind IN ('daily','weekly','monthly') AND revision >= 1)`
- `CONSTRAINT report_editions_status_check CHECK (status IN ('queued','running','complete','failed','unknown','stale'))`
- `CONSTRAINT report_editions_generator_check CHECK (generator IN ('template','model','manual'))`
- `CONSTRAINT report_editions_window_check CHECK (window_start < window_end AND cutoff_at >= window_end)`
- `CONSTRAINT report_editions_snapshot_check CHECK (jsonb_typeof(input_snapshot) = 'array')`
- `CONSTRAINT report_editions_content_check CHECK (content IS NULL OR jsonb_typeof(content) = 'object')`
- `CONSTRAINT report_editions_complete_check CHECK (status <> 'complete' OR (content IS NOT NULL AND body_markdown IS NOT NULL AND length(body_markdown) > 0))`
- `CONSTRAINT report_editions_fingerprint_check CHECK (length(input_fingerprint) = 64)`
- `CREATE INDEX report_editions_owner_period_idx ON report_editions(owner_id, kind, period_key, revision);`

## report_edition_schedules

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `first_period_key` | `VARCHAR(10) NOT NULL` |
| `scan_after_key` | `VARCHAR(10)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, kind)`
- `CONSTRAINT report_edition_schedules_kind_check CHECK (kind IN ('daily','weekly','monthly'))`
- `CONSTRAINT report_edition_schedules_key_check CHECK (length(first_period_key) BETWEEN 7 AND 10)`

## knowledge_exports

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `object_type` | `VARCHAR(16) NOT NULL CHECK ( object_type IN ('daily', 'weekly', 'event', 'topic', 'post', 'qa') )` |
| `object_id` | `UUID NOT NULL` |
| `relative_path` | `VARCHAR(512) NOT NULL CHECK (relative_path <> '')` |
| `content_sha256` | `VARCHAR(64) NOT NULL CHECK (content_sha256 ~ '^[0-9a-f]{64}$')` |
| `exported_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, object_type, object_id)`
- `CONSTRAINT knowledge_exports_owner_relative_path_key UNIQUE (owner_id, relative_path)`

## notification_targets

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `name` | `VARCHAR(80) NOT NULL` |
| `channel` | `VARCHAR(16) NOT NULL` |
| `recipients` | `JSONB NOT NULL` |
| `secret_env` | `VARCHAR(128)` |
| `enabled` | `BOOLEAN DEFAULT false NOT NULL` |
| `revision` | `INTEGER DEFAULT 1 NOT NULL` |
| `enabled_at` | `TIMESTAMPTZ` |
| `subscriptions` | `JSONB DEFAULT '[]'::jsonb NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT notification_targets_owner_name_key UNIQUE (owner_id, name)`
- `CONSTRAINT notification_targets_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT notification_targets_channel_check CHECK (channel IN ('feishu', 'email'))`
- `CONSTRAINT notification_targets_recipients_check CHECK (jsonb_typeof(recipients) = 'array')`
- `CONSTRAINT notification_targets_secret_env_check CHECK (secret_env IS NULL OR secret_env ~ '^HOTKEY_[A-Z][A-Z0-9_]*$')`
- `CONSTRAINT notification_targets_updated_at_check CHECK (updated_at >= created_at)`
- `CONSTRAINT notification_targets_revision_check CHECK (revision >= 1)`
- `CONSTRAINT notification_targets_subscriptions_check CHECK (jsonb_typeof(subscriptions)='array' AND jsonb_array_length(subscriptions)<=5 AND subscriptions <@ '["report","edition","selected","codex_reset","alert"]'::jsonb)`
- `CONSTRAINT notification_targets_enabled_at_check CHECK (enabled_at IS NULL OR enabled_at >= created_at)`

## notification_deliveries

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `report_id` | `UUID` |
| `report_version` | `INTEGER NOT NULL` |
| `target_id` | `UUID NOT NULL` |
| `subject_kind` | `VARCHAR(16) DEFAULT 'report' NOT NULL` |
| `subject_id` | `UUID` |
| `dedupe_key` | `VARCHAR(256)` |
| `revision` | `INTEGER DEFAULT 1 NOT NULL` |
| `target_revision` | `INTEGER DEFAULT 1 NOT NULL` |
| `input_fingerprint` | `BYTEA` |
| `frozen_payload` | `JSONB DEFAULT '{}'::jsonb NOT NULL` |
| `provider_receipt` | `JSONB DEFAULT '{}'::jsonb NOT NULL` |
| `expires_at` | `TIMESTAMPTZ` |
| `status` | `VARCHAR(16) NOT NULL` |
| `attempt_count` | `INTEGER DEFAULT 0 NOT NULL` |
| `last_error_code` | `VARCHAR(64)` |
| `sent_at` | `TIMESTAMPTZ` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT notification_deliveries_owner_target_fkey FOREIGN KEY(owner_id, target_id) REFERENCES notification_targets (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT notification_deliveries_report_version_target_key UNIQUE (report_id, report_version, target_id)`
- `CONSTRAINT notification_deliveries_subject_target_key UNIQUE (owner_id, target_id, subject_kind, dedupe_key)`
- `CONSTRAINT notification_deliveries_subject_check CHECK (subject_kind IN ('report','edition','selected','codex_reset','alert') AND ((subject_kind='report' AND report_id IS NOT NULL AND subject_id IS NULL) OR (subject_kind<>'report' AND report_id IS NULL AND subject_id IS NOT NULL)))`
- `CONSTRAINT notification_deliveries_snapshot_check CHECK (revision>=1 AND target_revision>=1 AND (input_fingerprint IS NULL OR octet_length(input_fingerprint)=32) AND (subject_kind='report' OR (input_fingerprint IS NOT NULL AND dedupe_key IS NOT NULL)) AND (dedupe_key IS NULL OR length(dedupe_key) BETWEEN 1 AND 256) AND jsonb_typeof(frozen_payload)='object' AND jsonb_typeof(provider_receipt)='object')`
- `CONSTRAINT notification_deliveries_version_check CHECK (report_version >= 1)`
- `CONSTRAINT notification_deliveries_status_check CHECK (status IN ('pending', 'sending', 'succeeded', 'failed', 'unknown'))`
- `CONSTRAINT notification_deliveries_attempt_check CHECK (attempt_count BETWEEN 0 AND 3)`
- `CONSTRAINT notification_deliveries_updated_at_check CHECK (updated_at >= created_at)`
- `FOREIGN KEY(report_id) REFERENCES reports (id) ON DELETE CASCADE`

## publication_source_policies

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, source_key)`
- `CONSTRAINT publication_source_policies_revision_check CHECK (revision >= 1)`

## publication_policy_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `actor_id` | `UUID NOT NULL` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `configuration` | `JSONB NOT NULL` |
| `reason` | `TEXT NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, source_key, revision)`
- `CONSTRAINT publication_policy_versions_policy_fk FOREIGN KEY (owner_id, source_key) REFERENCES publication_source_policies(owner_id, source_key)`
- `CONSTRAINT publication_policy_versions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT publication_policy_versions_revision_check CHECK (revision >= 1)`

## publication_records

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `visibility` | `VARCHAR(20) NOT NULL` |
| `eligible` | `BOOLEAN NOT NULL` |
| `selected` | `BOOLEAN NOT NULL` |
| `visible_after` | `TIMESTAMPTZ` |
| `timeline_at` | `TIMESTAMPTZ NOT NULL` |
| `sort_at` | `TIMESTAMPTZ NOT NULL` |
| `last_sequence` | `BIGINT NOT NULL` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `projection` | `JSONB NOT NULL` |
| `override` | `JSONB NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_id)`
- `CONSTRAINT publication_records_content_version_fk FOREIGN KEY (owner_id, content_id, content_version_id) REFERENCES content_versions(owner_id, content_id, id)`
- `CONSTRAINT publication_records_source_policy_fk FOREIGN KEY (owner_id, source_key) REFERENCES publication_source_policies(owner_id, source_key)`
- `CONSTRAINT publication_records_revision_check CHECK (revision >= 1)`
- `CONSTRAINT publication_records_visibility_check CHECK (visibility IN ('public','summary-only','withdrawn'))`
- `CREATE INDEX publication_records_timeline_idx ON publication_records(owner_id, timeline_at, content_id);`
- `CREATE INDEX publication_records_source_idx ON publication_records(owner_id, source_key, content_id);`
- `CREATE INDEX publication_records_selected_idx ON publication_records(owner_id, selected, visible_after);`

## publication_revisions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `actor_id` | `UUID` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `projection` | `JSONB NOT NULL` |
| `reason` | `TEXT NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, content_id, revision)`
- `CONSTRAINT publication_revisions_publication_fk FOREIGN KEY (owner_id, content_id) REFERENCES publication_records(owner_id, content_id)`
- `CONSTRAINT publication_revisions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT publication_revisions_revision_check CHECK (revision >= 1)`

## publication_sync_states

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID PRIMARY KEY` |
| `epoch` | `UUID NOT NULL` |
| `sequence` | `BIGINT NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT publication_sync_states_sequence_check CHECK (sequence >= 0)`

## publication_selected_changes

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `epoch` | `UUID NOT NULL` |
| `sequence` | `BIGINT NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `publication_revision` | `INTEGER NOT NULL` |
| `operation` | `VARCHAR(10) NOT NULL` |
| `visible_at` | `TIMESTAMPTZ NOT NULL` |
| `changed_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, epoch, sequence)`
- `CONSTRAINT publication_selected_changes_publication_fk FOREIGN KEY (owner_id, content_id) REFERENCES publication_records(owner_id, content_id)`
- `CONSTRAINT publication_selected_changes_sequence_check CHECK (sequence >= 1)`
- `CONSTRAINT publication_selected_changes_operation_check CHECK (operation IN ('upsert','remove'))`
- `CREATE INDEX publication_selected_changes_visible_idx ON publication_selected_changes(owner_id, epoch, visible_at, sequence);`

## publication_republish_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID PRIMARY KEY` |
| `owner_id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `policy_revision` | `INTEGER NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `status` | `VARCHAR(20) NOT NULL` |
| `after_content_id` | `UUID` |
| `processed_count` | `INTEGER NOT NULL` |
| `failure_code` | `VARCHAR(100)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT publication_republish_runs_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT publication_republish_runs_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT publication_republish_runs_policy_fk FOREIGN KEY (owner_id, source_key) REFERENCES publication_source_policies(owner_id, source_key)`
- `CONSTRAINT publication_republish_runs_job_fk FOREIGN KEY (owner_id, job_id) REFERENCES jobs(owner_id, id)`
- `CONSTRAINT publication_republish_runs_status_check CHECK (status IN ('queued','running','completed','failed','cancelled'))`
- `CONSTRAINT publication_republish_runs_count_check CHECK (processed_count >= 0)`

## publication_media_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `content_id` | `UUID NOT NULL` |
| `content_version_id` | `UUID NOT NULL` |
| `observation_id` | `UUID` |
| `observation_source_key` | `VARCHAR(64)` |
| `policy_revision` | `INTEGER NOT NULL` |
| `source_key` | `VARCHAR(64) NOT NULL` |
| `fixed_reference` | `JSONB NOT NULL` |
| `input_fingerprint` | `VARCHAR(64) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `reason` | `TEXT` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, id)`
- `CONSTRAINT publication_media_runs_job_fk FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT publication_media_runs_content_fk FOREIGN KEY(owner_id, content_id, content_version_id) REFERENCES content_versions (owner_id, content_id, id)`
- `CONSTRAINT publication_media_runs_observation_identity_fk FOREIGN KEY(owner_id, observation_id, content_id, content_version_id) REFERENCES content_observations (owner_id, id, content_id, content_version_id) ON DELETE RESTRICT`
- `CONSTRAINT publication_media_runs_observation_source_check CHECK (observation_source_key IS NULL OR observation_source_key=source_key)`
- `CONSTRAINT publication_media_runs_observation_source_fk FOREIGN KEY(owner_id, observation_id, content_id, content_version_id, observation_source_key) REFERENCES content_observations (owner_id, id, content_id, content_version_id, source_key) ON DELETE RESTRICT`
- `CONSTRAINT publication_media_runs_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT publication_media_runs_identity_key UNIQUE (owner_id, content_id, content_version_id, policy_revision, observation_id)`
- `CONSTRAINT publication_media_runs_status_check CHECK (status IN ('queued','running','complete','partial','unknown','failed','stale','cancelled'))`
- `CONSTRAINT publication_media_runs_policy_check CHECK (policy_revision >= 1)`
- `CREATE INDEX publication_media_runs_job_idx ON publication_media_runs (owner_id, job_id);`

## publication_media_files

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `id` | `UUID NOT NULL` |
| `run_id` | `UUID NOT NULL` |
| `media_key` | `VARCHAR(24) NOT NULL` |
| `source_url` | `TEXT NOT NULL` |
| `kind` | `VARCHAR(8) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `mime_type` | `VARCHAR(64)` |
| `content_sha256` | `VARCHAR(64)` |
| `byte_count` | `INTEGER` |
| `renditions` | `JSONB NOT NULL` |
| `evidence_resource_id` | `UUID` |
| `reason` | `TEXT` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id,id)`
- `CONSTRAINT publication_media_files_run_fk FOREIGN KEY (owner_id,run_id) REFERENCES publication_media_runs(owner_id,id)`
- `CONSTRAINT publication_media_files_key_key UNIQUE (owner_id,run_id,media_key)`
- `CONSTRAINT publication_media_files_kind_check CHECK (kind IN ('image','video'))`
- `CONSTRAINT publication_media_files_status_check CHECK (status IN ('pending','running','complete','unknown','failed','stale','cancelled'))`
- `CONSTRAINT publication_media_files_size_check CHECK (byte_count IS NULL OR byte_count > 0)`
- `CREATE INDEX publication_media_files_run_idx ON publication_media_files(owner_id,run_id);`

## leaderboard_models

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `slug` | `VARCHAR(160) NOT NULL` |
| `name` | `VARCHAR(300) NOT NULL` |
| `provider` | `VARCHAR(160)` |
| `provider_slug` | `VARCHAR(100)` |
| `released_at` | `TIMESTAMPTZ` |
| `release_date_source` | `VARCHAR(100)` |
| `metadata_source` | `VARCHAR(100) NOT NULL` |
| `context_window_tokens` | `INTEGER` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_models_slug_key UNIQUE (slug)`

## leaderboard_aliases

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(100) NOT NULL` |
| `alias` | `VARCHAR(600) NOT NULL` |
| `normalized_alias` | `VARCHAR(160) NOT NULL` |
| `model_id` | `UUID NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_aliases_source_alias_key UNIQUE (source_key, alias)`
- `FOREIGN KEY(model_id) REFERENCES leaderboard_models (id)`
- `CREATE INDEX leaderboard_aliases_model_idx ON leaderboard_aliases (model_id);`

## leaderboard_snapshots

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `source_key` | `VARCHAR(100) NOT NULL` |
| `source_name` | `VARCHAR(300) NOT NULL` |
| `source_url` | `TEXT NOT NULL` |
| `license` | `TEXT NOT NULL` |
| `attribution_url` | `TEXT NOT NULL` |
| `content_hash` | `VARCHAR(64) NOT NULL` |
| `published_at` | `TIMESTAMPTZ` |
| `fetched_at` | `TIMESTAMPTZ NOT NULL` |
| `record_count` | `INTEGER NOT NULL` |
| `metadata` | `JSONB NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_snapshots_count_check CHECK (record_count >= 0)`
- `CREATE INDEX leaderboard_snapshots_source_fetched_idx ON leaderboard_snapshots (source_key, fetched_at);`

## leaderboard_scores

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `snapshot_id` | `UUID NOT NULL` |
| `model_id` | `UUID NOT NULL` |
| `configuration_key` | `VARCHAR(800) NOT NULL` |
| `configuration_label` | `VARCHAR(400) NOT NULL` |
| `configuration_kind` | `VARCHAR(20) NOT NULL` |
| `configuration_priority` | `INTEGER NOT NULL` |
| `selected_for_product` | `BOOLEAN NOT NULL` |
| `selection_reason` | `TEXT NOT NULL` |
| `metric_key` | `VARCHAR(160) NOT NULL` |
| `metric_name` | `VARCHAR(300) NOT NULL` |
| `raw_score` | `FLOAT NOT NULL` |
| `lower_bound` | `FLOAT` |
| `upper_bound` | `FLOAT` |
| `source_rank` | `INTEGER` |
| `sample_size` | `INTEGER` |
| `source_model_name` | `VARCHAR(600) NOT NULL` |
| `source_organization` | `VARCHAR(200)` |
| `source_published_at` | `TIMESTAMPTZ` |
| `metadata` | `JSONB NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_scores_config_metric_key UNIQUE (snapshot_id, configuration_key, metric_key)`
- `CONSTRAINT leaderboard_scores_kind_check CHECK (configuration_kind IN ('FIRST_PARTY', 'SOURCE_DEFAULT', 'SCAFFOLDED'))`
- `CONSTRAINT leaderboard_scores_sample_size_check CHECK (sample_size IS NULL OR sample_size >= 0)`
- `CONSTRAINT leaderboard_scores_bounds_check CHECK (lower_bound IS NULL OR upper_bound IS NULL OR lower_bound <= upper_bound)`
- `FOREIGN KEY(snapshot_id) REFERENCES leaderboard_snapshots (id) ON DELETE CASCADE`
- `FOREIGN KEY(model_id) REFERENCES leaderboard_models (id)`
- `CREATE INDEX leaderboard_scores_model_snapshot_idx ON leaderboard_scores (model_id, snapshot_id);`
- `CREATE INDEX leaderboard_scores_snapshot_selected_idx ON leaderboard_scores (snapshot_id, selected_for_product);`

## leaderboard_runs

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `methodology_version` | `VARCHAR(100) NOT NULL` |
| `generated_at` | `TIMESTAMPTZ NOT NULL` |
| `source_snapshot_ids` | `JSONB NOT NULL` |
| `summary` | `JSONB NOT NULL` |
| `status` | `VARCHAR(20) NOT NULL` |
| `origin` | `VARCHAR(20) NOT NULL` |
| `fingerprint` | `VARCHAR(64) NOT NULL` |
| `failure_reason` | `TEXT` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_runs_status_check CHECK (status IN ('published', 'failed'))`
- `CONSTRAINT leaderboard_runs_origin_check CHECK (origin IN ('computed', 'refreshed'))`
- `CREATE INDEX leaderboard_runs_status_generated_idx ON leaderboard_runs (status, generated_at, created_at);`

## leaderboard_rankings

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `run_id` | `UUID NOT NULL` |
| `board` | `VARCHAR(40) NOT NULL` |
| `model_id` | `UUID NOT NULL` |
| `rank` | `INTEGER NOT NULL` |
| `score` | `FLOAT NOT NULL` |
| `coverage` | `FLOAT NOT NULL` |
| `metric_count` | `INTEGER NOT NULL` |
| `summary` | `TEXT NOT NULL` |
| `detail` | `JSONB NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_rankings_model_key UNIQUE (run_id, board, model_id)`
- `CONSTRAINT leaderboard_rankings_rank_key UNIQUE (run_id, board, rank)`
- `CONSTRAINT leaderboard_rankings_rank_check CHECK (rank >= 1)`
- `CONSTRAINT leaderboard_rankings_score_check CHECK (score >= 0 AND score <= 100)`
- `CONSTRAINT leaderboard_rankings_coverage_check CHECK (coverage >= 0 AND metric_count >= 0)`
- `FOREIGN KEY(run_id) REFERENCES leaderboard_runs (id) ON DELETE CASCADE`
- `FOREIGN KEY(model_id) REFERENCES leaderboard_models (id)`
- `CREATE INDEX leaderboard_rankings_model_run_idx ON leaderboard_rankings (model_id, run_id);`

## leaderboard_prices

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `model_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(30) NOT NULL` |
| `currency` | `VARCHAR(3) NOT NULL` |
| `input_price` | `FLOAT` |
| `output_price` | `FLOAT` |
| `cached_input_price` | `FLOAT` |
| `source_url` | `TEXT NOT NULL` |
| `verified_on` | `DATE NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_prices_model_kind_key UNIQUE (model_id, kind)`
- `CONSTRAINT leaderboard_prices_kind_check CHECK (kind = 'official')`
- `CONSTRAINT leaderboard_prices_input_check CHECK (input_price IS NULL OR input_price >= 0)`
- `CONSTRAINT leaderboard_prices_output_check CHECK (output_price IS NULL OR output_price >= 0)`
- `CONSTRAINT leaderboard_prices_cached_check CHECK (cached_input_price IS NULL OR cached_input_price >= 0)`
- `FOREIGN KEY(model_id) REFERENCES leaderboard_models (id)`

## leaderboard_fx_rates

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `pair` | `VARCHAR(10) NOT NULL` |
| `as_of` | `DATE NOT NULL` |
| `rate` | `FLOAT NOT NULL` |
| `source_name` | `VARCHAR(200) NOT NULL` |
| `source_url` | `TEXT` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT leaderboard_fx_rates_pair_date_key UNIQUE (pair, as_of)`
- `CONSTRAINT leaderboard_fx_rates_rate_check CHECK (pair = 'USD/CNY' AND rate > 0)`

## leaderboard_source_states

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `source_key` | `VARCHAR(100) NOT NULL` |
| `ok` | `BOOLEAN NOT NULL` |
| `checked_at` | `TIMESTAMPTZ NOT NULL` |
| `last_ok_at` | `TIMESTAMPTZ` |
| `changed` | `BOOLEAN` |
| `row_count` | `INTEGER` |
| `new_models` | `INTEGER` |
| `request_count` | `INTEGER NOT NULL` |
| `error_code` | `VARCHAR(100)` |

键与查询约束（现状）：

- `PRIMARY KEY (source_key)`
- `CONSTRAINT leaderboard_source_states_requests_check CHECK (request_count >= 0)`
- `CONSTRAINT leaderboard_source_states_rows_check CHECK (row_count IS NULL OR row_count >= 0)`

## operations_feedback

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `source_hash` | `BYTEA NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `content` | `VARCHAR(5000)` |
| `email` | `VARCHAR(200)` |
| `page_url` | `VARCHAR(500)` |
| `status` | `VARCHAR(16) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `note` | `VARCHAR(2000)` |
| `forwarded_at` | `TIMESTAMPTZ` |
| `forward_error` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT operations_feedback_scope_key UNIQUE (owner_id, id)`
- `CONSTRAINT operations_feedback_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT operations_feedback_hash_check CHECK (octet_length(source_hash)=32 AND octet_length(input_fingerprint)=32)`
- `CONSTRAINT operations_feedback_state_check CHECK (status IN ('new','reviewing','resolved','rejected','deleted') AND revision>=1)`
- `CONSTRAINT operations_feedback_content_check CHECK ((status='deleted' AND content IS NULL AND email IS NULL AND page_url IS NULL) OR (status<>'deleted' AND btrim(content)<>'' AND content IS NOT NULL))`
- `CREATE INDEX operations_feedback_inbox_idx ON operations_feedback (owner_id, status, created_at);`

## operations_feedback_cooldowns

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID NOT NULL` |
| `source_hash` | `BYTEA NOT NULL` |
| `available_at` | `TIMESTAMPTZ NOT NULL` |
| `banned` | `BOOLEAN NOT NULL` |
| `ban_reason` | `VARCHAR(2000)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (owner_id, source_hash)`
- `CONSTRAINT operations_feedback_cooldowns_hash_check CHECK (octet_length(source_hash)=32)`

## operations_feedback_attachments

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `feedback_id` | `UUID NOT NULL` |
| `mime` | `VARCHAR(16) NOT NULL` |
| `data` | `BYTEA NOT NULL` |
| `sha256` | `BYTEA NOT NULL` |
| `width` | `INTEGER NOT NULL` |
| `height` | `INTEGER NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT operations_feedback_attachments_feedback_fkey FOREIGN KEY(owner_id, feedback_id) REFERENCES operations_feedback (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT operations_feedback_attachments_feedback_key UNIQUE (owner_id, feedback_id)`
- `CONSTRAINT operations_feedback_attachments_format_check CHECK (mime IN ('image/png','image/jpeg','image/webp','image/gif') AND octet_length(data) BETWEEN 1 AND 8388608 AND octet_length(sha256)=32 AND width BETWEEN 1 AND 20000 AND height BETWEEN 1 AND 20000 AND width*height<=40000000)`

## operations_audit_operations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `action` | `VARCHAR(64) NOT NULL` |
| `target_ref` | `VARCHAR(256) NOT NULL` |
| `actor` | `VARCHAR(64) NOT NULL` |
| `reason` | `VARCHAR(2000) NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `before_state` | `JSONB NOT NULL` |
| `after_state` | `JSONB NOT NULL` |
| `job_id` | `UUID` |
| `error_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT operations_audit_operations_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT operations_audit_operations_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT operations_audit_operations_state_check CHECK (octet_length(input_fingerprint)=32 AND status IN ('accepted','succeeded','failed','unknown') AND jsonb_typeof(before_state)='object' AND jsonb_typeof(after_state)='object')`
- `CREATE INDEX operations_audit_operations_history_idx ON operations_audit_operations (owner_id, created_at);`

## operations_process_heartbeats

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `role` | `VARCHAR(16) NOT NULL` |
| `instance_id` | `VARCHAR(128) NOT NULL` |
| `pid` | `INTEGER NOT NULL` |
| `state` | `VARCHAR(16) NOT NULL` |
| `last_seen_at` | `TIMESTAMPTZ NOT NULL` |
| `started_at` | `TIMESTAMPTZ NOT NULL` |
| `detail` | `JSONB NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT operations_process_heartbeats_instance_key UNIQUE (owner_id, role, instance_id)`
- `CONSTRAINT operations_process_heartbeats_state_check CHECK (role IN ('api','worker','scheduler','watchdog') AND state IN ('alive','stopping','error') AND pid>0)`

## operations_dictionary_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `kind` | `VARCHAR(16) NOT NULL` |
| `version` | `INTEGER NOT NULL` |
| `active` | `BOOLEAN NOT NULL` |
| `content` | `JSONB NOT NULL` |
| `input_fingerprint` | `BYTEA NOT NULL` |
| `created_by` | `UUID NOT NULL` |
| `created_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT operations_dictionary_versions_version_key UNIQUE (owner_id, kind, version)`
- `CONSTRAINT operations_dictionary_versions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT operations_dictionary_versions_value_check CHECK (kind IN ('glossary','entities','categories') AND version>=1 AND jsonb_typeof(content)='object' AND octet_length(input_fingerprint)=32)`
- `CREATE UNIQUE INDEX operations_dictionary_versions_one_current_idx ON operations_dictionary_versions (owner_id, kind) WHERE active;`

## operations_site_configurations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `owner_id` | `UUID PRIMARY KEY` |
| `revision` | `INTEGER NOT NULL` |
| `contact_enabled` | `BOOLEAN NOT NULL` |
| `contact_title` | `VARCHAR(100) NOT NULL` |
| `contact_text` | `VARCHAR(4000) NOT NULL` |
| `contact_url` | `VARCHAR(1000)` |
| `wechat_qr_data` | `BYTEA` |
| `wechat_qr_sha256` | `BYTEA` |
| `wechat_qr_mime` | `VARCHAR(32)` |
| `feishu_qr_data` | `BYTEA` |
| `feishu_qr_sha256` | `BYTEA` |
| `feishu_qr_mime` | `VARCHAR(32)` |
| `updated_at` | `TIMESTAMPTZ NOT NULL` |

键与查询约束（现状）：

- `CONSTRAINT operations_site_configurations_revision_check CHECK (revision >= 1)`
- `CONSTRAINT operations_site_configurations_wechat_image_check CHECK ( (wechat_qr_data IS NULL AND wechat_qr_sha256 IS NULL AND wechat_qr_mime IS NULL) OR (wechat_qr_data IS NOT NULL AND wechat_qr_sha256 IS NOT NULL AND wechat_qr_mime = 'image/png' AND octet_length(wechat_qr_data) BETWEEN 1 AND 2097152 AND octet_length(wechat_qr_sha256) = 32) )`
- `CONSTRAINT operations_site_configurations_feishu_image_check CHECK ( (feishu_qr_data IS NULL AND feishu_qr_sha256 IS NULL AND feishu_qr_mime IS NULL) OR (feishu_qr_data IS NOT NULL AND feishu_qr_sha256 IS NOT NULL AND feishu_qr_mime = 'image/png' AND octet_length(feishu_qr_data) BETWEEN 1 AND 2097152 AND octet_length(feishu_qr_sha256) = 32) )`

## report_exports

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `report_id` | `UUID NOT NULL` |
| `report_version` | `INTEGER NOT NULL` |
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `format` | `VARCHAR(16) NOT NULL` |
| `renderer_version` | `VARCHAR(64) NOT NULL` |
| `schema_version` | `VARCHAR(32) NOT NULL` |
| `input_manifest` | `JSONB NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `request_hash` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `object_name` | `VARCHAR(512)` |
| `object_sha256` | `BYTEA` |
| `object_size` | `BIGINT` |
| `mime_type` | `VARCHAR(128)` |
| `failure_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT report_exports_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT report_exports_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT report_exports_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT report_exports_format_check CHECK (format IN ('markdown','pdf','csv','json'))`
- `CONSTRAINT report_exports_status_check CHECK (status IN ('pending','running','succeeded','failed','blocked','cancelled'))`
- `CONSTRAINT report_exports_input_check CHECK (jsonb_typeof(input_manifest)='object' AND octet_length(input_hash)=32 AND octet_length(request_hash)=32)`
- `CONSTRAINT report_exports_size_check CHECK (object_size IS NULL OR object_size BETWEEN 1 AND 5242880)`
- `CONSTRAINT report_exports_hash_check CHECK (object_sha256 IS NULL OR octet_length(object_sha256)=32)`
- `CONSTRAINT report_exports_artifact_check CHECK ((status='succeeded' AND object_name IS NOT NULL AND object_sha256 IS NOT NULL AND object_size IS NOT NULL AND mime_type IS NOT NULL) OR (status<>'succeeded' AND object_name IS NULL AND object_sha256 IS NULL AND object_size IS NULL AND mime_type IS NULL))`
- `CONSTRAINT report_exports_version_check CHECK (report_version>=1)`
- `CONSTRAINT report_exports_report_fkey FOREIGN KEY(owner_id, report_id) REFERENCES reports (owner_id, id) ON DELETE CASCADE`
- `CREATE UNIQUE INDEX report_exports_result_key ON report_exports (owner_id, report_id, report_version, format, renderer_version) WHERE status <> 'cancelled';`

## content_export_requests

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `job_id` | `UUID NOT NULL` |
| `format` | `VARCHAR(16) NOT NULL` |
| `renderer_version` | `VARCHAR(64) NOT NULL` |
| `schema_version` | `VARCHAR(32) NOT NULL` |
| `input_manifest` | `JSONB NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `request_hash` | `BYTEA NOT NULL` |
| `status` | `VARCHAR(16) NOT NULL` |
| `object_name` | `VARCHAR(512)` |
| `object_sha256` | `BYTEA` |
| `object_size` | `BIGINT` |
| `mime_type` | `VARCHAR(128)` |
| `failure_code` | `VARCHAR(64)` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT content_export_requests_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT content_export_requests_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT content_export_requests_job_fkey FOREIGN KEY(owner_id, job_id) REFERENCES jobs (owner_id, id)`
- `CONSTRAINT content_export_requests_format_check CHECK (format IN ('markdown','pdf','csv','json'))`
- `CONSTRAINT content_export_requests_status_check CHECK (status IN ('pending','running','succeeded','failed','blocked','cancelled'))`
- `CONSTRAINT content_export_requests_input_check CHECK (jsonb_typeof(input_manifest)='object' AND octet_length(input_hash)=32 AND octet_length(request_hash)=32)`
- `CONSTRAINT content_export_requests_size_check CHECK (object_size IS NULL OR object_size BETWEEN 1 AND 5242880)`
- `CONSTRAINT content_export_requests_hash_check CHECK (object_sha256 IS NULL OR octet_length(object_sha256)=32)`
- `CONSTRAINT content_export_requests_artifact_check CHECK ((status='succeeded' AND object_name IS NOT NULL AND object_sha256 IS NOT NULL AND object_size IS NOT NULL AND mime_type IS NOT NULL) OR (status<>'succeeded' AND object_name IS NULL AND object_sha256 IS NULL AND object_size IS NULL AND mime_type IS NULL))`
- `CREATE UNIQUE INDEX content_exports_result_key ON content_export_requests (owner_id, input_hash, format, renderer_version, schema_version) WHERE status <> 'cancelled';`

## alert_rules

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `name` | `VARCHAR(80) NOT NULL` |
| `revision` | `INTEGER NOT NULL` |
| `enabled` | `BOOLEAN DEFAULT false NOT NULL` |
| `last_trigger_at` | `TIMESTAMP WITH TIME ZONE` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `updated_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT alert_rules_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT alert_rules_revision_check CHECK (revision>=1)`
- `CONSTRAINT alert_rules_time_check CHECK (updated_at>=created_at)`

## alert_rule_versions

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `rule_id` | `UUID NOT NULL` |
| `version` | `INTEGER NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `operation_id` | `UUID NOT NULL` |
| `request_hash` | `BYTEA NOT NULL` |
| `name` | `VARCHAR(80) NOT NULL` |
| `topic_id` | `UUID NOT NULL` |
| `topic_rule_version` | `INTEGER NOT NULL` |
| `event_id` | `UUID` |
| `metric` | `VARCHAR(32) NOT NULL` |
| `threshold` | `FLOAT NOT NULL` |
| `cooldown_seconds` | `INTEGER NOT NULL` |
| `target_id` | `UUID NOT NULL` |
| `target_revision` | `INTEGER NOT NULL` |
| `enabled` | `BOOLEAN NOT NULL` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (rule_id, version)`
- `CONSTRAINT alert_rule_versions_owner_rule_fkey FOREIGN KEY(owner_id, rule_id) REFERENCES alert_rules (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT alert_rule_versions_owner_topic_fkey FOREIGN KEY(owner_id, topic_id) REFERENCES monitor_topics (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT alert_rule_versions_topic_version_fkey FOREIGN KEY(topic_id, topic_rule_version) REFERENCES monitor_topic_versions (topic_id, version) ON DELETE CASCADE`
- `CONSTRAINT alert_rule_versions_owner_target_fkey FOREIGN KEY(owner_id, target_id) REFERENCES notification_targets (owner_id, id) ON DELETE CASCADE`
- `CONSTRAINT alert_rule_versions_operation_key UNIQUE (owner_id, operation_id)`
- `CONSTRAINT alert_rule_versions_owner_version_key UNIQUE (owner_id, rule_id, version)`
- `CONSTRAINT alert_rule_versions_revision_check CHECK (version>=1 AND topic_rule_version>=1 AND target_revision>=1)`
- `CONSTRAINT alert_rule_versions_metric_check CHECK (metric IN ('negative_count','heat_increment') AND ((metric='negative_count' AND event_id IS NULL AND threshold>=1 AND threshold=trunc(threshold::numeric)) OR (metric='heat_increment' AND event_id IS NOT NULL AND threshold>0)) AND threshold<=1000000000)`
- `CONSTRAINT alert_rule_versions_config_check CHECK (cooldown_seconds BETWEEN 300 AND 86400 AND octet_length(request_hash)=32)`

## alert_evaluations

| 字段 | 类型、默认值与行内约束 |
|---|---|
| `id` | `UUID NOT NULL` |
| `owner_id` | `UUID NOT NULL` |
| `rule_id` | `UUID NOT NULL` |
| `rule_version` | `INTEGER NOT NULL` |
| `window_start` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `window_end` | `TIMESTAMP WITH TIME ZONE NOT NULL` |
| `status` | `VARCHAR(32) NOT NULL` |
| `reason` | `VARCHAR(64)` |
| `value` | `FLOAT` |
| `input_manifest` | `JSONB NOT NULL` |
| `input_hash` | `BYTEA NOT NULL` |
| `cooldown_until` | `TIMESTAMP WITH TIME ZONE` |
| `created_at` | `TIMESTAMP WITH TIME ZONE NOT NULL` |

键与查询约束（现状）：

- `PRIMARY KEY (id)`
- `CONSTRAINT alert_evaluations_owner_id_key UNIQUE (owner_id, id)`
- `CONSTRAINT alert_evaluations_window_key UNIQUE (owner_id, rule_id, rule_version, window_end)`
- `CONSTRAINT alert_evaluations_rule_version_fkey FOREIGN KEY(owner_id, rule_id, rule_version) REFERENCES alert_rule_versions (owner_id, rule_id, version) ON DELETE CASCADE`
- `CONSTRAINT alert_evaluations_status_check CHECK (status IN ('blocked','unknown','below_threshold','cooldown','triggered','withdrawn'))`
- `CONSTRAINT alert_evaluations_window_check CHECK (window_end=window_start+interval '1 hour' AND mod(date_part('epoch',window_end)::bigint,300)=0)`
- `CONSTRAINT alert_evaluations_input_check CHECK (jsonb_typeof(input_manifest)='object' AND octet_length(input_hash)=32)`
- `CONSTRAINT alert_evaluations_cooldown_check CHECK (cooldown_until IS NULL OR cooldown_until>window_end)`
