Skip to content

fix: use strict_booleans to avoid YAML 1.1 boolean key parsing#52

Merged
andyyu2004 merged 2 commits intoandyyu2004:masterfrom
hardbyte:fix/strict-booleans-yaml12
Apr 1, 2026
Merged

fix: use strict_booleans to avoid YAML 1.1 boolean key parsing#52
andyyu2004 merged 2 commits intoandyyu2004:masterfrom
hardbyte:fix/strict-booleans-yaml12

Conversation

@hardbyte
Copy link
Copy Markdown
Contributor

@hardbyte hardbyte commented Apr 1, 2026

Problem

Kustomizer fails to parse Kubernetes CRD resources that use YAML 1.1 boolean words (on, off, yes, no) as map keys:

Error: load resource postgrespolicy.yaml
Caused by: parsing resource: invalid type: boolean `true`, expected a string key at line 1, column 1

This happens because serde-saphyr defaults to YAML 1.1 boolean parsing, where on is parsed as boolean true. When #[serde(flatten)] in the Res struct buffers map entries, the boolean key can't be deserialized into the Map<String, Value> which requires string keys.

Reproduction

Any CRD with on: as a field name triggers this. For example, the pgroles PostgresPolicy CRD uses on in grant definitions:

apiVersion: pgroles.io/v1alpha1
kind: PostgresPolicy
metadata:
  name: test-policy
spec:
  profiles:
    editor:
      grants:
        - on: { type: schema }
          privileges: [USAGE]

Fix

Enable strict_booleans: true in serde_saphyr::Options. This switches to YAML 1.2 behavior where only true/false are booleans. Fields like login: true and inherit: false continue to work correctly, while on/off/yes/no are treated as plain strings.

This also avoids the broader Norway problem class of YAML 1.1 issues.

Test plan

  • Verified the fix resolves the PostgresPolicy CRD parsing failure
  • cargo test --lib passes (9/9 unit tests)
  • Integration tests require kustomize binary and are unrelated to this change

Enable `strict_booleans` in serde-saphyr options so that only
`true`/`false` are parsed as booleans (YAML 1.2 behavior).

YAML 1.1 treats `on`/`off`/`yes`/`no` as booleans, which causes
`#[serde(flatten)]` to fail when these words appear as map keys in
Kubernetes CRD resources. The flatten buffering layer stores the key
as boolean `true`, then errors with "expected a string key" when
reconstructing the `Map<String, Value>`.

This was hit in practice with a PostgresPolicy CRD that uses an `on`
field in grant definitions:

    grants:
      - on: { type: schema }
        privileges: [USAGE]

With this fix, `on` is treated as a plain string key while `login: true`
and `inherit: false` continue to work as booleans.
@andyyu2004
Copy link
Copy Markdown
Owner

I thought I had test cases for this. Can you make sure to add a regression test. Does kustomize not suffer from the same issue? I'm pretty sure kubernetes uses yaml 1.1

@andyyu2004
Copy link
Copy Markdown
Owner

Ok, looks good regarding existing tests. I would like a few more testing these yaml 1.1 vs 1.2 cases to ensure compat with kustomize, then will be happy to approve.

…olean key

- Make options a `const DESER_OPTS` instead of a function
- Add regression test with a CRD using `on:` as a map key alongside
  `login: true` and `inherit: false` boolean values
@hardbyte
Copy link
Copy Markdown
Contributor Author

hardbyte commented Apr 1, 2026

Thanks for the quick review, pushed updates:

  • const DESER_OPTS — made it a const as suggested
  • Regression test added in testdata/regression/yaml11-boolean-key/ — a CRD with on: as a map key alongside login: true and inherit: false.

Re: kustomize compatibility, kustomize (Go) uses sigs.k8s.io/yaml which also uses YAML 1.1 booleans, but it doesn't hit this bug because Go's map[string]interface{} coerces all keys to strings regardless. The issue is specific to Rust's serde #[serde(flatten)] which buffers entries and then fails when a boolean key can't be used as a String map key.

@andyyu2004 andyyu2004 merged commit fda6623 into andyyu2004:master Apr 1, 2026
1 check passed
@andyyu2004
Copy link
Copy Markdown
Owner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants