feat(server): Phase 0: add control version history and soft-delete unusable legacy controls#172
Open
feat(server): Phase 0: add control version history and soft-delete unusable legacy controls#172
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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
This is the first step in the control lifecycle work. It introduces version history for controls and cleans up legacy rows that no longer satisfy the control contract, so later phases can build on a consistent base.
Design doc and implementation plan: https://gist.github.com/lan17/6a08282243576f096626bb10996c024b
What changed
The migration adds
controls.deleted_at, replaces the old global name uniqueness constraint with an active-only unique index, and creates the newcontrol_versionstable. Every existing control is backfilled into version history as version 1.During that backfill, we validate each existing control against the shapes we still support today: normal control definitions and unrendered templates. Controls that are empty, corrupted, or otherwise unusable are automatically soft-deleted. Before tombstoning them, the migration removes any policy, agent, or store associations so we do not leave active references behind.
At runtime, active control lookups now consistently ignore soft-deleted rows.
GET /api/v1/controls/{id}no longer returns a successful response withdata: null; if an active row is corrupted, we surface that as corrupted data instead. Deletes now tombstone the control rather than hard-deleting it, which keeps the newly backfilled version history intact.The shared API model and generated SDK surfaces were updated to match that tighter contract, and the server tests now cover migration backfill, automatic legacy cleanup, and soft-delete filtering across the affected paths.
Why this shape
We want later phases to assume a clean, explicit control lifecycle instead of carrying around
{}controls and other invalid legacy cases. Doing that cleanup here keeps the follow-on work simpler and makes the new version table immediately trustworthy.Reviewer notes
The migration is the part worth the closest look. In particular:
GetControlResponse.datacontractValidation
make checkmake openapi-spec-checkmake sdk-ts-generatemake sdk-ts-overlay-testmake sdk-ts-name-checkorigin/mainwith no findings