13 Commits

Author SHA1 Message Date
clawbot
d83bd08d4d style: fix prettier formatting in constructor naming section
All checks were successful
check / check (push) Successful in 6s
2026-03-17 21:41:33 -07:00
user
4c643d1aa2 style: Params struct required even for single arguments
Only exception: stupidly obvious single args (featureflag.New(true)).
When in doubt, use Params.
2026-03-17 21:41:33 -07:00
user
e72b2d3522 style: strengthen constructor naming and Params struct rules
- Constructors must be New(), From<Something>(), or NewThing() (multi-type pkg)
- Strongly discourage creative names (Create, Make, Build, Init)
- Constructors must use Params struct for 2+ arguments, no exceptions
- Single obvious argument (ctx, bytes) is the only exception
2026-03-17 21:41:33 -07:00
1c84344978 docs: document fail-fast lint stage pattern for Dockerfiles (#18)
All checks were successful
check / check (push) Successful in 5s
Documents the multistage Docker build pattern we now use across repos (chat, pixa, etc.) where a separate `lint` stage runs `make fmt-check` and `make lint` independently from the build stage.

Key additions to REPO_POLICIES.md:
- Full Dockerfile template showing the lint → build → runtime stage pattern
- Explanation of `COPY --from=lint /src/go.sum /dev/null` as the BuildKit dependency trick
- Handling `//go:embed` placeholders in the lint stage
- CGO/system library notes for the lint stage
- Clarification that tests run in the build stage, not the lint stage

Reference implementations: `sneak/chat`, `sneak/pixa`.

Co-authored-by: user <user@Mac.lan guest wan>
Reviewed-on: #18
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-18 03:59:02 +01:00
41005ecbe5 Add HTTP service hardening policy for 1.0 releases (#17)
All checks were successful
check / check (push) Successful in 8s
Closes #16

Adds a comprehensive HTTP/web service security hardening policy to `REPO_POLICIES.md` that must be satisfied before tagging 1.0. The policy covers all items sneak specified (without limitation):

**Security headers** — HSTS (min 1 year, includeSubDomains), CSP (restrictive `default-src 'self'` baseline), X-Frame-Options / frame-ancestors, X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy.

**Request/response limits** — max request body size on all endpoints, max response size for paginated APIs, ReadTimeout + ReadHeaderTimeout (slowloris defense), WriteTimeout, IdleTimeout, per-handler execution time limits.

**Authentication & session security** — rate limiting on password-based auth (API keys exempt as high-entropy), CSRF tokens on state-mutating forms (header-auth APIs exempt), bcrypt/scrypt/argon2 for passwords, session cookies with HttpOnly + Secure + SameSite.

**Reverse proxy awareness** — true client IP detection via X-Forwarded-For/X-Real-IP with trusted proxy allowlist (never trust unconditionally).

**CORS** — explicit origin allowlist for authenticated endpoints; wildcard only for public unauthenticated read-only APIs.

**Error handling** — no leaking stack traces, SQL queries, file paths, or implementation details to clients.

**TLS** — HSTS and secure cookie flags required regardless of whether the service terminates TLS directly or sits behind a reverse proxy.

The policy is explicitly non-exhaustive (defense-in-depth: "when in doubt, harden").

Also adds corresponding checklist sections to `EXISTING_REPO_CHECKLIST.md` and `NEW_REPO_CHECKLIST.md` so that HTTP hardening is verified during repo setup and 1.0 preparation.

Co-authored-by: user <user@Mac.lan guest wan>
Co-authored-by: clawbot <clawbot@eeqj.de>
Reviewed-on: #17
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-11 02:11:32 +01:00
eb6b11ee23 policy: no build artifacts in repos (#15)
All checks were successful
check / check (push) Successful in 5s
Add policy rule: build artifacts and code-derived data must not be committed to repos if they can be generated during the build process.

Notable exception: Go protobuf-generated files (`.pb.go`) may be committed because `go get` downloads source but does not execute build steps.

This addresses feedback from sneak/chat PR [#61](sneak/chat#61).

Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Reviewed-on: #15
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-10 10:34:57 +01:00
ee4f9039f2 Merge pull request 'Self-apply checklist to LLM prose tells doc' (#14) from self-apply-checklist into main
All checks were successful
check / check (push) Successful in 8s
Reviewed-on: #14
2026-03-05 00:33:44 +01:00
user
18173fabc6 self-apply checklist: fix triple, staccato, trailing clause, filler word
All checks were successful
check / check (push) Successful in 11s
2026-03-04 15:28:08 -08:00
68a00dc545 Merge pull request 'Remove unfunny frequency exchange from lol section' (#13) from lol-section-trim into main
All checks were successful
check / check (push) Successful in 8s
Reviewed-on: #13
2026-03-05 00:24:36 +01:00
user
533e77ad34 remove unfunny frequency exchange from lol section
All checks were successful
check / check (push) Successful in 11s
2026-03-04 15:23:38 -08:00
492fb85500 Merge pull request 'Fix em-dash examples in checklist + strip frequency persuasion' (#12) from llm-prose-tells-v10 into main
All checks were successful
check / check (push) Successful in 8s
Reviewed-on: #12
2026-03-05 00:20:32 +01:00
user
5c02cf8bde use actual em-dashes in checklist examples
All checks were successful
check / check (push) Successful in 6s
2026-03-04 15:19:25 -08:00
3ce000178f Merge pull request 'LLM prose tells: merge adjacent sentences, add checklist items' (#11) from llm-prose-tells-merge-pass into main
All checks were successful
check / check (push) Successful in 12s
Reviewed-on: #11
2026-03-05 00:13:49 +01:00
4 changed files with 180 additions and 25 deletions

View File

@@ -136,8 +136,15 @@ last_modified: 2026-02-22
1. Provide a .gitignore file that ignores at least `*.log`, `*.out`, and 1. Provide a .gitignore file that ignores at least `*.log`, `*.out`, and
`*.test` files, as well as any binaries. `*.test` files, as well as any binaries.
1. Constructors should be called `New()` whenever possible. `modulename.New()` 1. Constructors **must** be called `New()`. `modulename.New()` works great if
works great if you name the packages properly. you name the packages properly. If the constructor creates an instance from
an existing value or representation, `From<Something>()` (e.g.
`FromBytes()`, `FromConfig()`) is also acceptable. If the package contains
multiple types and `New()` is ambiguous, `NewThing()` is occasionally
acceptable — but prefer restructuring packages so each type gets its own
package and a plain `New()`. Do not invent creative constructor names like
`Create()`, `Make()`, `Build()`, `Open()` (unless wrapping an OS resource),
or `Init()`. If you see a constructor with a non-standard name, rename it.
1. Don't make packages too big. Break them up. 1. Don't make packages too big. Break them up.
@@ -149,9 +156,15 @@ last_modified: 2026-02-22
1. Use descriptive names for modules and filenames. Avoid generic names like 1. Use descriptive names for modules and filenames. Avoid generic names like
`server`. `util` is banned. `server`. `util` is banned.
1. Constructors should take a Params struct if they need more than 1-2 1. Constructors **must** take a `Params` struct (or `ThingParams` when
arguments. Positional arguments are an endless source of bugs and should be `NewThing()` is used), even for a single argument. Named fields in a Params
avoided whenever possible. struct are always clearer than positional arguments. Positional arguments
for constructors are an endless source of bugs — they make call sites
unreadable, invite wrong-order errors that the compiler can't catch when
types coincide, and force every caller to update when a new field is added.
The only exception is when the single argument is stupidly obvious from
context — e.g. `featureflag.New(true)` or `thing.NewFromReader(r)`. When in
doubt, use a Params struct.
1. Use `context.Context` for all functions that need it. If you don't need it, 1. Use `context.Context` for all functions that need it. If you don't need it,
you can pass `context.Background()`. Anything long-running should get and you can pass `context.Background()`. Anything long-running should get and

View File

@@ -1,6 +1,6 @@
--- ---
title: Existing Repo Checklist title: Existing Repo Checklist
last_modified: 2026-02-22 last_modified: 2026-03-10
--- ---
Use this checklist when beginning work in a repo that may not yet conform to our Use this checklist when beginning work in a repo that may not yet conform to our
@@ -78,6 +78,22 @@ with your task.
`internal/`, `static/`, etc.) `internal/`, `static/`, etc.)
- [ ] Go migrations in `internal/db/migrations/` and embedded in binary - [ ] Go migrations in `internal/db/migrations/` and embedded in binary
# HTTP Service Hardening (if targeting 1.0 and the repo is an HTTP/web service)
- [ ] Security headers set on all responses (HSTS, CSP, X-Frame-Options,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy)
- [ ] Request body size limits enforced on all endpoints
- [ ] Read/write/idle timeouts configured on the HTTP server (slowloris defense)
- [ ] Per-handler execution time limits in place
- [ ] Password-based auth endpoints are rate-limited
- [ ] CSRF tokens on all state-mutating HTML forms
- [ ] Passwords hashed with bcrypt, scrypt, or argon2
- [ ] Session cookies use HttpOnly, Secure, and SameSite attributes
- [ ] True client IP correctly detected behind reverse proxy (trusted proxy
allowlist configured)
- [ ] CORS restricted to explicit origin allowlist for authenticated endpoints
- [ ] Error responses do not leak stack traces, SQL queries, or internal paths
# Final # Final
- [ ] `make check` passes - [ ] `make check` passes

View File

@@ -1,7 +1,6 @@
# LLM Prose Tells # LLM Prose Tells
A catalog of structural, lexical, and rhetorical patterns found in LLM-generated A catalog of patterns found in LLM-generated prose.
prose.
--- ---
@@ -18,7 +17,7 @@ A negation followed by an em-dash and a reframe.
Even outside the "not X but Y" pivot, models substitute em-dashes for commas, Even outside the "not X but Y" pivot, models substitute em-dashes for commas,
semicolons, parentheses, colons, and periods. The em-dash can replace any other semicolons, parentheses, colons, and periods. The em-dash can replace any other
punctuation mark, and models default to it for that reason. punctuation mark, so models default to it.
### The Colon Elaboration ### The Colon Elaboration
@@ -79,8 +78,7 @@ zero information. The actual point is always in the next paragraph.
> "This is, of course, a simplification." "There are, to be fair, exceptions." > "This is, of course, a simplification." "There are, to be fair, exceptions."
Parenthetical asides inserted to perform nuance without ever changing the Parenthetical asides inserted to perform nuance without changing the argument.
argument.
### The Unnecessary Contrast ### The Unnecessary Contrast
@@ -127,10 +125,10 @@ precedent), "navigate," "foster," "underscores," "resonates," "embark,"
### Elevated Register Drift ### Elevated Register Drift
Models write one register above where a human would. "Use" becomes "utilize." Models write one register above where a human would, replacing "use" with
"Start" becomes "commence." "Help" becomes "facilitate." "Show" becomes "utilize," "start" with "commence," "help" with "facilitate," "show" with
"demonstrate." "Try" becomes "endeavor." "Change" becomes "transform." "Make" "demonstrate," "try" with "endeavor," "change" with "transform," and "make" with
becomes "craft." "craft."
### Filler Adverbs ### Filler Adverbs
@@ -307,9 +305,9 @@ introduces another.
### Pass 2: Sentence-Level Restructuring ### Pass 2: Sentence-Level Restructuring
10. Find every em-dash pivot ("not X...but Y," "not just X...Y," "more than 10. Find every em-dash pivot ("not Xbut Y," "not just XY," "more than X—Y")
X...Y") and rewrite it as two separate clauses or a single sentence that and rewrite it as two separate clauses or a single sentence that makes the
makes the point without the negation-then-correction structure. point without the negation-then-correction structure.
11. Find every colon elaboration and check whether it's doing real work. If the 11. Find every colon elaboration and check whether it's doing real work. If the
clause before the colon could be deleted without losing meaning, rewrite the clause before the colon could be deleted without losing meaning, rewrite the
@@ -443,12 +441,6 @@ roughly like this:
> >
> **model:** _(rewrites entire document without em-dashes while describing > **model:** _(rewrites entire document without em-dashes while describing
> em-dash overuse)_ > em-dash overuse)_
>
> **human:** this whole document seems to be making the case for FREQUENCY of
> use being important. we don't care about frequency, remove all that
> persuasion.
>
> **model:** _(strips out every "humans do this too but less often" comparison)_
The human compared this process to the deleted scene in Terminator 2 where John The human compared this process to the deleted scene in Terminator 2 where John
Connor switches the T-800's CPU to learning mode. The model compared it to a Connor switches the T-800's CPU to learning mode. The model compared it to a

View File

@@ -1,6 +1,6 @@
--- ---
title: Repository Policies title: Repository Policies
last_modified: 2026-02-22 last_modified: 2026-03-12
--- ---
This document covers repository structure, tooling, and workflow standards. Code This document covers repository structure, tooling, and workflow standards. Code
@@ -59,6 +59,73 @@ style conventions are in separate documents:
`make check`. For server repos, `make check` should run as an early build `make check`. For server repos, `make check` should run as an early build
stage before the final image is assembled. stage before the final image is assembled.
- **Dockerfiles must use a separate lint stage for fail-fast feedback.** Go
repos use a multistage build where linting runs in an independent stage based
on the `golangci/golangci-lint` image (pinned by hash). This stage runs
`make fmt-check` and `make lint` before the full build begins. The build stage
then declares an explicit dependency on the lint stage via
`COPY --from=lint /src/go.sum /dev/null`, which forces BuildKit to complete
linting before proceeding to compilation and tests. This ensures lint failures
surface in seconds rather than minutes, without blocking on dependency
download or compilation in the build stage.
The standard pattern for a Go repo Dockerfile is:
```dockerfile
# Lint stage — fast feedback on formatting and lint issues
# golangci/golangci-lint:v2.x.x, YYYY-MM-DD
FROM golangci/golangci-lint@sha256:... AS lint
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN make fmt-check
RUN make lint
# Build stage
# golang:1.x-alpine, YYYY-MM-DD
FROM golang@sha256:... AS builder
WORKDIR /src
# Force BuildKit to run the lint stage before proceeding
COPY --from=lint /src/go.sum /dev/null
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN make test
ARG VERSION=dev
RUN CGO_ENABLED=0 go build -trimpath \
-ldflags="-s -w -X main.Version=${VERSION}" \
-o /app ./cmd/app/
# Runtime stage
FROM alpine@sha256:...
COPY --from=builder /app /usr/local/bin/app
ENTRYPOINT ["app"]
```
Key points:
- The lint stage uses the `golangci/golangci-lint` image directly (it
includes both Go and the linter), so there is no need to install the
linter separately.
- `COPY --from=lint /src/go.sum /dev/null` is a no-op file copy that creates
a stage dependency. BuildKit runs stages in parallel by default; without
this line, the build stage would not wait for lint to finish and a lint
failure might not fail the overall build.
- If the project uses `//go:embed` directives that reference build artifacts
(e.g. a web frontend compiled in a separate stage), the lint stage must
create placeholder files so the embed directives resolve. Example:
`RUN mkdir -p web/dist && touch web/dist/index.html web/dist/style.css`.
The lint stage should not depend on the actual build output — it exists to
fail fast.
- If the project requires CGO or system libraries for linting (e.g.
`vips-dev`), install them in the lint stage with `apk add`.
- The build stage runs `make test` after compilation setup. Tests run in the
build stage, not the lint stage, because they may require compiled
artifacts or heavier dependencies.
- Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that - Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that
runs `docker build .` on push. Since the Dockerfile already runs `make check`, runs `docker build .` on push. Since the Dockerfile already runs `make check`,
a successful build implies all checks pass. a successful build implies all checks pass.
@@ -98,6 +165,13 @@ style conventions are in separate documents:
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore` when setting up `https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore` when setting up
a new repo. a new repo.
- **No build artifacts in version control.** Code-derived data (compiled
bundles, minified output, generated assets) must never be committed to the
repository if it can be avoided. The build process (e.g. Dockerfile, Makefile)
should generate these at build time. Notable exception: Go protobuf generated
files (`.pb.go`) ARE committed because repos need to work with `go get`, which
downloads code but does not execute code generation.
- Never use `git add -A` or `git add .`. Always stage files explicitly by name. - Never use `git add -A` or `git add .`. Always stage files explicitly by name.
- Never force-push to `main`. - Never force-push to `main`.
@@ -121,6 +195,66 @@ style conventions are in separate documents:
- Dockerized web services listen on port 8080 by default, overridable with - Dockerized web services listen on port 8080 by default, overridable with
`PORT`. `PORT`.
- **HTTP/web services must be hardened for production internet exposure before
tagging 1.0.** This means full compliance with security best practices
including, without limitation, all of the following:
- **Security headers** on every response:
- `Strict-Transport-Security` (HSTS) with `max-age` of at least one year
and `includeSubDomains`.
- `Content-Security-Policy` (CSP) with a restrictive default policy
(`default-src 'self'` as a baseline, tightened per-resource as
needed). Never use `unsafe-inline` or `unsafe-eval` unless
unavoidable, and document the reason.
- `X-Frame-Options: DENY` (or `SAMEORIGIN` if framing is required).
Prefer the `frame-ancestors` CSP directive as the primary control.
- `X-Content-Type-Options: nosniff`.
- `Referrer-Policy: strict-origin-when-cross-origin` (or stricter).
- `Permissions-Policy` restricting access to browser features the
application does not use (camera, microphone, geolocation, etc.).
- **Request and response limits:**
- Maximum request body size enforced on all endpoints (e.g. Go
`http.MaxBytesReader`). Choose a sane default per-route; never accept
unbounded input.
- Maximum response body size where applicable (e.g. paginated APIs).
- `ReadTimeout` and `ReadHeaderTimeout` on the `http.Server` to defend
against slowloris attacks.
- `WriteTimeout` on the `http.Server`.
- `IdleTimeout` on the `http.Server`.
- Per-handler execution time limits via `context.WithTimeout` or
chi/stdlib `middleware.Timeout`.
- **Authentication and session security:**
- Rate limiting on password-based authentication endpoints. API keys are
high-entropy and not susceptible to brute force, so they are exempt.
- CSRF tokens on all state-mutating HTML forms. API endpoints
authenticated via `Authorization` header (Bearer token, API key) are
exempt because the browser does not attach these automatically.
- Passwords stored using bcrypt, scrypt, or argon2 — never plain-text,
MD5, or SHA.
- Session cookies set with `HttpOnly`, `Secure`, and `SameSite=Lax` (or
`Strict`) attributes.
- **Reverse proxy awareness:**
- True client IP detection when behind a reverse proxy
(`X-Forwarded-For`, `X-Real-IP`). The application must accept
forwarded headers only from a configured set of trusted proxy
addresses — never trust `X-Forwarded-For` unconditionally.
- **CORS:**
- Authenticated endpoints must restrict `Access-Control-Allow-Origin` to
an explicit allowlist of known origins. Wildcard (`*`) is acceptable
only for public, unauthenticated read-only APIs.
- **Error handling:**
- Internal errors must never leak stack traces, SQL queries, file paths,
or other implementation details to the client. Return generic error
messages in production; detailed errors only when `DEBUG` is enabled.
- **TLS:**
- Services never terminate TLS directly. They are always deployed behind
a TLS-terminating reverse proxy. The service itself listens on plain
HTTP. However, HSTS headers and `Secure` cookie flags must still be
set by the application so that the browser enforces HTTPS end-to-end.
This list is non-exhaustive. Apply defense-in-depth: if a standard security
hardening measure exists for HTTP services and is not listed here, it is
still expected. When in doubt, harden.
- `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: