specverb: optional base-url scheme, redirect-safe default client, Mount() path generation #88

Closed
opened 2026-06-07 02:23:00 +00:00 by coilysiren · 0 comments
Owner

Summary

Consumer-ergonomics pass on the specverb engine, surfaced while wiring the first real consumer (ward, ward#62). Three additive changes that move boilerplate out of the consumer and into the engine, so a consumer needs only the embeds + a TokenResolver, no hand-written mount glue.

Changes

  1. base-url scheme optional. A Guardfile base-url "forgejo.coilysiren.me/api/v1" should resolve to https://.... Build prepends https:// when the resolved base-url carries no scheme://. HTTPS is the only sane default for a token-auth API.

  2. Redirect-safe default HTTP client. When Config.HTTPClient is nil the engine now defaults to a client that follows redirects for GET/HEAD but refuses them for mutating methods (a redirected POST/PATCH/PUT is downgraded to GET with the body dropped by net/http, so it must fail loudly instead). Mirrors coily's forgejoCheckRedirect. Removes the need for every consumer to hand-roll this client.

  3. Mount(root, cfg) generates the whole command path. Build returns only the leaf group (e.g. forgejo). Mount grafts that group onto a root *cli.Command, creating the intermediate path groups the Guardfile names (wrap ward ops forgejo -> find-or-create ops under root, attach forgejo). The consumer no longer hand-writes the ops wrapper.

Done when

Build defaults the scheme + client, Mount exists with a test proving it creates intermediate path groups and is idempotent against an existing one, make test/make lint green, godoc-current.txt regenerated.

## Summary Consumer-ergonomics pass on the `specverb` engine, surfaced while wiring the first real consumer (ward, [ward#62](https://forgejo.coilysiren.me/coilyco-flight-deck/ward/issues/62)). Three additive changes that move boilerplate out of the consumer and into the engine, so a consumer needs only the embeds + a `TokenResolver`, no hand-written mount glue. ## Changes 1. **base-url scheme optional.** A Guardfile `base-url "forgejo.coilysiren.me/api/v1"` should resolve to `https://...`. `Build` prepends `https://` when the resolved base-url carries no `scheme://`. HTTPS is the only sane default for a token-auth API. 2. **Redirect-safe default HTTP client.** When `Config.HTTPClient` is nil the engine now defaults to a client that follows redirects for GET/HEAD but refuses them for mutating methods (a redirected POST/PATCH/PUT is downgraded to GET with the body dropped by net/http, so it must fail loudly instead). Mirrors coily's `forgejoCheckRedirect`. Removes the need for every consumer to hand-roll this client. 3. **`Mount(root, cfg)` generates the whole command path.** `Build` returns only the leaf group (e.g. `forgejo`). `Mount` grafts that group onto a root `*cli.Command`, creating the intermediate path groups the Guardfile names (`wrap ward ops forgejo` -> find-or-create `ops` under root, attach `forgejo`). The consumer no longer hand-writes the `ops` wrapper. ## Done when `Build` defaults the scheme + client, `Mount` exists with a test proving it creates intermediate path groups and is idempotent against an existing one, `make test`/`make lint` green, `godoc-current.txt` regenerated.
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
coilyco-flight-deck/cli-guard#88
No description provided.