P3-1: Config, policy overlay and branding #30
Labels
No labels
data-integrity
engine
platform
procurement
remote
scaffold
ui
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/cairn-desktop#30
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
First task of phase 3. Depends on the
phase-2-integrationmilestone.Goal
One config system that an end user can edit, an administrator can override, and a build can brand — with a clear, testable precedence order.
Files
internal/config/config.gointernal/config/policy.go,internal/config/policy_windows.go,internal/config/policy_darwin.go,internal/config/policy_linux.go,internal/config/branding.go,internal/config/policy_test.goPrecedence — highest wins
Where policy sets a value, the UI must render that field read-only with a visible "managed by your organisation" note. A field that silently ignores the user's edit is worse than one that refuses it.
Where policy comes from, per platform
HKLM\SOFTWARE\Policies\SwissCairn\Cairn. This is what a GPO ADMX template writes to.ch.swisscairn.cairn) written by an MDM configuration profile./etc/cairn/policy.json. There is no standard mechanism; a documented path is the honest answer.Policy-controllable keys — at minimum
server·localPath·autoUpdateEnabled·errorReportingEnabled·concurrency·allowUserToChangeServerautoUpdateEnabledanderrorReportingEnabledare the two an enterprise will actually check for. Both must be switchable off fleet-wide (seedocs/design-spec.md§8.1, §8.2).Branding
Compile-time constants via
-ldflags: application name, icon path, accent colour, default server URL. Free and unrestricted — deliberately unlike Nextcloud, which gates branding behind a paid tier. This is a stated competitive position, not an afterthought.Steps
Managed == true; a missing policy source is not an error; branding defaults apply when nothing else sets a value.git commit -s -m "feat(config): policy overlay and build-time branding"Acceptance criteria
Amendment — 2026-09-14: phase-3 pre-flight rulings for #30
These rulings come from the phase-3 pre-flight survey. The owner approved posting them and may veto any of them. They bind this issue.
Key set (P3-R2). Implement the union of the keys the other issues need. Spell them identically in
policy.json, the adminconfig.jsonand the macOS managed plist, and (through #38) as the ADMX value names:server,localPath,autoUpdateEnabled,errorReportingEnabled,concurrency,allowUserToChangeServer,autostartEnabled,locale.Managed contract (P3-R3). The resolved config reports a
Sourcefor each key, in the order Branding < User < Admin < Policy.Managed(key)is true exactly when that source is Policy. Keys are exported constants. #33, #34, #35, #36 and #41, and #51's read-only form variant, consume only this contract.Admin config paths (P3-R4, proposed; confirm them in this issue).
/etc/cairn/config.json%ProgramData%\SwissCairn\Cairn\config.json(the #38 MSI writes this file)/Library/Application Support/SwissCairn/Cairn/config.jsonA machine with none of these files behaves exactly as it does today, and cairnsync's precedence is unchanged.
macOS policy without cgo (P3-R5). Read
/Library/Managed Preferences/ch.swisscairn.cairn.plistand/Library/Managed Preferences/<user>/ch.swisscairn.cairn.plistwith a pure-Go plist decoder. The decoder must build withCGO_ENABLED=0. Do not usedefaults read, which cannot tell a forced value from a user-set one.Dependencies (P3-R22). go.mod stays at
go 1.25with no toolchain line, andgo mod tidy -diffstays clean.Closing (D4). Two checks cannot run here yet: Windows registry reads at runtime, and a real MDM or GPO round trip. The policy code is cross-built and vetted for
GOOS=windows. The closing comment records both runtime checks as an open checklist, to be run once the Windows runner (#19) and a test domain (see #38) exist.Posted by Claude on behalf of @Cordy: phase-3 pre-flight, owner-approved process; the owner may veto any point.
Done
What was built
Branding < User < Admin < Policy) with aSource/Managed/Lockedcontract per key, built on eight exportedKeyconstants spelled once (P3-R2, P3-R3)./etc/cairn/policy.json, WindowsHKLM\SOFTWARE\Policies\SwissCairn\Cairn, macOS device + per-user managed preferences via a pure-Go, cgo-free plist decoder (P3-R5).-ldflagsbranding (name, icon, accent colour, default server).localPathis now checked absolute from every layer, and WindowsREG_EXPAND_SZvalues are expanded (fix round 1, F2).Tests
internal/config: full suite green, incl.TestResolvePrecedenceAtEveryLayer(8 keys × 8 layer subsets),TestAPolicySetFieldReportsManaged,TestAMissingPolicySourceIsNotAnError,TestBrandingDefaultsApplyWhenNothingElseSetsAValue,TestAnAdminOrPolicySetFieldIsLocked,TestTheKeysAreTheEightOfTheRuling, plus JSON/plist/registry fixture tests.67b5ac2, both green on arm64:ci.ymlrun #37 —go vet/go test ./..., coveragetotal: 90.5%.interop.ymlrun #38 — full integration suite against livecairnd, all PASS.Acceptance criteria
Source/Managed;Lockedadded (fix round 1) so UI editability gates onLocked, notManagedalone (P3-R3 amendment).TestAMissingPolicySourceIsNotAnError,TestLoadSettingsOnAMachineWithNoPolicy.go mod tidy -diffclean, go.mod staysgo 1.25.Rulings
Source/Managedcontract, amended this round to addLocked— consumers (#33–#36, #41, #51) gate editability onLocked, neverManagedalone.go mod tidy -diffclean.D4 checklist (unverified here, tracked forward)
Deferred
F3–F7 from the first review (BSD build regression, JSON
null, user-layer strictness, plist panic recovery, branded-server checks) remain open, plus two new minor findings from this round (Windows registry tests compile-checked but not run;REG_EXPAND_SZexpansion applies by value type, not by key). None blocks this issue; all are tracked for the final review.Implemented and reviewed by Claude (subagent-driven), landed on main after review and green CI.