Enforce automation length caps at the CLI boundary, not on stored rows - #2219
Closed
SawyerHood wants to merge 2 commits into
Closed
Enforce automation length caps at the CLI boundary, not on stored rows#2219SawyerHood wants to merge 2 commits into
SawyerHood wants to merge 2 commits into
Conversation
SawyerHood
force-pushed
the
fix/2166-automation-cap-validation
branch
from
August 24, 2026 23:29
a4c8dc2 to
ee868a4
Compare
`bb automation create/update` built agent and script executions from argv without the request-side Zod caps the RPC route applies, so an over-cap `--prompt` was persisted and only rejected when the stored row was re-parsed for the response. Because the same capped schema also parsed stored rows, every later `list`, `show`, and repairing `update` for that project failed with the same `too_big` issue. - Parse agent executions and partial agent updates in the CLI with the same request schemas the RPC route uses, and parse inline/file script content with the shared script cap, before anything is persisted. - Split request policy from the stored/response shape: the prompt, script, and scriptFile caps now live only on the request schemas, so rows that already exceed a cap stay readable and repairable. - Make `service.list` skip a malformed row with a warning, like overview. Fixes #2166 Co-Authored-By: Claude <noreply@anthropic.com>
PR #2219 closed the #2166 write-then-fail mechanism on the execution column but left it intact on the trigger column, so the class the PR claims to close was still open one field over. `automationScheduleTriggerSchema` carried the cron and timezone caps and was simultaneously the RPC request shape and the stored-row parser (`parseAutomationTrigger`, used by every read: list, show, update, pause, resume, and the sweep). `buildTrigger` handed an unparsed value straight to `service.create`/`service.update`. A valid but over-cap `--cron` (60 comma-separated minutes is 177 characters and parses fine) was therefore committed, then rejected on read: `create` exited 1 with the row already written, `show`/`pause`/`resume` and any later `update` exited 1, `list` silently omitted the row through the try/catch this PR added, and the sweep logged "invalid stored configuration" every tick forever. Updating a healthy automation with an over-cap cron poisoned it the same way. The RPC route rejected the same input before the write, so the CLI and the route disagreed on policy. - Remove the caps from the stored trigger shape so an already-persisted over-cap row stays readable and repairable, matching the execution shape and the comment at rpc-types.ts. - Add `automationTriggerRequestSchema` (the schedule variant plus the caps; the one-shot variant carries no string and is unchanged) and compose it into `createAutomationInputSchema` and `updateAutomationInputSchema`, so the RPC routes keep rejecting pre-write. - Parse in `buildTrigger` with that request schema, so argv is held to the same policy as the route before anything is persisted. The timezone cap is unreachable through the CLI in practice, because no valid IANA name is anywhere near 100 characters; it is asserted at the schema level only. Co-Authored-By: Claude <noreply@anthropic.com>
SawyerHood
force-pushed
the
fix/2166-automation-cap-validation
branch
from
August 25, 2026 01:06
ee868a4 to
15482ec
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
bb automation createandbb automation updatebuilt the agent and script execution payloads from argv and handed them straight to the service, skipping the request-side Zod length caps that theautomations_create/automations_updateRPC routes apply. An over-cap--prompt(8,039 chars against the 8,000 cap) was therefore persisted, and thetoo_bigerror the user saw came from re-parsing the stored row for the response. Because that same capped schema (automationAgentExecutionSchema) was also used to parse stored rows, every laterlist,show, and repairingupdatefor the project failed with the sametoo_bigissue, andlisttook the healthy automations in the project down with it. Report: https://get-bb.github.io/reports/issues/2166.htmlWhat changed
The length caps were request policy applied in the wrong place. The same Zod schemas that parse incoming create/update input also parse the stored
executionandtrigger_configcolumns, so an over-cap value that got past the CLI was written and then made the row unreadable on every subsequent read.automationAgentExecutionSchema,automationScriptExecutionSchema, andautomationScheduleTriggerSchemano longer carry the prompt, script, scriptFile, cron, or timezone caps. New*RequestSchemavariants (automationAgentExecutionRequestSchema,automationScriptRequestSchema,automationTriggerRequestSchema) add the caps back and are whatcreateAutomationInputSchema/updateAutomationInputSchemacompose, so the RPC routes still reject over-cap input before any write. A row that already exceeds a cap now stays readable bylist/showand repairable byupdate.bb automation create/updatebuilds its execution and trigger from argv and calls the service directly, bypassing the route schemas.buildExecution,buildAgentExecutionUpdate, andbuildTriggernow parse with those request schemas, so an over-cap--prompt,--script, or--cronis rejected before anything is persisted, and the CLI and the RPC route agree on one policy.service.listskip a malformed row with a warning, likeoverviewalready did, so one bad row cannot fail the whole project listing.The one-shot trigger variant is unchanged (it carries no string). The timezone cap is unreachable through the CLI in practice — no valid IANA name approaches 100 characters — so it is asserted at the schema level only.
How you verified
Twelve regression tests across two blocks in
plugins/automations/src/automations.test.ts; each behavior test was run against the pre-fix source and fails there (6 execution-cap tests, 5 of 6 trigger-cap tests — the sixth is a guard asserting the over-cap cron is itself valid, so the others cannot degrade into "invalid cron rejected").pnpm exec turbo run test --filter=bb-plugin-automations --force— 5 files, 78 passed.pnpm exec turbo run build typecheck lint(repo-wide) — 92/92 tasks.node scripts/check-provider-literal-ratchet.mjs --base origin/main— 18 references across 8 core files, all allowlisted.scripts/bb-dev-appinstance: an over-cap--prompt(8039 chars) and an over-cap--cron(177 chars, valid 5-field expression) each exit 1 withtoo_bigand write no row; an over-cap--crononupdateleaves the stored trigger byte-identical; a row seeded with a 177-char cron is listed, shown, renamed, paused, resumed, and repaired, all exit 0; the sweep advances that row and claims a scheduled run instead of logginginvalid stored configurationevery tick.automations_createreturns HTTP 400invalid_inputwithpath: ["trigger","cron"]and withpath: ["execution","prompt"], and the automations table row count is unchanged after both.No server↔daemon wire contract changed, so
HOST_DAEMON_PROTOCOL_VERSIONis unchanged. No new CLI flag, command, or configuration knob, so no guide or skill surface needed an update.Fixes #2166