Actions
39 actions, callable from the panel, the command palette and the API as
POST /api/v1/a/<id>. Internal actions used between modules are not listed.
| Action | What it does | Risk | Preview |
|---|---|---|---|
software.os.list | List OS packages, updates, holds and reboot state (read) | low | No dry run |
software.os.refresh | Refresh the package index | low | No dry run |
software.os.plan | Dry-run a package change (read) | low | No dry run |
software.os.apply | Apply a package change | high | |
software.os.hold | Hold packages at their current version | medium | |
software.os.unhold | Release package holds | medium | |
software.os.allow.get | Show the package allow-list (read) | low | No dry run |
software.os.allow | Edit the package allow-list | high | |
software.repo.list | List package repositories (read) | low | No dry run |
software.repo.preview | Show a repository signing key and its fingerprint (read) | low | No dry run |
software.repo.add | Add a third-party repository | critical | No dry run |
software.repo.toggle | Enable or disable a repository | high | No dry run |
software.repo.remove | Remove a third-party repository | critical | No dry run |
software.updates.get | Show the update policy (read) | low | No dry run |
software.updates.configure | Set the update policy | high | No dry run |
software.inventory.export | Export the package and PHP inventory (read) | low | No dry run |
software.php.list | PHP versions on a node (read) | low | No dry run |
software.php.install | Install a PHP version | high | |
software.php.remove | Remove a PHP version | high | |
software.php.ext.list | PHP extensions of a version, per scope (read) | low | No dry run |
software.php.ext.set | Enable or disable a PHP extension for a scope | medium | |
software.php.ext.install | Install or remove a PHP extension package | high | No dry run |
software.php.ext.pecl | Build a PECL extension from the allow-list | high | No dry run |
software.php.default.get | Default PHP version (read) | low | No dry run |
software.php.default.set | Set the default PHP version | medium | |
software.php.ini.get | PHP settings form of an account or site (read) | low | No dry run |
software.php.ini.set | Change PHP settings of an account or site | medium | |
software.php.status | PHP-FPM and opcache status (read) | low | No dry run |
software.reconcile | Re-apply the saved extension switches | low | No dry run |
software.runtime.list | Runtimes, versions and EOL state (read) | low | No dry run |
software.runtime.install | Install a runtime version (shared store) | medium | |
software.runtime.remove | Remove a runtime version | medium | |
software.runtime.detect | Suggest versions from an app's files (read) | low | No dry run |
software.runtime.select | Select a version for an app or the account default | low | |
software.runtime.policy.set | Offered runtimes, versions and on-demand cap | medium | |
software.runtime.usage | Who uses which runtime (EOL report) (read) | low | No dry run |
software.runtime.request.resolve | Close a version request | low | No dry run |
software.tool.pin | Pin a global tool version | medium | |
software.tool.list | Managed tools and pins (read) | low | No dry run |
Permissions and limits
Permissions
software.os.viewView packages and repositoriessoftware.os.manageApply package changes, holds and update policysoftware.os.adminEdit the package allow-listsoftware.repo.manageAdd and change package repositoriessoftware.php.viewView PHP versions and settingssoftware.php.manageChange PHP extensions, version and settings of own sitessoftware.php.adminInstall PHP versions and extensions server-widesoftware.runtime.viewSee runtimes and their EOL statesoftware.runtime.useChoose runtime versions for own apps and accountsoftware.runtime.manageInstall or remove runtime versions in the shared storesoftware.runtime.adminSet which runtimes and versions are offeredsoftware.tool.managePin global tool versions
Engineering notes
Generated from modules/software/docs.md at build d90e9e2. These are the notes the engineers keep
next to the code: precise, technical, and honest about what is not done yet.
Spec: docs/specs/software.md AC-software-01..17. Card: docs/tasks/w9/w9-14-software-os-php.md.
Runtimes and tools: card w9-18, section below. Panel extensions are the built-in extensions.* module (w9-16).
OS packages
software.os.list(installed / upgradable / security / held / managed, search, reboot-required, lock state, index age),software.os.refresh(job) and an hourlysoftware.scheduled.refreshthat caches the counts per node and emitssoftware.updates.available/software.reboot.required/software.php.eol_soon.- Allow-list. Install / upgrade need the package to be on the allow-list: the panel-managed set (every module's
AllowPackagesin the agent) plus the administrator's additions (software.os.allow, stored inm_software.allow_listand sent with every request). Removal is further limited: a package owned by another module (nginx, mariadb, postfix ...) or essential to the OS is never removable here, directly or as a dependency of something else (the simulation is checked), and the refusal names the module that needs it. No API field carries raw apt/dnf arguments: names must match^[a-z0-9][a-z0-9+.-]*[a-z0-9]$(no option orname-/name+suffix lookalikes) and every command line is built by the agent. - Plan / apply.
software.os.plansimulates with the package manager itself (apt-get -s,dnf --assumeno) and returns steps (install/upgrade/remove with versions, dependency flag, installed size), download and disk deltas, services affected (active units owned by upgraded or removed packages),refusedreasons and a hash over the steps.software.os.apply(long: true, risk high => step-up) re-plans, comparesplan_hashwhen given, takes the node queue, waits (up to 2 min, "package manager busy" in the job log, thenbusy) while another process holds the dpkg/dnf lock, runs the groups (upgrade, install, remove) streaming the output, then callssecurity.updates.health_watchand records history +software.updates.applied.dry_runreturns amodule.Plan; refusals are errors (precondition_failed).upgrade_class: security|allupgrades every upgradable package of that class (held ones are skipped and listed). - Holds.
software.os.hold/unhold(apt-mark /dnf versionlock). A held package cannot be named in an upgrade. - Update policy lives in security:
software.updates.get/configureonly callsecurity.updates.status/configure. - Repositories.
software.repo.list(os / vendor / third_party, enabled, signed, key fingerprints),software.repo.preview(downloads a key over https and returns the fingerprint of every primary key, changes nothing),software.repo.add(risk critical => step-up; needs the fingerprint the administrator confirmed; the agent downloads the key again, requires that fingerprint, keeps ONLY that key in the repository's keyring, writes a deb822 source withSigned-By(apt) or a.repowithgpgcheck=1(dnf), runsapt-get update/dnf makecacheand removes everything again when that fails).toggleworks onrc-*repositories only (#rc-off#for.listfiles,Enabled: nofor.sources),removeon repositories added here only. OS repositories are shown read-only.
PHP
- Versions come from the version catalog (EOL date and label included):
software.php.list.installadds the PHP repository when needed (Debian family) and installs the standard extension set;removeis refused while sites use the version unlessmigrate_tonames an installed version (sites are moved throughweb.sites.updatefirst). After install/remove/default the module callsweb.server.ensurewith the installed set, because web only offers versions it was told about; the server default is web'sdefault_phpfor new sites. - Extensions per scope.
software.php.ext.list(installed/available, description, size, dependencies, conflicts, warnings, server state on/off/absent, account state inherit/on/off and the effective state).software.php.ext.setscopeserver(admin; the extension's ini linked in or out of the version's FPMconf.d) oraccount/site. PHP only loads extensions from the ini scan directories of the master process, never from a pool section, and web runs one master per account and version. So an account (site) switch is a private scan directory plus a systemd drop-inrc-fpm-<ver>-<user>.service.d/50-rc-software-ext.conf(PHP_INI_SCAN_DIR) and a restart of THAT master only (measured 0.2-0.5 s; other accounts' masters are not touched). The new directory is checked first (the extension must load,php-fpm -tmust accept the pool) and everything is rolled back on failure. A site-scope switch is therefore an account-wide switch for that PHP version (the response saysscope: account). software.php.ext.installinstalls/removes an extension package (admin scope;disabled: trueleaves it off server-wide).software.php.ext.pecl: vetted list apcu, igbinary, imagick, memcached, mongodb, redis, swoole, xdebug. The agent installs the build tools andphp<ver>-dev, finds the stable release on pecl.php.net, downloads over https, unpacks with a path-checked extractor into a temp directory owned bynobody, and runs phpize / configure / make asnobodywithno-new-privs, an empty environment and no network (unshare -n). Only the finished module is copied (by root) to/var/lib/respirecloud/software/pecl/<php>/<ext>-<release>/<ext>.so, proven to load, and only then is its ini written. Failure or cancel removes the temp directory and changes nothing. It starts off server-wide. RHEL family: not built; the Remi package of the same extension is installed instead (method: package).- Conflicts / warnings (AC-14) come back in the extension list and in the
ext.setdry-run plan (xdebug with pcov, swoole, the opcache JIT; "slows every request"). - php.ini forms.
software.php.ini.get/setfor a site or an account: 22 known keys with type, minimum and upper bound (memory_limit and upload sizes 2G, execution time 3600 s ...), custom directives only as name/value pairs from the same list,upload_max_filesize <= post_max_size. Bad values are rejected before anything is called; the change itself goes throughweb.layers.set(web validates again, renders, runsphp-fpm -tand reverts on failure). software.php.default.setscope site/account usesweb.sites.update(web's ownphp-fpm -t+ rollback); scope server stores the default and syncs web'sdefault_php.software.php.status: master state, workers, memory, restarts, overrides, error-log path, configured opcache settings.
Runtimes and global tools (w9-18, AC-software-18..22)
- Handlers are thin (
cp/runtimes.go); logic isruntimes/(catalog lines, EOL, detection,Decide,Select,Report), work is the agent ops insdk/agentop/software.go(software.mise.*,software.tool.pin,software.runtime.default|detect). - Catalog.
core.versions.listthroughHost.Call(retried as the platform when the actor lackscore.nodes.view, embedded catalog as last resort), cached 5 min. - State (
m_software, migration 0002):runtime_policy(offered lines, cap, on-demand; no row = every non-EOL line, cap 4, on-demand on),runtime_defaults(per account),tool_pins,runtime_requests. runtime.select: app scope with no version takes what the app's version files say;Decidethen installs on demand (streamed job) below the cap, else records a request (status: requested, eventsoftware.runtime.requested) and an administrator'sruntime.installof that line closes it. App scope callsapps.app.update {runtime, version}; account scope rewrites/opt/respirecloud/path.d/<user>.sh.runtime.removeis refused while an app or account default uses the version, and also when the apps cannot be listed.runtime.usagelists apps + defaults with EOL state (EOL first); the dailysoftware.scheduled.runtime_eolemitssoftware.runtime.eol_soononce per line and state.- Cron units of the apps module carry
PATH=/opt/respirecloud/tools/bin:...(apps.go, delimited w9-18 block).
Not done / limits
See docs/tasks/w9/w9-14-software-os-php.handover.md.