refactor(contracts): single-owner API contracts — cloud API is cloud-only, Box API owns box operations#748
Open
law-chain-hot wants to merge 5 commits into
Open
refactor(contracts): single-owner API contracts — cloud API is cloud-only, Box API owns box operations#748law-chain-hot wants to merge 5 commits into
law-chain-hot wants to merge 5 commits into
Conversation
|
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 |
This was referenced Jun 13, 2026
- Remove the publishable apps/libs/sdk-typescript project and its
Nx/build references.
- Replace Dashboard's prior @boxlite-ai/sdk usage with a
Dashboard-private cloudBox adapter backed by generated REST clients.
- Remove TypeScript Cloud SDK playground snippets so the UI no longer
teaches users to install @boxlite-ai/sdk.
The large diff is not because the delete itself is complicated. It is
because `apps/libs/sdk-typescript` had two roles mixed together: it was
a customer-facing package, and Dashboard was also importing it as an
internal cloud box facade.
Legend:
- `*** DELETE TARGET ***` = the package this PR removes.
- `*** REMOVED USER SURFACE ***` = user-facing code/docs path removed
because it advertised that package.
- `[kept]` = still exists after this PR.
- `[new internal]` = Dashboard-only replacement, not a public SDK.
```text
BEFORE
*** REMOVED USER SURFACE ***
+------------------------------------------------+
| Playground TypeScript snippet |
| tells users: npm install @boxlite-ai/sdk |
+-------------------------+----------------------+
|
| teaches users this package exists
v
+------------------------------------------------+ imports +------------------------------------------------+
| Dashboard Playground | -----------------> | *** DELETE TARGET *** |
| hooks/providers/VNC/snippets | | apps/libs/sdk-typescript |
| | | public package: @boxlite-ai/sdk |
+------------------------------------------------+ +-------------------------+----------------------+
|
| wraps
v
+------------------------------------------------+
| [kept] generated REST API clients |
| api-client / toolbox-api-client |
+-------------------------+----------------------+
|
| HTTP
v
+------------------------------------------------+
| [kept] BoxLite API / toolbox runtime |
+------------------------------------------------+
Build graph tied to the delete target:
Dashboard tsconfig alias -> Vite SDK alias/polyfills -> Nx dependency -> Docker COPY -> eslint exception
```
```text
AFTER
*** REMOVED USER SURFACE ***
+------------------------------------------------+
| Playground TypeScript snippet |
| npm install @boxlite-ai/sdk |
| |
| STATUS: DELETED |
+------------------------------------------------+
*** DELETE TARGET ***
+------------------------------------------------+
| apps/libs/sdk-typescript |
| public package: @boxlite-ai/sdk |
| |
| STATUS: DELETED |
+------------------------------------------------+
Dashboard internal path, after removing the public SDK dependency:
+------------------------------------------------+ imports +------------------------------------------------+
| [kept] Dashboard Playground | -----------------> | [new internal] Dashboard-private cloudBox |
| hooks/providers/VNC/snippets | | apps/dashboard/src/lib/cloudBox.ts |
| | | small adapter; not published to customers |
+------------------------------------------------+ +-------------------------+----------------------+
|
| calls
v
+------------------------------------------------+
| [kept] generated REST API clients |
| api-client / toolbox-api-client |
+-------------------------+----------------------+
|
| HTTP
v
+------------------------------------------------+
| [kept] BoxLite API / toolbox runtime |
+------------------------------------------------+
Build graph cleanup after deleting the target:
No @boxlite-ai/sdk alias -> no SDK Vite polyfills -> no Nx build edge -> no Docker COPY -> no SDK lint exception
```
So the diff fans out into four necessary buckets:
1. Delete the public SDK project itself: `apps/libs/sdk-typescript/**`.
2. Keep Dashboard working by replacing SDK imports with
`apps/dashboard/src/lib/cloudBox.ts`.
3. Stop advertising the removed SDK in Playground code snippets.
4. Remove build-system references that would otherwise point at a
deleted project.
- NX_DAEMON=false corepack yarn nx build dashboard
--configuration=development --nxBail=true --output-style=stream
- NX_DAEMON=false corepack yarn nx build api --configuration=development
--nxBail=true --output-style=stream
- make lint:apps
- rg -n "@boxlite-ai/sdk|sdk-typescript" . -S
…oolbox/workspace surfaces and box verbs
- Delete toolbox.deprecated.{controller,service,dto} (68 proxy endpoints).
Their only real consumer was the TypeScript cloud SDK removed in #743;
the dashboard Playground/VNC routes that also called them are dark.
- Delete workspace.deprecated.controller + dtos (legacy Daytona alias
surface, zero consumers).
- Delete createBox/deleteBox/startBox/stopBox from box.controller.
Box verbs are now owned solely by the Box API contract
(openapi/box.openapi.yaml), served by boxlite-rest. Cloud-capability
endpoints (signed URLs, ssh, archive, recover, paginated reads, getBox)
stay: they consume cloud-only ingredients the engine cannot provide.
- boxlite-rest CreateBoxDto + box.openapi.yaml: add cloud-optional create
fields (labels/public/auto_stop_interval/auto_delete_interval) so the
dashboard create form can speak the Box API dialect. Local engine
servers ignore them (serde drops unknown fields).
- metrics.interceptor: move box-create/start/stop capture from the
removed /api/box routes to the /api/v1 boxes routes.
- apps/api/Dockerfile: drop the toolbox-api-client COPY (package removed
later in this branch).
… the dead Playground/VNC chain
- cloudBox.ts rewritten as a small handwritten client for the Box API
contract (openapi/box.openapi.yaml, served by boxlite-rest):
toBoxApiCreateRequest mapping + create/start/stop/delete helpers
calling /v1/{org}/boxes through the ApiClient axios instance.
- create/start/stop/delete mutations and Boxes.tsx bulk actions switch
from the generated boxApi verbs (removed from the cloud contract in
the previous commit) to those helpers. Create re-reads the full
organization-scoped Box via boxApi.getBox so caller types stay
unchanged. All call sites fail fast on a missing organization.
- Delete dead code: the Playground suite (pages/components/providers/
contexts/hooks/lib), VNC components and queries (BoxVncTab/Fullscreen,
useVncSession/StatusQuery, useStartVncMutation), useBoxSession (zero
consumers — terminals use useBoxSessionContext + useTerminalSessionQuery),
useArchiveBoxMutation (byte-duplicate of useStopBoxMutation, zero
importers), vnc/playground enums, feature flags, routes, queryKeys,
and the ToolboxApi wiring in apiClient.ts.
- Add cloudBox.test.ts covering the contract translation (GiB→MiB,
networkBlockAll→network.mode, cloud-only field passthrough).
- tsconfig.app.json: drop the toolbox-api-client path mapping.
…d cloud spec; drop toolbox-api-client; add contract boundary CI guard - apps/libs/api-client (TS) and apps/api-client-go regenerated from the slimmed cloud spec in the CI-faithful BoxLite-box pipeline: the ToolboxApi/WorkspaceApi classes, their models, and the four box verb operations disappear from both clients. - apps/libs/toolbox-api-client deleted entirely. It was the generated TS client for the in-box daemon contract; its last consumer was a type-only import removed with the Playground. - api-client-drift workflow: stop regenerating the removed package and add a contract boundary guard — the exported cloud spec must not re-grow /toolbox//exec//files//workspace paths, and openapi/box.openapi.yaml must stay tenancy-free (organizationId//organizations/billing). - apps/tsconfig.base.json: drop the toolbox-api-client path mapping.
15c2913 to
999a2e2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Architecture: single owner per contract
Why ~90k deletions is not as large as it looks
Impact
toolbox.deprecated(68 endpoints),workspace.deprecated, and 4 box verbs frombox.controller. Only known consumer was the TS SDK (removed in this PR) — confirm no external callers before merge./v1/{org}/boxes); Playground/VNC retired.api-client+api-client-goregenerated (ToolboxApi/WorkspaceApi + the verbs disappear);toolbox-api-clientdeleted.Summary
Give each REST contract a single owner, before launch locks them in:
openapi.json) = cloud capabilities only: organizations, billing, keys, audit, webhooks, signed preview URLs, ssh access, archive/recover, rich org-scoped reads.openapi/box.openapi.yaml, served byapps/api/src/boxlite-rest) = the only contract for box operations: create/start/stop/delete, exec, files, snapshots.Ownership rule, one line: an endpoint lives where its capability lives — if the engine can fulfil it, it belongs to the Box API; if it needs cloud ingredients (signing keys, gateways, the billing clock), it belongs to the cloud API.
Commits
refactor(api)— deletetoolbox.deprecated.*(68 endpoints; their only real consumer was the TS SDK removed in chore(apps): remove TypeScript cloud SDK (re-apply #738 onto main) #743) andworkspace.deprecated.*(legacy Daytona alias, zero consumers); delete the four box verbs frombox.controller(now owned by boxlite-rest); add cloud-optional create fields (labels/public/auto_stop_interval/auto_delete_interval) to the Box API contract (local engines ignore them); rewire metrics capture to the/api/v1routes.refactor(dashboard)—cloudBox.tsbecomes a small handwritten Box API client; create/start/stop/delete mutations and bulk actions switch to/v1/{org}/boxes(create re-reads the full org-scoped Box viagetBox, so UI types are unchanged); delete the dead Playground suite, VNC chain (route was hidden, flag default-false, feature retired),useBoxSession(zero consumers), and ToolboxApi wiring. Adds a unit test for the contract translation (GiB→MiB etc.).chore(clients)— regenerateapi-client(TS) +api-client-goin the CI-faithful box pipeline (ToolboxApi/WorkspaceApi and the verbs disappear); deleteapps/libs/toolbox-api-cliententirely (zero callers); add a contract boundary guard to the drift workflow: cloud spec must never re-grow/toolbox//exec//files//workspacepaths, Box API spec must stay tenancy-free.What still overlaps (by design, documented)
Cloud
getBox/paginated list stay on the cloud API: they are org-scoped metadata reads (region, labels, billing states) the engine cannot serve — per the ownership rule they are cloud capabilities that happen to be about a box. Same for signed URLs/ssh/archive/recover.Consumer safety (each verified in code)
vite build+ vitest greenfor-runner/state endpoints, untouched;go buildgreenapi-client/api-client-gousersVerification
nx test apigreen (incl. new mapper spec);tsc --noEmitclean.vite build --minify false: 0 TS errors (baseline-equal); vitest 6/6.go build ./...green forapi-client-goandapps/proxy. (apps/runnercmd link needslibboxlite.a, not built in this worktree — environment-only, packages compile.)/toolbox/,/workspace, or verb paths; boundary guard dry-run clean both directions.Out of scope / follow-ups
cloudBox.tsstill carries the Daytona AGPL header (pre-existing from chore(apps): remove TypeScript cloud SDK (re-apply #738 onto main) #743) — clean-room pass tracked separately.labelsonboxlite serve(currently ignored there, as documented in the spec).