management: config presence authorises a production store deploy; 56 dispatches of one commit observed #79
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Observed while checking whether the new checks workflow fired on a pull request. Filed with the attribution unresolved — the evidence is solid, the cause is not, and guessing would be worse than saying so.
What was measured
/actions/tasksshows 57deployruns for the single commitd0b58259— 56 triggered byworkflow_dispatch, 1 by thepushthat merged it. Of those, 36 cancelled and 21 succeeded.They arrive in bursts:
Each success is a real
wrangler pages deploy apps/store/out— a production release of the storefront. So the live store was rebuilt and redeployed at least 21 times for one unchanged commit.The
cancel-in-progressconcurrency group is working as designed and is why most were cancelled; it collapses a burst rather than preventing one. The concurrency group is the mitigation, not the fix.Why this is a real defect and not just noise
lib/store/deploy.ts#requestStoreDeployis called by every inventory write path, by design: the store is a static export whose catalog is read at build time, so a published change is invisible until a rebuild. That reasoning is sound and is documented in the file.What is missing is any notion of which environment is allowed to dispatch:
if (!url || !token) return;. Configuration presence is the authorisation.STORE_DEPLOY_WORKFLOW_URLandSTORE_DEPLOY_TOKEN— a developer's shell, a dev server started from a worktree that inherited the environment, a test that forgot to point at a sink — dispatches a production deploy onref: "main", from a write to a non-production database.console.error, so nothing surfaces to the person who caused it.The content risk is low: the deploy builds from the production catalog API, so a dev-database row cannot reach the live site through this path. The risk is that a non-production action causes a production release, invisibly, and that nothing in the code distinguishes the two.
Attribution, stated honestly
Not established. At the time of filing, no
apps/management/.envin the default checkout or in any of the four live worktrees containsSTORE_DEPLOY_WORKFLOW_URL, so the obvious explanation does not hold. Candidates not ruled out:.envis gitignored and several were created and destroyed during recent workDo not treat the count as proven waste until this is resolved. It is proven exposure either way.
Scope
requestStoreDeploy. PR #68 and PR #78 both added rejections; if a rejection still queues a build, that is a burst source with no cause.console.erroron failure and silence on skip means nobody learns they nearly released. At minimum log the reason and the environment.ref: "main"is right. A dispatch from a non-main context still deploysmain, which is the surprising part of the current shape.Not this issue
cancel-in-progressconcurrency group. It is correct and should stay.deploy.tsand was deliberate when price and availability became public.Verification
buy_price, per PR #68's matrix) and assert no dispatch is queued.PATCHthat changes nothing) and assert no dispatch is queued./actions/tasksafterwards and confirm the dispatch rate for an unchanged commit falls to zero.Acceptance
A non-production process cannot dispatch a production deploy even with the URL and token present; a rejected or no-op write queues no build; a declined dispatch is logged with its reason; and the dispatch-per-write ratio is measured rather than assumed.