Commit 0134412
fix(onboard): release the dashboard port reservation (#9569)
<!-- markdownlint-disable MD041 -->
## Summary
Created-sandbox finalization invokes the dashboard port release callback
through its dashboard object. The callback previously read that object
instead of the original reservation scope, so the host port remained
bound. The callback now closes over the original scope, and a real
loopback test protects this contract.
## Related Issue
Fixes #9568
## Changes
- Add a fail-first loopback test that invokes the extracted callback
through the object-property call used by created-sandbox finalization.
- Make the dashboard port release callback read and clear its original
reservation scope, independent of the call receiver.
- Preserve the build-time reservation, release-before-forwarding order,
and failure cleanup established by #8798 and #8863.
E2E root cause:
`32209785348/dashboard-reservation/unbound-release-receiver`
Source run:
[32209785348](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348)
(run 32209785348, attempt 1, commit
`9d75205307d70c820c9f8000edc2257ce6744460`)
Failed jobs:
- [`cloud-onboard`
(95940197627)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940197627)
- [`hermes-e2e`
(95940197656)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940197656)
- [`Onboarding: repairs a missing sandbox and rejects conflicting resume
input`
(95940197969)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940197969)
- [`Health: treats a 401 authentication response as reachable`
(95940197990)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940197990)
- [`Inference: OpenClaw switches providers and remains responsive`
(95940197991)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940197991)
- [`Inference: rejects unsafe routes and proves runtime identities`
(95940198016)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198016)
- [`Network policy: enforces restricted allow and deny rules`
(95940198049)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198049)
- [`Authorization: approves a write-scope upgrade without
operator.admin`
(95940198056)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198056)
- [`Onboarding: resumes interrupted setup from recorded progress`
(95940198061)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198061)
- [`Rebuild: preserves Hermes state and recovers cron dispatch`
(95940198079)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198079)
- [`Backup: restores workspace files and memory`
(95940198088)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198088)
- [`OpenClaw: installs, onboards, and completes an agent turn`
(95940198127)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198127)
- [`Security: Hermes retains the required sandbox posture`
(95940198149)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198149)
- [`Upgrade: preserves v0.0.36 state on x86-64`
(95940198181)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198181)
- [`Inference: OpenClaw uses hosted inference`
(95940198182)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198182)
- [`Upgrade: preserves v0.0.74 state on x86-64`
(95940198183)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198183)
- [`Rebuild: preserves OpenClaw state and rotates the gateway token`
(95940198190)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198190)
- [`Security: OpenClaw retains the required sandbox posture`
(95940198200)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198200)
- [`Upgrade: preserves v0.0.55 state on x86-64`
(95940198203)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198203)
- [`Upgrade: preserves v0.0.55 state on Arm64`
(95940198235)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198235)
- [`Upgrade: migrates v0.0.89 state on x86-64`
(95940198258)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95940198258)
- [`ubuntu-repo-cloud-langchain-deepagents-code`
(95945453609)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95945453609)
- [`ubuntu-repo-cloud-openclaw`
(95945453613)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95945453613)
- [`ubuntu-policy-custom-missing-presets-negative`
(95945453618)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95945453618)
- [`ubuntu-repo-docker-post-reboot-recovery`
(95945453626)](https://github.com/NVIDIA/NemoClaw/actions/runs/32209785348/job/95945453626)
Signature: `Could not allocate a dashboard port`; `Dashboard port 18789
became host-bound during sandbox build; cannot reallocate to 18790`
after `CHAT_UI_URL=18789`.
Commit under review: `0f2ec3fcb7d70884fd529f808cef91d5bd15cb72` against
base `7afe39541e81f70d9e1aa39c49415084d8276524`.
- Fail-first commit `72a0eab6609ce9b32f1c104b05c12b3fec613132`: the
dashboard-port test file reported 32 passes and one failure. The new
test showed that `scope.current` still held the live reservation after
the extracted callback returned.
- Product correction `67327620caea9247565b6a28b754a07a5f21ddaf`: the
callback closes over the original scope instead of reading its call
receiver.
- Reconciled commit under review
`0f2ec3fcb7d70884fd529f808cef91d5bd15cb72`: the two focused CLI test
files passed all 45 tests, including all 33 dashboard-port tests. `npm
run typecheck:cli` passed. The growth-guardrail test file passed all 32
tests.
Scope: one root cause.
## Type of Change
- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)
## Quality Gates
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — [independent nine-category security review
PASS](#9569 (comment))
for `0f2ec3fcb7d70884fd529f808cef91d5bd15cb72` against
`7afe39541e81f70d9e1aa39c49415084d8276524`; no findings.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:
## DGX Station Hardware Evidence
- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:
## Verification
- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npm exec -- vitest run --project cli
src/lib/onboard/dashboard-port.test.ts
src/lib/onboard/created-sandbox-finalization.test.ts`: 45 passed,
including 33 dashboard-port tests; `npm run typecheck:cli`: passed; `npm
exec -- vitest run --project integration
test/growth-guardrails.test.ts`: 32 passed.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
---
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Fixed dashboard port reservation cleanup so released reservations
reliably allow the port to be reused.
- **CI/CD**
- Added secure validation for public container image digests on Linux
AMD64.
- Added bounded retries for transient image visibility delays while
failing immediately on other errors.
- Improved temporary credential isolation and cleanup during image
checks.
- **Tests**
- Added coverage for dashboard port release behavior, digest validation,
retry handling, cleanup, and workflow watch triggers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Prekshi Vyas <34834085+prekshivyas@users.noreply.github.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>1 parent d7c33bf commit 0134412
2 files changed
Lines changed: 32 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
43 | 48 | | |
44 | 49 | | |
45 | 50 | | |
| |||
363 | 368 | | |
364 | 369 | | |
365 | 370 | | |
366 | | - | |
| 371 | + | |
367 | 372 | | |
368 | 373 | | |
369 | 374 | | |
| |||
375 | 380 | | |
376 | 381 | | |
377 | 382 | | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
378 | 406 | | |
379 | 407 | | |
380 | 408 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
610 | 610 | | |
611 | 611 | | |
612 | 612 | | |
613 | | - | |
614 | | - | |
615 | | - | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
616 | 616 | | |
617 | 617 | | |
618 | 618 | | |
| |||
0 commit comments