Repository navigation
Enforce the installed workspace policy on launch - #1260
Conversation
Explicit ug configure now installs the workspace policy at /etc/unitygateway/managed-settings.json on Linux and macOS, using a non-interactive-sudo-capable writer. Unchanged policy writes nothing, and no-config or feature-disabled removes the installed file. A failed install raises ManagedPolicyInstallDenied with an actionable message. Launches keep reading the per-user cache and never touch the machine file. Co-authored-by: Isaac <no-reply@databricks.com>
Launches read the policy installed at /etc/unitygateway/managed-settings.json, refuse a selection for another workspace, and refresh at most every five minutes using user-owned stamps in ~/.ucode/refresh_ts.json. Non-root launches never install or remove the policy. The per-user cache remains only for Windows, UG_SKIP_OS_SETTINGS, and --user. Configure restores the saved workspace on a denied install, and other agents refuse early on a machine managed elsewhere. Also adds ug export, dry-run workspace adoption, and the CUJ recorder and harness reading the installed policy. Co-authored-by: Isaac <no-reply@databricks.com>
`ug revert` deletes /etc/unitygateway/managed-settings.json with sudo; nothing else writes that file. Without sudo it warns and keeps it, and Windows, UG_SKIP_OS_SETTINGS and `--user` leave it alone. Test cleanup keeps a backstop removal in its own finally, so a failed or skipped revert can no longer leave the policy behind for later cases. Co-authored-by: Isaac <no-reply@databricks.com>
# Conflicts: # docs/managed-workspace-policy.md # src/ucode/managed_config.py # tests/test_managed_config.py
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
/ug-review |
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Removal hands the replace script the exact bytes of the installed file, so a file with a BOM or CRLF endings still matches its byte-for-byte check. Add a regression test and a comment on why the copy is binary. Co-authored-by: Isaac <no-reply@databricks.com>
- The --agent refusal says the selection stays on the installed workspace and to rerun configure from a terminal with sudo access. - The launch refusal tells skip-mode users to switch without UG_SKIP_OS_SETTINGS, which is the only way the policy can change. - _launch_workspace_state resolves the target workspace once. - The configure integration test checks the policy folder is root-owned. Co-authored-by: Isaac <no-reply@databricks.com>
Polly AI ReviewBlocking issues
Security vulnerabilitiesNo confirmed new vulnerability found in the reviewed changes. Installed-policy precedence under Non-blocking notes
No added or modified source comments warrant a conciseness finding. ApproachSeparating protected policy from user-owned refresh metadata is sound when an installed policy exists. The first-launch storage/throttling conflict needs resolution rather than another fallback branch. The repeated refresh-result construction and overlapping token/fetch handling in SummaryDiff size (computed): 20 files; +1829 / -537 lines (2366 changed text lines); 0 binary files.
Shares use additions + deletions, including generated text and lockfiles. Binary files have no line count. Tests include fixtures/helpers under test paths and colocated test/spec files; categories are path-based, not coverage measurements. ChangesThe PR makes installed machine policy authoritative for launch workspace selection, separates freshness metadata into a user-owned sidecar, and restores the installed workspace after denied configure writes. It also migrates integration/CUJ evidence sources and updates documentation. Most of the size follows the persistence migration and state-transition coverage. No dependency or lockfile changes are included. Sharing refresh plumbing could reduce duplication without changing the design. TestsTest-by-test assessmentThe frozen diff’s checksum was verified and both trusted policy files were read. Tests were not executed; the PR’s reported green results were not independently verified. The supplied base/head Git objects were unavailable locally, so unchanged context came from the supplied trusted checkout rather than the exact target tree. The tables account for changed cases, removed cases, and support edits. Existing callers are identified where a changed helper alters their evidence source. Parameterized inputs with the same purpose share a row. Shared support, documentation, and CUJ adapters
Integration cases
CLI cases
Persistence and TTL cases
Machine-policy refresh cases
Per-user fallback and workspace resolution
Removed installation cases These rows refer to the removed
Revert and recorder adaptations
The concrete missing regressions are failed authoritative reads during workspace switching and repeated non-root first-launch reads. Existing unit/component scenarios are the smallest suitable place to add them; new live suites are unnecessary. Removed installation assertions should be transferred as noted rather than restoring a separate integration journey. After those changes, run the focused suites in a prepared environment: uv run --offline pytest tests/test_managed_config.py tests/test_cli.py tests/test_tui_request_recorder.pyOn a disposable machine, also verify that configuring B while its policy read fails leaves A selected, and that two ordinary-user launches within five minutes follow the resolved first-launch throttling contract. ScopeNo clearly unrelated changes were found. Policy persistence, workspace enforcement, configure recovery, harness migration, and documentation support the stated outcome. The first-launch TTL inconsistency is a contract problem within that scope, not a separate feature. Automated review by Polly · workflow run |
## 🥞 Stacked PR Use this [link](https://github.com/databricks/unity-gateway/pull/1259/files) to review incremental changes. - [**mdm-policy-write**](databricks#1259) [[Files changed](https://github.com/databricks/unity-gateway/pull/1259/files)] ← _this PR_ - [mdm-policy-read](databricks#1260) [[Files changed](https://github.com/databricks/unity-gateway/pull/1260/files/6ba7a3011ea0819265eedf572012cac0bbbb4192..99fe5a1a10574107c95c514d99fb5ac770d07dc0)] - [mdm-policy-windows](databricks#1262) [[Files changed](https://github.com/databricks/unity-gateway/pull/1262/files/054432159de3b7c08ada7587c110d35a4be1190e..653d83aa3ea952cc4c5d82e79ad00810d8c2a49c)] --------- **Worktree:** unity-gateway | **Branch:** mdm-policy-write ## What did you change, and why? First of two stacked PRs that replace databricks#1228, porting databricks#1105's machine workspace policy. This one only writes it: on Linux and macOS, `ug configure` for Claude or Codex installs the workspace's managed config as root-owned `/etc/unitygateway/managed-settings.json` (`{workspace, config}`, `0644` in a root `0755` folder) using sudo. It rewrites the file only on change and removes it when the workspace publishes none. If sudo is denied, configure fails with steps to fix it. Launches don't change: they still read the per-user cache. Windows, `UG_SKIP_OS_SETTINGS` and `--user` write nothing. databricks#1260 makes launches read the file. ## How do you know it works? New unit tests cover the writer and the install, replace and remove paths. One integration test checks that configure installs a root-owned file. Lint and ty are clean. https://github.com/user-attachments/assets/4ba1ca86-b04a-4aa7-bc89-a091be265642 --------- Co-authored-by: Isaac <no-reply@databricks.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
🥞 Stacked PR
Use this link to review incremental changes.
Worktree: unity-gateway | Branch: mdm-policy-read
What did you change, and why?
Second of two stacked PRs replacing #1228. It's based on #1259, which installs the policy file. Launches now read the installed policy instead of the per-user cache on Linux and macOS:
ug,ug claudeandug codexrefuse any other workspace. Onlyug configurecan switch it.~/.ucode/refresh_ts.json.Windows,
UG_SKIP_OS_SETTINGSand--userkeep the per-user cache unchanged.How do you know it works?
Unit tests cover enforcement, refresh and fallback. The CUJ and integration harnesses read the installed policy. Lint and ty are clean.
Screen.Recording.2026-10-23.at.7.18.08.AM.mov