forked from niuniu/llm-intelligence
feat(audit): add pricing signature guards and reporting
Add snapshot, signature, and drift guard support for Vertex AI, Cloudflare Workers AI, and Perplexity API, backed by a queryable audit table and recent-window view. This commit also wires the audit query layer into daily signal materialization and report generation so structure drift becomes a first-class signal instead of a log-only artifact.
This commit is contained in:
31
db/migrations/013_official_import_signature_audit.sql
Normal file
31
db/migrations/013_official_import_signature_audit.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
-- 官方导入结构签名审计
|
||||
|
||||
CREATE TABLE IF NOT EXISTS official_import_signature_audit (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
source_key TEXT NOT NULL,
|
||||
checked_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
status TEXT NOT NULL,
|
||||
drift_detected BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
baseline_initialized BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
source_url TEXT,
|
||||
fixture_path TEXT,
|
||||
snapshot_path TEXT,
|
||||
signature_path TEXT,
|
||||
baseline_path TEXT,
|
||||
structure_sha256 TEXT,
|
||||
previous_structure_sha256 TEXT,
|
||||
byte_size INTEGER,
|
||||
signature_payload JSONB,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_official_import_signature_audit_source_checked_at
|
||||
ON official_import_signature_audit(source_key, checked_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_official_import_signature_audit_status
|
||||
ON official_import_signature_audit(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_official_import_signature_audit_structure_sha256
|
||||
ON official_import_signature_audit(structure_sha256);
|
||||
|
||||
COMMENT ON TABLE official_import_signature_audit IS '官方导入结构签名巡检审计表,记录每次 guard 抓取、签名与漂移判定结果';
|
||||
COMMENT ON COLUMN official_import_signature_audit.signature_payload IS '当前抓取页面的结构签名 JSONB 快照';
|
||||
@@ -0,0 +1,57 @@
|
||||
-- 官方导入结构签名近期变化视图
|
||||
|
||||
CREATE OR REPLACE VIEW official_import_signature_audit_recent_view AS
|
||||
WITH ordered AS (
|
||||
SELECT
|
||||
a.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY a.source_key
|
||||
ORDER BY a.checked_at DESC, a.id DESC
|
||||
) AS recent_rank,
|
||||
LAG(a.structure_sha256) OVER (
|
||||
PARTITION BY a.source_key
|
||||
ORDER BY a.checked_at, a.id
|
||||
) AS previous_observed_structure_sha256,
|
||||
LAG(a.checked_at) OVER (
|
||||
PARTITION BY a.source_key
|
||||
ORDER BY a.checked_at, a.id
|
||||
) AS previous_checked_at
|
||||
FROM official_import_signature_audit a
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
source_key,
|
||||
checked_at,
|
||||
status,
|
||||
drift_detected,
|
||||
baseline_initialized,
|
||||
source_url,
|
||||
fixture_path,
|
||||
snapshot_path,
|
||||
signature_path,
|
||||
baseline_path,
|
||||
structure_sha256,
|
||||
previous_structure_sha256,
|
||||
previous_observed_structure_sha256,
|
||||
byte_size,
|
||||
signature_payload,
|
||||
error_message,
|
||||
created_at,
|
||||
recent_rank,
|
||||
CASE
|
||||
WHEN previous_observed_structure_sha256 IS NULL THEN FALSE
|
||||
WHEN previous_observed_structure_sha256 IS DISTINCT FROM structure_sha256 THEN TRUE
|
||||
ELSE FALSE
|
||||
END AS structure_changed,
|
||||
CASE
|
||||
WHEN previous_observed_structure_sha256 IS NULL THEN 'initial'
|
||||
WHEN previous_observed_structure_sha256 IS DISTINCT FROM structure_sha256 THEN 'changed'
|
||||
ELSE 'stable'
|
||||
END AS structure_state,
|
||||
CASE
|
||||
WHEN previous_checked_at IS NULL THEN NULL
|
||||
ELSE EXTRACT(EPOCH FROM (checked_at - previous_checked_at))::BIGINT
|
||||
END AS seconds_since_previous
|
||||
FROM ordered;
|
||||
|
||||
COMMENT ON VIEW official_import_signature_audit_recent_view IS '官方导入结构签名近期变化视图,按 source_key 给出 recent_rank、结构是否变化与变化状态';
|
||||
Reference in New Issue
Block a user