From 0f79d266a7c9b933026ed72c2ec8c7a94c8f9cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Thu, 1 Oct 2026 12:47:46 -0700 Subject: [PATCH] docs: whether a driver belongs in the URL, and where each layer gets its name Four domains run some tool underneath. Two name it in the URL and two do not, and nothing said which was right, so the provider tree, the API directories and the agent processors each answered it differently. The question is whether the caller chooses the tool or the host does. A caller chooses a container runtime, so /container/docker names it and Podman can sit beside it. A caller does not choose a package manager, so /package hides apt, because a fleet-wide install cannot require knowing which hosts run Debian. /ntp and /schedule follow the second shape: chrony and cron are behind the entrypoint, swappable without the caller caring. The second section records where each layer takes its name from, which is always the URL. The API layer is flat, one directory per first segment with the second segment as a filename prefix, which is what network already does and what the container handlers do not. The provider tree is the deliberate exception. It nests by implementation so a second driver is a new directory rather than scattered files, and it is therefore allowed to be deeper than the URL. Refs osapi-io/osapi#566 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FuKUsHFG1EqZXamffh9M2c --- components/osapi/domains.md | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/components/osapi/domains.md b/components/osapi/domains.md index 3f3ab66..288b2bb 100644 --- a/components/osapi/domains.md +++ b/components/osapi/domains.md @@ -106,6 +106,53 @@ or a `key:value` label selector. `IsBroadcastTarget` in `internal/job/subjects.go` decides which, and **it has one implementation.** A domain must not write its own target parser. +## Whether the driver is in the URL + +Most domains are implemented by some tool. `package` runs apt, `ntp` runs +chrony, `container` runs Docker, `schedule` writes crontab entries. Whether that +tool appears in the URL comes down to one question. + +**Does the caller choose it, or does the host?** + +A caller chooses a container runtime. Running Docker rather than Podman is a +decision somebody made and wants to address directly, so the runtime is a path +segment: `/container/docker`. Adding Podman adds `/container/podman` beside it, +and both can exist on one host. + +A caller does not choose a package manager. The host already decided, and asking +a fleet to install a package cannot mean knowing which of them run apt. So the +tool is absent: `/package`, with the provider picking apt or anything else by OS +family. `/ntp` is the same, with chrony behind it today and room for another +driver later at the same entrypoint. `/schedule` likewise: cron now, possibly +`at` later, and the caller should not have to care which. + +Getting this backwards in either direction costs something real. A tool in the +URL that the caller did not choose makes a fleet-wide call impossible. A tool +missing from the URL that the caller did choose makes two runtimes on one host +unaddressable. + +## Each layer takes the name from the URL it serves + +Once the URL is settled, nothing below it invents a name. + +| Layer | Takes its name from | `/container/docker` | `/network/dns` | +| --------------------- | ------------------- | ------------------------ | ---------------------- | +| API handler directory | the first segment | `api/node/container/` | `api/node/network/` | +| API handler files | the second segment | `docker_create.go` | `dns_get.go` | +| agent processor | the first segment | `processor_container.go` | `processor_network.go` | +| SDK service | the last segment | `client/docker.go` | `client/dns.go` | +| CLI command | the path | `node container docker` | `node network dns` | + +The API layer is flat. A domain gets one directory named for the first segment, +and the second segment is a filename prefix inside it rather than a +subdirectory. + +The provider tree is the exception, and deliberately. It nests by what +implements a thing, so a second driver is a new directory beside the first +rather than a scattering of files: `provider/container/docker` and, when it +exists, `provider/container/podman`. That tree may therefore be deeper than the +URL, which is how `provider/network/netplan/dns` serves `/network/dns`. + ## Broadcast is not optional Every operation under `/node/{hostname}/...` supports broadcast targeting, and