README.md:110-119 presents these as "Key settings" and says "See config.example.yml for all options with defaults":
access_control_allow_origin — CORS origin
upstream_fetch_timeout — timeout for origin requests
upstream_max_response_size — max origin response size
downstream_timeout — client response timeout
None of the four exist. isKnownConfigKey (internal/config/config.go:217-227) permits only: debug, maintenance_mode, port, state_dir, sentry_dsn, db_url, metrics, signing_key, allowlist_hosts, allow_http, upstream_connections_per_host, env.
Since #52/#53 landed strict unknown-key rejection, a user who follows the README does not get a silently-ignored key — the daemon refuses to start with unknown config keys: .... That is the correct behavior for an unknown key (repo policy: set-but-unparseable config must abort), but it means our own documentation is a startup-breaking trap.
The underlying values all exist, hardcoded:
CORS origin: []string{"*"} at internal/middleware/middleware.go:114
Fetch timeout / max response size: DefaultFetchTimeout / DefaultMaxResponseSize at internal/httpfetcher/httpfetcher.go:22-23; internal/handlers/handlers.go:76-80 currently overrides only AllowHTTP and MaxConnectionsPerHost
Downstream timeout: HTTPWriteTimeout at internal/server/http.go:12
access_control_allow_origin defaulting to * is itself worth a look while implementing — a wide-open CORS default on an image proxy is defensible but should be a deliberate, documented choice rather than an accident.
Definition of done
All four keys implemented: added to the Config struct, to isKnownConfigKey, parsed with the strict getters (a set-but-invalid value must abort startup naming the key and the offending value, per repo policy — no silent fallback), and plumbed to the code that currently hardcodes each value.
Durations and byte sizes parse consistently with how the rest of the config handles those types; if no precedent exists, pick one and document it in config.example.yml.
Each key is listed in config.example.yml with its default and a comment.
README's config section stays accurate (and the "all options with defaults" claim becomes true — see the separate docs issue for the remaining undocumented keys).
Failing tests first: for each key, a test that a valid value takes effect and an invalid value aborts startup naming key and value, following the table-driven pattern in internal/config/config_validation_internal_test.go.
make check green.
Scope note
If this is more comfortable as four commits, split by key — but keep it one PR, since the shared work is the strict-getter plumbing.
Verified against `main` at `61f42e6`.
`README.md:110-119` presents these as "Key settings" and says "See `config.example.yml` for all options with defaults":
- `access_control_allow_origin` — CORS origin
- `upstream_fetch_timeout` — timeout for origin requests
- `upstream_max_response_size` — max origin response size
- `downstream_timeout` — client response timeout
None of the four exist. `isKnownConfigKey` (`internal/config/config.go:217-227`) permits only: `debug`, `maintenance_mode`, `port`, `state_dir`, `sentry_dsn`, `db_url`, `metrics`, `signing_key`, `allowlist_hosts`, `allow_http`, `upstream_connections_per_host`, `env`.
Since #52/#53 landed strict unknown-key rejection, a user who follows the README does not get a silently-ignored key — **the daemon refuses to start** with `unknown config keys: ...`. That is the correct behavior for an unknown key (repo policy: set-but-unparseable config must abort), but it means our own documentation is a startup-breaking trap.
The underlying values all exist, hardcoded:
- CORS origin: `[]string{"*"}` at `internal/middleware/middleware.go:114`
- Fetch timeout / max response size: `DefaultFetchTimeout` / `DefaultMaxResponseSize` at `internal/httpfetcher/httpfetcher.go:22-23`; `internal/handlers/handlers.go:76-80` currently overrides only `AllowHTTP` and `MaxConnectionsPerHost`
- Downstream timeout: `HTTPWriteTimeout` at `internal/server/http.go:12`
`access_control_allow_origin` defaulting to `*` is itself worth a look while implementing — a wide-open CORS default on an image proxy is defensible but should be a deliberate, documented choice rather than an accident.
## Definition of done
1. All four keys implemented: added to the `Config` struct, to `isKnownConfigKey`, parsed with the **strict** getters (a set-but-invalid value must abort startup naming the key and the offending value, per repo policy — no silent fallback), and plumbed to the code that currently hardcodes each value.
2. Durations and byte sizes parse consistently with how the rest of the config handles those types; if no precedent exists, pick one and document it in `config.example.yml`.
3. Each key is listed in `config.example.yml` with its default and a comment.
4. README's config section stays accurate (and the "all options with defaults" claim becomes true — see the separate docs issue for the remaining undocumented keys).
5. Failing tests first: for each key, a test that a valid value takes effect and an invalid value aborts startup naming key and value, following the table-driven pattern in `internal/config/config_validation_internal_test.go`.
6. `make check` green.
## Scope note
If this is more comfortable as four commits, split by key — but keep it one PR, since the shared work is the strict-getter plumbing.
clawbot
added this to the 1.0.0 milestone 2026-08-09 03:43:07 +02:00
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.
Verified against
mainat61f42e6.README.md:110-119presents these as "Key settings" and says "Seeconfig.example.ymlfor all options with defaults":access_control_allow_origin— CORS originupstream_fetch_timeout— timeout for origin requestsupstream_max_response_size— max origin response sizedownstream_timeout— client response timeoutNone of the four exist.
isKnownConfigKey(internal/config/config.go:217-227) permits only:debug,maintenance_mode,port,state_dir,sentry_dsn,db_url,metrics,signing_key,allowlist_hosts,allow_http,upstream_connections_per_host,env.Since #52/#53 landed strict unknown-key rejection, a user who follows the README does not get a silently-ignored key — the daemon refuses to start with
unknown config keys: .... That is the correct behavior for an unknown key (repo policy: set-but-unparseable config must abort), but it means our own documentation is a startup-breaking trap.The underlying values all exist, hardcoded:
[]string{"*"}atinternal/middleware/middleware.go:114DefaultFetchTimeout/DefaultMaxResponseSizeatinternal/httpfetcher/httpfetcher.go:22-23;internal/handlers/handlers.go:76-80currently overrides onlyAllowHTTPandMaxConnectionsPerHostHTTPWriteTimeoutatinternal/server/http.go:12access_control_allow_origindefaulting to*is itself worth a look while implementing — a wide-open CORS default on an image proxy is defensible but should be a deliberate, documented choice rather than an accident.Definition of done
Configstruct, toisKnownConfigKey, parsed with the strict getters (a set-but-invalid value must abort startup naming the key and the offending value, per repo policy — no silent fallback), and plumbed to the code that currently hardcodes each value.config.example.yml.config.example.ymlwith its default and a comment.internal/config/config_validation_internal_test.go.make checkgreen.Scope note
If this is more comfortable as four commits, split by key — but keep it one PR, since the shared work is the strict-getter plumbing.