Skip to main content

is_chart_maintainer_name_shape

Function is_chart_maintainer_name_shape 

Source
pub fn is_chart_maintainer_name_shape(s: &str) -> Result<(), String>
Expand description

Predicate: assert that s is a valid chart-maintainer-name shape. The :autores axis is a per-entry maintainer identifier that lands in the rendered lareira-<nome> Helm chart’s Chart.yaml maintainers: [{name: …, email: null}] array via [caixa-helm]’s build_chart_yaml (caixa-helm/src/lib.rs:251); each entry becomes the name: value of a single Maintainer record (a YAML scalar consumed by helm list, helm search, Artifact Hub’s maintainer index, and every chart-aware UI). The contract — modeled on the same YAML 1.2 plain-style scalar grammar is_chart_description_shape enforces on the sibling :descricao axis, with a tighter length cap for the per-entry identifier class:

  • 1..=CHART_MAINTAINER_NAME_MAX_LEN (128) bytes;
  • no leading whitespace (paste-from-aligned-doc footgun — YAML plain-style scalars round-trip trim-and-restore on leading whitespace, so an authored " pleme-io" lands as "pleme-io" in the rendered Chart.yaml and the round-trip back through caixa.lisp silently drops the space);
  • no trailing whitespace (paste-from-doc footgun — every YAML dumper trims trailing whitespace from plain-style scalars, so an authored "pleme-io " round-trips inconsistently);
  • no ASCII control characters anywhere (0x00..=0x1F plus 0x7F DEL) — tabs, newlines, carriage returns, and every other control byte break the single-line YAML scalar shape and the helm list / helm search / Artifact Hub maintainer-column rendering. The newline / CR arms are the canonical paste-from-multiline-doc footgun (the author pasted a multi-line block of author records into one :autores entry instead of splitting them into one entry per author); the tab arm is the canonical paste-from-aligned-doc footgun; the other-control-byte arm catches every more-exotic paste-from-binary-blob shape;
  • non-ASCII bytes (UTF-8 continuation sequences) are accepted — realistic maintainer names carry Unicode ("François", "日本語", "naïve") and every downstream consumer (YAML 1.2, Helm v3, every chart-aware UI) round-trips Unicode losslessly;
  • no Unicode bidirectional-override / isolate format codepoints (U+202A LRE, U+202B RLE, U+202C PDF, U+202D LRO, U+202E RLO, U+2066 LRI, U+2067 RLI, U+2068 FSI, U+2069 PDI) — the nine codepoints UAX #9 names as the structural prerequisite of the “Trojan Source” attack class (CVE-2021-42574). A maintainer-name with an embedded RLO flips the visual order of every trailing byte, so an :autores "alice\u{202E}example.com<bob@" (the paste-from-attacker-crafted-doc footgun) renders in helm list’s maintainer column / Artifact Hub as alice<@bob>moc.elpmaxe but rides verbatim into the rendered Chart.yaml maintainers: array — same Trojan Source class is_chart_description_shape closes on the sibling :descricao axis. Routed through the same lifted [find_unicode_bidi_override] helper so the nine-codepoint accepted set is shared, structurally consistent.
  • no non-ASCII Unicode line-break codepoints (U+0085 NEL, U+2028 LS, U+2029 PS) — the three codepoints UAX #14 (Unicode Line Breaking Algorithm) and YAML 1.1 §4.1 b-char production both treat as line terminators outside the ASCII \n / \r arms above. YAML 1.2 §5.4 retired them per UTR #20 so the cross-parser line-break disagreement (go-yaml v2 / YAML 1.1 still splits; YAML 1.2-strict parsers preserve) breaks the THEORY.md §V.2 render- determinism contract on the same axis the per-byte \n / \r arms close for ASCII. A maintainer-name with an embedded U+2028 parses as one entry through a YAML 1.2 parser and as two maintainers: array entries through a YAML 1.1 parser — same paste-from-multiline-doc class the \n arm above closes, extended to the non-ASCII line-break codepoints the per-byte non-ASCII pass deliberately admits for Unicode letters. Routed through the same lifted [find_unicode_line_break] helper so the three-codepoint accepted set is shared with is_chart_description_shape on the sibling YAML-plain-style-scalar surface, structurally consistent.
  • no Unicode invisible-format codepoints (U+00AD SHY, U+200B ZWSP, U+2060 WJ, U+2061 FA FUNCTION APPLICATION, U+2062 IT INVISIBLE TIMES, U+2063 IS INVISIBLE SEPARATOR, U+2064 IP INVISIBLE PLUS, U+FEFF ZWNBSP / BOM) — the eight BMP Cf-category zero-width codepoints with no visible glyph. A maintainer-name with an embedded U+200B ("alice\u{200B}") renders identically to "alice" in helm list / Artifact Hub’s maintainer column, yet the byte sequence is distinct — the Artifact Hub maintainer-index lookup misses the authored "alice" entry, and a future CLA-signer lookup matches a visually- identical-but-byte-distinct identity (the canonical invisible-codepoint homograph footgun on the maintainer- identity axis). Closes the canonical paste-from-Microsoft- Word (SHY), paste-from-text-editor-saved-as-UTF-8-with-BOM (BOM), paste-from-typesetting-doc (ZWSP / WJ), and paste-from-MathJax/LaTeX-rendered-formula (FUNCTION APPLICATION / INVISIBLE TIMES / INVISIBLE SEPARATOR / INVISIBLE PLUS — math-formula invisible operators MathJax / LaTeX2RTF / InDesign emit between symbols for screen-reader operator semantics) footguns. Routed through the same lifted [find_unicode_invisible_format] helper so the eight-codepoint accepted set is shared with is_chart_description_shape, third lift in the UAX- driven render-determinism trio (peer of [find_unicode_bidi_override] on the visual-order axis and [find_unicode_line_break] on the single-line/multi- line axis). The eight-codepoint set excludes U+200C ZWNJ / U+200D ZWJ (emoji ZWJ sequences are canonical for modern maintainer-display names) and U+200E LRM / U+200F RLM (mixed-script direction hints are canonical for “Arabic name with embedded ASCII email” shapes).

Same structural single-line printable-UTF-8 floor as is_chart_description_shape — both :descricao and :autores land as YAML plain-style scalars in the same Chart.yaml and share every paste-from-doc footgun the YAML 1.2 grammar refuses at parse time. The two predicates differ only on the byte length cap: 512 bytes for :descricao (multi-sentence prose shape) vs 128 bytes for :autores entries (short-identifier shape). Returns the parser-shaped reason on rejection (without wrapping in any error variant) so each per-axis caller — crate::Caixa::validate_autores for the universal :autores axis at validate time, every future per-maintainer-name axis (a future caixa-registry maintainer-index entry, a future chart-author CLA-signer lookup) — wraps the same reason in its own typed *Invalid { <axis>, reason } variant.

Empty input is rejected here (defensively) and at each call site via the narrower crate::ManifestError::AutorEmpty variant — the same empty-first cascade is_dns_1123_label, is_gateway_api_http_path, is_wit_world_ref, is_nats_subject, is_wasi_keyvalue_slot, is_git_ref_name, is_git_oid, is_git_repo_url, is_cargo_feature_name, is_spdx_expression_shape, and is_chart_description_shape all carry.

§Errors

Returns the parser-shaped reason naming the specific violation (length / leading-whitespace / trailing-whitespace / tab / newline / carriage-return / other-control-byte / Unicode-bidi-override-codepoint), without wrapping in any error variant — every caller maps the same String into its own typed *Invalid { <axis>, reason } enum variant.