Repository navigation
fix(profiles): share the Kubernetes image reference rule - #2372
Conversation
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.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
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.
|
Codex review: blocked before merge. What this changesThis PR shares Kubernetes-compatible image-reference validation across profile rendering, Compute, Helm, and deployment tools. Example: Use [fd00::1]:5000/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete 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 Before merge
Findings
Tests
Agent review detailsHow this fits togetherOperator 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
Technical reviewBest 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:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against cd046a062fe3. Provenance checked
TestingProof path: in-process harness. SecurityNone. EvidenceWhat I checked:
Likely related people:
Review metrics
LabelsLabel changes:
Label justifications:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale6/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. WorkflowClawSweeper edits this one comment on every review. Comment Reviewed October 13, 2026, 7:19 PM ET / 23:19 UTC. |
Problem
Image references were checked by five different rules (profile preflight, Compute, the chart's
images.*/repositoryCredentials.image, the chart'slogging.collector.image, and the bash tools). None matched Kubernetes:InvalidImageNameat 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.[::1]:5000/img@sha256:..., which Kubernetes accepts) were refused byimages.*,controllerImage,repository.imageand both bash tools, but accepted by the Collector,runtime.imageand Compute.Change
packages/occ/src/image-reference.ts:imageReferenceProblem(image), a port of distribution/reference v0.6.0ParseNormalizedNamed(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 returnsuppercase-repository,invalid, or nothing.controlPlane.controllerImage,runtime.imageandrepository.image; each still requires a lowercase@sha256:digest.requireImmutableDigest.prepare-bootstrap-volumeandupgrade-production-imagescall it throughscripts/lib/image-reference-problem.mjs.prepare-bootstrap-volumenow quotes the image in its Pod manifest, so a bracketed IPv6 host stays a string.openclaw.validateImageReferencein_helpers.tplapplies the same steps with Helm's Go regexp andlower, forimages.*,repositoryCredentials.imageandlogging.collector.image. IPv6 registry hosts are now accepted everywhere.... repository path must be lowercasefor 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 asRUNTIME_IMAGE_INVALID(covered inconfiguration-startup.test.mjs).upgrade-production-imagesfingerprints the rule and its helper inparameters.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) andproduction-image-upgrade.test.mjs(all three image flags).Verification
github.com/distribution/referencev0.6.0 agrees withimageReferenceProblemon all 66 table cases and on accept/refuse for 141,685 unique fuzzed references (16,085 accepted). The Helm define, rendered by Helm 3.19.2 in a minimal chart, agrees with the same Go program on about 2,500 unique fuzzed references with a SHA-256 digest.node --testonprofile-preflight-chart-parity,bootstrap-volume,production-image-upgrade,logging-packaging,production-kubernetes-packaging,configuration-startup,observability-demo-chartandtests/conformance/kubernetes-compute.test.mjs: all pass.taskset -c 0,1), on d19ebdd; f576f70 only changes a resume error string and one docs sentence.tsc --build apps/controller/tsconfig.json, eslint and prettier on the touched files, the workspace and module boundary checks: clean.git merge-treeshows no new conflicted file or hunk compared with main.Risks
helm template, the tools or startup. Kubernetes could not pull those images anyway.upgrade-production-imagesalready required it;prepare-bootstrap-volumeruns from the same checkout as the Node-based profile renderer and resolves its helper through symlinks.