Files
headquarter/apps/api/tests/unit/test_builtin_tool_users.py
Developer add7c1b500 feat: add live config profile refresh
- Standardize built-in tool users for shared writable profile mounts
- Mount canonical non-Git profile sources across compatible instances
- Report restart-required outcomes and guard active profile deletion
- Surface restart feedback in config profile editing

Quality gates: frontend build passed; backend py_compile and LSP passed.
Skipped: backend pytest/Ruff unavailable; Docker/manual checks not approved.
2026-07-21 11:12:41 +00:00

63 lines
2.3 KiB
Python

"""Tests for the shared non-root user used by built-in tools."""
from pathlib import Path
from src.seeds.builtin_tool_types import (
BUILTIN_TOOL_TYPES,
BUILTIN_USER_GID,
BUILTIN_USER_UID,
_standardize_builtin_manifest_user,
)
def test_builtin_compose_templates_use_shared_runtime_ids() -> None:
"""Every legacy built-in Compose tool declares the shared UID/GID."""
templates = {
str(tool["name"]): str(tool["compose_template"]) for tool in BUILTIN_TOOL_TYPES
}
assert "- PUID=1000" in templates["code-server"]
assert "- PGID=1000" in templates["code-server"]
assert "- NB_UID=1000" in templates["jupyter-notebook"]
assert "- NB_GID=1000" in templates["jupyter-notebook"]
assert "setpriv --reuid=node --regid=node --init-groups" in templates["opencode"]
def test_only_builtin_user_manifest_is_standardized() -> None:
"""The startup migration cannot rewrite a future custom tool user."""
builtin_manifest = {"user": {"name": "user", "uid": 1001, "gid": 1001}}
custom_manifest = {"user": {"name": "custom", "uid": 2000, "gid": 2000}}
assert _standardize_builtin_manifest_user(builtin_manifest)
assert builtin_manifest["user"] == {
"name": "user",
"uid": BUILTIN_USER_UID,
"gid": BUILTIN_USER_GID,
}
assert not _standardize_builtin_manifest_user(custom_manifest)
assert custom_manifest["user"] == {"name": "custom", "uid": 2000, "gid": 2000}
def test_tool_image_templates_define_shared_ids() -> None:
"""Project-owned image templates explicitly create or map UID/GID 1000."""
root = Path(__file__).resolve().parents[4]
sources = {
name: (root / "tool-images" / name).read_text()
for name in (
"base.dockerfile",
"opencode.dockerfile",
"pi-agent.dockerfile",
"code-server.dockerfile",
"jupyter.dockerfile",
)
}
for name in ("base.dockerfile", "opencode.dockerfile", "pi-agent.dockerfile"):
assert "groupadd -g 1000 user" in sources[name]
assert "useradd -m -u 1000 -g 1000" in sources[name]
assert "PUID=1000" in sources["code-server.dockerfile"]
assert "PGID=1000" in sources["code-server.dockerfile"]
assert "NB_UID=1000" in sources["jupyter.dockerfile"]
assert "NB_GID=1000" in sources["jupyter.dockerfile"]