Skip to content

fix(profiles): share the Kubernetes image reference rule - #2372

Merged
freeqaz merged 3 commits into
mainfrom
fix-1280-1281
Oct 13, 2026
Merged

freeqaz merged 3 commits into
mainfrom
fix-1280-1281

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Image references were checked by five different rules (profile preflight, Compute, the chart's images.*/repositoryCredentials.image, the chart's logging.collector.image, and the bash tools). None matched Kubernetes:

  • All of them accepted references Kubernetes refuses as InvalidImageName at pull time: .., a leading hyphen, a trailing or triple underscore or an empty component in the path; a host with a trailing dot; a tag over 128 characters or starting with .; a repository path over 255 characters; a tag followed by more path.
  • runtime.image, the Collector and Compute also accepted non-ASCII letters (including non-ASCII uppercase such as É and the Kelvin sign), zero-width characters and NBSP; Compute alone accepted two digests, a leading space, @ in the path, an IPv6 zone ID and a host starting with a hyphen.
  • IPv6 registry hosts ([::1]:5000/img@sha256:..., which Kubernetes accepts) were refused by images.*, controllerImage, repository.image and both bash tools, but accepted by the Collector, runtime.image and Compute.

Change

  • packages/occ/src/image-reference.ts: imageReferenceProblem(image), a port of distribution/reference v0.6.0 ParseNormalizedNamed (Docker Hub normalization, the lowercase repository check, the reference grammar, the 255-character path limit, the bare image ID refusal) plus go-digest v1.0.0 digest validation. It returns uppercase-repository, invalid, or nothing.
  • Profile preflight uses it for controlPlane.controllerImage, runtime.image and repository.image; each still requires a lowercase @sha256: digest.
  • Compute uses it for the gateway and Agent images, with or without requireImmutableDigest.
  • prepare-bootstrap-volume and upgrade-production-images call it through scripts/lib/image-reference-problem.mjs. prepare-bootstrap-volume now quotes the image in its Pod manifest, so a bracketed IPv6 host stays a string.
  • The chart cannot share JS, so openclaw.validateImageReference in _helpers.tpl applies the same steps with Helm's Go regexp and lower, for images.*, repositoryCredentials.image and logging.collector.image. IPv6 registry hosts are now accepted everywhere.
  • Error messages are unchanged: ... repository path must be lowercase for an uppercase repository, the field's existing immutable-image message otherwise; Compute adds ... image must be a container image reference Kubernetes can pull., which API and worker startup report as RUNTIME_IMAGE_INVALID (covered in configuration-startup.test.mjs).
  • upgrade-production-images fingerprints the rule and its helper in parameters.json.
  • tests/fixtures/image-reference-cases.mjs: 66 cases with Kubernetes' verdict, used by new table tests in the preflight/chart parity test (preflight, Compute in both digest modes, and all three chart fields), bootstrap-volume.test.mjs (the helper runs end to end with its fake kubectl and writes accepted references into the Pod as written) and production-image-upgrade.test.mjs (all three image flags).
  • Docs: the 2026-10-13 breaking-change entry gains a clause; the profile guide and rendering flow describe the shared rule.

Verification

Risks

  • Breaking, as noted in breaking-changes.md: profiles, values or tool flags that used one of the refused spellings now fail preflight, helm template, the tools or startup. Kubernetes could not pull those images anyway.
  • The two bash tools now need Node.js 24 to check images. upgrade-production-images already required it; prepare-bootstrap-volume runs from the same checkout as the Node-based profile renderer and resolves its helper through symlinks.
  • The chart define duplicates the TS rule; the table tests pin them together.

Preflight, Compute, the chart and the image tools each had their own
image rule: ASCII-only, laxer than Kubernetes (.., empty components,
long tags, unicode), and split on IPv6 registry hosts.

Add imageReferenceProblem in packages/occ, a port of
distribution/reference ParseNormalizedNamed plus go-digest, and use it
in profile preflight, Compute and (through a small Node helper)
prepare-bootstrap-volume and upgrade-production-images. The chart gets
the same steps in openclaw.validateImageReference for images.*,
repositoryCredentials.image and logging.collector.image, and now
accepts IPv6 registry hosts. prepare-bootstrap-volume quotes the image
in its Pod manifest so a bracketed host stays a string.

A shared case table pins every caller to Kubernetes' verdict.
@freeqaz
freeqaz requested a review from a team as a code owner October 13, 2026 23:04
@clawsweeper

clawsweeper Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Oct 13, 2026
Review follow-ups:
- API and worker startup map Compute's new "must be a container image
  reference Kubernetes can pull" refusal to RUNTIME_IMAGE_INVALID
  instead of a bare STARTUP_FAILED; configuration-startup covers it.
- prepare-bootstrap-volume resolves its helper through symlinks and
  ignores CDPATH; both tools check the helper exists and word the node
  failure accurately.
- upgrade-production-images fingerprints the image reference rule and
  its helper in parameters.json.
- The case table covers the 255-character path limit for an unparsable
  dotted host and for an explicit docker.io host.
Review nits: the upgrade resume refusal names the image rule the fingerprint now covers, and the breaking-change steps cover references Kubernetes cannot parse, not only uppercase paths.
@freeqaz
freeqaz deployed to integration-qa-pr October 13, 2026 23:15 — with GitHub Actions Active
@freeqaz
freeqaz deployed to integration-qa-pr October 13, 2026 23:15 — with GitHub Actions Active
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Oct 13, 2026
@clawsweeper

clawsweeper Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Codex review: blocked before merge.

What this changes

This PR shares Kubernetes-compatible image-reference validation across profile rendering, Compute, Helm, and deployment tools.

Example: Use [fd00::1]:5000/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.

  • Before: The controller-image chart rule and bootstrap tool reject the bracketed registry host.
  • After: Both accept the reference while retaining the immutable SHA-256 requirement.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Useful repair with independent parser comparisons and meaningful caller coverage; the installation-guidance defect and unresolved compatibility gate prevent a merge-ready verdict.
Proof confidence 🦐 gold shrimp (3/6) The supplied maintainer-author classification exempts the ordinary contributor proof gate; reported renderer, Helm, Compute, and tool checks support parser parity, but the persisted parameters.json additions lack an existing-state upgrade/resume demonstration, and the prepared role-sharing screenshots concern unrelated behavior.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Operators can pass validation with image references Kubernetes later refuses, while some deployment paths reject valid IPv6 registry references.
Reason: The inconsistent rules create real deployment failures; the supplied maintainer-author classification establishes approval for the documented validation cutover.

Merge readiness

⛔ Blocked before merge - 2 items remain

Keep open for maintainer triage: this PR addresses image-validation drift still present on main and preserves valid IPv6 registry references.

Priority: P2
Reviewed head: f576f701b0e49f00261cdaad0bcf605b19976834

Before merge

  • Document Node.js as a prerequisite for manual installation (P2) - Every valid bootstrap image now executes host Node.js here. The supported manual-YAML path in docs/guides/deploy/production-installation.md:119-122 explicitly says Node.js is unnecessary and then requires prepare-bootstrap-volume at line 387. An operator following that path without Node now stops before PVC preparation despite satisfying the documented prerequisites. Update the manual installation guidance and the bootstrap preparation step to require Node.js 24+, and remove the obsolete no-Node promise.
  • Add data-model compatibility proof - The review found that existing stored data may not work after upgrade. Show that existing data still loads and works with this change.

Findings

  • [P2] Document Node.js as a prerequisite for manual installation — scripts/prepare-bootstrap-volume:90-93

Tests

  • Missing end-to-end proof: No supplied existing-state upgrade and resume run demonstrates retained Installation settings and safe handling of the changed parameters.json record.
Agent review details

How this fits together

Operator image references enter through profiles, Helm values, deployment flags, and Installation configuration; validation either rejects them before deployment or passes the original references into Kubernetes workloads.

flowchart TD
  A[Operator image references] --> B[Profile renderer and deployment tools]
  A --> C[Helm values]
  A --> D[Compute configuration]
  B --> E[Shared OCC reference validator]
  D --> E
  C --> F[Matching Helm reference validator]
  E --> G[Validated workload images]
  F --> G
Loading

Technical review

Best possible solution:

Retain the shared validator, correct the operator prerequisites, and demonstrate safe existing-state upgrade and resume behavior.

Do we have a high-confidence way to reproduce the issue?

Current-main rules visibly accept malformed repository components and reject valid IPv6 references in selected callers; the added case table and reported base-versus-head runs cover these disagreements, but no target code was executed during this review.

Is this the best way to solve the issue?

Sharing the TypeScript rule and checking the necessary Helm equivalent against an independent parser oracle is appropriate; the implementation preserves the prior IPv6 acceptance decisions.

Full review comments:

  • [P2] Document Node.js as a prerequisite for manual installation — scripts/prepare-bootstrap-volume:90-93
    Every valid bootstrap image now executes host Node.js here. The supported manual-YAML path in docs/guides/deploy/production-installation.md:119-122 explicitly says Node.js is unnecessary and then requires prepare-bootstrap-volume at line 387. An operator following that path without Node now stops before PVC preparation despite satisfying the documented prerequisites. Update the manual installation guidance and the bootstrap preparation step to require Node.js 24+, and remove the obsolete no-Node promise.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.94

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against cd046a062fe3.

Provenance checked

Testing

Proof path: in-process harness.

Security

None.

Evidence

What I checked:

Likely related people:

  • freeqaz: Raw commit 362d86b adds scripts/render-installation-profile.mjs:4 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 362d86bb6507; files: scripts/render-installation-profile.mjs)
  • kevinlin-openai: Raw commit ee48017 adds scripts/render-installation-profile.mjs:3 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: ee4801774d14; files: scripts/render-installation-profile.mjs)
  • Eric Cai: Raw commit 177f576 adds scripts/render-installation-profile.mjs:870 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 177f57647b28; files: scripts/render-installation-profile.mjs)

Review metrics

Metric Value Why it matters
Production and regression coverage Production +216/-86; tests and fixtures +337/-19 The shared grammar replaces several weaker rules; most test growth exercises the same independent reference cases through distinct production callers.

Labels

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.

Label justifications:

  • P2: This is a bounded deployment-validation repair affecting malformed image references and valid IPv6 registry references.
  • merge-risk: 🚨 compatibility: The intended cutover rejects previously accepted configuration and introduces a host Node.js requirement for bootstrap preparation; upgrade-record compatibility also requires evidence.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action.

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Supply an existing-state upgrade/resume trace showing settings remain intact and incompatible evidence records stop before mutation.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

Reviewed October 13, 2026, 7:19 PM ET / 23:19 UTC.

@freeqaz
freeqaz merged commit e2c845b into main Oct 13, 2026
51 checks passed
@freeqaz
freeqaz deleted the fix-1280-1281 branch October 13, 2026 23:36

This branch was successfully deployed

1 active deployment
integration-qa-pr — f576f701 Deployed Oct 13, 2026 by freeqaz via QA advisory (kubernetes) #747
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant