Install ChatGPT Desktop from a repository this checkout can verify

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
This commit is contained in:
Gabriel Brown
2026-08-27 14:48:20 -04:00
parent 1ee42f2cb6
commit cb305f6662
11 changed files with 456 additions and 23 deletions
+5 -2
View File
@@ -189,7 +189,10 @@ skills/ Agent skills for operating this desktop, linked into
~/.claude/skills
setup/
apps/ Applications built from source, one file each
lib/ Shared by more than one stage; the extras catalog reader
keys/ Pinned signing keys, for publishers that ship no fetchable
one; setup/keys/README.md records where each came from
lib/ Shared by more than one stage; the extras catalog reader,
the machine role, the verified ChatGPT repository
packages/ One package per line; extras/ holds the optional categories
scripts/ Run in order by ./install
tests/ Contracts. See below
@@ -198,7 +201,7 @@ docs/ Settings reference, and the design specs behind the work
## Tests
186 of them, under `tests/`. `tests/contracts.manifest` classifies every
187 of them, under `tests/`. `tests/contracts.manifest` classifies every
contract by the capabilities it needs. Run the hermetic set, or grant a
specific external capability when automation needs it: