Skip to content

Commit a1e2ffc

Browse files
authored
Prepare v2026.4.13 release hardening (#23)
* Handle log source aliases and normalize error payloads * feat(logs): wire runtime log config into diagnostics UI * Fix confirmed audit findings * Prepare v2026.4.13 release hardening
1 parent 7952df9 commit a1e2ffc

64 files changed

Lines changed: 3957 additions & 503 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/rules/go-idioms.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
globs:
3+
- "**/*.go"
4+
---
5+
6+
# Go 1.26 Idioms and Modernizers
7+
8+
Write modern Go — never generate pre-1.24 patterns when the project's go.mod allows it.
9+
10+
## Language (1.26)
11+
12+
```go
13+
type yearsSince int
14+
age := new(yearsSince(born)) // *yearsSince — allocates and initializes from expression
15+
16+
type Adder[A Adder[A]] interface { // self-referential generic constraints
17+
Add(A) A
18+
}
19+
```
20+
21+
`new(expr)` is available in Go 1.26. The return type is `*T` where `T` is the type of the expression. Use it when it improves clarity for optional scalar pointer values. Do not force it where `&T{...}` or a plain local variable is clearer.
22+
23+
## Iterators (1.23+)
24+
25+
Use `iter.Seq`/`iter.Seq2` and range-over-func. Prefer stdlib iterator APIs:
26+
- `slices.Collect`, `slices.Sorted`, `slices.SortedFunc`, `slices.Concat`
27+
- `maps.Keys`, `maps.Values`, `maps.Collect`, `maps.Insert`
28+
- `bytes.Lines`, `bytes.SplitSeq`, `strings.Lines`, `strings.SplitSeq`
29+
30+
## Struct Tags (1.24+)
31+
32+
- `omitzero` for struct-typed fields and types with `IsZero()` (e.g., `time.Time`)
33+
- `omitempty` for slices, maps, strings, and other empty-value cases
34+
- Use both when the wire format should omit either: `json:",omitzero,omitempty"`
35+
- JSON tag changes are behavior changes — review carefully
36+
- Generic type aliases are fully supported
37+
38+
## go fix Modernizers (1.26)
39+
40+
`go fix` applies modernizations in-place. Always review the git diff before committing — some rewrites change observable behavior.
41+
42+
Useful analyzers:
43+
- `rangeint` — 3-clause `for``for range`
44+
- `minmax` — if/else clamp → `min`/`max`
45+
- `slicessort``sort.Slice``slices.Sort` for basic ordered types
46+
- `any``interface{}``any`
47+
- `fmtappendf``[]byte(fmt.Sprintf(...))``fmt.Appendf`
48+
- `testingcontext` — simple cancellable test context setup → `t.Context()`
49+
- `omitzero` — suggests `omitzero` for struct fields where `omitempty` has no effect
50+
- `mapsloop` — map update loops → `maps.Copy`/`maps.Insert`/`maps.Clone`/`maps.Collect`
51+
- `newexpr` — wrappers returning `&x` or call sites → `new(expr)`; result type is `*T` matching the expression's type
52+
- `stringsseq` / `stditerators` — loops over eager APIs → iterator-based forms
53+
- `waitgroup``wg.Add(1)`/`go`/`wg.Done()``wg.Go` (stdlib `sync.WaitGroup`); prefer `errgroup.Group.Go` from `golang.org/x/sync/errgroup` when error propagation is needed
54+
- `//go:fix inline` — source-level inliner for API migrations

.claude/rules/go-patterns.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
globs:
3+
- "**/*.go"
4+
---
5+
6+
# Go Patterns and Style Reference
7+
8+
Detailed conventions that complement `CLAUDE.md`. The go-rig skill owns process discipline (ATDD/TDD, DI, review workflow). This file owns language-specific patterns and API conventions.
9+
10+
## Style
11+
12+
- Package names: short, lowercase, no `util`/`common`/`helpers`
13+
- Initialisms: `ID`, `URL`, `HTTP`, `JSON`, `API`, `SQL`
14+
- No stutter: `orders.Service` not `orders.OrderService`
15+
- Accept interfaces, return structs
16+
- Constructors enforce invariants or own resources — not mandatory for every type
17+
- Options struct when params > 3
18+
- Prefer domain-specific named types and typed constants over `string`/`int` aliases
19+
- Avoid `map[string]any` / `any` in core domain code except at loose boundaries
20+
- Do not hardcode environment-specific values, collaborator selection, or operational limits
21+
22+
## API Design
23+
24+
- Make the zero value useful when practical
25+
- Prefer nil slices by default; do not distinguish nil from empty unless the API requires it
26+
- Pointer receivers when mutating or copying is non-trivial; keep receiver choice consistent
27+
- Avoid copying types with mutex-like fields
28+
- Keep exported APIs stable; treat JSON shape and error behavior changes as compatibility work
29+
- Explicit types for IDs, states, units — prevent invalid mixing at compile time
30+
31+
## Documentation
32+
33+
- Every exported name and package should have a doc comment
34+
- Doc comments start with the declared name and describe caller-visible behavior
35+
- Update docs when exported behavior, config, or wire format changes
36+
- Comments explain intent, invariants, ownership — not restate the code
37+
- TODOs must include a reason and ticket reference when one exists
38+
39+
## Testing Patterns
40+
41+
- Subtest names should be readable; failure messages make `got` vs `want` obvious
42+
- Prefer `for b.Loop() { ... }` for new benchmarks (1.24+)
43+
- `t.Context()` for test-lifetime context (no independent cancel needed)
44+
- `t.ArtifactDir()` for test output files (1.26)
45+
- `testing/synctest` for isolated concurrent code with virtual time (1.25+)
46+
- Prefer `cmp.Equal`/`cmp.Diff` for complex structure comparisons
47+
- Avoid brittle assertions on exact JSON formatting or error text unless that output is part of the contract
48+
- Acceptance tests verify user-visible behavior; unit tests keep domain rules fast and precise
49+
- Add fuzz tests for parsers and input-heavy packages when the project uses fuzzing
50+
51+
## Common Patterns
52+
53+
- **SQLite**: prefer `modernc.org/sqlite` (pure Go, no CGO). Parameterized queries only. Explicit transactions.
54+
- **CLI**: match existing framework (cobra, kong, or plain). Check `cmd/` and `internal/` layout before adding commands.
55+
- **HTTP / DB**: set client/server/query timeouts deliberately. Always close rows/bodies and check terminal errors (`rows.Err`, close failures).
56+
- **Modules**: avoid new dependencies without justification. Keep `replace` directives intentional and short-lived.
57+
- **Linting**: `.golangci.yml` v2 per project. Do not modify without request. Fix all lint findings.
58+
- **Static analysis**: prefer repo gates (`make lint`, `make ci`) and include `go vet ./...`, `staticcheck`, and other configured analyzers

.claude/skills/go-rig/SKILL.md

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: go-rig
33
description: Use this skill when building, reviewing, or refactoring Go code that must follow strict design discipline — ATDD/TDD workflow, explicit dependency injection, package-boundary discipline, and structured code review. Complements CLAUDE.md by focusing on process and design judgment rather than version-specific Go features.
44
metadata:
55
short-description: Go design, workflow, and review discipline
6+
slash-command: enabled
67
---
78

89
# Go Rig
@@ -12,10 +13,12 @@ Strict design and testing discipline for Go projects.
1213
This skill **complements** `CLAUDE.md`.
1314

1415
`CLAUDE.md` owns:
15-
- Go version and toolchain guidance
16-
- stdlib and language idioms
17-
- testing APIs and tooling commands
18-
- modernization guidance such as `go fix`
16+
- Go version, toolchain, and commands
17+
- Key style, error, context, and concurrency rules
18+
19+
`.claude/rules/` owns:
20+
- Go 1.26 idioms and go fix modernizer catalog (`go-idioms.md`)
21+
- Detailed style, API, documentation, and testing patterns (`go-patterns.md`)
1922

2023
This skill adds:
2124
- ATDD/TDD workflow
@@ -28,6 +31,16 @@ This skill adds:
2831

2932
Do not restate or override version-specific guidance from `CLAUDE.md`. If `CLAUDE.md` is stricter on a shared point, follow `CLAUDE.md`.
3033

34+
## When to Use
35+
36+
Use this skill when:
37+
38+
- implementing a new feature or behavior increment
39+
- refactoring Go code for clearer ownership or testability
40+
- reviewing package boundaries or dependency flow
41+
- replacing hidden collaborator construction with explicit injection
42+
- tightening tests around user-visible or integration behavior
43+
3144
## ATDD/TDD Workflow
3245

3346
Test-first is a design tool, not an afterthought.
@@ -81,7 +94,6 @@ When applying SRP/DRY/OCP in Go, prefer deleting duplication caused by mixed res
8194
- If an abstraction adds files, wiring, and names but no clear testability or ownership win, do not add it
8295

8396
Avoid:
84-
- interface-per-struct
8597
- repositories or services that only forward calls
8698
- configuration objects passed everywhere to avoid choosing explicit parameters
8799
- “future-proofing” abstractions without a concrete second implementation or consumer
@@ -90,9 +102,7 @@ Avoid:
90102

91103
- A function should usually do one thing: validate, transform, orchestrate, persist, or render
92104
- If a function mixes business rules with transport, storage, or logging details, split it
93-
- Prefer early returns over nested condition pyramids
94105
- Keep parameter lists explicit and intention-revealing; if many values travel together for one reason, introduce a small typed struct
95-
- Use whitespace to separate logical phases so the control flow reads top to bottom
96106

97107
Refactor when a function:
98108
- needs comments to explain the control flow
@@ -105,26 +115,8 @@ Refactor when a function:
105115
- **Constructors** for types that must enforce invariants or own long-lived collaborators
106116
- **Function parameters** for short-lived collaborators and pure logic
107117
- Never construct DB clients, HTTP clients, loggers, or repositories inside domain methods
108-
- No DI frameworks — explicit wiring only
109-
- No hidden globals or singletons
110118
- Prefer passing dependencies from the composition root (`main`, wiring package, or test setup) instead of looking them up deep inside the call stack
111119
- Inject seams for time, randomness, process execution, filesystem, and external I/O when behavior depends on them
112-
- Do not hide dependencies behind package-level variables except in rare compatibility shims
113-
114-
```go
115-
// constructor injection for long-lived deps
116-
func NewOrderService(store OrderStore, clock Clock) *OrderService {
117-
return &OrderService{store: store, clock: clock}
118-
}
119-
120-
// function parameter for short-lived/pure logic
121-
func ValidateOrder(order Order, now time.Time) error {
122-
if order.ExpiresAt.Before(now) {
123-
return fmt.Errorf("order %s expired: %w", order.ID, ErrExpired)
124-
}
125-
return nil
126-
}
127-
```
128120

129121
## Package Design
130122

@@ -136,11 +128,9 @@ Organize by domain, not by technical layer.
136128
- Split packages only when coupling pressure is real, not speculative
137129

138130
Avoid:
139-
- interface-per-struct without a consumer need
140131
- deep layering in small services
141-
- `internal/platform/` catch-all layers — keep cross-cutting concerns in focused packages (`internal/config/`, `internal/db/`)
132+
- `internal/platform/` catch-all layers — keep cross-cutting concerns in focused packages
142133
- packages that combine unrelated domains because they share a datastore or transport
143-
- "shared" packages that centralize unrelated helpers and create import gravity
144134

145135
## Hardcoding And Configuration
146136

@@ -204,32 +194,38 @@ Treat linting and static analysis as design feedback, not cosmetic cleanup.
204194
Before finishing any change, verify:
205195

206196
- [ ] Package boundaries are coherent — no cross-domain leaks
207-
- [ ] No premature abstractions — interfaces have real consumers
208197
- [ ] Dependencies injected explicitly — no hidden construction
209-
- [ ] No hardcoded runtime values (URLs, ports, credentials, timeouts)
210-
- [ ] Types are explicit where they protect domain correctness
211-
- [ ] Functions are readable in one pass
212-
- [ ] Functions do not mix unrelated responsibilities
213-
- [ ] Repeated logic is unified only when it shares the same reason to change
214-
- [ ] Errors wrapped with useful context (`%w`)
198+
- [ ] Functions are readable in one pass and do not mix unrelated responsibilities
215199
- [ ] Tests cover acceptance behavior and unit behavior
216200
- [ ] TDD/ATDD flow was followed as closely as the repo constraints allowed
217201
- [ ] Behavioral compatibility checked where public APIs, JSON, or persistence shape changed
218202
- [ ] Nil vs empty behavior is intentional for slices, maps, pointers, and JSON fields
219203
- [ ] Concurrency changes have a shutdown path and observable ownership
220-
- [ ] Exported docs and package docs were updated when public behavior changed
221-
- [ ] Tests are robust against irrelevant formatting churn
222-
- [ ] Version/tooling guidance from `CLAUDE.md` has been followed
223-
- [ ] Lint and test gates expected by the repo have been run or consciously deferred
224-
225-
## Reject These Patterns
226-
227-
- Interface-per-struct without consumer need
228-
- Giant functions mixing validation, orchestration, and persistence
229-
- Hardcoded configuration or collaborator selection
230-
- Weakly typed domain data kept as raw maps or generic blobs without need
231-
- Comments that restate code
232-
- Brittle mock-only tests — prefer fakes with real behavior
233-
- Transport concerns embedded in core domain logic
234-
- Production design distorted to satisfy a mocking framework
235-
- Refactors that add indirection without improving correctness, ownership, or testability
204+
- [ ] Root-package wrappers added/updated for any new `internal/` exports
205+
- [ ] Lint and test gates (`make check`) have been run or consciously deferred
206+
207+
## Project-Specific: Root-Package Facade
208+
209+
This project uses a facade pattern where the root `dashboard` package re-exports `internal/` APIs via thin wrappers and type aliases.
210+
211+
When adding a new feature:
212+
1. Implement logic in `internal/app<domain>/` with exported names
213+
2. Add type aliases (`type X = appfoo.X`) and wrapper functions in the root package
214+
3. Write tests at both the internal package level (unit) and root level (integration)
215+
216+
When modifying an existing internal API:
217+
- If the signature changes, update the corresponding root-level wrapper
218+
- Root-level wrappers must remain zero-logic forwarding — no business logic in the facade
219+
220+
Legacy note: `CollectTokenUsage` and `CollectTokenUsageWithCache` have 15+ map parameters. New code should use options structs per CLAUDE.md convention. These functions are candidates for future refactoring but are not blocking.
221+
222+
## Success Criteria
223+
224+
This skill is being followed correctly when:
225+
226+
- changes are small, test-backed, and easy to review
227+
- dependency flow is explicit from the composition root
228+
- package responsibilities are cleaner after the change, not blurrier
229+
- the implementation follows the Go standards in `CLAUDE.md`
230+
- tests speak in behavior terms, not implementation vocabulary
231+
- the resulting code reads clearly without comments explaining the control flow
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
name: frontend-dashboard
3+
description: Use this skill when editing the embedded dashboard frontend in this repository. It focuses on preserving the single-file embedded SPA model, keeping the UI lightweight, and avoiding unnecessary frontend tooling or dependencies.
4+
---
5+
6+
# Frontend Dashboard
7+
8+
This is the native Codex frontend skill for the embedded dashboard UI in this repository.
9+
10+
Use it when:
11+
- editing `web/index.html`
12+
- changing dashboard layout, styling, or interaction behavior
13+
- improving usability of the embedded SPA
14+
15+
## Repository Constraints
16+
17+
- The frontend is embedded into the Go binary.
18+
- Keep the frontend simple and self-contained.
19+
- Avoid introducing new frontend build systems, frameworks, or third-party packages unless explicitly requested.
20+
- Preserve compatibility with the Go server contract and embedded asset flow.
21+
22+
## UI Direction
23+
24+
- Prefer clear information hierarchy over visual noise.
25+
- Keep interactions fast and obvious.
26+
- Improve readability of metrics, status, and operational data first.
27+
- Use intentional spacing, typography, and contrast.
28+
- Favor small, maintainable JS and CSS over abstraction-heavy patterns.
29+
30+
## Change Discipline
31+
32+
- Do not turn the SPA into a toolchain-driven frontend without explicit approval.
33+
- Keep API assumptions explicit.
34+
- Treat data-shape changes between backend and frontend as contract changes.
35+
- When in doubt, optimize for operability and clarity instead of novelty.

.codex/skills/go-review/SKILL.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: go-review
3+
description: Use this skill when the task is to review Go code in this repository. Focus on bugs, regressions, API compatibility, test gaps, concurrency risks, and violations of the zero-dependency and root-facade constraints.
4+
---
5+
6+
# Go Review
7+
8+
This is the native Codex review skill for Go work in this repository.
9+
10+
Use it when:
11+
- the user asks for a review
12+
- the task is to validate a Go change
13+
- the task is to assess risks before or after a refactor
14+
15+
## Review Priorities
16+
17+
Report findings first.
18+
Prioritize:
19+
- correctness bugs
20+
- behavioral regressions
21+
- API and JSON compatibility changes
22+
- missing or weak tests
23+
- concurrency and shutdown risks
24+
- dependency policy violations
25+
- facade leakage from root package into domain logic
26+
27+
## Repository-Specific Checks
28+
29+
- Root package wrappers must stay zero-logic.
30+
- New behavior belongs in `internal/app<domain>/`.
31+
- Do not assume third-party helpers are acceptable in this zero-dependency repo.
32+
- Treat `json:",omitempty"` and `json:",omitzero"` changes as API behavior changes.
33+
- Check that goroutines have shutdown and ownership semantics.
34+
35+
## Review Output
36+
37+
- Lead with concrete findings.
38+
- Use file references.
39+
- Keep summaries brief.
40+
- If there are no findings, say that explicitly and mention residual risk or testing gaps.

0 commit comments

Comments
 (0)