"""Seed the monthly compliance-posture summary. Revision ID: 500 Revises: 499 本主题里**唯一会花 Token 的定时任务**。事实全部确定性计算并冻结成快照,模型只拿到 计数、比例和匿名编号 —— 它不能改数字、不能点名、不能引入事实,既有的接地 / 匿名引用 / 低可信度三道闸照常生效。 排在每月 3 号 09:00,即证据预编译(2 号 03:20)之后:先有证据,再谈覆盖率。同一个月 事实未变则复用已有结论(30 天缓存),重开月报既不额外花钱、也不会换一套说法 —— 一份 每次读都不一样的月报,读者会很快学会不读它。 缓存命中时**不发信**:同一个月的信发两遍,是让月报变得无用的最省事的方式。 """ import uuid import sqlalchemy as sa from alembic import op revision = "500" down_revision = "499" branch_labels = None depends_on = None _KEY = "auditor.compliance_posture_summary" _DISPLAY = "合规态势月报" _DESCRIPTION = ( "每月 3 号 09:00(Asia/Shanghai)把上一个完整自然月的合规态势汇总成一封给 " "auditor / global_admin 的月报:控制项通过率、证据预编译覆盖、未决访问漂移、" "待决策事项。\n" "【本主题里唯一会花 Token 的任务】事实全部确定性计算并冻结成快照,模型只拿到" "计数、比例和匿名编号 —— 不能改数字、不能点名、不能引入事实,既有的接地 / " "匿名引用 / 低可信度三道闸照常生效。\n" "同一个月事实未变则复用已有结论(30 天缓存),重开月报不额外花钱也不会换一套说法;" "缓存命中时不发信 —— 同一个月的信发两遍是让月报变得无用的最省事的方式。\n" "排在预编译(2 号 03:20)之后:先有证据,再谈覆盖率。\n" 'config={"month":"YYYY-MM"} 补发历史月份;{"notify": false} 只生成不发信。' ) # 3 号 09:00:预编译在 2 号 03:20 跑完,证据已经在;09:00 是收件人真会看信的时间。 _CRON = "0 9 3 * *" def upgrade() -> None: op.get_bind().execute( sa.text( "INSERT INTO scheduled_jobs " "(id, name, handler_key, display_name, description, " " trigger_type, cron_expr, timezone, enabled, config, " " created_at, updated_at) " "SELECT :id, :name, :k, :dn, :desc, 'cron', :cron, " " 'Asia/Shanghai', 1, '{}', NOW(), NOW() " "FROM DUAL WHERE NOT EXISTS (" " SELECT 1 FROM scheduled_jobs WHERE handler_key = :k)" ), { "id": str(uuid.uuid4()), "name": _KEY, "k": _KEY, "dn": _DISPLAY, "desc": _DESCRIPTION, "cron": _CRON, }, ) def downgrade() -> None: op.get_bind().execute( sa.text("DELETE FROM scheduled_jobs WHERE handler_key = :k"), {"k": _KEY}, )