Compare commits
1 Commits
issue-52-c
...
1e21653f44
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e21653f44 |
3
TODO.md
3
TODO.md
@@ -21,9 +21,6 @@ fmt-check, and commit.
|
|||||||
|
|
||||||
# Completed Steps
|
# 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
|
- 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
|
linter directly when `LINT_IN_CONTAINER=1` and otherwise builds
|
||||||
`Dockerfile.lint`, so the linter never runs on a developer host — closing the
|
`Dockerfile.lint`, so the linter never runs on a developer host — closing the
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Repository Policies
|
title: Repository Policies
|
||||||
last_modified: 2026-08-25
|
last_modified: 2026-08-10
|
||||||
---
|
---
|
||||||
|
|
||||||
This document covers repository structure, tooling, and workflow standards. Code
|
This document covers repository structure, tooling, and workflow standards. Code
|
||||||
@@ -94,13 +94,11 @@ style conventions are in separate documents:
|
|||||||
reading the Makefile.
|
reading the Makefile.
|
||||||
|
|
||||||
- Every repo should have a `Dockerfile`. All Dockerfiles must run `make check`
|
- Every repo should have a `Dockerfile`. All Dockerfiles must run `make check`
|
||||||
as a build step so the build fails if the branch is not green — the one
|
as a build step so the build fails if the branch is not green — which requires
|
||||||
exception being `Dockerfile.lint`, which runs `make lint` alone because that
|
`ARG CHECK_EPOCH` and its guard in every stage containing a check-running
|
||||||
is its entire purpose — which requires `ARG CHECK_EPOCH` and its guard in
|
`RUN`, per the `CHECK_EPOCH` rule below. Without them a Dockerfile satisfies
|
||||||
every stage containing a check-running `RUN`, per the `CHECK_EPOCH` rule
|
this criterion while its check layers are served from cache, so the build
|
||||||
below. Without them a Dockerfile satisfies this criterion while its check
|
cannot fail on a branch that is not green.
|
||||||
layers are served from cache, so the build cannot fail on a branch that is not
|
|
||||||
green.
|
|
||||||
|
|
||||||
**Every Dockerfile must also set `ENV LINT_IN_CONTAINER=1`**, above the
|
**Every Dockerfile must also set `ENV LINT_IN_CONTAINER=1`**, above the
|
||||||
checks. `script/lint` builds `Dockerfile.lint` when it is not already in a
|
checks. `script/lint` builds `Dockerfile.lint` when it is not already in a
|
||||||
@@ -126,17 +124,11 @@ style conventions are in separate documents:
|
|||||||
**after** the dependency-install layer so that layer stays cached:
|
**after** the dependency-install layer so that layer stays cached:
|
||||||
|
|
||||||
```dockerfile
|
```dockerfile
|
||||||
ENV LINT_IN_CONTAINER=1
|
|
||||||
ARG CHECK_EPOCH
|
ARG CHECK_EPOCH
|
||||||
RUN [ -n "$CHECK_EPOCH" ] || exit 1
|
RUN [ -n "$CHECK_EPOCH" ] || exit 1
|
||||||
RUN echo "check epoch: ${CHECK_EPOCH}" && make check
|
RUN echo "check epoch: ${CHECK_EPOCH}" && make check
|
||||||
```
|
```
|
||||||
|
|
||||||
`ENV LINT_IN_CONTAINER=1` belongs in every such stage too, and is the line
|
|
||||||
most often missed: without it `make check` reaches `script/lint`, which
|
|
||||||
tries to build `Dockerfile.lint` from inside a build step where there is no
|
|
||||||
daemon. See the containerised-lint rule below.
|
|
||||||
|
|
||||||
and in both `script/cibuild` and `script/docker`:
|
and in both `script/cibuild` and `script/docker`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -237,11 +229,6 @@ style conventions are in separate documents:
|
|||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
|
||||||
if [ "${LINT_IN_CONTAINER:-}" = "1" ]; then
|
if [ "${LINT_IN_CONTAINER:-}" = "1" ]; then
|
||||||
# config verify lives here, not in a Dockerfile, so every path
|
|
||||||
# that lints inherits it — the lint stage of the main image as
|
|
||||||
# well as Dockerfile.lint. Duplicating it into each Dockerfile
|
|
||||||
# is how one of them silently loses it.
|
|
||||||
golangci-lint config verify --config .golangci.yml
|
|
||||||
exec golangci-lint run --config .golangci.yml ./...
|
exec golangci-lint run --config .golangci.yml ./...
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -276,7 +263,9 @@ style conventions are in separate documents:
|
|||||||
# ARG after the dependency layer so only the lint re-runs.
|
# ARG after the dependency layer so only the lint re-runs.
|
||||||
ARG CHECK_EPOCH
|
ARG CHECK_EPOCH
|
||||||
RUN [ -n "$CHECK_EPOCH" ] || exit 1
|
RUN [ -n "$CHECK_EPOCH" ] || exit 1
|
||||||
RUN echo "lint epoch: ${CHECK_EPOCH}" && make lint
|
RUN echo "lint epoch: ${CHECK_EPOCH}" && \
|
||||||
|
golangci-lint config verify --config .golangci.yml
|
||||||
|
RUN make lint
|
||||||
```
|
```
|
||||||
|
|
||||||
Load-bearing properties:
|
Load-bearing properties:
|
||||||
@@ -298,10 +287,7 @@ style conventions are in separate documents:
|
|||||||
- **Non-Go repos get the same pattern around their own linter** — `eslint`,
|
- **Non-Go repos get the same pattern around their own linter** — `eslint`,
|
||||||
`ruff`, `prettier`, `shellcheck`. Only the base image and the native lint
|
`ruff`, `prettier`, `shellcheck`. Only the base image and the native lint
|
||||||
command change.
|
command change.
|
||||||
- **Keep `golangci-lint config verify`, put it in `script/lint`, and it
|
- **Keep `golangci-lint config verify`, and it costs no network.** The two
|
||||||
costs no network.** It goes in the native branch, not in a Dockerfile, so
|
|
||||||
the lint stage of the main image inherits it along with `Dockerfile.lint`;
|
|
||||||
putting it in one Dockerfile leaves the other path unverified. The two
|
|
||||||
commands catch disjoint classes, measured under the pinned v2.12.2: a
|
commands catch disjoint classes, measured under the pinned v2.12.2: a
|
||||||
bogus top-level key and a bogus key under `linters.settings.lll` both pass
|
bogus top-level key and a bogus key under `linters.settings.lll` both pass
|
||||||
`golangci-lint run` with **exit 0 and `0 issues`** while `config verify`
|
`golangci-lint run` with **exit 0 and `0 issues`** while `config verify`
|
||||||
@@ -338,9 +324,9 @@ style conventions are in separate documents:
|
|||||||
3. Add `ENV LINT_IN_CONTAINER=1` to **every** stage of every Dockerfile that
|
3. Add `ENV LINT_IN_CONTAINER=1` to **every** stage of every Dockerfile that
|
||||||
runs checks — the lint stage and the build stage both.
|
runs checks — the lint stage and the build stage both.
|
||||||
4. Delete any golangci-lint install from `script/bootstrap`, with its
|
4. Delete any golangci-lint install from `script/bootstrap`, with its
|
||||||
version and ref variables and its call site. No lint verdict comes from
|
version and ref variables and its call site. Nothing on the host lints,
|
||||||
the host any more, so it can only reintroduce version skew. A JS repo's
|
so it can only reintroduce version skew. A JS repo's `yarn install`
|
||||||
`yarn install` stays.
|
stays.
|
||||||
5. Delete the per-checkout lint state: `GOLANGCI_LINT_CACHE` and `TMPDIR`
|
5. Delete the per-checkout lint state: `GOLANGCI_LINT_CACHE` and `TMPDIR`
|
||||||
exports, `--allow-serial-runners`, the retry/VOID wrapper, and
|
exports, `--allow-serial-runners`, the retry/VOID wrapper, and
|
||||||
`.lint-cache/` from both `.gitignore` and `.dockerignore`.
|
`.lint-cache/` from both `.gitignore` and `.dockerignore`.
|
||||||
@@ -847,26 +833,6 @@ style conventions are in separate documents:
|
|||||||
hardening measure exists for HTTP services and is not listed here, it is
|
hardening measure exists for HTTP services and is not listed here, it is
|
||||||
still expected. When in doubt, harden.
|
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:
|
- `README.md` is the primary documentation. Required sections:
|
||||||
- **Description**: First line must include the project name, purpose,
|
- **Description**: First line must include the project name, purpose,
|
||||||
category (web server, SPA, CLI tool, etc.), license, and author. Example:
|
category (web server, SPA, CLI tool, etc.), license, and author. Example:
|
||||||
|
|||||||
Reference in New Issue
Block a user