OpenAI ships an official Linux RPM now, so the community wrapper goes away:
`panama app chatgpt-desktop` built codex-desktop from the upstream macOS disk
image and ran a local rebuild daemon to keep it current, and the official
package comes from a repository that upgrades with everything else. The app
file, the help example and the dock's pinned id all move over, and a migration
replaces the build on machines that already have it -- official package on
before the community one comes off, so a failure part-way still leaves an app.
The install itself does not follow upstream's instructions. Those are "download
this RPM and install it", and the RPM's own root scriptlet is what writes the
repository file and drops the signing key into /etc/pki/rpm-gpg -- so root runs
an unverified download and then learns from it what to trust. That is the shape
the repository audit forbids: no network response is executed as root without a
verified digest or signature first.
OpenAI publishes no key and no fingerprint anywhere an install could fetch and
check them, so the key is pinned here instead. setup/keys/ carries it and says
where it came from, including the honest part -- this is trust established on
first use and then held, not trust verified against the publisher. setup/lib/
chatgpt-package verifies that copy's fingerprint, installs it, and writes the
repository with gpgcheck and repo_gpgcheck on before anything is installed, so
dnf checks the metadata signature and the package signature itself. It is byte
for byte the repository the scriptlet would have written, so nothing churns
afterwards, and every later upgrade goes through the same key. Both callers use
it; a verification failure skips ChatGPT rather than installing it anyway.
The contract proves the pinned key is the key the library names, that a
missing, unreadable or mismatched key writes nothing at all, that what is
written actually turns the checks on, and that neither caller hands root a
downloaded RPM.
Claude-Session: https://claude.ai/code/session_017zzbtfnMLoYrB8WesqANFY
A machine's role is now the interview's first question and the one answer
Panama records. Servers get the same shell minus the screen: core packages,
nvm, Bun, Claude Code and Codex (desktops get Codex too), linger, rootless
ports from 80, firewalld, the nginx-bridge network, and a nightly image
updater that replaced watchtower for cause.
server/containers/ carries junior's 23 compose services -- secrets moved to
per-machine .env files that never enter this public repo, every transformed
compose proven to render byte-identical to what is live. 'panama server'
enables, disables and relinks them; nothing here restarts a running service.
'boot --server' walks a fresh VPS from its root login to a normal install.
Five new contracts pin the secrets rule, the catalog's shape, panama-server's
behavior, the role plumbing, and the dotfile classification.
Claude-Session: https://claude.ai/code/session_01NU5JGiN3JfzqrLQB6wmJ1E
The catalog held fourteen applications. This machine runs thirty-four flatpaks,
so most of what is actually used had no way to be installed from here at all --
Zoom, Slack, Obsidian, Spotify, LibreOffice, OBS and its sixteen plugins.
So the catalog is seeded from the machine, and `panama apps` opens it: pick a
category, tick what you want, install just those. ./install still offers the
same catalog as whole categories, because during a first install you want coarse
and fast. Both read setup/lib/extras-catalog. Two parsers would eventually
disagree about what a category contains, and the one that disagreed quietly
would be the one that runs unattended.
Two pieces of syntax earn their keep. A `| Name` suffix gives the menu something
readable, since com.obsproject.Studio is not a name anybody wants to pick from a
list. An indented line belongs to the entry above it, which is how OBS carries
its plugins as one thing to tick rather than seventeen -- they are extensions of
the flatpak, useless alone.
That is also why creative moved from dnf to Flathub: the plugins attach only to
the flatpak, so the dnf build cannot have them. The rest of the category
followed rather than leave one machine with GIMP from dnf and its neighbour from
Flathub.
The contract now reads the catalog through the same parser instead of keeping a
third idea of the format, and checks the two things this syntax can break
silently: a label leaking into an install command, and a bundle that installs
the application without its plugins. It caught a typo in the Pixelorama id on
the first run.
It also got slow enough to be worth fixing -- fifty-one names, each its own
network call. One bulk query per manager took it from minutes to four seconds.
That query needs `flatpak remote-ls --all`: without it, end-of-life applications
are hidden and read as missing, which reported yuzu as gone from Flathub when it
installs perfectly well.
Claude-Session: https://claude.ai/code/session_01Q84axqUE5inJhf5Jz9CFy1