Files
pmg/.cursor/plans/system_install_design_98a8f15f.plan.md
T
Sahilb315andCursor 8f6d0fcce0 feat: add Linux system-wide setup
Install shared shims, managed configuration, and login-shell PATH integration so golden images and multi-user hosts can protect package installs for every user.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-11 02:19:59 +05:30

165 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: System install design
overview: "Design for `pmg setup install --system` (Linux): general system-wide shims + config + `/etc/profile.d`, motivated by Docker golden images but not Docker-specific. Venv-after-activate remains a documented limitation."
todos:
- id: spec
content: Write design spec to docs/specs/ after user approves design
status: completed
- id: eventlog-root
content: Eventlog soft-fail + root-without--system warning
status: completed
- id: system-artifacts
content: System shim manager, profile.d writer, WriteSystemTemplateConfig
status: completed
- id: cli-flags
content: Wire --system on install/remove with uid checks
status: completed
- id: info-doctor
content: Update setup info and doctor for system scope
status: completed
- id: docs-tests
content: Docs (golden image, venv limit) + unit tests
status: completed
isProject: false
---
# PMG System Install (`--system`) — Design
Re-evaluation of [issue #317](https://github.com/safedep/pmg/issues/317) against current codebase. Prerequisite [PR #323](https://github.com/safedep/pmg/pull/323) (`PMG_SHIM_PATH`) is already merged.
## Goal
Root can install PMG once for **all users** on a Linux host (golden Docker image, shared VM). Later `USER appuser` / non-root logins get interception without per-user `pmg setup install`.
Primary motivator: package installs inside `docker build` (host GHA PMG cannot see them). Feature itself is a **general Linux system install**, not a Docker mode.
## Non-goals (v1)
- macOS / Windows `--system`
- Persistent proxy baked into images
- In-place wrap of `/usr/local/bin` binaries
- Shell **function** wrappers (venv interactive fix)
- Making host PMG intercept `docker build` from outside the image
- Closing the venv-after-`activate` PATH race via shims
## Locked decisions
| Topic | Choice |
| -------------------------- | -------------------------------------------------------------------------------------------- |
| Scope | Linux only |
| Shim location | `/usr/local/lib/pmg/bin` (not `/usr/local/bin`) |
| Config | Write `/etc/safedep/pmg/config.yml` (read path already exists) |
| PATH on VMs / login shells | `/etc/profile.d/pmg.sh` prepends shim dir |
| PATH in Docker builds | Image author sets `ENV PATH="/usr/local/lib/pmg/bin:$PATH"` (documented; required for `RUN`) |
| Venv after `activate` | Documented limitation → use `pmg pip …` |
| Proxy-in-image | Rejected for this use case |
| Layers | System and per-user installs independent |
## User flows
### Golden Docker base
```dockerfile
RUN curl -fsSL … | sh && pmg setup install --system
ENV PATH="/usr/local/lib/pmg/bin:$PATH"
```
Child images:
```dockerfile
FROM company/golden:latest
USER appuser
RUN npm ci # intercepted
RUN pip install pkg # intercepted (system pip)
# RUN .venv/bin/activate && pip install x # NOT intercepted — use pmg pip
```
### Multi-user Linux VM
```bash
sudo pmg setup install --system
# new login shells get PATH via /etc/profile.d/pmg.sh
```
### CLI UX
```bash
sudo pmg setup install --system # root-only; fail fast otherwise
sudo pmg setup remove --system
pmg setup info # reports system / user / both
pmg setup doctor # checks system shim dir + on PATH
```
- Root without `--system` → warn (other users not covered; point to `--system`), then proceed with per-user install into roots HOME.
- Non-root `--system``usefulerror` + sudo guidance.
## Architecture
```mermaid
flowchart TB
subgraph install [pmg setup install --system]
Cfg["/etc/safedep/pmg/config.yml"]
Shims["/usr/local/lib/pmg/bin/*"]
Profile["/etc/profile.d/pmg.sh"]
end
subgraph path [How PATH gets shims]
Env["Docker ENV PATH"]
Prof["profile.d on login shells"]
end
Shims --> Env
Shims --> Prof
Env --> Run["Dockerfile RUN / any process with ENV"]
Prof --> Login["VM interactive/login shells"]
```
### Components to add/change
- `[cmd/setup/setup.go](cmd/setup/setup.go)``--system` flag, uid-0 preflight, branch install/remove; root warning without flag
- `[config/config.go](config/config.go)``WriteSystemTemplateConfig()``globalConfigDir()`; remove only with `--system`
- `[internal/shim/shim.go](internal/shim/shim.go)``NewSystemShimManager()` with `BinDir=/usr/local/lib/pmg/bin`, no per-user rc edits
- New system profile writer — `/etc/profile.d/pmg.sh` (marker-gated, PATH prepend only)
- `[cmd/setup/info.go](cmd/setup/info.go)` / `[cmd/setup/doctor.go](cmd/setup/doctor.go)` — system scope reporting + PATH check
- `[main.go](main.go)` / eventlog — soft-fail when log init fails (unusable HOME); do not `Fatalf`
Reuse existing `PMG_SHIM_PATH` filtering in `[internal/shim/path.go](internal/shim/path.go)`; no recursion work needed for the new shim dir.
## Corner cases (handled or documented)
| Case | Handling |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Docker `RUN` does not source profile.d | Document `ENV PATH=…` in golden image |
| Login shell resets PATH via `/etc/profile` | profile.d restores shim dir |
| Child Dockerfile overwrites `PATH` without shim dir | Document; doctor can detect when run |
| Venv `activate` then `pip` | Documented limitation → `pmg pip` |
| System + per-user both present | Independent; remove is scoped |
| `PMG_SHIM_PATH` unset + direct `pmg npm` | Legacy `/.pmg/bin` only; system dir not stripped — prefer shim invocation or ensure env from shim |
| Unwritable HOME | Eventlog soft-fail |
| Windows | `--system` → not supported |
## Testing
- Unit tests with path overrides (same pattern as `globalConfigDirOverride`)
- Install/remove idempotence for system shims + profile.d
- Doctor/info system detection
- Document a minimal Dockerfile golden-image smoke example in docs (not necessarily CI matrix in v1)
## Docs
- Setup / config docs: `--system`, golden-image snippet, VM vs Docker PATH, venv limitation
- Clarify host GHA PMG does not protect in-image `docker build` installs — bake PMG into the image
## Implementation order (after spec approval)
1. Soft-fail eventlog + root warn (small, unblocks containers)
2. System shim manager + profile.d writer + config write
3. Wire `--system` on install/remove
4. info/doctor
5. Docs + tests