draft doesn't capture service hostnames — teach --emit-draft the per-service GET (sibling of #75) #83

Closed
opened 2026-07-16 15:57:16 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-16 15:57:16 +00:00 (Migrated from github.com)

Summary

#73/#81 made a service's per-container hostnames settable (urls) and readable (GET /services/{uuid}applications[].fqdn), and diff/apply now carry them as service_domains. The draft path was not brought along.

The inventory sweep reads the environment list (GET /projects/{uuid}/{env}), which eager-loads services but not service.applications (ProjectController@environment_details, v4.1.2), and it does not make the supplementary per-service GET. So --emit-draft emits a service with no hostnames — a drafted service that serves analytics.example.com today comes back serving none, until a human declares service_domains by hand.

This is the exact shape of #75, one resource type over: the API answers, the sweep has not been taught to ask. #81 says so honestly rather than papering over it (serviceSpec's UNCAPTURED row and the NO_API_COVERAGE row both spell it out), but it is a gap worth closing — and closing it is what makes a drafted blueprint actually rebuildable.

What to do

  • --emit-draft: per drafted service, GET /services/{uuid} and emit service_domains from applications[].fqdn
  • Reuse attachServiceDomains' projection + canonicalizeServiceDomains (cli.ts) rather than writing a second one — draft and diff must agree on the shape, or a drafted manifest diffs dirty the moment it is applied
  • Keep an UNCAPTURED entry only for what genuinely cannot be answered (a service whose GET is unreadable/unrecognized — attachServiceDomains already fails closed there; the draft path likely wants to report rather than abort a whole-instance sweep)
  • Delete the service_domains (hostnames) uncaptured row and the service hostnames NO_API_COVERAGE row once captured, and correct the matching semantics.md line (the one that currently reads "…but inventory --emit-draft does not yet make the per-service GET")

Worth deciding once, for both this and #75

Both add one supplementary GET per resource to a verb that walks every project on the instance — a very different cost profile from diff/apply, which are scoped to one project+environment and where the reads are already gated (opts.backups / opts.serviceDomains in fetchLive). Whatever gating/parallelism answer #75 picks for databases should almost certainly be the same one here for services, which is why these two may be better done together than separately.

Found in #72; falls out of #81 (which fixed the write/read/diff half).

## Summary #73/#81 made a service's per-container hostnames settable (`urls`) and readable (`GET /services/{uuid}` → `applications[].fqdn`), and `diff`/`apply` now carry them as `service_domains`. **The draft path was not brought along.** The inventory sweep reads the environment list (`GET /projects/{uuid}/{env}`), which eager-loads `services` but **not** `service.applications` (`ProjectController@environment_details`, v4.1.2), and it does not make the supplementary per-service GET. So `--emit-draft` emits a service with **no hostnames** — a drafted service that serves `analytics.example.com` today comes back serving none, until a human declares `service_domains` by hand. This is **the exact shape of #75**, one resource type over: *the API answers, the sweep has not been taught to ask.* #81 says so honestly rather than papering over it (`serviceSpec`'s UNCAPTURED row and the `NO_API_COVERAGE` row both spell it out), but it is a gap worth closing — and closing it is what makes a drafted blueprint actually rebuildable. ## What to do - [ ] `--emit-draft`: per drafted service, `GET /services/{uuid}` and emit `service_domains` from `applications[].fqdn` - [ ] Reuse `attachServiceDomains`' projection + `canonicalizeServiceDomains` (cli.ts) rather than writing a second one — draft and diff must agree on the shape, or a drafted manifest diffs dirty the moment it is applied - [ ] Keep an UNCAPTURED entry only for what genuinely cannot be answered (a service whose GET is unreadable/unrecognized — `attachServiceDomains` already fails closed there; the draft path likely wants to *report* rather than abort a whole-instance sweep) - [ ] Delete the `service_domains (hostnames)` uncaptured row and the `service hostnames` `NO_API_COVERAGE` row once captured, and correct the matching `semantics.md` line (the one that currently reads "…but `inventory --emit-draft` does not yet make the per-service GET") ## Worth deciding once, for both this and #75 Both add **one supplementary GET per resource** to a verb that walks *every project on the instance* — a very different cost profile from `diff`/`apply`, which are scoped to one project+environment and where the reads are already gated (`opts.backups` / `opts.serviceDomains` in `fetchLive`). Whatever gating/parallelism answer #75 picks for databases should almost certainly be the same one here for services, which is why these two may be better done together than separately. Found in #72; falls out of #81 (which fixed the write/read/diff half).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/cast#83
No description provided.