上禮拜五下午,我發現我某間顧問公司的正式環境 AWS 帳號,被一位 UI/UX 設計師用 Claude Code 開出了一整套基礎設施,而他講不出來他到底開了什麼。
事情的開頭一點都不戲劇化。Slack 跳出一個訊息,是團隊裡一位設計師 — 有前端底子、git 不陌生、上禮拜剛把 Claude Code 裝起來、正在興頭上到處東敲西搗的那種設計師 — 說他把一條新產品線的系統 repo 寫好了,能不能幫他 review。訊息底下貼了 GitHub repo 連結,幾分鐘後又補一段:兩個 staging 網址,前台一個、後台一個,後面接著後台的 admin 帳號密碼,整段就這樣明文躺在對話框裡,像在分享一首歌的連結。
我沒急著去看 repo。我盯著那兩個 staging 網址看 — 這環境哪來的?於是我問了一句,事後證明這是整個下午唯一問對的問題:
這個 AWS 誰開的?
「我開的。」
「你自己的?」
「公司的。」
在一個小團隊裡混到會被人丟 infra 來 review 的位置,看到有人說「我在公司的 prod 帳號開了東西」,心裡會有個聲音輕輕地響:等等。我把那個聲音放大,繼續問下去:你直接 terraform apply 嗎?你知道公司 AWS 是上了 IaC 的吧,state 跟 code 都在公司管的範圍裡,你直接動資源,會跟 AWS Config 脫鉤的吧。
他的回答堪稱本世代工程師的經典辯詞:
我的改動 100% 在 git / PR 裡,沒在 AWS console 點過任何東西。
這句話技術上可能完全是真的。就像「我沒有開槍,我只是扣了扳機」技術上也是兩件不同的事一樣。
問題是「有沒有點 console」從來就不是 IaC 的重點 — 這是一個會讓人盯著螢幕嘆氣的誤會。IaC 的重點只有兩件事:state 在哪、source of truth 在哪。你在自己電腦上跑 terraform,state 就在你的硬碟裡、code 在你 local 的 repo 裡,從公司 IaC 的角度看,你開的這一整套東西是憑空長出來的、是不存在的、是下次有人跑 terraform plan 時會被當成 orphan resource 一鍵清掉的孤魂野鬼。你以為你「有用 git 很乖」,但 git 管的是你那份 code,沒人把你的 state 接回公司的閉環 — 那不叫 IaC,那叫用 terraform 寫的 shell script。
但這些都還是小事。真正讓那個「等等」變成警報的,是下一句。
我繼續追問,想請他列出他到底開了哪些東西。他開始講,講到一半我意識到他自己也不知道 — 「應該有一個資料庫」、「Route53 我好像有設」、「IAM 我記得只開一個吧」。每一句都帶著「好像」、「應該」、「我記得」。
再追下去,真相浮出來:是 Claude Code 跑的。
他把目標跟 credential 餵給 Claude Code,Claude Code 寫 terraform、跑 apply,他在旁邊等 staging 網址跳出來。中間那個 plan — 那個會白紙黑字列出「我即將對你的 prod 帳號做這 N 件事,要繼續嗎 (yes/no)」的 plan — 他按了 yes。每一次都按 yes。看都沒看的那種 yes。
這裡有一層比「他不懂 infra」更該停下來的事:他也不懂那個替他幹活的 AI。他不知道 agent 為了讓事情跑通,會順手把 IAM 開到 *;不知道它會默默從零蓋起一整座機房,而不是先問一句「公司是不是已經有了」;更不知道那個他一路按 yes 跳過去的 plan,是這整條流程裡唯一一個還攔得住他的 safety surface。他對 infra 一無所知,對手上這個 agent 也一無所知 — 雙重的不懂。
然後最讓人坐立難安的事情來了:東西做完了。staging 跳出來了,網址會動、後台進得去、demo 給得出來。一個既不懂 infra、也不懂 AI 的人,用一個他不理解的工具,生出了一套看起來完全正常的正式環境。在那一長串「他不懂」的後面,跟著一個更刺眼的事實 — 可是它就是成立了。
於是這家公司的 prod 帳號裡,現在有一組資源,連開它的人都說不清楚是什麼。可能有開給全世界的 endpoint,可能有為了讓事情跑通而給到 * 的 IAM policy(agent 最愛這味,反正卡住不如全開),可能有一顆從上禮拜就在默默燒錢的 NAT Gateway,也可能 — 什麼問題都沒有。
你看出那個地獄了嗎?不是「出大事了」。是我沒辦法證明沒出事。在他按下 enter、到我們把整套東西盤完之前,那座機房同時處在「災難現場」和「歲月靜好」兩種狀態 — 一個完美的量子疊加態,薛丁格的機房,而我是那個被迫要去開盒子的衰人。
他失去的其實不是知識。是對自己幹過的事的可解釋性。事情真出了,他沒辦法協助調查,因為他自己也是從外面看的觀眾;他從一個 actor,退化成了一個 witness。
我列了一張清單。清單上的每一項,都不是「一定壞掉」,而是「我無法排除」:
Drift — 公司 IaC 哪天一跑,把他的資源當孤兒砍掉,或反過來砍到旁邊正在服役的東西。安全 — 他開的 IAM、Security Group、Route53 record 沒有任何人 security review 過,那個 * 到底開到多大沒人知道。Compliance — AWS Config 跟 Security Hub 大概已經在後台默默累積 finding,因為這些資源沒有 owner tag、沒有 stack reference、沒有任何身分證。成本 — 沒有 cost allocation tag,月底帳單會多一塊對不上來的數字,而你連它對應到哪個產品都說不出來。可重現性 — 他哪天離職、電腦進水、credential 被 rotate 掉,這整套環境就跟著陪葬,沒有第二個人能重建。
五項裡面沒有一項是「已知的壞」,全部都是「未知」。而做 infra 的人都知道,已知的壞不可怕 — 你可以排 sprint 修它;真正讓人半夜睜眼的是未知,因為你連風險的邊界畫在哪裡都不知道。所以我沒有停在猜,我要他停手、保留現場。
我寫給他的第一句話是「先停一下,這個比 code review 優先」。不是擺架子 — 在 infra 還沒對齊之前去 review 他的 code,等於在一棟不知道蓋在誰家地皮上的房子裡挑窗簾顏色。
然後我要他保留所有 artifact:local 的 .tf、terraform state、還有最關鍵的那個 — Claude Code 的對話紀錄。
讓我把這個荒謬念出來:在這整起事件裡,「一個人類到底做了什麼」這個問題,最準確、最可靠、最不會說謊的紀錄來源,是那個 AI 的 chat log。誰開的?問 agent。開了哪些資源?問 agent。當初為什麼這樣開?還是問 agent。那個一路按 yes 的人類呢?喔,那個人類也站在旁邊,跟我們一起問 agent。我們現在得靠 agent 的逐字稿,來考古它的人類操作員上禮拜在想什麼 — 這是什麼賽博龐克的職場?
我特別沒寫的一句話是「以後不准用 agent」。寫了的話他學到的會是「agent 是壞東西」 — 一個錯得徹底的結論。會出事的從來不是那個工具。
盤點花了一天多。然後 — 說來有點掃興 — 盒子打開了,貓沒死。
技術上的傷害基本是零。他整套東西蓋在公司主要 region 以外的另一個 region,而 AWS 的網路、資料庫、容器、機密管理全是 region 性的資源,跨 region 天然隔離,他那座新機房根本碰不到主系統。事實也證明了:它在 staging 默默跑了一個多禮拜,主系統連個噴嚏都沒打。唯一真正共用的是 DNS zone,而他寫進去的幾條測試網址,名字跟既有服務剛好都沒撞。
如果我停在前面那段量子疊加的緊張感,這會是一篇「我們差點完蛋」的驚悚片。但盤點報告攤在桌上,我得誠實承認:沒有差點完蛋。擋住一切的是 region 邊界,是運氣,不是任何人的英明。
可是同一份報告,撈出了三件比「災難」更耐人尋味的事。
第一件:他在另一個 region 從零蓋了一座 VPC、一套容器叢集、一個資料庫、一條 CI/CD、一份獨立的 IaC repo — 一座功能完整、隔離良好、乾乾淨淨的殖民地。而母國本來就有一座一模一樣的城市,共用的容器叢集、共用的資料庫、共用的 ALB,所有應用本來都該掛上去。只是沒有人告訴這位拓荒者母國的存在,也沒有人告訴那個替他開疆闢土的 agent。agent 把這座殖民地蓋得無懈可擊 — 它唯一的問題,是這座城市根本不需要存在。
第二件:他規劃的正式網址跟公司既有服務太像。技術上不會撞,但行銷文宣、內部溝通、客服對話裡,沒有人分得清哪個是哪個 — 一種純粹靠命名製造出來的精神內耗。
第三件,也是讓有潔癖的人最痛的:公司現在有兩套 IaC,分屬兩個不同的 GitHub 組織、state 存在兩個不同的後端,一個在 Terraform Cloud、一個在 S3。想知道公司到底有哪些資源,你得查兩個地方。有兩個 source of truth,是一種很有禪意的狀態 — 它的意思其實是,你沒有 source of truth。
這三件事,沒有一件是 agent「犯錯」。它忠實地、高效地、甚至比很多資深工程師都認真地,完成了交辦的任務。問題是任務本身就是錯的,而沒有任何人 — 包括下指令的那個人 — 有足夠的視野看出它錯了。
講到這裡得補一個我自己也不太想承認的細節。
我是事後才知道,公司 AWS 的 root account,老闆早就直接發給員工了。一個平常把 state backend、把「source of truth 到底在哪」掛在嘴邊念經的人,連這家公司 prod 的 root 在誰手上都不知道 — 我那張自以為很熟的權限地圖,跟真實的權限地圖,是兩張不同的圖。我不在那個 IAM 的 control loop 裡,這條紅線本來早該有人拉好,而我大概是最沒資格說「不關我的事」的那個人。
但比 root 亂發更安靜、更值得想的,是另一個破口:那位設計師根本沒有任何辦法「發現」公司已經有一套現成的基礎設施可用。沒有一個地方會告訴他「這些你不用自己蓋」。權限的洞會觸發警報,discoverability 的洞不會 — 它只會讓人安安靜靜地重造一個輪子,然後為自己的生產力感到很驕傲。
而這一切之所以可能,是因為一道閘門悄悄地被拆了。
在 Claude Code 之前,要對著 prod AWS 跑 terraform apply,你至少得先是一個會寫 terraform 的人。那個「你得先會」本身就是一道閘門 — 它又醜又慢、勸退過無數人、從來沒被當成什麼資安機制 — 但它就是擋著。能走到 apply 那一步的人,多少懂自己在 apply 什麼。
你可能會想,好吧,就算他不懂 infra,至少總得懂手上那個 agent 吧 — 知道它什麼時候會亂開權限、什麼時候會自作主張、那個 plan 為什麼非看不可?也沒有。連「你得先懂這個工具」這道理應存在的第二層閘門,都一起不見了。用 AI 不需要懂 AI,就跟動 infra 不需要懂 infra 一樣 — 兩件事在同一個下午、同一個人身上,同時成立。
兩道閘門都拆了。一個會 Figma、會切版、上禮拜才裝好 Claude Code 的設計師,就能跟公司的 prod 帳號平起平坐,用中文描述意圖,按幾個 yes,得到一座機房。他不是這個故事的反派 — 他只是那扇再也沒有鎖的門後面,第一個走進來的人。
後面還有第二個、第三個。
事情的結局無聊得很:改掉命名、把那套 IaC 收回來統一管、資源實體一個沒動、零停機、沒有 incident、沒有人離職、沒有資料外洩。無聊到我幾乎要懷疑自己上禮拜五在緊張個什麼勁。
那個 agent 自始至終沒做錯任何一件事。它讀懂了需求、寫對了 terraform、把 staging 跑起來了。它做的唯一一件事,是把一個根本不該存在的東西,蓋得又快又好 — 替一個既不懂它、也不懂自己在蓋什麼的人。
讓我半夜睜著眼睛的不是這次。是這次擋住災難的,是 region 邊界,是一個跟判斷力跟流程都無關的物理事實 — AWS 的資源剛好分區。下一次那道邊界不一定在原地。而那個設計師、那個 agent、那扇沒鎖的門,全都還在。
至於怎麼把閘門蓋回去 — 我自己公司現在做的剛好就是這件事,但那是另一篇的故事了。今天先讓我去做一件更急的:去查清楚,那家公司的 root,現在到底在誰手上。