Skip to content

feature: managed settings. - #10589

Draft
camilasan wants to merge 16 commits into
masterfrom
feature/5497/mdm
Draft

feature: managed settings.#10589
camilasan wants to merge 16 commits into
masterfrom
feature/5497/mdm

Conversation

@camilasan

@camilasan camilasan commented Aug 12, 2026

Copy link
Copy Markdown
Member

Resolves

#5497

This PR is branched off #9191, that why the 22 commits (for now).

Summary

First slice of managed settings support for the desktop client as described in #5497. It adds a small resolver that computes the effective value of a setting from a set of sources and reports where the value came from and whether it is locked. No production settings are routed through it yet; this is the foundation the later work builds on.

This starts from the Migration logic refactoring in PR #9191, which ties the settings readers this will extend.

TODO

  • Concrete sources, the settings schema, and routing existing getters through the resolver.

See plan in #5497 (comment).

Checklist

AI (if applicable)

@camilasan camilasan added this to the 35.0.0 milestone Aug 12, 2026
@camilasan camilasan changed the title Feature/5497/mdm feature: managed settings. Aug 12, 2026
camilasan and others added 16 commits August 19, 2026 08:43
It should cover upgrade, downgrade as well as upgrade from unbranded to branded,
from legacy to branded and from legacy to unbranded.

- Detect upgrade only scenario: If no legacy file is found, it means it might be upgrade only.
- Refactor find and readlegacy config files in Migration.
- Make all Migration class members static.
- Rename Migration class members.
- Update code base to reflect the refactoring and move of functions.
- Add tests.
- Add extended comment with Migration flow.

Signed-off-by: Camila Ayres <hello@camilasan.com>
Add test cases covering: isInProgress for all phases, rollback prevention,
isUpgrade/isDowngrade without side effects, downgrade scenario,
version unchanged path, shouldTryToMigrate for both true and false cases,
and shared static state across instances.

Signed-off-by: Camila Ayres <hello@camilasan.com>
Use the existing local variable instead.

Signed-off-by: Camila Ayres <hello@camilasan.com>
legacyData() calls setDiscoveredLegacyConfigPath() and setLegacyData()
on this, which are non const methods. Marking the function const was
wrong since it has side effects and GCC/Clang both reject it with
-Werror. Remove the const qualifier.

Signed-off-by: Camila Ayres <hello@camilasan.com>
…ration.

These four constexpr variables were already moved to migration.cpp as
part of the refactor. The leftover copies in accountmanager.cpp were
causing -Wunused-const-variable errors on Linux and macOS.

Signed-off-by: Camila Ayres <hello@camilasan.com>
QSettings had two owners and was freed twice at shutdown or on the next reset.

Make LegacyData a std::unique_ptr, move it to the caller, drop the unused
_legacyData static, and std::move it into settings at the call site so a
single owner remains.

Add tests for legacy config discovery and the no legacy config case.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
…nary.

Once an upgrade settled those two values to be equal, later upgrades were
no longer detected, while a freshly upgraded config whose clientVersion
already matched the running binary still fired a redundant migration pass.

Add tests for the already current config and the upgrade from equal versions
cases.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
Make both queries self contained and const.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
…gration.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
Add per test teardown to the tests (folder manager reset, AccountManager
shutdown) so created accounts do not bleed across tests through the singleton,
and drop the now meaningless state shared across instances test.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
Resolves the effective value of a setting from a set of injectable sources
and returns metadata (winning source, default or locked). Precedence: locked
policy, then user config, then the highest default, then the builtin default.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <hello@camilasan.com>
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <camila.ayres@nextcloud.com>
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <camila.ayres@nextcloud.com>
Native registry, plist and conf adapters plus buildDeviceSources, replicating
the app name selection of ConfigFile::getValue and getPolicySetting. The OS
adapters are not unit tested on the Linux build; only the factory is smoke tested.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <camila.ayres@nextcloud.com>
…ngs resolver

skipUpdateCheck and autoUpdateCheck now go through ManagedSettings with the
device sources and the user config, preserving the precedence policy over user
over OS default over builtin. The user source carries the connection group so a
locked policy still overrides a group scoped user value.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <camila.ayres@nextcloud.com>
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Camila Ayres <camila.ayres@nextcloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant