feat(drop): deploy uploaded source archives - #549
Merged
Conversation
Add browser and CLI Drop flows, preset inspection, persisted source bundles, uploaded-source workflow planning, and project container cleanup.
📓 Changelog previewThis is what your commits will add to the generated ## [Unreleased]
### Added
- **drop:** Deploy uploaded source archives
- **drop:** Add header entry point and a project-scoped drop page
### Fixed
- **drop:** Harden uploaded deployments and cleanup
- **drop:** Bound archive inspection memory and CPU
### Testing
- **deployments:** Stub container-ownership lookup in cleanup tests |
Resolve conflicts: - crates/temps-presets/src/mod.rs: keep the branch's deduplicated import block and fold in main's autopack_preset re-export. - Generated SDKs (apps/temps-cli + web/src/api/client): regenerated from a three-way merged openapi.json instead of hand-merging, so both clients now match a fresh codegen and pick up the react-query hooks for the Drop endpoints.
Both the security audit and the standards review flagged /api/drop/inspect as an unbounded-allocation vector. - inspect_zip_manifests capped count and per-entry size but not the aggregate. MAX_FILES x MAX_MANIFEST_BYTES is 20 GiB, and manifests compress ~1000:1, so a ~5 MB upload could pin gigabytes of String per request and OOM the whole binary on the 4 GB reference box. Add an aggregate manifest budget (16 MiB, counted against bytes actually read, not the declared header size), a manifest count cap, and a budget on the retained entry paths. - detect_project_candidates ran after the spawn_blocking closure, so the concurrency permit no longer covered it and the work landed on an async runtime thread. Its has_extension closure also rescanned every key per root, making it O(roots x files). Index paths by directory once, run detection inside the same spawn_blocking, skip dependency/build-output directories, bound root depth, and cap the candidate list. - archive_security: replace the two .expect() calls with typed errors. Verified against a 5.2 MB archive of 4000 x 1 MiB manifests: 413 in 36 ms with server RSS flat at 301 MB.
Picks up teams/project-scoped RBAC (#486) and AI-proposed metric alert rules (#521). Resolve conflicts: - migration/mod.rs: both sides add a migration; keep both in date order (m20260730 teams RBAC before m20260731 source bundles). - Generated SDKs: regenerated from a three-way merged openapi.json rather than hand-merged, so both clients match a fresh codegen.
Drop was only reachable from the project-creation flow, and re-uploading source into an existing project used a bare `<input type="file">` dialog that accepted a ZIP only — no drag-and-drop, no folder support, no preset detection. That was a worse experience than the front door for the users most likely to repeat the action. - Add a global header button (UploadCloud, matching every other Drop surface) so Drop follows you across the console instead of living only under Projects. - Extract the drag-and-drop surface into `components/drop/DropZone` and the browser file-reading helpers into `lib/drop-files`, so `/drop` and the new page cannot drift apart. - Add `/projects/:slug/drop`, replacing the modal. Accepts a folder, a single HTML file, or a ZIP; runs the same detect-then-deploy flow. It may change the build directory and preset only — ports, resources and environment variables are deliberately left alone.
This branch added a runtime ownership check to `cleanup_project_containers` — it calls `get_container_info` and refuses to remove a container whose `sh.temps.*` labels do not match the project and environment being deleted. Three pre-existing cleanup tests were not updated, so they panicked on `MockContainerDeployer::get_container_info(...): No matching expectation found` rather than exercising the behaviour they assert. Add a shared `expect_owned_container_info` helper and wire it into all three, plus a test for the guard itself: a container whose labels claim a different project must fail closed, must never reach `remove_container`, and must not be marked deleted.
dviejokfs
marked this pull request as ready for review
August 4, 2026 14:03
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.
Summary
/dropproject inspection and uploaded-source deployment APIsPaired fixture PR: gotempsh/temps-examples#13
Status
Draft — security review is currently
REQUEST_CHANGES. Do not merge yet.Known blocking work:
uploaded-source-*treesproject.directoryneeds strict relative-path validation and canonical containment before becoming a Docker build contextAdditional follow-up findings include streaming large multipart uploads rather than buffering 500 MB, enforcing extraction quotas from actual bytes written, regenerating SDK operations for both endpoints, restricting advertised archives to implemented formats, and adding .NET manifest detection.
Evidence
Rust
Result: both completed successfully. Cargo check built 540 crates with zero errors; clippy completed with zero errors.
Web
Result: TypeScript passed; 11 tests passed, 0 failed.
Compatibility harness
Result:
zero-config compatibility harness test passed.Uploaded-source runtime matrix
The paired
temps-examplesrunner packaged each source directory, called/api/drop/inspect, created an uploaded-source project, deployed it, verified/and/health, deleted the project, and checked Docker cleanup..csprojdetection is not implementedProject rows, stored fixture archives, and labeled Docker containers were removed. The run reproduced the extraction-directory leak; the seven test directories were then removed manually.
Known baseline check failure
apps/temps-cli/bun run typecheckreports existing errors inopenapi-ts.config.ts,env-sync, environments, notifications, and providers. It reported no error in the new Drop command. This draft does not claim the repository-wide CLI type-check is green.Review findings to resolve
.tempsignore/.gitignorepackaging behavior to avoid uploading secrets and build directories