fix(ci): golangci-lint + feat(bench): 500k-request harness & report#2
fix(ci): golangci-lint + feat(bench): 500k-request harness & report#2
Conversation
- Downgrade go.mod directive to go 1.23 so golangci-lint v1.61.0 can parse - Pin pgx/v5, validator, zerolog, viper, jwt, x/crypto to 1.23-compatible minor versions (behavior-identical for our use) - Switch fiber.Error type-assert to errors.As (errorlint) - Switch validator.ValidationErrors type-assert to errors.As (errorlint) - Run gofmt -s + goimports with -local github.com/dedeez14/goforge - Simplify auth_test helper to not return unused repo value (unparam) - Dockerfile: use golang:1.23-alpine
- Add cmd/bench with goroutine-based harness supporting
healthz/register/login/login-refresh/me scenarios.
Each scenario issues total=500_000 unique requests by default,
reports rps, p50/p90/p95/p99/max and status breakdown.
- Expose Argon2id parameters via config (security.argon_*) so
load-test profiles can lower the cost without touching code.
- Add docs/benchmark-500k.md with full run results:
healthz : 18 276 rps (p50=12ms) — 500 000 × 200
register : 640 rps (p50=66ms) — 500 000 × 201
login : 855 rps (p50=46ms) — 500 000 × 200
me : 2 708 rps (p50=45ms) — 500 000 × 200
All on 2 vCPU/8 GiB VM, API RSS stayed at 33 MiB.
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…urity docs + 200k benchmark
- README rewritten with clear quickstart, architecture diagram, 200k bench table, HTTP reference, configuration table, scaffolding, production checklist, doc index
- Split detailed reference into docs/{architecture,configuration,scaffolding,security}.md
- Renamed docs/benchmark-500k.md to docs/benchmark.md and added the 200k smoke run alongside the 500k run with a unified methodology section
Co-Authored-By: dede febriansyah <febriansyahd65@gmail.com>
| ArgonMemoryKiB uint32 `mapstructure:"argon_memory_kib"` | ||
| ArgonIters uint32 `mapstructure:"argon_iters"` | ||
| ArgonParallel uint8 `mapstructure:"argon_parallel"` |
There was a problem hiding this comment.
🔴 Missing validation on Argon2id config allows zero iterations/parallelism, causing runtime panic
The new config fields ArgonIters and ArgonParallel (internal/config/config.go:74-76) have no minimum-value validation. If a user sets GOFORGE_SECURITY_ARGON_ITERS=0 or GOFORGE_SECURITY_ARGON_PARALLEL=0, these zero values pass through to argon2.IDKey at internal/infrastructure/security/hasher.go:60, which panics with "argon2: number of rounds too small" or "argon2: parallelism degree too low" respectively. The NewPasswordHasher guard at internal/infrastructure/security/hasher.go:49 only falls back to defaults when Memory == 0, so a non-zero memory with zero iterations/parallelism bypasses the safety net. The panic is caught by the recover middleware, but every register/login call returns a 500 — authentication is completely broken. Other config fields like JWT.Secret and HTTP.Port already carry validate:"min=..." tags that are checked at startup; these new fields should follow the same pattern.
| ArgonMemoryKiB uint32 `mapstructure:"argon_memory_kib"` | |
| ArgonIters uint32 `mapstructure:"argon_iters"` | |
| ArgonParallel uint8 `mapstructure:"argon_parallel"` | |
| ArgonMemoryKiB uint32 `mapstructure:"argon_memory_kib" validate:"min=1"` | |
| ArgonIters uint32 `mapstructure:"argon_iters" validate:"min=1"` | |
| ArgonParallel uint8 `mapstructure:"argon_parallel" validate:"min=1"` |
Was this helpful? React with 👍 or 👎 to provide feedback.
feat(forge): rbac sync — auto-register permission codes from RequirePermission scans (Tier-A #2)
Summary
Follow-up to #1. Two things:
1. Fix the failing
golangci-lintcheck onmain.Root cause:
go.modwas pinned togo 1.25, butgolangci-lint v1.61.0(the pinned CI version) is built against go1.23 and refuses to analyse modules targeting a newer language version. That forced a cascade: every transitive dep had also drifted to a go1.25-required release.go.mod→go 1.23, drop thetoolchaindirective so the module stays buildable with Go 1.23 too.pgx v5.7.2,validator v10.22.1,zerolog v1.33.0,viper v1.19.0,jwt/v5 v5.2.1,x/crypto v0.31.0,x/text v0.21.0,x/sync v0.10.0..(*T)type assertions onerrortoerrors.Assoerrorlintstops flagging them:internal/infrastructure/server/server.go→var fe *fiber.Error; errors.As(err, &fe)pkg/validatorx/validator.go→errors.As(err, &validator.ValidationErrors)gofmt -s -wandgoimports -local github.com/dedeez14/goforge -wover the tree to satisfygofmt/goimportslinters.*inMemoryUserReporeturn fromauth_test.newAuthFixture(unparam).Dockerfile: base image switched togolang:1.23-alpineto matchgo.mod.2. Expose Argon2id cost via config + ship a 500 000-request benchmark harness + publish the report.
Argon2id parameters are now read from
config.Security.ArgonMemoryKiB / ArgonIters / ArgonParallel(with OWASP-2023 defaults65 536 / 3 / 2). This allows lowering the hash cost for load-testing profiles without touching code — the feature is useful in its own right (e.g. tuning cost up over time or lowering it for integration tests).cmd/bench/main.gois a Go harness that:-total=500000requests across-concurrency=Ngoroutines,/me, etc.),login/mecan replay them,Ran all four scenarios × 500 000 requests on the same 2 vCPU / 8 GiB VM (client, API, and Postgres all co-located):
GET /healthzPOST /registerPOST /loginGET /meFull report:
docs/benchmark-500k.md.Review & Testing Checklist for Human
go 1.23is acceptable — it widens the audience of Go toolchains that can build the module without changing runtime behaviour, but it does pin some deps to older minors.make upthen the four/tmp/bench -scenario=…commands fromdocs/benchmark-500k.md.make test && golangci-lint run ./...is clean locally. CI should now be all green onmain.Notes
mem=1024, t=1, p=1) so the run fits in a reasonable wall-clock window; production defaults remain OWASP-recommended and unchanged. The report explicitly calls this out and explains why register/login p50 scales with Argon2 cost, not framework overhead.cmd/bench) or config-surface (security.argon_*).Link to Devin session: https://app.devin.ai/sessions/8fdfc20358514c97a766adca630a2527
Requested by: @dedeez14