fix(cloudflare): declare Container's network shape, and correct the documented example - #1763
Open
Cyberistic wants to merge 1 commit into
Open
Cyberistic wants to merge 1 commit into
Cyberistic wants to merge 1 commit into
Conversation
…ocumented example
The doc example for `Cloudflare.Container` could not work: it used
`network: { assignIpv4: "predefined", mode: "public" }`, but the API takes
snake_case `assign_ipv4` and rejects the camelCase spelling with
`configuration.network: unrecognized key: "assignipv4"`.
It could not fail any earlier either. The generated schema types the whole
object as `unknown` (`network: S.optional(S.NullOr(S.Unknown))` in the distilled
containers service) and alchemy inherited that, so copying the example compiled
cleanly and only failed at deploy.
Two things follow from declaring the shape, and running real deploys showed the
rules are tighter than the example suggests:
- `assign_ipv4: "predefined"` is not a neutral "give it an address" — it requests
public reachability, so the API infers `mode: "public"` when `mode` is omitted
and rejects it on an account that only permits private.
- `assign_ipv4` and `mode: "private"` are mutually exclusive; combining them is
refused with `assigning an IP with network mode private is not allowed`.
So the example now shows the private shape, which deploys anywhere, and the
notes state both rules. `Network` is declared locally as `Constraints` and
`Affinities` already are, which turns a misspelled key into a compile error.
Measured with a throwaway stack (`--stage probe`), varying only the `network`
block, destroyed afterwards:
{ assignIpv4: "predefined" } -> unrecognized key "assignipv4"
{ assign_ipv4: "predefined" } -> infers public; not allowed on a private-only account
{ assign_ipv4: "predefined", mode: "private" } -> assigning an IP with network mode private is not allowed
{ assign_ipv4: "none", assign_ipv6: "none", mode: "private" } -> accepted
The type test asserts each rule; it reports 4 errors against the inherited
`unknown` and compiles clean with the declaration.
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.
Fixes #1761.
What
Two changes, both needed:
Networkis declared instead of inheritingunknown, which is what turns the mistake into a compile error rather than a deploy-time rejection.The doc example could not work
It also could not fail any earlier: the generated schema types the whole object as
unknown, and alchemy inherited that:So copying the example type-checked cleanly and only failed at deploy. The same is true of a key typed from memory.
What measuring showed
I ran real deploys varying only the
networkblock (throwaway stack,--stage probe, destroyed afterwards), and the rules are tighter than the docs suggest:network{ assignIpv4: "predefined" }unrecognized key: "assignipv4"{ assign_ipv4: "predefined" }network.mode: "public" is not allowed for this account, only "private"{ assign_ipv4: "predefined", mode: "private" }network.assign_ip: assigning an IP with network mode private is not allowed{ assign_ipv4: "none", assign_ipv6: "none", mode: "private" }Two consequences the example did not convey, and which the type declaration and the docs notes now do:
assign_ipv4: "predefined"impliesmode: "public". With nomodegiven, the API inferred public and rejected it on an account restricted to private — sopredefinedis a public-networking request spelled in a different field, not a neutral "give it an address".assign_ipv4andmode: "private"are mutually exclusive. Combined with the account restriction, a private-only account has no usableassign_ipv4value at all and must set"none".I have therefore replaced the example with the private shape (which deploys anywhere) rather than merely re-spelling the old one, and documented both rules on the type.
NetworkDeclared locally, for the same reason
ConstraintsandAffinitiesalready are in this file — the generated schema is opaque, so anything not declared here cannot be type-checked:Tests
test/types/ContainerNetwork.ts, following the existing type-test convention (test/types/, checked bytsc -b). Each rule is a@ts-expect-error, which is a real check in both directions: if the type wrongly accepts, the directive itself becomes an error.Verified both ways — against the inherited
unknownthe file reports 4 errors; with the declaration it compiles clean, andpnpm exec tsc -bis clean across the workspace.Not done, deliberately
The type does not express the
assign_ipv4+mode: "private"exclusion, becauseNetworkis a single object type and that rule is a cross-field constraint. A union of accepted combinations could encode it, but that is a heavier change than a doc correction warrants and it would fight the optional-key ergonomics. Happy to do it if you would prefer the constraint enforced rather than documented.Scope
Cloudflare.Containeras declared for an image/context container (the.main/.imagepath); the effect-native.make()variant was not exercised.