Conversation
Replace hand-rolled parseByteSize with humanize.ParseBytes, adding support for SI units (KB, MB, GB), fractional values, and flexible whitespace. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The server runs behind an Envoy reverse proxy, so there is no need to bind on all interfaces by default. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add http.cache.default_ttl config option (env: ATTESTATION_SERVER_HTTP_CACHE_DEFAULT_TTL) to control the fallback TTL when responses have no Cache-Control header. Default bumped from 30m to 1h. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously, parse errors for endorsements.client.timeout, http.cache.size, http.cache.default_ttl, revocation.refresh_interval, and ratelimit.stall_timeout were silently replaced with defaults. This masked misconfigurations in a security-critical service. Now the server exits with a clear error on any unparseable value. Viper defaults still apply when no override is provided. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe PR narrows the server default bind address from Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Server as Server
participant Fetcher as Fetcher (cachedHTTPSGetter)
participant External as External API
participant Cache as HTTP Cache
Client->>Server: Request resource
Server->>Fetcher: Request external data
Fetcher->>Cache: Check cache for item
alt Cache hit
Cache-->>Fetcher: Return cached response + TTL
else Cache miss
Fetcher->>External: HTTP request
External-->>Fetcher: HTTP response (with/without Cache-Control/Expires)
Fetcher->>Fetcher: parseCacheTTL(response headers, defaultTTL)
Fetcher->>Cache: Store response with computed TTL
end
Fetcher-->>Server: Return data
Server-->>Client: Respond
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
internal/endorsements_test.go (1)
384-386: Use a non-default sentinel TTL in the no-header case.This still exercises the new parameter with
time.Hour, so an implementation that ignoresdefaultTTLand hardcodes1hwould also pass. Giving that case its own distinct TTL would actually lock down the new behavior.Also applies to: 425-425
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/endorsements_test.go` around lines 384 - 386, The test case "no headers returns default" currently uses time.Hour (the existing default) which masks implementations that ignore the provided defaultTTL; change the sentinel TTL in that case to a distinct non-default value (e.g., time.Minute or another constant) so the test exercises the defaultTTL parameter, and make the same change for the other occurrence referenced (the case at the later line). Update the test cases in endorsements_test.go that set want: time.Hour for the no-headers scenarios to use the new sentinel TTL and ensure any helper variables (e.g., defaultTTL) or assertions still compare against that sentinel value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/config.go`:
- Around line 335-339: The code converts humanize.ParseBytes result (n uint64)
to int64 without checking overflow; add a guard after ParseBytes in the same
function (where n, err := humanize.ParseBytes(s) is used) that returns an error
if n > uint64(math.MaxInt64) (use math.MaxInt64) so the function returns a clear
overflow error instead of silently truncating/producing a negative int64; keep
the existing error message style (e.g., fmt.Errorf) when returning the overflow
error.
In `@internal/cosign.go`:
- Around line 134-136: The code currently forces a default cache TTL whenever
ttl <= 0 which overwrites explicit non-cacheable or already-expired responses;
change the condition so the default is applied only when ttl == 0 (unspecified),
and preserve ttl when it's negative (explicit no-cache/no-store/expired). Update
the check that references ttl and s.cfg.HTTPCacheDefaultTTL in
internal/cosign.go so it sets ttl = s.cfg.HTTPCacheDefaultTTL only for ttl == 0
and does not override ttl < 0.
In `@internal/endorsements.go`:
- Around line 104-106: The current check in endorsements.go overrides a TTL of 0
(which parseCacheTTL uses to mean "no-cache"/"no-store"/expired), causing
responses that should not be cached to get the default TTL; locate the code that
calls parseCacheTTL (reference parseCacheTTL and the local variable ttl) and
change the conditional so you only apply s.cfg.HTTPCacheDefaultTTL when ttl is
negative (e.g. change "if ttl <= 0" to "if ttl < 0"), preserving ttl==0 values
returned intentionally by parseCacheTTL.
In `@internal/fetch.go`:
- Around line 123-124: The function parseCacheTTL currently returns defaultTTL
as-is, allowing configured defaults >24h to bypass the documented cap; update
parseCacheTTL to clamp defaultTTL to a maximum of 24 hours (time.Hour*24) at the
start (or before any early return) so any return path that yields defaultTTL
respects the 24h cap; ensure existing logic that parses the Expires header still
applies the same cap to parsed values as well.
---
Nitpick comments:
In `@internal/endorsements_test.go`:
- Around line 384-386: The test case "no headers returns default" currently uses
time.Hour (the existing default) which masks implementations that ignore the
provided defaultTTL; change the sentinel TTL in that case to a distinct
non-default value (e.g., time.Minute or another constant) so the test exercises
the defaultTTL parameter, and make the same change for the other occurrence
referenced (the case at the later line). Update the test cases in
endorsements_test.go that set want: time.Hour for the no-headers scenarios to
use the new sentinel TTL and ensure any helper variables (e.g., defaultTTL) or
assertions still compare against that sentinel value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5c300660-fd7c-4163-83da-8f6bd23d7d4d
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (10)
CLAUDE.mdcmd/root.goconfig/config.tomlgo.modinternal/config.gointernal/cosign.gointernal/endorsements.gointernal/endorsements_test.gointernal/fetch.gointernal/server.go
A configured http.cache.default_ttl >24h would bypass the documented 24h cap because the default return path did not clamp the value. Now parseCacheTTL clamps defaultTTL at entry so all return paths (max-age, Expires, and default) respect the cap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
humanize.ParseBytes returns uint64; values above math.MaxInt64 (e.g. "9EiB") would silently wrap to negative on the int64 cast. Now returns a clear error instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
parseCacheTTL returns 0 to signal "do not cache" (no-cache, no-store, or expired Expires header). The ttl <= 0 guard in endorsements.go and cosign.go was overriding this with the default TTL, causing responses that should not be cached to be cached. Changed to ttl < 0 so only truly invalid values get the fallback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/config.go`:
- Around line 316-325: Update the comment for parseDuration to accurately
reflect its behavior: state that it reads a viper string key and parses it as a
time.Duration and returns an error if the value is empty or cannot be parsed
(i.e., for empty strings and any unparseable duration strings). Reference the
parseDuration function and ensure the docstring no longer implies empty values
are allowed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 65248c58-2399-481a-ad3a-db093a1ac4ec
📒 Files selected for processing (5)
internal/config.gointernal/cosign.gointernal/endorsements.gointernal/endorsements_test.gointernal/fetch.go
✅ Files skipped from review due to trivial changes (1)
- internal/fetch.go
🚧 Files skipped from review as they are similar to previous changes (3)
- internal/cosign.go
- internal/endorsements.go
- internal/endorsements_test.go
The comment said "non-empty and unparseable" implying empty strings
were accepted, but time.ParseDuration("") returns an error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
internal/config.go (1)
316-344: Please add tests for these new startup-failure paths.
internal/config_test.gostill doesn't cover invalid durations or byte-size overflow, even though this code now decides whether the server starts. A small table-driven test here would lock in the new fail-fast contract.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/config.go` around lines 316 - 344, Add table-driven tests in internal/config_test.go to cover the new fail-fast paths in parseDuration and parseByteSize: write cases that pass an empty/invalid duration string to parseDuration (e.g., "" and "5xs") and assert it returns a non-nil error, and cases for parseByteSize that pass empty string and an oversized value (a string that parses to > math.MaxInt64) and assert errors; call the functions directly (parseDuration, parseByteSize) and verify the error messages contain the problematic input to lock in the behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/config.go`:
- Around line 118-136: Parsed durations from parseDuration (used to populate
endorsementTimeout, httpCacheDefaultTTL, revocationRefreshInterval,
rateLimitStallTimeout, etc.) can be negative and must be rejected; after each
parseDuration call check if the returned duration is < 0 and return an error
(e.g., fmt.Errorf("%s: negative duration %s", "<config.key>", d)) consistent
with existing parseByteSize error handling so invalid negative timeouts/TTLs
fail fast. Ensure you update all places that call parseDuration in this block
and include the specific config key name in the error message to aid debugging.
---
Nitpick comments:
In `@internal/config.go`:
- Around line 316-344: Add table-driven tests in internal/config_test.go to
cover the new fail-fast paths in parseDuration and parseByteSize: write cases
that pass an empty/invalid duration string to parseDuration (e.g., "" and "5xs")
and assert it returns a non-nil error, and cases for parseByteSize that pass
empty string and an oversized value (a string that parses to > math.MaxInt64)
and assert errors; call the functions directly (parseDuration, parseByteSize)
and verify the error messages contain the problematic input to lock in the
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
time.ParseDuration accepts negative values like "-5s" which are nonsensical for timeouts and TTLs. Now returns a clear error with the config key name. Added tests for parseDuration (empty, unparseable, negative) and parseByteSize (empty, overflow) error paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/config.go`:
- Around line 118-121: parseDuration currently accepts zero which breaks callers
that require positive durations (RevocationRefreshInterval used by
time.NewTicker, EndorsementClientTimeout used with
context.WithTimeout/http.Client.Timeout, and RateLimitStallTimeout used with
context.WithTimeout). Fix by making parseDuration return an error for zero
durations (treat zero as invalid) and update callers (e.g., where
endorsementTimeout is assigned in internal/config.go) to handle that error path;
alternatively, if you prefer per-callsite validation, add explicit checks that
parsed values for RevocationRefreshInterval, EndorsementClientTimeout, and
RateLimitStallTimeout are > 0 and return a clear error instead of allowing zero
to propagate.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2f34da73-1561-497b-b113-4124e2d77367
📒 Files selected for processing (2)
internal/config.gointernal/config_test.go
✅ Files skipped from review due to trivial changes (1)
- internal/config_test.go
endorsements.client.timeout (http.Client.Timeout=0 disables timeout), revocation.refresh_interval (time.NewTicker(0) panics), and ratelimit.stall_timeout (context.WithTimeout(ctx,0) expires instantly) all require positive durations. http.cache.default_ttl is intentionally left allowing zero (meaning "don't cache"). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
internal/config.go (1)
122-146: Consider extracting aparsePositiveDurationhelper to reduce repetition.The pattern of calling
parseDurationfollowed by a zero-check is repeated three times for fields that require positive values. A dedicated helper could consolidate this:func parsePositiveDuration(key string) (time.Duration, error) { d, err := parseDuration(key) if err != nil { return 0, err } if d == 0 { return 0, fmt.Errorf("%s: must be positive", key) } return d, nil }This is a minor DRY improvement and entirely optional.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/config.go` around lines 122 - 146, Extract a helper named parsePositiveDuration that wraps parseDuration and enforces a non-zero result (signature: parsePositiveDuration(key string) (time.Duration, error)); replace the repeated parseDuration + zero-check blocks (used for keys "http.cache.default_ttl", "revocation.refresh_interval", and "ratelimit.stall_timeout") with calls to parsePositiveDuration, and update the surrounding code to return the helper's error directly where those durations are assigned (e.g., httpCacheDefaultTTL, revocationRefreshInterval, rateLimitStallTimeout).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@internal/config.go`:
- Around line 122-146: Extract a helper named parsePositiveDuration that wraps
parseDuration and enforces a non-zero result (signature:
parsePositiveDuration(key string) (time.Duration, error)); replace the repeated
parseDuration + zero-check blocks (used for keys "http.cache.default_ttl",
"revocation.refresh_interval", and "ratelimit.stall_timeout") with calls to
parsePositiveDuration, and update the surrounding code to return the helper's
error directly where those durations are assigned (e.g., httpCacheDefaultTTL,
revocationRefreshInterval, rateLimitStallTimeout).
Summary by CodeRabbit
Configuration
0.0.0.0to127.0.0.1.http.cache.default_ttlsetting added (default1h) to control fallback cache TTL.Improvements
Tests
Chores