Skip to content

SEP-1707: Make override-row lookup canonical-key-aware in the DELETE and PATCH settings-override paths - #1344

Open
peter-o-addo wants to merge 9 commits into
mainfrom
SEP-1707
Open

SEP-1707: Make override-row lookup canonical-key-aware in the DELETE and PATCH settings-override paths#1344
peter-o-addo wants to merge 9 commits into
mainfrom
SEP-1707

Conversation

@peter-o-addo

@peter-o-addo peter-o-addo commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Make DELETE and PATCH settings-override paths resolve rows by canonicalizing the stored key, so a legacy mixed-case override is seen, deleted, or updated instead of being skipped or duplicated.

  • app/core/settings_override/registry.py: add override_rows_for_key, which lists a class's rows and keeps those whose stored key canonicalizes to the requested key.
  • app/core/settings_override/api/routes.py: DELETE finds and removes every matching row (including duplicates); PATCH updates matching legacy rows instead of inserting a second one.
  • changelog.d/SEP-1707.fixed.md: add the release-note fragment.
  • tests: cover the helper and the DELETE/PATCH HTTP cases for legacy-cased and duplicate rows.

Tested

  • GET /api/sep/admin/settings/Settings/PMM__endpoint after inserting pmm__ENDPOINT returns 200 with has_override: true.
  • DELETE /api/sep/admin/settings/Settings/PMM__endpoint returns 204 and removes the pmm__ENDPOINT row.
  • DELETE of the canonical key with both pmm__ENDPOINT and PMM__endpoint present returns 204 and clears both rows.
  • PATCH {"PMM__endpoint": "https://pmm.example.com"} returns 200, keeps a single row, and updates the legacy pmm__ENDPOINT value in place.

Checklist

  • New/modified functions have type hints and rST docstrings
  • New tests added for new features or bug fixes
  • All tests pass locally (make test)
  • Pre-commit hooks pass (make run-pre-commit)
  • Database migrations generated if models changed (make makemigrations)
  • User-facing changes documented (README, inline help, UI text)
  • Configuration changes documented with examples
  • Changelog fragment added under changelog.d/ if the change is user-facing (make changelog-add), or confirmed N/A (internal-only change, or a same-release-cycle fix for an unreleased sibling ticket)

@peter-o-addo
peter-o-addo marked this pull request as ready for review August 17, 2026 18:01
Copilot AI lite review requested due to automatic review settings August 17, 2026 18:02
@peter-o-addo
peter-o-addo requested review from a team and yyyyyyyan as code owners August 17, 2026 18:02
@peter-o-addo peter-o-addo added the qa in progress Someone is currently testing this PR - do not merge it label Aug 17, 2026
@peter-o-addo

Copy link
Copy Markdown
Contributor Author

1. Read path already sees a legacy row

INSERT INTO settingoverride (created_at, setting_class, key, value, is_active)
VALUES (datetime('now'), 'SETTINGS', 'pmm__ENDPOINT', '"https://stale.example.com"', 1);
GET /api/sep/admin/settings/Settings/PMM__endpoint

200

{
  "setting_class": "Settings",
  "key": "PMM__endpoint",
  "value": "https://127.0.0.1:9090",
  "has_override": true,
  "reload": "hot"
}

has_override: true is the check. Snapshot value can still be YAML until the next refresh.


2. DELETE removes the legacy row (was a silent 204 that left the row)

DELETE /api/sep/admin/settings/Settings/PMM__endpoint

204

SELECT COUNT(*) FROM settingoverride
 WHERE setting_class='SETTINGS' AND key='pmm__ENDPOINT';
-- 0

3. DELETE removes both spellings

INSERT INTO settingoverride (created_at, setting_class, key, value, is_active)
VALUES
  (datetime('now'), 'SETTINGS', 'pmm__ENDPOINT', '"https://legacy.example.com"', 1),
  (datetime('now'), 'SETTINGS', 'PMM__endpoint', '"https://canonical.example.com"', 1);
id  key            value
--  -------------  -------------------------------
6   PMM__endpoint  "https://canonical.example.com"
5   pmm__ENDPOINT  "https://legacy.example.com"
DELETE /api/sep/admin/settings/Settings/PMM__endpoint

204SETTINGS rows for either spelling: none.


4. PATCH updates the legacy row (no duplicate)

Seeded only pmm__ENDPOINT = "https://stale.example.com" (id 5).

PATCH /api/sep/admin/settings/Settings
{"PMM__endpoint": "https://pmm.example.com"}

200

[{
  "setting_class": "Settings",
  "key": "PMM__endpoint",
  "value": "https://pmm.example.com",
  "has_override": true
}]
id  key            value                      is_active
--  -------------  -------------------------  ---------
5   pmm__ENDPOINT  "https://pmm.example.com"  1

One row, same id, stored key left as pmm__ENDPOINT.

@peter-o-addo peter-o-addo added qa passed Tests for this PR are completed and successful. and removed qa in progress Someone is currently testing this PR - do not merge it labels Aug 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a legacy-compatibility gap in the settings-override write paths by making DELETE and PATCH resolve override rows using canonicalized nested keys, so mixed-case historical rows are found and updated/deleted instead of being skipped or duplicated.

Changes:

  • Added a registry helper to resolve override rows whose stored key canonicalizes to a requested key.
  • Updated DELETE to remove all matching rows (including duplicates) and PATCH to update matching legacy rows rather than inserting a second row.
  • Added test coverage for the helper and the HTTP DELETE/PATCH behaviors, plus a changelog fragment.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
app/core/settings_override/registry.py Adds override_rows_for_key() to resolve rows by canonicalized key equivalence.
app/core/settings_override/api/routes.py Switches DELETE and PATCH persistence logic to operate on canonical-key-matched rows (including duplicates).
tests/app/core/settings_override/test_registry.py Unit tests for override_rows_for_key() across legacy casing, duplicates, class filtering, inactive rows, and top-level behavior.
tests/app/core/settings_override/api/test_policy_lockdown.py HTTP tests covering DELETE/PATCH against legacy-cased and duplicate stored rows.
changelog.d/SEP-1707.fixed.md Release note describing the behavior change.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +1284 to +1288
await SettingsOverrideManager.delete_where(
session,
col(SettingOverride.key).in_({row.key for row in rows}),
setting_class=setting_class,
)
Comment on lines 1355 to 1362
for key, value in to_apply:
stored_value = unwrap_secrets_for_storage(value)
existing = await SettingsOverrideManager.first(
session, setting_class=setting_class, key=key
existing_rows = await override_rows_for_key(
session,
settings_cls=settings_cls,
setting_class=setting_class,
key=key,
)
@github-actions

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  app/core/settings_override
  registry.py
  app/core/settings_override/api
  routes.py 1126, 1128, 1130, 1363-1375
  app/sep
  inventory.py
  app/sep/sync/syncers
  pmm.py
Project Total  

This report was generated by python-coverage-comment-action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend python qa passed Tests for this PR are completed and successful.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants