refactor: rename Sandbox -> Box (Part 1: apps/api epicenter)#706
Conversation
…er) [WIP part 1 of N] Renames apps/api product-entity symbols (types/services/enums/DTOs/controllers/ methods/vars/files, dir sandbox/ -> box/) while FREEZING DB/wire/event literals: @entity('sandbox') pinned, FK cols pinned to name:'sandboxId', sandbox_state_enum and sandbox_* indexes/tables unchanged; webhook 'sandbox.*', telemetry boxlite.sandbox.*, BOXLITE_SANDBOX_ID kept. Internal CreateSandboxDto -> CreateBoxInternalDto. runner-api-client refs kept as generated Sandbox* until runner renamed+regenerated. Verified: tsc --build api == baseline (0 new errors). CI red until consumer subsystems + 9-client regen land.
|
Important Review skippedToo many files! This PR contains 300 files, which is 150 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (300)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…IP part 2 of N] Codemods runner/cli/dashboard/proxy/ssh-gateway/otel-collector/daemon/common-go/ sdk-typescript symbols Sandbox->Box, sandboxId->boxId (frozen literals protected) + file/dir renames. Generated artifacts NOT committed (regen as build step). Pipeline verified: swag -> Box swagger -> openapi-generator -> BoxApi. WIP/CI-red: regen 9 clients, un-isolate api runner-adapter, rename remaining Sandbox*-cased files, finish runner swag residue + .md, build all + remote E2E. api stays typecheck-baseline-green (adapter isolated).
…ums, ApiTags, file casing [WIP part 3 of N] Continues the rename with categories the identifier codemod initially froze: - Go route-param ctx.Param(sandboxId)->boxId (mismatched vs renamed :boxId routes) - Go uppercase enum/jobtype SANDBOX->BOX (BOXLITE_SANDBOX_* wire frozen) - api @ApiTags/@controller 'sandbox'->'box' (drives generated BoxApi not SandboxApi) - remaining Sandbox-cased files (dashboard SandboxTable/, sdk Sandbox.ts) - removed dead ToolboxApi client (never called) Regen pipeline verified end-to-end: swag->Box swagger->runner-api-client BoxApi; generate-openapi->Box spec(137 boxId/0 sandboxId)->api-client BoxApi+api-client-go BoxAPI. WIP/CI-red tail: api JobType enum values + re-spec + regen + go/nx builds + E2E. api stays typecheck-baseline-green (adapter isolated).
…-verified [WIP part 4 of N] Finishes the rename tail + regenerates generated clients so the tree is Box-consistent and compiles across every subsystem: - api JobType enum CREATE_SANDBOX->CREATE_BOX (was snake/upper double-frozen); reverted RBAC OrganizationResourcePermission.*_SANDBOXES (persisted/migration-referenced) - runnerAdapter un-isolated -> regenerated BoxApi/EnumsBoxState/CreateBoxDTO - Go+TS import-path tails /sandbox -> /box (trailing-quote was protected) - regenerated runner-api-client/api-client/api-client-go (BoxApi/BoxAPI; spec 137 boxId/0 sandboxId) Compile-verified (0 sandbox errors): api tsc==baseline; runner/cli/proxy/ssh-gw/otel/daemon/ common-go go vet clean; sdk-typescript tsc clean; dashboard 0 sandbox errors. Remaining (env/remote, not rename): CGO link needs libboxlite.a (make); build libs before dashboard; remote E2E (KVM). Generated client comments keep cosmetic 'sandbox'. PR B not started.
🐞 Runtime bug survives into Part 4:
|
Request: complete the rename — the frozen
|
The e2e bootstrap ran 'cd apps && yarn install' but yarn only treats apps/ as its own project root when a lockfile anchors it. The repo doesn't commit one (make/dev.mk seeds an empty one for the same reason), so on any fresh checkout — including the CI e2e-stack runner — yarn aborted instantly with 'apps isn't part of the project', failing 'make test:e2e:setup' at step 4 before the stack ever built. Seed the empty lockfile first, matching make/dev.mk. Unblocks the e2e-stack gate.
…[part 5] Addresses DorianZheng's review on #706: the codemod's quote-protection renamed colon-prefixed route tokens (:sandboxIdOrName -> :boxIdOrName) but froze the single-quoted @Param('sandboxIdOrName') / @ApiParam({name:'sandboxIdOrName'}), so NestJS bound a dead token -> handler arg undefined at runtime on ~20 box endpoints (get/delete/recover/start/stop/resize/labels/backup/autostop/...). - rename sandboxIdOrName -> boxIdOrName in all @Param/@ApiParam (route param, no DB column) - rename controller-level 'sandboxId' -> 'boxId' in @Param/@ApiParam ONLY (entities keep @Column/@joincolumn name:'sandboxId' pinned -> DB still zero-DDL) - guard: every @Param('x')/@ApiParam name:'x' now has a matching :x route token (audited all api controllers; 0 sandbox mismatches) tsc --build api == baseline (the break was runtime binding only, type-invisible).
|
Fixed in Root cause exactly as you diagnosed: the codemod's quote-protection renamed Fix:
|
…ation, wire, RBAC names, env) [part 6] Completes the product-entity rename by un-freezing the literals parts 1-5 deliberately kept for zero-DDL/backward-compat. Source-only change; generated clients are left at their part-5 state for CI regeneration. - DB: entity pins flipped sandbox*->box* (@entity, @Column/@joincolumn name, @Index, ::sandbox_state_enum) + QueryBuilder aliases/raw-SQL refs. New reversible contract migration post-deploy/1781016743403 renames the physical schema (table sandbox/_last_activity/_usage_periods/_archive, columns sandboxId + organization sandbox_*_rate_limit*/max_*_per_sandbox, enum sandbox_state_enum, all sandbox_*_idx + idx_sandbox_* indexes). - Wire: webhook event values sandbox.*->box.*, redis channel sandbox.event.channel->box.event.channel, analytics meter keys boxlite.sandbox.*->boxlite.box.* + sandbox_*->box_* (producers + dashboard/ws consumers flipped in lockstep). - RBAC: enum MEMBER names WRITE_SANDBOXES/DELETE_SANDBOXES->*_BOXES (string VALUES were already 'write:boxes'/'delete:boxes' - no data migration). - Env: SANDBOX env vars -> BOX (RATE_LIMIT_*, *_PER_*, RUNNER_*_STARTED_*, *_OTEL_*, BOXLITE_SANDBOX_ID/USER/AUTH_KEY, DEFAULT_*_SORTING) across api/runner/proxy/daemon/sdk + infra .env.example. Verification: apps/api tsc == cfeb019 baseline (identical error set, 0 new); Go apps (cli/daemon/runner/common-go/proxy/otel/ssh-gateway) go build/vet clean. NOT verified / follow-ups (env-bound, intentionally deferred to CI): - DDL migration is NOT DB-verified (no database here) - needs a real run + review. - Generated clients (api-client, api-client-go, analytics/runner/toolbox-api-client) + cli cobra docs + daemon swaggo MUST be regenerated from the renamed specs. - PostHog feature flag DASHBOARD_CREATE_SANDBOX -> DASHBOARD_CREATE_BOX must also be renamed in the PostHog dashboard or the flag silently goes dead. - Webhook event rename is breaking for external consumers (no dual-emit window). Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
|
Pushed Done:
Verified:
Pushed directly at the maintainer's request; revert with |
…wait) Addresses the github-code-quality 'Missing await' comment on useBoxSession.ts: make queryFn async and await client.get(boxId), preserving the 'Client not initialized' guard. Behavior unchanged (React Query already awaited the returned promise); silences the analyzer and reads clearer. Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
|
Addressed the review-bot comments in ✅ Fixed — github-code-quality "Missing await" ( ℹ️ CodeQL "Clear-text logging of sensitive information" (7 alerts) — pre-existing, not from this PR I deliberately did not bundle a fix into this rename PR — sanitizing credential-tainted API-client errors across cli/proxy/ssh-gateway is a security change that deserves its own reviewed PR (shared redaction helper), not a drive-by in a rename. Happy to open that separately. (They also look like conservative taint flow — the generated client's |
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
…f sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
Reverts changes that crept into the un-freeze commit but are NOT part of the Sandbox->Box rename: - apps/otel-collector/exporter/go.sum: stray go.mod checksum additions (dep churn) - apps/dashboard/.../useBoxSession.ts: async/await queryFn refactor (behavioral, was a code-quality suggestion, not a rename) -> restored original one-liner - Sidebar.tsx / Onboarding.tsx / eslint.config.mjs: prettier re-wrapping triggered by shorter identifiers -> restored original wrapping (rename tokens kept) Kept: all sandbox->box token renames, and the DB-rename DDL migration (that IS the rename of the physical schema). Copilot Autofix commits for the CodeQL clear-text-logging findings are left intact (not mine, deliberate security fix). Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> Signed-off-by: dorianzheng <8065637+DorianZheng@users.noreply.github.com>
The committed runner swagger was stale (pre-rename 'Create sandbox' descriptions) and the runner-api-client was incomplete — its index.ts exported BoxApi/CreateBoxDTO/ RecoverBoxDTO/EnumsBoxState but the backing files were never committed, so apps/api failed to compile (6x TS2305 'no exported member' in runnerAdapter.v0/v2). - regenerated runner swagger via swag from the (already box) runner Go handlers (apps/runner/pkg/api/docs/*): 0 sandbox, 111 box - regenerated apps/libs/runner-api-client from it (openapi-generator 7.23, typescript-axios): exports BoxApi/CreateBoxDTO/RecoverBoxDTO/EnumsBoxState, 0 sandbox Effect: apps/api TS2305 errors 6 -> 0 (api now compiles re: the runner client; remaining ~160 tsc errors are pre-existing WIP type issues unrelated to this). NOT done (blocked): api-client + api-client-go regen still needs the api OpenAPI spec, whose generation bootstraps the full NestJS app (DB/Redis/Kafka/OIDC/S3, ~205 env vars) — not runnable in this worktree; must run in the configured dev/CI env. Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
✅ Rename-only verification (94-agent sweep over all 937 changed files)Ran an automated check across every changed file: normalize
All 20 review flags triaged to non-issues for the rename: the intended DB-name pins ( Two things surfaced that are not rename-related and worth your eyes: 1. 2. Generated clients were regenerated with a newer openapi-generator than |
…clients (#716) Closes the "regenerate api-client/api-client-go" follow-up from #711 (post-#706 rename), and makes the regeneration reproducible so the clients can't silently go stale again. ## Why the clients were stale The `apps/` subtree import from daytonaio/daytona dropped the root-level machinery that upstream uses to regenerate clients (researched against upstream — `daytonaio/daytona@main`): | Upstream piece | State in boxlite before this PR | Consequence | |---|---|---| | `openapitools.json` generator pin | missing | every machine floats to the latest jar (committed tree mixed 7.12/7.23 output) | | `hack/{ts,go}-client/` postprocess + Go mustache templates | missing (referenced by nx targets!) | Go client lost `version.go` + branded `User-Agent`; targets failed at the postprocess step | | `format-lint-api-clients` CI drift gate (`pr_checks.yaml`) | missing | nothing detected stale clients — how `WebhookEvent="sandbox.created"` survived the rename merge | | committed `apps/api/.env` dev env | missing (boxlite gitignores `.env`) | `generate-openapi.ts` (boots the full NestJS app) had no env to run under | | repo-root-relative nx target paths | broken (workspace root moved into `apps/`) | `nx run api:openapi` resolved `apps/apps/api/...` | ## Commit 1 — machinery - **`apps/openapitools.json`** pins openapi-generator at **7.23.0** (matches the committed clients; upstream pins 7.21.0 — deliberate deviation to minimize this diff). - **`apps/hack/{ts,go}-client/`** copied byte-identical from upstream (User-Agent branding, `version.go` via `go:embed`, Go model templates). - **nx path fixes** in `api`, `libs/api-client`, `api-client-go` project.json (apps/-rooted workspace), plus `TS_NODE_TRANSPILE_ONLY=true` (api has pre-existing WIP type errors) and upstream's `enumUnknownDefaultCase=true` restored on both clients. - **`apps/api/.env.example`** — offline placeholder env for spec generation (`cp api/.env.example api/.env`), following the repo's existing `.env.example` gitignore-exception precedent. `SKIP_CONNECTIONS=true` (already in the nx target) keeps it offline; values are docker-compose placeholders. - **`@ApiExcludeController()` on the four `boxlite-rest` controllers.** That surface is spec-first — its contract is `openapi/box.openapi.yaml` (the controllers' own docs say so) — and in the swagger-emitted product spec it is OpenAPI-3.0-invalid: `:prefix` route tokens have no declared path param, and the proxy's `@All()` expands to the `SEARCH` verb, which OpenAPI 3.0 cannot express. This invalidity is what broke `openapi-generator` entirely. The generated `BoxLiteREST` surface had **zero consumers** (verified across cli/sdk-go/sdk-typescript/dashboard/daemon). - **`.github/workflows/api-client-drift.yml`** — port of upstream's drift gate: regenerate both clients on `apps/**` PRs and fail on diff (redis service container avoids a bootstrap retry-race; actionlint/shellcheck clean). ## Commit 2 — regenerated clients (generator output only, no hand edits) - `WebhookEvent` enums now match the server: `sandbox.created` → **`box.created`**, `sandbox.state.updated` → **`box.state.updated`** (TS + Go) — this was the consumer-facing break from #711. - `sandboxIdOrName` path-template vars → `boxIdOrName`; stale "…of the sandbox" doc text → box. Both clients now contain **zero** `sandbox` tokens. - Go client regression fixed: `version.go` (`go:embed VERSION`) restored, `UserAgent: "api-client-go/" + ClientVersion` instead of the stock `"OpenAPI-Generator/1.0.0/go"`. - `UNKNOWN_DEFAULT_OPEN_API` enum members added across both clients (upstream's `enumUnknownDefaultCase=true` — forward-compat with unknown server enum values). - New TS models/apis picked up (drift catch-up: DTOs and tags added to the api since the last regen), plus the generator's `src/docs/*.md` — not previously committed, but the drift gate requires committed output to match emitted output exactly, so they're in (upstream suppresses docs; we commit-as-emitted). - `api_box_lite_rest.go` deleted (−4801 lines): the excluded, consumer-less spec-first surface above. ## Verification - Spec generates cleanly: 0 sandbox tokens, `box.*` webhook events, 0 `{prefix}` paths. - Regeneration is **idempotent** (two consecutive runs → identical `git status`). - `tsc -p libs/api-client/tsconfig.lib.json` → exit 0. - `go build ./...` clean in `api-client-go` **and** `apps/cli` (the Go consumer). - No source anywhere references the removed `BoxLiteREST` generated API or old `SANDBOX_*` enum members. - New workflow passes actionlint + shellcheck. ## Not in scope - `analytics-api-client`: its input swagger comes from the external analytics service (upstream excludes it from regen for the same reason); it still contains `sandbox.*` until that service renames. - `apps/yarn.lock` stays uncommitted (explicitly gitignored by repo policy); the drift job does a plain `yarn install`. Committing a lockfile would make the gate fully deterministic — separate policy decision. - Remaining cosmetic `sandbox` strings in cli docs / shim (tracked in #711). --------- Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
…column names Migration1781016743403 (PR boxlite-ai#706) renamed most sandbox-vocabulary objects to box-vocabulary equivalents but missed three pieces; the API and runner crashed on every box-touching path until those caught up. fixture_setup also still wrote the old organization-quota column names. Schema gaps added in a follow-up post-deploy migration: - `runner.currentStartedSandboxes` -> `currentStartedBoxes` - `organization.sandboxLimitedNetworkEgress` -> `boxLimitedNetworkEgress` - `job_resourcetype_enum` value `SANDBOX` -> `BOX` Symptoms before the fix: - ResourceManager / SnapshotManager queries: `column Runner.currentStartedBoxes does not exist` - Box service create path: `column Organization.boxLimitedNetworkEgress does not exist` - Runner job poll: `invalid input value for enum job_resourcetype_enum: "BOX"` - fixture_setup: `column "max_cpu_per_sandbox" of relation "organization" does not exist` Each migration step is guarded with a state check (`information_schema` / `pg_enum`), so partial-state environments are safe to re-run and the migration is idempotent on hosts where someone has already hand-applied any of the three renames. The down() restores the previous names. Verified locally: applied the migration to a partial-state DB; API + runner come up clean; `scripts/test/e2e/cases/test_unread_stream_back_pressure.py` (3 cases) and existing e2e cases pass against the restored stack. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Building on the path/tsconfig blockers fixed in the previous commit,
this clears the remaining 163 TS errors that surface once webpack
reaches tsc:
- 157 errors from Express 5's @types/express-serve-static-core@5.1.1
widening ParamsDictionary[key] from `string` to `string | string[]`.
Express still only returns strings at runtime, so narrow the three
Request types that funnel into the controllers + interceptors:
audit.decorator.ts — AuditContext + TypedRequest
audit.interceptor.ts — RequestWithUser
metrics.interceptor.ts — RequestWithUser
- 3 errors from an OTel package version skew: sdk-node@^0.218.0 brings
otlp-exporter-base@0.218 to the hoisted root, but the http exporters
(exporter-trace/metrics/logs-otlp-http) are still pinned at ^0.207
and carry their own nested 0.207 copy with an incompatible `headers`
typing. Cast at the three call sites in tracing.ts until the http
exporters get bumped to 0.218 in a follow-up dep-bump PR.
- 2 TS2307 errors from runner-api-client not being reachable. The
Dockerfile COPYs libs to /boxlite/libs/ (which nx's project sourceRoot
expects) but tsconfig paths declare libs at apps/libs/ relative to
apps/tsconfig.base.json. Bridge with `ln -s ../libs apps/libs` so both
consumers see the libs where they expect.
- TS6059 (lib files outside rootDir) that surfaced once the symlink let
TS reach the lib sources. Widen tsconfig.base.json rootDir from "."
to ".." so /boxlite/libs/* falls inside the rootDir of /boxlite/.
End state: `docker build -f apps/api/Dockerfile .` produces a working
2.21 MiB dist/apps/api/main.js. Dashboard build (Step 22 of the same
Dockerfile) is still blocked by an *independent* boxlite-ai#706 fallout —
apps/libs/api-client/src/models/index.ts references 12 box-*.ts files
that boxlite-ai#706 forgot to regenerate via openapi-generator. That regen
machinery was restored in upstream boxlite-ai#716; rebasing onto post-boxlite-ai#716 main
picks up the regenerated files and dashboard should follow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…olumn names (#720) ## Bug Migration1781016743403 (#706) renamed most sandbox-vocabulary objects to box-vocabulary equivalents but missed three pieces, leaving the schema inconsistent with the renamed TypeORM entities and TS enum. Every box- touching API path crashed until I added the catch-up rename below; fixture_setup also still wrote the old organization-quota column names. | Layer | What got missed | Symptom | |---|---|---| | `runner.currentStartedSandboxes` | entity renamed to `currentStartedBoxes`, no schema migration | every ResourceManager / SnapshotManager query: \`column Runner.currentStartedBoxes does not exist\` | | `organization.sandboxLimitedNetworkEgress` | entity / service renamed to `boxLimitedNetworkEgress`, no schema migration | box create: \`column Organization.boxLimitedNetworkEgress does not exist\` | | `job_resourcetype_enum` value `SANDBOX` | TS `ResourceType.BOX = 'BOX'`, Postgres enum still only knows 'SANDBOX' | runner job poll: \`invalid input value for enum job_resourcetype_enum: \"BOX\"\` | | `scripts/test/e2e/fixture_setup.py` | still UPDATEs `max_cpu_per_sandbox` / `max_memory_per_sandbox` / `max_disk_per_sandbox` (#706's main migration already renamed those columns to `max_*_per_box`) | fixture_setup: \`column \"max_cpu_per_sandbox\" of relation \"organization\" does not exist\` | ## Fix New post-deploy migration `Migration1781072797240` performs the three schema renames the original missed. Each step is guarded with an `information_schema` / `pg_enum` state check, so partial-state environments are safe to re-run and the migration is idempotent on hosts where someone has already hand-applied any of the three renames. `fixture_setup.py` is updated to use the new column names. ## Test plan Verified locally on a partial-state DB: 1. Confirmed the bug: API 500 on box create with the three errors above, fixture_setup 500 on quota patch. 2. Applied this migration: schema renames cleanly (guards skip no-ops), `migrations` row recorded. 3. Restarted API + ran the e2e back-pressure suite — all 3 cases pass: ``` [same-box] elapsed_b=0.456s rc=0 out='fast-b\n' [cross-box] elapsed_b=0.482s rc=0 out='fast-b\n' [slow-consumer x-box] elapsed_b=0.419s rc=0 out='fast-b\n' ``` No down() change to data — the down() just inverts the renames so the migration is reversible if needed. Each down step is also guarded. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Applied post-deployment database migration to standardize schema naming conventions across multiple tables. * Updated database enumeration values to align with current system terminology. * **Tests** * Updated e2e test fixture quota configuration to ensure test environment compatibility with revised resource limit parameters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…wagger spec (#721) ## Summary Closes out the **analytics-api-client** item of #711 (Sandbox→Box Part 1 follow-ups). #706 renamed the dashboard's analytics consumers to Box-named symbols (`ModelsBoxUsage`, `organizationOrganizationIdUsageBoxGet`, …) but the committed client still only exported Sandbox-named ones — the dashboard could not typecheck against the in-repo client. The client also couldn't be regenerated from this repo at all: its generator input was an uncommitted `tmp/swagger.json` from the external analytics service (the reason #716 excluded it). ## Changes - **Commit the contract in-repo**: `apps/libs/analytics-api-client/swagger.json`, reconstructed 1:1 from the previously committed client with only sandbox→box renamed (paths `/organization/{organizationId}/box/{boxId}/…`, `models.BoxUsage`, `boxId`, `boxCount`). This is now the spec any future analytics service must implement — same spec-first direction as `openapi/box.openapi.yaml`. - **Point `generate:api-client` at it** (`project.json`), with nx cache inputs tracking the spec instead of the unrelated `apiClient` named input. - **Regenerate** with the pinned openapi-generator **7.23.0** (committed client was stale 7.12.0 output — the last client on the old generator). Zero `sandbox` tokens remain. - **Drift gate**: drop the analytics exclusion from `api-client-drift.yml` — it now regenerates + diffs analytics like the other clients (actionlint clean). - **eslint**: ignore `**/.nx/**` — the generate target caches its `src/` output under the gitignored `apps/.nx/cache`, and lint after a local regen tripped on the cached copy of generated code. ## Verification - Two-side dashboard typecheck: against the **old** client → 13 rename-mismatch errors (`'ModelsBoxUsage'… Did you mean 'ModelsSandboxUsage'?`); against the **new** client → **zero** analytics-related errors (remaining 24 are pre-existing, unrelated: Playground/VNC files + unbuilt `@boxlite-ai/sdk` dist). - Regen is byte-identical across runs (`--skip-nx-cache`), so the drift gate won't false-positive. - `make lint:apps` exit 0. ## Notes - Runtime risk is nil: the analytics client is only instantiated when `ANALYTICS_API_URL` is configured, no analytics service exists in the org today, and the API's own (already-renamed) `box/:boxId/telemetry/*` endpoints serve the dashboard otherwise (`AnalyticsApiDisabledGuard` makes the two mutually exclusive). - Pre-existing, **not** fixed here (scope): `apps/dashboard/tsconfig.app.json` path mappings (`\"@boxlite-ai/*\": [\"../../libs/*\"]`) have pointed outside the workspace since the apps tree was flattened (#460), so raw `tsc -p` never resolved any `@boxlite-ai/*` import. Worth its own follow-up. Part of #711. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added AWS Signature V4 support for API requests. * Telemetry and usage endpoints now operate at box (per-box) and organization levels (replacing sandbox-level variants). * **Documentation** * Comprehensive API docs added/updated with examples for box telemetry, per-box usage, aggregated usage, and usage chart endpoints. * **Chores** * Drift detection updated to include the analytics API client; linting ignores extended for generated files. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
Admin observability module (new in Task12B) was authored pre-boxlite-ai#706 and never renamed: broken imports (sandbox-telemetry/, sandbox/ paths) + queried the wrong sandbox- service prefix / boxlite.sandbox_id while the daemon already emits box-<id>. Renamed emitter + consumer in lockstep so new data is fully box: - daemon: trace tracer scope boxlite.sandbox -> boxlite.box - api interceptor: consolidate to { keys:[boxId,boxIdOrName], attr:boxlite.box_id } - admin (11 files): symbols (SandboxState->BoxState, sandboxId->boxId), broken import paths -> box*, wire strings sandbox-/boxlite.sandbox_id -> box-/boxlite.box_id - box-telemetry trace-span doc example sandbox-<id> -> box-<id> Old ClickHouse data (sandbox-keyed) is disposable per decision; no CH schema change (attribute keys are Map values). Fixed two latent boxlite-ai#706 bugs in passing (currentStartedSandboxes->currentStartedBoxes, /admin/sandbox->/admin/box). Left intentionally sandbox: box.manager raw SQL (frozen sandbox DB table/column), PostHog product-analytics event names (separate system, pending decision).
…lient, fix dead env vars + stale refs (#723) Part of #711 — closes out the "Part 1 of N" remainder. A repo-wide sweep found the rename effectively complete in source (`runner`/`cli`/`daemon`/`dashboard`/`proxy` at zero tokens; `apps/api` leftovers are historical migrations, correct as-is). What remained is below. ## Generated client (the bulk of the diff) **`toolbox-api-client` regenerated** from the committed `apps/daemon/pkg/toolbox/docs/swagger.json` (which #718 already renamed — `git grep "sandbox entrypoint"` has zero hits outside the generated client). This kills the last 4 generated `sandbox entrypoint session` doc-comments and moves the client from generator 7.12.0 to the pinned 7.23.0, same modernization #721 did for analytics (hence the `src/docs/*.md` additions — 7.23 emits them, and the drift gate requires committed == emitted). Determinism verified: regen run twice locally (with and without `--excludeTaskDependencies`), byte-identical both times. **Drift gate now covers it** (`api-client-drift.yml`): regen via `--excludeTaskDependencies` so the committed daemon swagger is the contract and the job needs no Go/swag toolchain. Daemon-source↔swagger drift stays ungated (the cli/daemon-docs sibling gate noted in #711 remains a follow-up). actionlint + shellcheck clean. ## Why the toolbox client was never regenerated: broken nx paths The regen target failed outright: `-i apps/daemon/pkg/toolbox/docs/swagger.json` resolves relative to the nx workspace root, which *is* `apps/` → `apps/apps/daemon/...` (spec not found). Kept from upstream daytona's repo layout; #716 fixed only the product clients' targets. Fixed here: - `libs/toolbox-api-client/project.json` — `-i daemon/pkg/toolbox/docs/swagger.json` - `libs/runner-api-client/project.json` — same latent bug (`-i runner/...` + its `{workspaceRoot}` input) - `nx.json` — `apiClient`/`goProduction` named inputs pointed at `{workspaceRoot}/apps/...` paths that don't exist, so swagger/go.work changes never invalidated task caches ## Functional config fixes - **`scripts/test/e2e/bootstrap.sh` + `apps/infra-local/configs/api.env`** wrote `ADMIN_MAX_{CPU,MEMORY,DISK}_PER_SANDBOX`, but the API reads `ADMIN_MAX_*_PER_BOX` (`apps/api/src/config/configuration.ts:292-294`) with default `0` — admin-org per-box quotas were silently unset. - **`apps/infra-local/scripts/stack-reset.sh` + README runbook snippets** ran `TRUNCATE TABLE sandbox, ...` / `SELECT ... FROM sandbox` — that table was renamed to `box` by migration `1781016743403`, so these failed as written. Also `/api/sandbox` → `/api/box` (route is `@Controller('box')`) and `{{sandboxId}}` → `{{boxId}}` (matches the `configuration.dto.ts` example). infra-local merged in #595 on a pre-#706 vocabulary. ## Vocabulary sweep (no behavior change) Comments, docstrings, and three e2e test function names (`test_*_above_per_sandbox_limit_*` → `per_box`; no `-k` selector, workflow, or Makefile references them) across `scripts/test/e2e/`, `scripts/deploy/runner-update-binary.sh`, and `apps/infra-local/`. File/path references verified against the tree (`box.service.ts`, `volume.manager.ts:47`, `box_sync.go`, `CREATE_BOX` journal tokens). All three trees now grep-clean for `sandbox`. Also includes 3 files prettier-normalized by the repo's `make lint:fix` pre-commit autofixer (`eslint.config.mjs`, `Sidebar.tsx`, `Onboarding.tsx`) — they were out of format on `main` and the repo-wide hook re-applies them on every commit until committed. ## Verification - Regen byte-identical across repeated runs, including the exact CI invocation - `actionlint` + `shellcheck` on the workflow; `shellcheck` on all 6 edited shell scripts (only pre-existing findings on untouched lines); `py_compile` on all 7 edited Python files - Every text replacement applied with an exact-unique-match assertion (count==1 before replace) - OS-isolation uses of "sandbox" (jailer/seatbelt/bwrap, docs/faq) deliberately untouched — different concept per the rename's scope Signed-off-by: dorianzheng <xingzhengde72@gmail.com>
The convergence merge (623a043) left apps/api internally inconsistent: some files used pre-boxlite-ai#706 'sandbox' naming while the enums/constants they reference were already 'box' on main (and vice-versa) -> 65 compile errors. main is the authoritative box-consistent version. Renamed identifiers to box (NOT wholesale checkout from main, which would re-introduce the deleted image system): AuditTarget.SANDBOX->BOX, WRITE/DELETE_SANDBOXES->WRITE/DELETE_BOXES, SANDBOX_EVENT_CHANNEL->BOX_EVENT_CHANNEL, SANDBOX_STATES_CONSUMING_*->BOX_*, SANDBOX_SORT_*->BOX_*, SANDBOX_WARM_POOL_*->BOX_*, SANDBOXES_ADMIN->BOXES_ADMIN (UUID unchanged), plus duplicate-field merge artifacts in box-lookup-cache-invalidation + box.repository. Frozen (kept sandbox, matches main): DB entity/column/enum/index, raw SQL aliases, PostHog event names, JobType enum values. Image/snapshot deletion untouched. api tsc: 65 -> 0 errors. 16 files.
The convergence merge (623a043) regressed nearly all of apps code from main's post-boxlite-ai#706 box naming back to pre-boxlite-ai#706 sandbox. main's non-migration code has ZERO sandbox (verified) -- it is the authoritative all-box version. This branch had 834 sandbox in apps/api/src alone (JobType.CREATE_SANDBOX vs main's CREATE_BOX, @Index('sandbox_*') vs box_*, etc.). Applied sandbox->box codemod across all apps source to match main, keeping image deletion intact (rename only, no content from main): - apps/api (834->0), apps/dashboard (115->0), apps/libs/sdk-typescript (2->0) - apps/cli (25->0), apps/runner (88->0), apps/daemon (5->0), apps/infra (3->0) - fixed codemod duplicate-property collisions (sandboxId+boxId -> boxId) in admin observability dashboard hooks - @entity('box') restored to match main Verified: api tsc 0 errors; cli/daemon go build clean; runner only the pre-existing boxlite.WithPort gap; dashboard remaining errors are module-resolution (generated clients not linked in this worktree, 272->244 pre/post codemod). Migrations and generated clients untouched. No image/snapshot symbols reintroduced.
…715) ## What this is A **convergence "super PR"**: it merges everything sitting on the `codex/overnight-20260608` line into `main`, so that `main` becomes the single source of truth again. Intended to be **reviewed then split** — opened as one piece for visibility, not to be squash-merged blind. `main` ← merge of (52 commits ahead): MVP box journey + agent-ready image catalog + A2 snapshot-manager deletion + Task12B observability wiring + default-org membership + W3C traceId, reconciled against `main`'s `Sandbox→Box` rename (#706) and recent REST/CI fixes. **Net vs main:** 771 files, +85k/−23.7k. ## Suggested split for review (5 logical blocks) | # | Block | Rough surface | |---|---|---| | 1 | **A2 — delete snapshot-manager machinery** | drops self-hosted registry / backup / build / docker-registry; collapses to `box_template` + `runner_artifact_cache`; direct ghcr pull; 68 files deleted; migrations `17809…`–`17812…` | | 2 | **MVP box journey** | simplified onboarding, templates-as-images, public Box IDs, archive-lifecycle retirement | | 3 | **Agent-ready image catalog** | `boxlite/base|python|node` pinned-digest runtime catalog | | 4 | **Observability (Task12B)** | admin diagnose UX + runner/daemon traceId propagation | | 5 | **Org membership** | default-org state moved into memberships (backward-compatible) | ## Conflict-resolution policy (527 conflicts) - **A2-deleted machinery** (snapshot/backup/build/docker-registry): **deletion wins** over main's edits to those files. - **Generated clients** (`api-client`, `runner-api-client`, `api-client-go`): took **main's regenerated side**; a fresh regen against the merged API surface is still pending (see Caveats). - **Source files**: kept the A2/MVP side and re-applied **#706's published codemod recipe** (`Sandbox→Box`, with the frozen-literal allowlist preserved — DB table/column/enum, OS-isolation `sandbox`, telemetry `boxlite.sandbox.*`, webhook event names). - **Renamed-path ports**: 3-way merged onto the post-#706 `box/` paths. - **Go consumers** aligned to the regenerated client enum names (`BOXSTATE_*`). ## Caveats — read before merging -⚠️ **CI will be red until generated clients are regenerated** against the merged API surface, and a full build + remote E2E is run. This was **not** done locally (no DB/KVM here); **build/test verification is deferred to CI on purpose**, stated honestly rather than claimed green. -⚠️ Single migration variant of `1780200000000` is present (verified) — do not reintroduce a second. -⚠️ Deploy ordering for the A2 block is **runner-first** (swap runner binary before the registry-deleting deploy), per Task 13. ## Not in this PR `feat/admin-ui-redesign` (POL-14 admin UI v2) and the unmerged Task12 ClickHouse `sst.config.ts` wiring are intentionally left out — separate follow-ups. --- ## Commit inventory — 48 commits, 6 blocks (+1 merge) **A2 — delete snapshot-manager machinery (7)** p2 direct-ghcr · p3 drop build · p4 drop backup · p5 drop registry→2 tables · p6 rebuild `box_template` + `runner_artifact_cache` · P1 runtime-scoped ghcr auth · ghcr credential delivery (Secrets Manager) **MVP box journey (16)** streamline box journey · templates-as-images · public BoxID + archive retirement · simplified onboarding · BoxID/SDK onboarding polish · quickstart + dev-smoke **Template-artifact refactor (11)** from `d3a60c7c`: cloud templates + runtime artifacts refactor and follow-up fixes **Observability (3)** Task12B admin diagnose + saved-image fix · runner W3C traceparent · daemon traceId **Agent-ready images (3)** runtime catalog · pin digests · catalog merged into MVP journey **Org membership (3)** default-org state → memberships · backward-compatible · post-merge overview fix **Misc (5)** JWT issuer validation · ESLint flat-config fix · lint config · logo assets · yarn.lock --- ## Superseded branches — intentionally NOT included Verified by file-level comparison: these are earlier iterations whose final form is already in this PR. Re-submitting them would regress newer code. - `feat/admin-overview`, `feat/frontend-slim-box-rename` — fully superseded by Task12/12B + #706/MVP journey - `feat/admin-ui-redesign`, `codex/task7-observability-data-layer` — ~52% file-overlap with Task12B's rewrite already here; any truly-missing UI/data-layer fragments will come later as small focused PRs - `codex/snapshot-image-naming`, `codex/runtime-artifact-split`, `codex/api-template-contract` — abandoned saved_image naming line (carries a conflicting variant of migration `1780200000000`; must never merge) **Generated clients now carry ZERO diff in this PR** (reset to main in `f9ea0730`) — regenerate upstream against the merged API surface. --- ## Image subsystem removed (commit fbf99d9) The inherited Daytona-fork image-management (box_template + runner_artifact_cache) is **fully removed** so it can be rebuilt the team's own way. Box image-pull/boot is intentionally non-functional until the rebuild PR. Old impl preserved at tag `pre-image-rewrite`. - **Deleted (45):** box-template.* + runner-artifact-cache.* + RuntimeArtifactManager + the dashboard templates UI + template-states usage constant - **Gutted (49):** box.entity (template field), box.service (image resolution), box-start.action (pull state machine → ERROR stub), runner svc/controller, notifications/webhooks, metrics/openapi, org-usage billing (template metering → 0, `TODO(billing-rewrite)`), dashboard create/playground/routes - **Untouched:** migrations, generated clients (apps/libs, api-client-go), box list/delete + all non-image subsystems - Verified: zero dangling references to deleted symbols; zero conflict markers --------- Signed-off-by: dorianzheng <xingzhengde72@gmail.com> Co-authored-by: dorianzheng <xingzhengde72@gmail.com>
What
Part 1 of N of the repo-wide product-entity rename
Sandbox→Box.This PR renames the
apps/apiepicenter (the ~851-refapps/api/src/sandbox/mega-module and its consumers within
apps/api), and is intentionally a WIPdraft: CI will be red until the remaining subsystems + generated-client regen
land (see Remaining).
Done in this PR (verified)
apps/apiproduct-entity symbols renamedSandbox*→Box*,sandboxId→boxId,files + module dir
sandbox/→box/(231 files).@Entity('sandbox')pinned; FK columnspinned to
name: 'sandboxId';sandbox_state_enum+ allsandbox_*index/table names unchanged; no migration added.
CreateSandboxDto→CreateBoxInternalDto(avoids colliding with theexisting
boxlite-restCreateBoxDto).runner-api-clientreferences temporarily kept as generatedSandbox*names(flip when the runner is renamed + its client regenerated, Part 2).
tsc --build apps/api== pre-change baseline (0 new type errors).No local DB/KVM here, so the remote E2E suite was not run.
Frozen
sandboxallowlist (deliberately NOT renamed)sandbox, colsandboxId,sandbox_state_enum,sandbox_*_idx,sandbox_usage_periods*src/boxlite/jailer/*, seccomp/Seatbelt/sandbox-exec,--no-sandbox,IS_SANDBOX, Cargo keywordsBOXLITE_SANDBOX_IDsandbox.created,sandbox.state.updated, …boxlite.sandbox.*'sandbox.<col>'join/where stringsReproducible codemod recipe (for the overnight/a2pr deploy line to rebase)
Identifier-level, quote/snake/dot-protected (so frozen literals survive):
then
git mvpathssandbox→box, pin entity@Entity/column names, regen clients.Remaining (separate installments — NOT in this PR)
runner/cli/dashboard/ glue (proxy/ssh-gateway/otel/daemon) /sdk-typescript.api-client,runner/analytics/toolbox-api-client,api-client-go, swaggo docs, cli docs).e4bbd0ea).UUID → BoxIdid model (public box-id lookup, dashboard shows box id), stacked on this.