1 Commits

Author SHA1 Message Date
clawbot
4a7bdf8f61 chore: root .editorconfig and hardened .gitignore (closes #15)
All checks were successful
check / check (push) Successful in 26s
Three root-level dotfiles diverged from the org models. Two are fixed
here; the third is deferred for a reason spelled out below.

Move backend/.editorconfig to the repo root. The file is byte-identical
to the org model, so this is a pure relocation with no content change.
It carries root = true, which one level down was actively harmful: it
stopped editors walking further up, leaving the entire frontend
(src/, index.html, vite.config.js, nginx.conf, script/) with no
indentation settings at all. At the root the same file covers the whole
tree, backend included, so the subdirectory copy is redundant.

Replace .gitignore with the org model verbatim, then re-append the two
repo-specific entries the model does not carry: dist/ (Vite output) and
*.log. This adds the OS entry Thumbs.db, the entire Editors section
(*.swp, *.swo, *~, *.bak, .idea/, .vscode/, *.sublime-*), and the
Environment / secrets section (.env, .env.*, *.pem, *.key).

The secrets section is the substantive part. The backend loads .env via
godotenv and only backend/.gitignore ignored it, so a .env at the repo
root was untracked but unignored -- one git add -A away from being
committed. Policy allows no exceptions there.

Not done here: excluding .git from .dockerignore. Both images read git
metadata at build time. Dockerfile.backend has an explicit
COPY .git /repo/.git feeding git describe in backend/Makefile, and the
frontend Dockerfile's make check runs vite, whose config calls
git rev-parse at config-eval time. Ignoring .git breaks both builds
outright rather than degrading them, and decoupling them from git
metadata belongs to the Dockerfile rework in #17. Deferred deliberately,
not overlooked; tracked separately so it is not lost.

No tracked file becomes ignored by the new patterns: git ls-files
differs only by the .editorconfig relocation, and check-ignore over the
full tracked set matches nothing.
2026-08-09 04:59:24 +00:00
8 changed files with 60 additions and 66 deletions

27
.gitignore vendored
View File

@@ -1,4 +1,27 @@
node_modules/
dist/
# OS
.DS_Store
Thumbs.db
# Editors
*.swp
*.swo
*~
*.bak
.idea/
.vscode/
*.sublime-*
# Node
node_modules/
# Environment / secrets
.env
.env.*
*.pem
*.key
# Build output
dist/
# Logs
*.log

View File

@@ -3,8 +3,8 @@ FROM golang:1.25-alpine@sha256:f6751d823c26342f9506c03797d2527668d095b0a15f1862c
RUN apk add --no-cache git make gcc musl-dev
# golangci-lint v2.12.2 (2026-08-09)
RUN CGO_ENABLED=0 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@c0d3ddc9cf3faa61a4e378e879ece580256d76e5
# golangci-lint v2.7.2 (2026-02-27)
RUN CGO_ENABLED=0 go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@9f61b0f53f80672872fced07b6874397c3ed197b
WORKDIR /repo/backend
COPY backend/go.mod backend/go.sum ./

40
TODO.md
View File

@@ -10,31 +10,30 @@
# Status
pre-1.0. No git tags. `feat/reportbuf-storage` is merged; the backend, the CI
workflow, and the backend repo standard files are all on `main`. Frontend and
backend are both functional. Working toward the 1.0.0 milestone by closing the
remaining repo-compliance issues on the tracker.
pre-1.0. No git tags. Backend work in flight on feat/reportbuf-storage (dirty:
src/main.js). Frontend is functional; backend is new and unmerged.
# Next Step
Compliance top-up as one small commit: add an `.editorconfig` at the repo root.
`backend/.editorconfig` exists but the root has none. (The `hooks` target this
step used to also name is already present in both the root `Makefile` and
`backend/Makefile`.)
Land feat/reportbuf-storage: finish the in-progress src/main.js change, get make
check green, and merge the branch to main. The branch adds the backend (buffered
zstd-compressed report storage), the CI workflow, and backend repo standard
files, so merging it also closes most compliance gaps.
# Completed Steps
- 2026-08-09: adopted the org-standard `backend/.golangci.yml` verbatim and
bumped the pinned golangci-lint to v2.12.2; the previous config declared
`version: "2"` but used v1 schema keys, so every threshold in it was inert and
its green result was meaningless. `backend/Makefile`'s `lint` target now
asserts the config's sha256 against the canonical file first, so drift from
the org standard fails the build instead of silently degrading to defaults
- 2026-08-09: dotfile compliance — lifted `backend/.editorconfig` to the repo
root so `root = true` covers the frontend too, and replaced `.gitignore` with
the org model (OS, editor, node, and environment/secrets sections) plus this
repo's `dist/` and `*.log`. `.env`, `.env.*`, `*.pem`, and `*.key` are now
ignored repo-wide, not just under `backend/`. Excluding `.git` from
`.dockerignore` stays deferred: both images read git metadata at build time
(`COPY .git` in `Dockerfile.backend`, `git rev-parse` in `vite.config.js`)
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
shims, README Entrypoints section
- 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow
and backend repo standard files; backend Dockerfile fixed (Go 1.25,
golangci-lint) and moved to repo root (feat/reportbuf-storage)
golangci-lint) and moved to repo root (feat/reportbuf-storage, unmerged)
- 2026-02-26: host row layout redesigned with CSS grid; overflow and spacing
fixes; nginx config extracted; port hardcoded to 8080
- 2026-02-26: debug log panel, median stats, recovery probe, Docker build fix,
@@ -47,12 +46,9 @@ step used to also name is already present in both the root `Makefile` and
# Future Steps
- Confirm `.gitea/workflows/check.yml` is on `main` and CI is green (main always
green policy)
- Compliance top-up as one small commit: add .editorconfig and add the hooks
target to the Makefile
- After merge, confirm .gitea/workflows/check.yml is on main and CI is green
(main always green policy)
- Decide what to do with untracked resume.sh: commit it, gitignore it, or delete
it
- Upstream fix needed in `sneak/prompts`: the org-standard `.golangci.yml`
enables `gomodguard`, which golangci-lint v2.12.2 reports as deprecated since
v2.12.0 and replaced by `gomodguard_v2`, so every backend lint run prints a
deprecation warning. The file is standardized and must never be edited in this
repo, so nothing can be done here beyond tracking it

View File

@@ -1,9 +1,5 @@
version: "2"
# Config schema uses the golangci-lint v2 layout (settings live under
# linters.settings, not top-level linters-settings) so that the
# thresholds below are actually applied by golangci-lint >= v2.
run:
timeout: 5m
modules-download-mode: readonly
@@ -18,17 +14,19 @@ linters:
- wsl # Deprecated, replaced by wsl_v5
- wrapcheck # Too verbose for internal packages
- varnamelen # Short names like db, id are idiomatic Go
settings:
lll:
line-length: 88
funlen:
lines: 80
statements: 50
cyclop:
max-complexity: 15
dupl:
threshold: 100
linters-settings:
lll:
line-length: 88
funlen:
lines: 80
statements: 50
cyclop:
max-complexity: 15
dupl:
threshold: 100
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0

View File

@@ -8,20 +8,10 @@ GOLDFLAGS += -X main.Buildarch=$(BUILDARCH)
ifeq ($(UNAME_S),Darwin)
GOFLAGS := -ldflags "$(GOLDFLAGS)"
SHA256SUM := shasum -a 256
else
GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)"
SHA256SUM := sha256sum
endif
# .golangci.yml is standardized org-wide and must never be edited here
# (REPO_POLICIES.md). Its last silent drift replaced the v2 schema with
# v1 keys, which left every threshold in the file inert while the build
# stayed green. The lint target therefore asserts the file still matches
# the canonical copy byte for byte. The check is a local hash comparison:
# no network, no remote schema, nothing unpinned in the build path.
GOLANGCI_CONFIG_SHA256 := 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb
.PHONY: all build test lint fmt fmt-check check docker hooks run clean
all: build
@@ -35,14 +25,6 @@ test:
timeout 30 go test ./...
lint:
@actual=$$($(SHA256SUM) .golangci.yml | cut -d' ' -f1); \
if [ "$$actual" != "$(GOLANGCI_CONFIG_SHA256)" ]; then \
echo ".golangci.yml has drifted from the org standard."; \
echo " expected $(GOLANGCI_CONFIG_SHA256)"; \
echo " actual $$actual"; \
echo "Restore it verbatim from sneak/prompts; do not edit it."; \
exit 1; \
fi
golangci-lint run ./...
fmt:

View File

@@ -163,9 +163,7 @@ func (b *Buffer) writeFile(data []byte) {
name := fmt.Sprintf("reports-%s.jsonl.zst", ts)
path := filepath.Join(b.dataDir, name)
// path is built from the operator-supplied dataDir plus a
// generated timestamp, so it carries no external input.
f, err := os.OpenFile( //nolint:gosec // see comment above
f, err := os.OpenFile( //nolint:gosec // path built from controlled dataDir + timestamp
path,
os.O_WRONLY|os.O_CREATE|os.O_EXCL,
filePerms,

View File

@@ -62,10 +62,7 @@ func New(
OnStart: func(_ context.Context) error {
s.startupTime = time.Now().UTC()
// The fx OnStart context is scoped to startup and is
// cancelled once the hook returns; run() derives its
// own context instead of inheriting this one.
go func() { //nolint:contextcheck // see comment above
go func() { //nolint:contextcheck // fx OnStart ctx is startup-only; run() creates its own
s.run()
}()
@@ -97,7 +94,7 @@ func (s *Server) run() {
}
func (s *Server) serve() int {
var ctx context.Context
var ctx context.Context //nolint:wsl // ctx must be declared before multi-assign
ctx, s.cancelFunc = context.WithCancel(
context.Background(),