Skip to content

feat(provider): add Unikraft Cloud service provider#986

Open
zozo123 wants to merge 7 commits into
openclaw:mainfrom
zozo123:feat/unikraft-cloud-provider
Open

feat(provider): add Unikraft Cloud service provider#986
zozo123 wants to merge 7 commits into
openclaw:mainfrom
zozo123:feat/unikraft-cloud-provider

Conversation

@zozo123

@zozo123 zozo123 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a built-in unikraft-cloud provider for creating, inspecting, listing, and deleting claimed Unikraft Cloud OCI-image microVM services.
  • Wire Unikraft Cloud config/env provenance, provider registration, docs, and generated provider matrix metadata.
  • Cover client safety, auth redaction, claim-scoped cleanup, run rejection, status/list/stop behavior, and provider registration with focused tests.

Test plan

  • go test ./internal/providers/unikraftcloud ./internal/providers/all ./internal/cli
  • go test ./cmd/crabbox
  • node scripts/generate-provider-matrix.mjs --check
  • node scripts/check-command-docs.mjs
  • node scripts/check-docs-links.mjs
  • git diff --check

Made with Cursor

Co-authored-by: Cursor <cursoragent@cursor.com>
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed July 9, 2026, 3:49 AM ET / 07:49 UTC.

Summary
The PR adds a built-in Unikraft Cloud service-control provider with CLI config/env/flags, provider registration, docs/provider metadata, an API client/backend, and focused tests.

Reproducibility: not applicable. for the feature itself. For the retained review finding, the current merge result still shows the direct CHANGELOG.md addition at line 7.

Review metrics: 3 noteworthy metrics.

  • Provider Surface: 1 built-in provider added. A new provider changes the public provider list, config schema, docs matrix, lifecycle behavior, and support surface.
  • Diff Size: 18 files, +2425/-2. The provider/docs/test addition is broad enough that maintainers should notice the ownership decision before merge.
  • Live Proof: 1 redacted terminal transcript. The proof covers create, status, list, stop, raw API verification, direct deleted-UUID lookup, and zero residue.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Remove the direct CHANGELOG.md edit before merge.

Risk before merge

  • [P1] Merging would make Crabbox core own a new funded remote service-control provider and its support surface; CI cannot decide whether that belongs built-in or external.
  • [P1] The branch still edits release-owned CHANGELOG.md, which should be removed before ordinary merge even though it is a small cleanup.

Maintainer options:

  1. Approve Built-In Ownership After Cleanup (recommended)
    Accept the support-surface risk after the direct changelog edit is removed and ordinary merge gates pass.
  2. Keep Unikraft Cloud External
    Pause or close the PR if this funded service should not become a built-in Crabbox provider yet.
  3. Ask For Maintainer-Sponsored Live Smoke
    Require a maintainer-run or maintainer-sponsored live lifecycle proof before deciding core ownership.

Next step before merge

  • [P2] Needs human product-scope approval for adding Unikraft Cloud as a built-in funded provider; the contributor-facing fix is removing the release-owned changelog line.

Maintainer decision needed

  • Question: Should Crabbox accept Unikraft Cloud as a built-in service-control provider, or should this integration stay external for now?
  • Rationale: The adapter fits the provider boundary and has live zero-residue proof, but accepting a funded remote provider into core is a support and product-scope choice automation cannot make.
  • Likely owner: steipete — steipete has the strongest recent history on provider lifecycle safety and already authored Unikraft hardening commits on this branch.
  • Options:
    • Accept Built-In Provider (recommended): Approve this as a core service-control provider after the release-owned changelog line is removed and normal merge gates pass.
    • Keep It External For Now: Ask the contributor to maintain Unikraft Cloud outside the built-in provider list until Crabbox maintainers want to sponsor it in core.
    • Request Maintainer Live Smoke: Keep the PR open while a maintainer repeats or sponsors one more live create/use/destroy validation before accepting built-in scope.

Security
Cleared: No concrete security or supply-chain regression was found; the provider avoids API-key CLI flags, validates API URLs, redacts API-key echoes, and refuses cross-origin redirects.

Review findings

  • [P3] Remove the direct changelog edit — CHANGELOG.md:7
Review details

Best possible solution:

Land the provider only after maintainer acceptance of built-in Unikraft Cloud support, with the direct changelog line removed and release-note context preserved in the PR body or commits.

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

Not applicable for the feature itself. For the retained review finding, the current merge result still shows the direct CHANGELOG.md addition at line 7.

Is this the best way to solve the issue?

Unclear: the provider-local adapter approach and live proof fit the repository direction, but built-in provider acceptance remains a maintainer product decision. The release-owned changelog edit should be removed before merge.

Full review comments:

  • [P3] Remove the direct changelog edit — CHANGELOG.md:7
    CHANGELOG.md is release-owned in this review flow, so feature PRs should leave release-note wording to the release process. Please drop this line and keep the release-note context in the PR body or commit message instead.
    Confidence: 0.84

Overall correctness: patch is correct
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 7239e753df64.

Label changes

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): A PR comment provides a redacted live terminal transcript from a real Unikraft Cloud lifecycle run with zero-residue verification; later current-head commits are focused cleanup/error hardening.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a normal-priority provider feature with bounded blast radius but real product-scope and remote lifecycle review needs.
  • merge-risk: 🚨 other: Merging would add a funded remote service-control provider to core, and CI cannot settle the built-in ownership decision.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): A PR comment provides a redacted live terminal transcript from a real Unikraft Cloud lifecycle run with zero-residue verification; later current-head commits are focused cleanup/error hardening.
  • proof: sufficient: Contributor real behavior proof is sufficient. A PR comment provides a redacted live terminal transcript from a real Unikraft Cloud lifecycle run with zero-residue verification; later current-head commits are focused cleanup/error hardening.
Evidence reviewed

What I checked:

  • Repository policy read: AGENTS.md was read fully; its provider-neutral adapter boundary, generic example guidance, and secret-handling rules apply to this provider review. (AGENTS.md:1, 7239e753df64)
  • Vision scope check: VISION.md requires exact ownership for destructive lifecycle paths and real create/use/destroy proof with zero residue for funded or remote providers. (VISION.md:3, 7239e753df64)
  • Current main does not already implement this provider: A current-main search found no Unikraft/UKC provider implementation or docs, so the PR is not obsolete or implemented on main. (7239e753df64)
  • Provider registration: The PR registers unikraft-cloud with unikraftcloud and ukc aliases, service-control kind, Linux target, and coordinator disabled. (internal/providers/unikraftcloud/provider.go:18, 6d2b60979e4a)
  • Lifecycle ownership path: Warmup creates an instance and records an endpoint- and UUID-bound claim; stop requires that unchanged claim before stop/delete and keeps the claim when delete fails. (internal/providers/unikraftcloud/backend.go:73, 6d2b60979e4a)
  • API error hardening: The latest head maps Unikraft per-item missing-instance error 8 to HTTP 404 and rejects malformed success envelopes, covering the previous missing-instance review finding. (internal/providers/unikraftcloud/client.go:346, 6d2b60979e4a)

Likely related people:

  • steipete: Authored the latest Unikraft cleanup/malformed-response hardening commits on this branch and has recent current-main provider lifecycle safety history. (role: recent area contributor and likely product decision owner; confidence: high; commits: 6d2b60979e4a, e0dc40de32e6, c41c6e1cc740; files: internal/providers/unikraftcloud/backend.go, internal/providers/unikraftcloud/client.go, internal/cli/provider_backend.go)
  • zozo123: Beyond this PR, authored merged provider work including CubeSandbox that touched similar provider registration, config, docs, metadata, and credential-provenance surfaces. (role: recent adjacent provider contributor; confidence: medium; commits: 8c8a3c3e57ca, 52d272fbc45e; files: internal/providers/cubesandbox, internal/cli/config.go, internal/cli/credential_provenance.go)
  • Coy Geek: Recently authored a comparable provider integration with config, lifecycle ownership, docs, and safety tests. (role: adjacent provider lifecycle contributor; confidence: medium; commits: b2d058605239; files: internal/providers/sealosdevbox, internal/cli/config.go, docs/providers/README.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-06T15:16:52.390Z sha bbe1c20 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-08T07:52:07.409Z sha 9c79a26 :: needs changes before merge. :: [P2] Classify Unikraft missing-instance item errors
  • reviewed 2026-07-08T08:03:15.986Z sha 6427879 :: needs changes before merge. :: [P2] Classify Unikraft 200 missing-instance errors
  • reviewed 2026-07-09T07:42:30.016Z sha 6d2b609 :: found issues before merge. :: [P3] Remove the direct changelog edit

Co-authored-by: Cursor <cursoragent@cursor.com>
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 6, 2026
The Unikraft Cloud instance-create API expects `image` to be a JSON string
(e.g. "nginx:latest"), but the client serialized it as an object
{"url": "..."}. Live create requests failed with HTTP 400:
"'image' in instance creation arguments has type 'object', but expected
'string'", so warmup never provisioned an instance against the real API.

Verified end-to-end against api.fra.unikraft.cloud (metro fra):
warmup -> status --wait -> list -> stop, with zero residual instances
after cleanup (confirmed via crabbox list, raw API list, and direct
UUID lookup).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@zozo123

zozo123 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

✅ Live create → use → destroy proof (metro fra), + a correctness fix

Ran the full provider lifecycle against the real Unikraft Cloud API
(https://api.fra.unikraft.cloud, Authorization: Bearer <token>; token redacted throughout). This addresses the ClawSweeper P1 live-proof and zero-residue blockers.

🐛 Bug found by the live run (now fixed)

The create call serialized image as an object {"url": "..."}, but the API expects a string:

unikraft-cloud API error status=400: 'image' in instance creation arguments has type 'object', but expected 'string'

So warmup never provisioned an instance against the real service. Fixed in 9c79a26createInstanceRequest.Image is now a string (source + tests updated, go test ./internal/providers/unikraftcloud/ green). The proof below is from that commit.

🔒 Zero residue (three independent views + safety trap)

After stop, the instance is absent from crabbox list, the raw API GET /v1/instances, and a direct UUID lookup (No instance with uuid …). Baseline and post-run account listings are both empty. A hard cleanup trap force-deletes the created UUID even on mid-run failure — confirmed harmless (the earlier image-object failure created nothing).

Failed-cleanup path: if the local claim write fails after the remote create succeeds, cleanupCreateFailure deletes the orphaned instance before returning — unit-tested by TestWarmupCleansUpInstanceWhenClaimFails.

📜 Full redacted transcript (commit 9c79a26)
==================================================================
 crabbox unikraft-cloud provider — live smoke (metro=fra)
 crabbox commit: 9c79a26
==================================================================

## 0. BASELINE — account instances before test (independent: raw API)
{"status":"success","data":{"instances":[]}}


## 1. WARMUP (create instance from nginx:latest)
$ crabbox warmup --provider unikraft-cloud --unikraft-cloud-metro fra --unikraft-cloud-image nginx:latest --unikraft-cloud-memory 256 --slug ukc-smoke
leased ukc_119cc074-ef7d-4126-b898-4527c680fbee slug=ukc-smoke provider=unikraft-cloud instance=119cc074-ef7d-4126-b898-4527c680fbee state=starting fqdn=-
warmup complete total=344ms
-> captured UUID=119cc074-ef7d-4126-b898-4527c680fbee

## 2. STATUS --wait (poll until running)

$ /tmp/cbx/crabbox status --provider unikraft-cloud --unikraft-cloud-metro fra --id ukc-smoke --wait
ukc_119cc074-ef7d-4126-b898-4527c680fbee slug=ukc-smoke provider=unikraft-cloud target=linux windows_mode=- state=running type=unikraft-cloud-instance host= pond=- network=public ready=true has_host=false idle_for=- idle_timeout=- expires=-
(exit=0)

## 3. LIST (crabbox-owned instances)

$ /tmp/cbx/crabbox list --provider unikraft-cloud --unikraft-cloud-metro fra
119cc074-ef7d-4126-b898-4527c680fbee nginx-1552d                  running                                     lease=ukc_119cc074-ef7d-4126-b898-4527c680fbee slug=ukc-smoke keep= target=linux
(exit=0)

## 3b. Independent cross-check: raw API sees the instance
{"status":"success","data":{"instances":[{"uuid":"119cc074-ef7d-4126-b898-4527c680fbee","name":"nginx-1552d","created_at":"2026-07-08T07:46:23Z","state":"running","image":"nginx@sha256:019538f4210538a8e4f868b2944e816c46d82eea7d12285527119857ed0ae2c6","memory_mb":256,"vcpus":1,"restart_policy":"never","start_count":1,"started_at":"2026-07-08T07:46:23Z","uptime_ms":1527,"boot_time_us":22224,"network_interfaces":[{"uuid":"37339ab4-9b6f-4c8b-b27b-73f0e539ee97","private_ip":"10.0.5.69","mac":"12:b0:0a:00:05:45"}],"private_ip":"10.0.5.69","volumes":[]}]}}


## 4. STOP (stop + delete the claimed instance)

$ /tmp/cbx/crabbox stop --provider unikraft-cloud --unikraft-cloud-metro fra ukc-smoke
released lease=ukc_119cc074-ef7d-4126-b898-4527c680fbee instance=119cc074-ef7d-4126-b898-4527c680fbee
(exit=0)

## 5. ZERO-RESIDUE VERIFICATION (three independent views)
-> crabbox list (should show no unikraft-cloud lease):

$ /tmp/cbx/crabbox list --provider unikraft-cloud --unikraft-cloud-metro fra
(exit=0)
-> raw API GET /v1/instances (should be empty):
{"status":"success","data":{"instances":[]}}

-> direct GET of the deleted UUID (should be 404/not found):
http=200 {"status":"error","message":"Failed to perform all operations","data":{"instances":[{"status":"error","uuid":"119cc074-ef7d-4126-b898-4527c680fbee","message":"No instance with uuid '119cc074-ef7d-4126-b898-4527c680fbee'","error":8}]}}


## DONE

### SAFETY CLEANUP TRAP ###
final account instance list (must be empty):
{"status":"success","data":{"instances":[]}}

🏗️ Built-in vs external provider (maintainer call)

That's a scope decision for @steipete — happy to keep it built-in or move it external per your preference. The implementation and live behavior are verified either way.

Live run performed with a scoped robot token (redacted); metros without the account return 401, fra is the account's home metro.

…rovider

# Conflicts:
#	docs/features/provider-live-smoke.md
#	docs/providers/README.md
@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. 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. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 8, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed 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. labels Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants