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:
phamnazage-jpg
2026-05-15 22:34:22 +08:00
parent 958245537a
commit 256975e10c
46 changed files with 5822 additions and 34 deletions

View 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 快照';

View File

@@ -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、结构是否变化与变化状态';