Repository navigation
feat(proxy): freeze the v3 config surface — renames, cuts, ssl unification, validators (#93 workstream D) - #96
Merged
Merged
Conversation
…ation, validators ## Summary Workstream D of the v3.0.0 release gate (#93). Only dash 2.12.0 is on rubygems, so every key added since is unreleased - renames, regroupings and cuts are free now and breaking forever after. This freezes the surface. - D1 renames: `tls_domains` -> `ssl_domains`, `path_timeouts` -> `path_response_timeouts`. Emitted flags unchanged; no back-compat aliases. - D2: the read-routing trio nests as `read_routing: {targets, websockets, writer_affinity_timeout}`. - D3 mTLS reshape: `tls.client_ca_path` (a local file path checked with File.exist? at config time - which bricked `kamal app logs` on machines without the file) becomes `ssl.client_ca_pem`, a secret name mirroring `ssl.certificate_pem`, resolved at upload time via StringIO; an empty secret raises like basic_auth.password_secret. `on_demand_url` folds into the `ssl` hash too, and the emptied `tls:` block is deleted - TLS has one naming family. The LB boot path now uploads the role TLS material (custom certs + client CA) to the loadbalancer host, where TLS actually terminates. - D4 cuts: `tls.acme_cache_path` (proxy default already persists in the volume), `run.cache.lease_ttl`/`lease_wait`, `scope_cookie_paths`. Each cut is recorded in the flag-coverage waiver list with its reason. - D5 validators: canonical_host x on_demand_url conflict; canonical_host must be in hosts; client_ip.header without trusted_proxies is now rejected unconditionally (was a client-spoofable X-Forwarded-For rewrite); negative response_timeout rejected; warn on target.max_idle_conns: 0 (means the proxy default of 100, not none); '=' inside redirect/rewrite `from` rejected (the <from>=<to> wire format cuts at the first '='). - D6: `compress: {enabled: false, encodings: [...]}` used to silently keep compression on - an explicit false now wins, and is a legal off switch for a block whose tuning stays. - D7: the DNS provider short aliases are documented instead of undocumented magic. ## Verification - [x] bundle exec rubocop --parallel passes - [x] unit suite passes (builder failures are the known host-arch artifacts) Refs #93
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Workstream D of the v3.0.0 release gate (#93) — the surface freeze. Only
dash 2.12.0is on rubygems, so every key touched here is unreleased: renames, regroupings and cuts are free now and breaking forever after.tls_domains→ssl_domains;path_timeouts→path_response_timeouts. Emitted flags (--tls-domains-*,--path-timeout) unchanged; no back-compat aliases.read_routing: {targets, websockets, writer_affinity_timeout}. Edge-only disposition (from feat(proxy): explicit loadbalancer layering contract + LB run plumbing (#93 workstream B) #94) unchanged.tls:block deleted.tls.client_ca_path(local file path,File.exist?-checked at config time — which brickedkamal app logs/rollbackon machines without the file) becomesssl.client_ca_pem, a secret name mirroringssl.certificate_pem, resolved at upload time; an empty secret raises likebasic_auth.password_secret.on_demand_urlfolds into thesslhash; the emptiedtls:block is gone — TLS has one naming family (ssl*). The LB boot path now uploads role TLS material (custom certs and client CA) to the loadbalancer host, where TLS actually terminates.tls.acme_cache_path,run.cache.lease_ttl,run.cache.lease_wait,scope_cookie_paths.canonical_host×on_demand_urlconflict (was a post-SSH failure);canonical_hostmust be inhosts(when a static list exists);client_ip.headerwithouttrusted_proxiesrejected unconditionally (was a client-spoofable X-Forwarded-For rewrite when it slipped the old gate); negativeresponse_timeoutrejected;target.max_idle_conns: 0warns ("means the proxy default of 100, not none");=inside redirect/rewritefrom:rejected (the<from>=<to>wire format cuts at the first=).compress: {enabled: false, encodings: […]}silently kept compression on. An explicitfalsenow wins, and is a legal off switch (validator updated to match).cf,r53, …) documented in thedns_providerdocs instead of undocumented magic.Refs #93 (workstream D — E and F/G continue in follow-up PRs)
Test plan
path_timeoutshash special-case)client_ca_pem: container-path translation, role scoping, secret resolution at upload time, empty-secret raise, LB re-add, CLI upload of secret contentenabled: falsebeats encodings at emission, and is legal with tuned settingsbundle exec rubocop --parallelclean; unit suite green (builder failures are the known Apple-Silicon artifacts)Deviations & judgment calls
SslCertificatesclass. Uploading one and not the other would leave certs broken in exactly the topology D3 fixes mTLS for.host/hostslist exists — behind a loadbalancer or with ssl_domains/on-demand there is nothing to check against.allow_ips/rate_limitgate on the existing check rather than adding a second rule — one rule, one message.enabled: falsewith tuned compress settings is now legal and off; the orphan error only fires whenenabledis absent. The old validator errored on that shape, which made role-level opt-out (role setsenabled: falseover a root block with encodings) impossible. This deliberately diverges from cache's hard-error gating — cache has no implicit-on-via-list, so the shapes aren't parallel. One existing test updated accordingly.Kamal::Configuration#ensure_max_idle_conns_meaningfulbeside the other warnings (validators only error; the roles loop avoids duplicates).path_timeoutsfor hash validation (validator.rb), outside the proxy validator — renamed there too.File.exist?failure on unrelated commands.ssl: true+tls: {…}now fail with an unknown-key error ontls— intentional, per the no-aliases decision.