You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(gitops): scope credential walker, harden state and retries
Ports the bug fixes landed in gitops-mudflap to this repo. The push
pipeline had a class of bugs that surfaced as cryptic POST validation
errors and silent state corruption.
src/credentials.ts
Rewrite credential resolution to walk only `credentialId` and
`credentialIds` keys instead of every string in the payload. The old
walker swapped any string matching a credential-name slug with its
UUID, which collided with provider enum values like `openai`,
`langfuse`, `11labs`, `cartesia` — those appear in `model.provider`,
`voice.provider`, `voice.fallbackPlan.voices[].provider`, and
`observabilityPlan.provider`, all of which the API enforces as enums
on POST. PATCH silently tolerated the UUID-replaced fields, which
hid the bug for resources that already existed.
Also add a plain-object guard (Date/Map/Set/Buffer pass through) and
a WeakSet to short-circuit cycles.
src/state.ts
Atomic write via tmp file + rename so a crash mid-write leaves the
prior state intact instead of truncating it. Loud throw on JSON
parse error: silently falling back to an empty state would cause
the next push to recreate every remote resource as new, duplicating
the entire org.
src/push.ts
Wrap the apply body in try/finally so saveState always runs. If a
5xx kills the run after a few resources got UUIDs from the API, we
still record them locally — otherwise the next run creates duplicates.
src/cleanup.ts
Double-gate destructive cleanup: --force now also requires
`--confirm <env>` matching VAPI_ENV. Refuse to run if the state
file has zero tracked resources (almost always a fresh clone or
bootstrap-not-run, where deletion would wipe the org).
src/pull.ts
Preserve `null` values in cleanResource — `null` is the API's way
to express "this field is intentionally cleared", which is different
from "field absent". Stripping it caused round-trip drift.
Switch git status parsing to `--porcelain -z` so filenames with
spaces, quotes, or newlines parse correctly.
src/api.ts
Extend the retry loop to cover 5xx responses (transient gateway
errors, deploys in progress) in addition to 429. A single 502
shouldn't force the operator to re-run the whole push.
src/resources.ts
Sort directory entries before iteration so push order is stable
across filesystems (APFS sorts, ext4 doesn't). Non-deterministic
ordering makes duplicate-resourceId bugs hard to reproduce.
.gitignore
Add .claude/ (local agent lock state).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments