docs(draft): correct the stale "backup schedules are not exposed by the API" claim (#72)

`draft.ts` still told the operator that a database's backup schedule "is
not exposed by Coolify's API" and is "create-time-only in cast" — in the
`backup` uncaptured flag, its comment, and the NO_API_COVERAGE table. #51
disproved both: `GET /databases/{uuid}/backups` answers, and `diff` and
`apply` now read and write it.

The audit (#72) flags this as the #51 failure mode repeating — a defect
filed as a limitation does not get fixed. semantics.md was already
corrected when #51 landed; this brings draft.ts's three copies of the old
claim in line with it.

What is still true, and now said accurately: the DRAFT path
(`inventory --emit-draft`) does not yet read that route, so no `backup:`
block is captured and a rebuild from a draft still has no backups until
the operator declares one — not because the API cannot express it.

Text-only; no behavior change. `npm run check` clean, tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude-hdb 2026-07-16 14:56:14 +00:00
parent e3e52680e1
commit b560317da0
2 changed files with 9 additions and 7 deletions

View file

@ -585,13 +585,15 @@ function databaseSpec(
`image "${image}" — no version could be read from its tag, so none was written and \`apply\` would create this database on Coolify's default image.`, `image "${image}" — no version could be read from its tag, so none was written and \`apply\` would create this database on Coolify's default image.`,
); );
} }
// Coolify exposes no backup schedule on a database's GET, so a `backup:` block // Coolify DOES expose a database's backup schedule — GET /databases/{uuid}/backups
// cannot be recovered. It is create-time-only in cast (see README's known // answers, and `diff`/`apply` read and write it (#51). What the DRAFT path cannot
// limitations), so a rebuild from this draft would come up with NO BACKUPS — // yet do is CAPTURE it: `inventory --emit-draft` does not read that route, so a
// the quietest possible loss, and the one you discover at the worst moment. // `backup:` block is not recovered here. Until it is taught to, a rebuild from
// this draft still comes up with NO BACKUPS — the quietest possible loss, and the
// one you discover at the worst moment — unless the block is declared by hand.
flag( flag(
"backup", "backup",
"backup schedules are not exposed by Coolify's API and are NOT in this draft. If this database is backed up, a rebuild from here would not be. Check the Coolify UI (Backups tab) and declare `backup: { frequency, retention }` yourself.", "backup schedules are NOT in this draft — `inventory --emit-draft` does not yet read `GET /databases/{uuid}/backups` (which `diff` and `apply` do, #51). If this database is backed up, a rebuild from here would not be until you declare it. Read the schedule from a `cast diff` or the Coolify UI (Backups tab) and set `backup: { frequency, retention }` yourself.",
); );
return { type, ...(version ? { version } : {}) }; return { type, ...(version ? { version } : {}) };
} }
@ -798,7 +800,7 @@ const NO_API_COVERAGE: Array<[string, string]> = [
], ],
[ [
"backup schedules", "backup schedules",
"a database's backup config is not exposed on its GET. A rebuild from this draft has NO backups until you declare them.", "the API exposes them (`GET /databases/{uuid}/backups`, which `diff`/`apply` use — #51), but `inventory --emit-draft` does not yet read that route, so no `backup:` block is captured. A rebuild from this draft has NO backups until you declare them.",
], ],
[ [
"database kinds cast does not model", "database kinds cast does not model",

View file

@ -352,7 +352,7 @@ describe("cast inventory --emit-draft (#27)", () => {
expect(md).toContain("destination_id 3"); expect(md).toContain("destination_id 3");
expect(md).toContain("legacy-analytics"); // a MySQL cast cannot model expect(md).toContain("legacy-analytics"); // a MySQL cast cannot model
expect(md).toContain("custom_labels"); // Basic Auth / Traefik labels expect(md).toContain("custom_labels"); // Basic Auth / Traefik labels
expect(md).toContain("backup"); // not exposed by the API expect(md).toContain("backup"); // API exposes it, draft doesn't capture it yet (#51)
expect(md).toContain("legacy.flag"); // not a name a template can hold expect(md).toContain("legacy.flag"); // not a name a template can hold
// And the standing sections, emitted on every run whatever was found: // And the standing sections, emitted on every run whatever was found: