Repository navigation
fix(projects,environments): finish project delete after client disconnect; audit env var writes - #1543
Merged
Conversation
…nect; audit env var writes
Project delete: the DELETE /projects/{id} teardown ran inside the request
future, so a client disconnect dropped it right after the is_deleted fence,
leaving the project listed, serving and refused by write endpoints. The
teardown now runs on a spawned task that the handler awaits; a dropped
request no longer cancels it.
Env vars: create, update and delete were not written to the audit log (only
reveal and promote-to-secret were). Add ENVIRONMENT_VARIABLE_CREATED,
ENVIRONMENT_VARIABLE_UPDATED (with changed_fields) and
ENVIRONMENT_VARIABLE_DELETED entries. The value, old or new, is never
recorded. .env import goes through the create handler, so it is covered.
Fixes #1539
Fixes #1537
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: David Viejo <dviejokfs@temps.sh>
📓 Changelog previewThis is what your commits will add to the generated ## [Unreleased]
### Fixed
- **projects,environments:** Finish project delete after client disconnect; audit env var writes
- **projects:** Log project deletion failures from the detached teardown task |
[Critical impact] The PR appears safe to merge; the previous finding is fixed and no new actionable issues remain. SummaryProject deletion now runs on a separate task so cleanup can finish after the client disconnects. Environment variable writes also gain audit entries without recording their values.
|
…wn task After a client disconnect nobody awaits the teardown result, so errors from begin_project_deletion and the final row delete were returned but never logged, leaving a fenced project with no trace of why cleanup stopped. Log both inside the task with the project id, and log successful completion. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: David Viejo <dviejokfs@temps.sh>
dviejokfs
enabled auto-merge (squash)
October 15, 2026 17:56
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
Project delete survives a client disconnect (#1539)
DELETE /projects/{id}awaited every teardown step in the request future. Axum drops that future when the client disconnects, so the project stayed fenced (is_deleted = true) with its environment, deployments and containers intact: still listed, still serving, and refused by write endpoints.The teardown (fence, deletion hook, cancel deployments, container cleanup, archive cleanup, row delete, audit entry) now lives in
run_project_teardownand runs on atokio::spawned task that the handler awaits. Dropping the request drops only theJoinHandle, which detaches the task. Errors and the response contract are unchanged; a panic in the task is reported as a 500 that tells the caller to retry.Not changed: the read-side items in the issue's checklist (#2 and #3, a fenced project still returned by list/get). Happy to follow up if wanted.
Audit env var create / update / delete (#1537)
ENVIRONMENT_VARIABLE_CREATED,ENVIRONMENT_VARIABLE_UPDATEDandENVIRONMENT_VARIABLE_DELETED, emitted from the three handlers like the existing promote entry (an audit failure is logged and does not fail the write).is_secret, and for updateschanged_fields(key,value,environments,include_in_preview,is_secret). The value, old or new, is never recorded;valueonly means a new value was supplied.EnvVarService::delete_environment_variablenow returns aDeletedEnvVar(id, key, is_secret, environment ids) andUpdateEnvVarOutcomegainschanged_fields, both computed inside the existing locked transaction, so there is no extra read outside it.ENVIRONMENT_VARIABLE_PROMOTED_TO_SECRETentry is kept; a promotion now also produces anUPDATEDentry withis_secretinchanged_fields.Testing
cargo test --lib -p temps-environments: 125 passed (new: changed-field reporting, delete reporting, audit payloads carry no value).cargo test --lib -p temps-projects handlers::: 81 passed (new: teardown runs on a detached task and none of its steps are inline in the handler; a spawned task outlives a dropped awaiter).cargo clippy --lib --tests -p temps-environments -p temps-projects: clean.python3 scripts/source_attribution.py check: passes.custom_domainstests intemps-projectsneed a Docker socket, which was not available locally, so they were not exercised.--max-timerepro) was done.Fixes #1539
Fixes #1537
🤖 Generated with Claude Code