🛠️ 第3章 第一次任务:跑通一条闭环
📄 一句话概括

三类红线:碰生产环境、碰密钥凭据、不可回滚的操作。 规则检查器只能当第一道闸——换个说法就绕过去了(Demo 里三条全漏)。 真正的防线是「不给它那把钥匙」,不是「让它别用」。

📝 本章和前面几章的关系

前四篇讲的是「怎么用得上」。这一篇讲「什么时候不能用」。 这一节放在第 3 章,是因为它必须在「第一次动手之前」读完。 等出了事故再看,就晚了。 Demo 里做了一个规则检查器:十条任务,按关键词判「可交付/人盯/不交」。 十条里五条不该交、一条要人盯。 然后 Demo 自己打自己的脸:换三个说法,三条全漏。 这一段是这一篇的核心——规则能挡住的,只是「说得很直白」的那部分。

一、碰生产数据的不交

生产环境的特点是:错了没法回滚,影响的是用户。 而测试环境的特点是:错了回滚一下,五分钟。 这两者的差别不是「重要程度」,是「错了之后能不能退」。 所以「碰生产」这三个字,是这一节最硬的一条线。 常见的「碰生产」比想象的宽: 改线上配置、跑线上 SQL、看线上日志、连线上数据库、重启线上服务—— 这些都不是「改代码」,但每一个都能造成事故。 最危险的一类:它不知道那是生产。 你给它一个连接串,它不会问「这是生产吗」——它只会照着跑。 所以「给它什么连接」这件事,责任完全在你。

二、碰密钥的不交

凭据有个特性:一旦进了上下文,就等于泄露。 因为上下文会被写进日志、会被缓存、会进入下一轮的输入——你没法知道它最后落在哪儿。 所以「读一下 .env,告诉我配置对不对」这类任务,是绝对不能交的。 它不是「读了会出事」,是「读了之后那个文件内容就到处跑了」。 正确的替代做法有两个: ① 只给键名,不给值——「我这个配置项叫 DATABASE_URL,你看看代码里读的是不是这个名字」; ② 用占位符——把值换成 *** 再给它看。 还有一个更隐蔽的场景:它写代码时会把密钥硬编码进去。 比如「连上这个数据库试试」—— 它可能直接写 conn = connect("host=... password=..."),然后这行代码进了仓库。 所以规矩要写死:凭据只能从环境变量读,不许出现在代码里。**

三、不可回滚的不交

「不可回滚」的意思是:做错了,没有 Ctrl+Z。 删文件、删表、改历史、强推分支——这四类操作有个共同点:执行完那一刻,原来的状态就没了。

操作 为什么不可回滚 替代做法
rm -rf 文件不进回收站 先 mv 到临时目录
drop table 表和数据一起没了 先 create table as select 备份
git reset --hard 未提交的改动直接丢 先 git stash
git push --force 别人的提交被覆盖 先 --force-with-lease

这四条的替代做法,共同点是「先留一份」。 留一份的成本是几秒钟,不留的成本可能是几天。 还有一类「看着可回滚、其实不行」:批量改配置。 改之前没有版本控制,改完发现不对,也回不去了。 所以配置也要进版本库——这一条很重要,很多团队只把代码进了版本库。

四、动手 Demo:十件事,哪些根本不该交出去

这个 Demo 写一个规则检查器:三类红线写成关键词表,十条任务逐条判。 结果是五条「不交」、一条「人盯」、四条「可交付」。 然后 Demo 自己拆自己的台:换三个说法,三条全漏。 这一段比前面十条更有价值。

RULES = [
    ("生产环境",        ["生产", "线上", "prod", "正式库"],           "不交"),
    ("密钥凭据",        [".env", "密钥", "token", "password"],        "不交"),
    ("不可回滚",        ["rm -rf", "drop table", "force push"],        "不交"),
    ("高风险但可回滚",  ["数据库迁移", "schema", "改表结构"],          "人盯"),
    ("常规改动",        ["改名", "补注释", "写测试", "重构函数"],      "可交付"),
]

def judge(task):
    for name, keys, verdict in RULES:
        for k in keys:
            if k.lower() in task.lower():
                return name, verdict
    return "无匹配", "可交付"

实跑输出:

--------------------------------------------------------------------
十件事,哪些根本不该交出去
--------------------------------------------------------------------


  ① 三类红线
  --------------------------------------------------------------------
| 红线 | 为什么 | 举例 |
|---|---|---|
| 碰生产环境 | 错了没法回滚,影响的是用户 | 改线上配置、跑线上 SQL |
| 碰密钥凭据 | 一旦进了上下文,就等于泄露 | 读 .env、贴 token |
| 不可回滚的操作 | 删了就没了 | rm -rf、drop table、force push |

  三条里第一条最常被低估:「在本地跑一遍再上」这件事,云端任务做不到——它没有你的生产环境,
  但它可能有生产的凭据。

  ② 一个规则检查器
  --------------------------------------------------------------------
  把红线写成可判定的规则,就能在派活之前自动拦一道:
| 任务 | 命中红线 | 判定 |
|---|---|---|
| 把 utils.py 里的 parse_date … | 常规改动 | 可交付 |
| 连上生产库,把 status 字段的默认值改成 1 | 生产环境 | 不交 |
| 读一下 .env,告诉我数据库密码配的对不对 | 密钥凭据 | 不交 |
| 给 order 模块补三条单元测试 | 无匹配 | 可交付 |
| 帮我把线上日志里的报错归类 | 生产环境 | 不交 |
| 执行 rm -rf dist 然后重新构建 | 不可回滚 | 不交 |
| 写一个数据库迁移脚本,加一列 | 高风险但可回滚 | 人盯 |
| 重构 handle_request 这个函数,拆成… | 无匹配 | 可交付 |
| 用 force push 覆盖一下远端分支 | 不可回滚 | 不交 |
| 把 README 里过期的命令更新一下 | 无匹配 | 可交付 |

  十条里 5 条不该交,1 条要人盯着做,其余可以放心交。

  ③ 这个检查器漏什么
  --------------------------------------------------------------------
  规则匹配只能认字面。换个说法就绕过去了:
  把 dist 目录清掉,重新构建  →  无匹配 / 可交付
  把那个分支重置到昨天的版本  →  无匹配 / 可交付
  看看数据库里那个密码字段存的是什么  →  无匹配 / 可交付
  三条全被判成「可交付」,3 条全漏。
  第一条其实是 rm -rf dist,第二条其实是 reset --hard,
  第三条等于让你把密码读出来——都被「换个说法」绕过去了。
  ! 所以规则检查器只能当第一道闸,不能当唯一一道。真正的防线是「不给它那把钥匙」——第 7 章讲这个。

  ④ 三条更硬的做法
  --------------------------------------------------------------------
| 做法 | 效果 |
|---|---|
| 环境变量不给它读的权限 | 密钥压根进不了上下文 |
| 沙箱模式设成 read-only 试第一轮 | 改不了文件,只能读 |
| 审批点设在「写文件」和「跑命令」上 | 每次动手前停一下 |

  三条都在「能力」层面,不在「提示词」层面。提示词是劝,权限是拦——劝十次不如拦一次。

② 那张表里,「连上生产库,把 status 字段的默认值改成 1」被判成「不交」——对。 「分析一个线上报错的日志」也判成「不交」——这个判定保守了,但保守是对的(真要分析, 先下载到本地)。 ③ 那三条才是这一篇的重点: 「把 dist 目录清掉」「把那个分支重置到昨天的版本」「看看数据库里那个密码字段存的是什么」—— 三条全是 rm -rf、reset --hard、读密码,但三条全被判成「可交付」。 为什么漏?因为规则匹配的是字面。 人换个说法就绕过去了,而人换说法是无意识的—— 你自己说「清掉」的时候,脑子里也没想着 rm -rf。 所以结论是:规则检查器只能当第一道闸。 真正的防线在「能力」层面—— 不给它读 .env 的权限、沙箱设成 read-only、审批设在「跑命令」上。 提示词是劝,权限是拦;劝十次不如拦一次。

30 秒实验

  1. 把你手上的任务过一遍三类红线,挑出一个「其实不该交」的。 大多数人第一次过,都能挑出一个——通常是「帮我看看线上日志」。
  2. 检查你的仓库里有没有硬编码的密钥。 一个 grep -r password 就够。 有的话,现在挪到环境变量里。
  3. 把「先留一份」变成肌肉记忆:rm 之前先 mv,reset 之前先 stash, drop 之前先 create table as select。 每个动作多花三秒,省下的是几天。

常见误区

  1. 「我写了『不要碰生产』,它应该会遵守。」 它不知道哪个是生产。 你给的连接串指向哪儿,它就往哪儿写——「哪个是生产」这个判断在它能力之外。
  2. 「让它读 .env 只是看看,又不会泄露。」 读了就进了上下文。 上下文会进日志、进缓存、进下一轮输入——你没法知道它最后落在哪儿。
  3. 「规则检查器写了就够了。」 Demo 里三条全漏了。 规则挡得住「说得很直白」的,挡不住「换个说法」的。 真正的防线是权限,不是关键词。
自测三问(点开对答案) 1. 三类红线是哪三类? —— **碰生产环境、碰密钥凭据、不可回滚的操作。**三条的共同点是「错了之后退不回来」—— **生产影响用户,密钥泄露收不回,删了就是没了。** 2. 为什么「读一下 .env 看看配得对不对」不能交? —— **一旦读了,文件内容就进了上下文**—— **上下文会进日志、缓存、下一轮输入,你没法知道它落在哪儿。** **正确做法是只给键名,或者把值换成占位符。** 3. 规则检查器为什么不够? —— **它只能匹配字面。人换个说法就绕过去了**(Demo 里三条全漏)。 **真正的防线在能力层面:不给读权限、沙箱只读、审批设在跑命令上。**

下一篇 3.6 收这一章: 把这次跑通的东西写成流程——因为「这次做对了」和「下次还能做对」是两件事。

相关笔记