devantler-tech / devantler-tech/ksail
chore(hetznerbase): separate the user-data inspection bound from the forwarding bound
- Dominant language
- Go
- Stars
- 165
- Forks
- 12
- Avg merge
- 5h 41m
- Merged PRs (30d)
- 337
Description
> 🤖 Generated by the Agentic Engineer
**Evidence.** ksail#6609 makes `validateProviderUserData` return the text it inspected, and
`DeriveServerSpecs` now forwards *that* value as `CreateServerOpts.UserData` instead of the caller's
`node.UserData`. For raw-gzip user-data this is a deliberate and well-argued change — cloud-init
accepts gzip directly, the compressed bytes are not YAML, and raw gzip cannot survive a JSON string
field intact, so expanding before forwarding is the correct call and is documented as such.
The observation is narrower: **`maxDecodedUserDataBytes` now has two different jobs with one value.**
| job | what the right value depends on |
|---|---|
| how far to decompress *while inspecting* (pre-existing) | how much text the guard is willing to scan before treating a payload as evasive |
| how large an expanded payload may be *and still be forwarded* (new) | whatever the Hetzner API actually accepts for `user_data` |
Those are unrelated quantities that happen to share the constant `1 << 20` (1 MiB). Nothing is wrong
today, and this is **not** a security gap — the guard still inspects everything it forwards.
**Why it is worth recording.** An expanded payload between the provider's real `user_data` ceiling and
1 MiB now passes the guard and is rejected by Hetzner instead, surfacing as an opaque provider API
error rather than a clear local one. Gzip is often used *precisely* to fit a size ceiling, so that is
the population most likely to hit it.
I deliberately did **not** put a number on the provider ceiling here: I could not verify it from the
repository (it encodes no such constant) and asserting a remembered figure into a tracking issue is
how a wrong number becomes durable.
**First step is therefore measurement, not a fix:** establish the documented `user_data` limit for the
hcloud API, then decide whether the forwarding path needs its own bound with its own name and its own
error message. If the limit turns out to sit above 1 MiB, the correct outcome is to close this and
record why.
**Not a duplicate of #6611**, which is about the marker denylist failing to converge over shell
spellings. This is about the size bound on the forwarding path.
**Acceptance criteria**
- The hcloud `user_data` ceiling is established from primary documentation and recorded here.
- Either the forwarding path gets its own named bound with a local, actionable error, or this is
closed with the measured reason.
- Whichever way it goes, the two roles of `maxDecodedUserDataBytes` are no longer implicit.
**Size:** small.
Contributor guide
Research direction
Start with validateProviderUserData and DeriveServerSpecs, tracing maxDecodedUserDataBytes through inspection and forwarding into CreateServerOpts.UserData. Check the primary hcloud API documentation to establish the user_data ceiling. Done means separating the two bounds with an actionable local error, or recording why no change is needed if the measured limit exceeds 1 MiB.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- cloud
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100