Both touch the same surface (JWTConfig plumbing), so kept together.
1. Bug fix (pre-existing)
pkg/server/server.go was hardcoding ExpirationTime: time.Hour * 24 when building JWTConfig, completely ignoring auth.jwt.ttl from config (default 1h). Production has been signing tokens with 24h TTL regardless of config since the field was added.
2. Hot-reload (ADR-0023 Phase 2)
Extends JWTConfig with GetTTL func() time.Duration callback. New effectiveTTL() helper prefers GetTTL() when set, falls back to ExpirationTime otherwise (test-friendly).
server.go wires GetTTL: cfg.GetJWTTTL — a method value capturing *Config. When WatchAndApply re-unmarshals into the same Config on file change, the next token generation reads the new TTL. Tokens already issued keep their original expiry — only newly-generated tokens are affected.
WatchAndApply now also logs the new jwt_ttl on every reload.
Tests
New TestWatchAndApply_JWTTTL in pkg/config/config_hot_reload_test.go: rewrites the config file and asserts c.GetJWTTTL() flips within 2s. Polling (no fixed sleep), race-clean.
Existing pkg/user tests (incl. JWT manager + cleanup loop from PR #41) all pass with -race.
Full BDD suite (auth/config/greet/health/info/jwt) green.
Dim A: APPROVE — effectiveTTL() is 6 lines, defensive on nil + non-positive TTL; method value captures cfg cleanly without globals.
Dim B: APPROVE — ADR-0023 status updated accurately; bug fix called out in commit message and PR body so it doesn't get lost.
Dim C: APPROVE — race detector clean; new test follows the polling pattern from Phase 1; full BDD suite still green.
Test plan
go test -race ./pkg/config/... passes
go test -race ./pkg/user/... passes
Full BDD suite passes
go vet ./... clean
Reviewer to verify the bug fix in production: server logs at startup should show jwt_ttl=1h0m0s (default) instead of the previous-but-unused 24h
## Two fixes in one diff
Both touch the same surface (`JWTConfig` plumbing), so kept together.
### 1. Bug fix (pre-existing)
`pkg/server/server.go` was hardcoding `ExpirationTime: time.Hour * 24` when building `JWTConfig`, **completely ignoring `auth.jwt.ttl` from config** (default 1h). Production has been signing tokens with 24h TTL regardless of config since the field was added.
### 2. Hot-reload (ADR-0023 Phase 2)
Extends `JWTConfig` with `GetTTL func() time.Duration` callback. New `effectiveTTL()` helper prefers `GetTTL()` when set, falls back to `ExpirationTime` otherwise (test-friendly).
`server.go` wires `GetTTL: cfg.GetJWTTTL` — a method value capturing `*Config`. When `WatchAndApply` re-unmarshals into the same Config on file change, the next token generation reads the new TTL. **Tokens already issued keep their original expiry** — only newly-generated tokens are affected.
`WatchAndApply` now also logs the new `jwt_ttl` on every reload.
## Tests
- New `TestWatchAndApply_JWTTTL` in `pkg/config/config_hot_reload_test.go`: rewrites the config file and asserts `c.GetJWTTTL()` flips within 2s. Polling (no fixed sleep), race-clean.
- Existing `pkg/user` tests (incl. JWT manager + cleanup loop from PR #41) all pass with `-race`.
- Full BDD suite (auth/config/greet/health/info/jwt) green.
## ADR-0023 status
Was: `Phase 1 Implemented (logging.level)`.
Now: `Phase 1+2 Implemented (logging.level + auth.jwt.ttl)`.
Remaining:
- **Phase 3**: telemetry sampler (type / ratio) — needs tracer provider re-init
- **Phase 4**: `api.v2_enabled` — needs router refactor (always-register + middleware gate); deferred
## Verifier verdict (skill-driven)
**APPROVE**
- **Dim A**: APPROVE — `effectiveTTL()` is 6 lines, defensive on nil + non-positive TTL; method value captures `cfg` cleanly without globals.
- **Dim B**: APPROVE — ADR-0023 status updated accurately; bug fix called out in commit message and PR body so it doesn't get lost.
- **Dim C**: APPROVE — race detector clean; new test follows the polling pattern from Phase 1; full BDD suite still green.
## Test plan
- [x] `go test -race ./pkg/config/...` passes
- [x] `go test -race ./pkg/user/...` passes
- [x] Full BDD suite passes
- [x] `go vet ./...` clean
- [ ] Reviewer to verify the bug fix in production: server logs at startup should show `jwt_ttl=1h0m0s` (default) instead of the previous-but-unused 24h
Two changes in one diff because they share the same surface (JWTConfig
plumbing):
1. **Bug fix** : pkg/server/server.go was hardcoding ExpirationTime to
24h, ignoring the auth.jwt.ttl config value entirely (default 1h).
Production has been signing tokens with 24h TTL regardless of config
since the config field was added.
2. **Hot-reload (ADR-0023 Phase 2)** : extends JWTConfig with a GetTTL
func() time.Duration callback. effectiveTTL() prefers GetTTL when
set, falls back to ExpirationTime otherwise (test-friendly). server.go
wires GetTTL = cfg.GetJWTTTL — a method value that captures the
*Config, so when WatchAndApply re-unmarshals, the next token
generation reads the new TTL automatically. Tokens already issued
keep their original expiry.
WatchAndApply now also logs the new jwt_ttl on every reload event.
Tests:
- New TestWatchAndApply_JWTTTL in pkg/config/config_hot_reload_test.go
rewrites the config file and asserts the in-memory ttl flips within
2s. Polling (no fixed sleep), race-clean.
- Existing pkg/user tests (including JWT manager + cleanup loop) all
pass with -race.
- Full BDD suite (auth/config/greet/health/info/jwt) green.
ADR-0023 status: Phase 1+2 Implemented. Phase 3 (telemetry sampler)
and Phase 4 (api.v2_enabled — needs router refactor) remain Proposed.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Two fixes in one diff
Both touch the same surface (
JWTConfigplumbing), so kept together.1. Bug fix (pre-existing)
pkg/server/server.gowas hardcodingExpirationTime: time.Hour * 24when buildingJWTConfig, completely ignoringauth.jwt.ttlfrom config (default 1h). Production has been signing tokens with 24h TTL regardless of config since the field was added.2. Hot-reload (ADR-0023 Phase 2)
Extends
JWTConfigwithGetTTL func() time.Durationcallback. NeweffectiveTTL()helper prefersGetTTL()when set, falls back toExpirationTimeotherwise (test-friendly).server.gowiresGetTTL: cfg.GetJWTTTL— a method value capturing*Config. WhenWatchAndApplyre-unmarshals into the same Config on file change, the next token generation reads the new TTL. Tokens already issued keep their original expiry — only newly-generated tokens are affected.WatchAndApplynow also logs the newjwt_ttlon every reload.Tests
TestWatchAndApply_JWTTTLinpkg/config/config_hot_reload_test.go: rewrites the config file and assertsc.GetJWTTTL()flips within 2s. Polling (no fixed sleep), race-clean.pkg/usertests (incl. JWT manager + cleanup loop from PR #41) all pass with-race.ADR-0023 status
Was:
Phase 1 Implemented (logging.level).Now:
Phase 1+2 Implemented (logging.level + auth.jwt.ttl).Remaining:
api.v2_enabled— needs router refactor (always-register + middleware gate); deferredVerifier verdict (skill-driven)
APPROVE
effectiveTTL()is 6 lines, defensive on nil + non-positive TTL; method value capturescfgcleanly without globals.Test plan
go test -race ./pkg/config/...passesgo test -race ./pkg/user/...passesgo vet ./...cleanjwt_ttl=1h0m0s(default) instead of the previous-but-unused 24h