From 4e6a782edfabc5977a88d3e5b67f8250ae7e0e8f Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 25 Aug 2026 20:43:48 +0000 Subject: [PATCH] An unguessable capability URL is the whole credential (closes #52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HTTP hardening section ends with "when in doubt, harden", which as written authorises adding HMAC signing or a shared secret on top of an endpoint already gated by an unguessable per-entrypoint UUID URL. That has been ruled against twice, and inbound signature verification was removed from webhooker on exactly that reasoning; until now the only text contradicting the policy was webhooker's own README. Adds one scoped carve-out immediately after that sentence: such a URL is a complete credential and gets no second factor, not even as defence in depth. The consequences that do follow — keep it out of logs and tickets, rotate by minting a new entrypoint — are stated, as is what to do with a sender that only supports signed payloads. Nothing in the surrounding hardening guidance is removed or weakened. --- TODO.md | 3 +++ prompts/REPO_POLICIES.md | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index bf8d674..4cddd21 100644 --- a/TODO.md +++ b/TODO.md @@ -21,6 +21,9 @@ fmt-check, and commit. # Completed Steps +- 2026-08-25: Carved capability-URL services out of "when in doubt, harden" in + REPO_POLICIES.md: an unguessable per-entrypoint UUID URL is a complete + credential and gets no second authentication factor. - 2026-08-10: Moved every lint run into a container. `script/lint` now runs the linter directly when `LINT_IN_CONTAINER=1` and otherwise builds `Dockerfile.lint`, so the linter never runs on a developer host — closing the diff --git a/prompts/REPO_POLICIES.md b/prompts/REPO_POLICIES.md index 424a877..b6d05c0 100644 --- a/prompts/REPO_POLICIES.md +++ b/prompts/REPO_POLICIES.md @@ -1,6 +1,6 @@ --- title: Repository Policies -last_modified: 2026-08-10 +last_modified: 2026-08-25 --- This document covers repository structure, tooling, and workflow standards. Code @@ -847,6 +847,26 @@ style conventions are in separate documents: hardening measure exists for HTTP services and is not listed here, it is still expected. When in doubt, harden. + **One carve-out: capability URLs.** Where a service's credential is an + unguessable URL — a v4 UUID path segment minted per entrypoint — that URL is + the complete credential, not a partial one. Knowing it is authorization. + Such an endpoint does not get a second authentication factor added on top: + no HMAC request signing, no shared secrets, no bearer tokens, not as + defense-in-depth and not as a belt-and-braces extra. This has been + considered and rejected; "when in doubt, harden" is not license to propose + it again. + + What does follow from a capability URL is that it is a secret, and is + handled as one: + - Keep it out of logs, error messages, tickets, screenshots, and support + transcripts. Log the entrypoint's internal ID, never its URL. + - Rotate by minting a new entrypoint and retiring the old one. There is no + key to change. + + A sender that cannot accept a secret URL and supports only signed payloads + is a constraint on that integration. Raise it — that is not grounds to + reintroduce shared secrets. + - `README.md` is the primary documentation. Required sections: - **Description**: First line must include the project name, purpose, category (web server, SPA, CLI tool, etc.), license, and author. Example: -- 2.49.1