I had a small reminder this week that AI-assisted development does not really change the old rule: if a human or an agent can edit a deployment path, the deployment path needs to prove the important thing still works.
The bug was not dramatic. A routing service sits behind a tiny Caddy gate because the upstream server has no auth of its own. Requests without ?key= should get 403; requests with a valid key should route.
That was already checked after deploy:
check 403 "without key" "https://$FQDN/route?$ROUTE"
check 200 "with key" "https://$FQDN/route?$ROUTE&key=$KEY"
Good enough for the live app. Not good enough for App Review.
The app also needs a separate review key. A reviewer opening a fresh install cannot use a key already typed into my own devices. So Caddy accepts two values for the same query param:
@authorized query key=LIVE_KEY key=REVIEW_KEY
The failure mode was easy to miss: a deploy could ship a Caddyfile that still accepted the live key but silently dropped the review key. The health check would pass. The app would still work for me. Then days later App Review would open the build, hit the first-run screen, and reject it.
That is the worst kind of infrastructure bug: green deploy, delayed failure, wrong human paying the cost.
The fix was nine lines:
# The key issued to Apple's Beta App Review, when this machine holds one.
# Absent file, no review key in play, nothing to check.
if [ -f .secret-review ]; then
check 200 "review key" \
"https://$FQDN/route?$ROUTE&key=$(cat .secret-review)" || ok=1
fi
No framework. No secret-management migration. Just make the deploy assert every key path that matters.
Claude co-authored this change, which is the bit that made it worth writing down. Not because the agent did something dangerous. Because agent-written code has the same problem as human-written code, only faster: it can make a local patch that looks right while missing the operational contract around it.
The useful pattern is simple:
- let the agent edit the boring deployment code
- make the deploy script test the real external behaviour
- fail before the broken state becomes somebody else's problem
For anything with AI in the development loop, I care less about whether the diff looks plausible and more about whether the system can prove the side effect survived.
In this case the proof is three HTTP codes:
without key -> 403
with key -> 200
review key -> 200
That is not a big security architecture. It is just a tripwire in the place I am guaranteed to step before shipping.
Top comments (0)