is_static stays create-time-only until Coolify serializes settings on a read — track the upstream fix, and make draft admit what it couldn't see #70
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:apply
scope:capture
scope:coolify-api
scope:fleet
scope:manifest
scope:secrets
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/cast#70
Loading…
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?
Summary
#68 / PR #69 settle cast's side of the
is_staticstory: Coolify 4.1.2 never returns the field on any read, so cast degrades it to create-time-only (staticNotCompared, warn-and-skip). This issue tracks the two things that outlive that fix:inventory --emit-draftsilently omitsstatic: trueand UNCAPTURED.md never says so.Why the field is unreadable (source-confirmed, v4.1.2 tag)
is_staticis not anapplicationscolumn — it lives onapplication_settings, reached via thesettingshasOne relation. Every API read serializes theApplicationmodel bare:GET /applications/{uuid}→removeSensitiveData→serializeApiResponse=collect($model)— emits only loaded relations, and nothing on any read path loadssettings(no$with, no->load('settings');$appendscarries onlyserver_status).PATCHresponds{"uuid": ...}even though its handler lazy-loadssettingsto write it./applications/{uuid}/settingsroute exists inroutes/api.php.openapi.jsonagrees: theApplicationresponse schema has nois_staticproperty.ConfigurationGenerator::getApplicationSettings, which the "Download config" button uses) is Livewire-only — the dashboard reads the relation directly through Eloquent, never through the API.Upstream
mainis identical as of 2026-07-15 — this is not fixed-and-awaiting-release.The upstream errand
Open a PR on coollabsio/coolify. Preferred framing: an additive
GET /applications/{uuid}/settingssub-route (mirrors the existing/envspattern; zero risk to existing consumers), over widening the main GET response (changes response shape for everyone).Odds look decent — external API PRs land there:
feat(api): add REST endpoints for destinations(pksorensen),fix(api): allow source commit build setting(vaguul — same shape as this),fix(parsers): populate docker_compose_domains for API-created Docker Compose apps(creazy231 — the sibling field from #68). Open-PR backlog ~30. And coollabsio/coolify#6044 showsis_staticAPI behavior is already on their radar.What changes in cast when it ships
Nothing, by design — PR #69's projection already handles a future Coolify that returns the field: a real boolean flows through
projectLiveFields,staticNotComparedstays unset, and the diff compares normally again. The work here is verification, not code: after the box's Coolify upgrades past the fix, adiffagainst a static app must show the field compared (no once-per-run warn) and still converge.The cast-side gap that stands regardless
draft.ts(~L506) emitsstatic: trueonly whenraw.is_static === true— on 4.1.2 the key is simply absent, so a drafted manifest of a live static app silently omits the flag, and UNCAPTURED.md does not list it. That breaks the draft's own contract ("an honest list of what it could not capture", #27). A reviewer approving the draft has no cue that the field even exists to lose; the #63 failure mode (static site rebuilt and run as a plain app) re-enters through the draft door.Fix: when the live read cannot see
is_static(thestaticNotComparedcondition) and the app is plausibly static (nixpacks/static pack with apublish_directory), UNCAPTURED.md must nameis_staticas unreadable-on-this-Coolify — check the box in the UI, not the draft.Checklist
--emit-draft: listis_staticin UNCAPTURED.md for apps whose live read couldn't see it (cast code, independent of upstream)diffcomparesis_staticagain (warn gone, converges) and closeRefs
is_staticdoes) · #27 (UNCAPTURED.md contract)docs/brain/STATE.mdTask 8 residuals (D-272 era)Status update from the #72 audit — the upstream errand is dead, and not because we ran it: upstream did it themselves.
Commit
34e6a6dd5("feat(api): add application settings to application endpoints", 2026-07-14) on coollabsio/coolifynextmakesGET /applications/{uuid}eager-loadsettingsand return the wholeApplicationSettingrow (minus ids/timestamps), plus adds 13 more settings fields to the create/PATCH allowlists. That is a superset of the sub-route this issue asked for. Maintainer confirmed the v4.2 targeting in coollabsio/coolify discussion #10823 ("This will be added to the next (4.2) version!"); our own duplicate attempts (coollabsio/coolify#10948 / #10949) were closed as redundant. The fork branches carrying theGET /applications/{uuid}/settingssub-route have been deleted.One correction to this issue's body: "Upstream
mainis identical as of 2026-07-15" was checked against the wrong branch — the fix had been sitting onnextsince 2026-07-14.nextis where v4.2 is assembled (coollabsio/coolify#10872).Updated checklist:
--emit-draft: listis_staticin UNCAPTURED.md for apps whose live read couldn't see it (cast code, still needed for as long as we run 4.1.2)Open the upstream PR— obsolete: upstream shipped it onnextas34e6a6dd5, a superset of the planned sub-routenextbranch, release train coollabsio/coolify#10872)diffcomparesis_staticagain (warn gone, converges) — note the real response shape is a nestedsettingsobject with ids/timestamps hidden, not a top-level field;projectLiveFieldswas written before this shape existed and must be checked against it, not assumed compatibleRemaining scope is the two unchecked items. Broader v4.2 upgrade prep (token abilities, OpenAPI re-vendor, settings as diffed fields) is tracked separately — see #72.
Closing — the cast-side work is done and the only remaining item is tracked in #77.
Checklist status:
--emit-draftnamesis_staticin UNCAPTURED.md when the live read can't see it — landed as50b0d2d,src/draft.ts:466-47534e6a6dd5onnext(a superset of the sub-route this asked for); our duplicates were closed as redundant#77's settings bullet carries it verbatim, including the sharp part: "
is_staticun-degrades (verify per #70's remaining checklist — the response shape is a nestedsettingsobject,projectLiveFieldspredates it)". Nothing is lost by closing here.Also worth recording that this issue's body is now misleading in one respect: "Upstream
mainis identical as of 2026-07-15" was checked against the wrong branch — the fix had been onnextsince 2026-07-14. That's already corrected in the comment above, but leaving it open with a stale premise and a done checklist reads as unfinished work when it isn't.Reopen if the v4.2 verification turns up something #77 doesn't cover.