BIOS 2423→4101 update on yarn required an fTPM reset, which broke the
sealed age identity at /var/lib/agenix/tpm-identity. Bootstrapped a new
identity against the new SRK and rotated yarn's recipient.
age-plugin-tpm 1.0+ emits age1tag1… (p256tag) recipients by default and
refuses to encrypt to legacy age1tpm1… ones, so rotated mreow's recipient
to the same encoding (same key, new bech32 HRP) and added an
age-plugin-tag→age-plugin-tpm symlink in the rage wrapper so rage's
plugin dispatch finds the binary under the new prefix. Stripped the
trailing host labels from the tpm recipient strings — rage's stricter
bech32 parser now rejects the trailing whitespace; labels live in
adjacent Nix comments instead.
oo7-server 0.6.0 only feeds the systemd / PAM secret to existing
keyrings discovered on disk. On first run no keyring exists yet, the
daemon creates an empty 'Login' collection via LockedKeyring::open,
the credential is silently ignored, and any client Unlock() routes to
a prompt that nothing on a niri desktop can satisfy.
Patches/oo7-server/0001-... is upstream commit cf7b9a9 (PR #443)
regenerated relative to the package's sourceRoot ('server/'). It
switches the auto-created default-keyring path to UnlockedKeyring::open
when a secret is available.
The override threads the patch through pkgs.oo7-server.overrideAttrs
in modules/desktop-oo7-daemon.nix and uses the patched derivation for
both services.dbus.packages and systemd.packages so the user unit and
D-Bus activation file land from the same store path. Cargo.lock is
untouched, so the existing cargoDeps hash stays valid.
Drop the override once nixpkgs ships an oo7-server release that
includes the fix (anything past 0.6.0).
oo7-daemon was running but its 'Login' keyring stayed locked because
nothing supplied a master password, so libsecret clients (flare in
particular) blocked indefinitely on keyring.unlock().
The upstream user unit declares
ImportCredential=oo7.keyring-encryption-password
which picks up matching credentials from systemd's per-service
credential machinery. Wire LoadCredential=oo7.keyring-encryption-password
to the agenix-decrypted secret so the daemon unlocks at session start
without any prompt.
The password itself is a fresh 64-byte urandom value encrypted to all
desktop recipients (admin SSH key + mreow + yarn TPM identities); it's
opaque to the user and never typed manually. Owner is primary so the
user-scope unit's LoadCredential read works without elevating.
Verified the activation script chowns the decrypted file primary:users
mode 0400, the user unit override carries the LoadCredential line, and
the resulting drv builds clean.
Without a secret-service implementation on the bus, libsecret clients
like flare fail at startup with 'The communication with libsecret
failed'. None of the desktop hosts had one wired up.
oo7-daemon is the matching pure-Rust implementation (same project as
the oo7 crate flare uses internally), without the GNOME plumbing that
gnome-keyring would drag in. Register the package's D-Bus service
file and systemd user unit, start the daemon at user login, and alias
the unit as dbus-org.freedesktop.secrets.service so D-Bus
auto-activation also resolves cleanly when the wantedBy start hasn't
fired yet.
Verified the toplevel build and that the resulting system carries the
oo7-daemon user unit, the dbus alias symlink, and the
default.target.wants entry.
- patches/flare/000{1..5}-*.patch: typing indicators, formatted
messages, edited messages, multi-select with delete-for-me, and
in-channel message search. Mirror the matching commits in
~/projects/forks/flare and apply cleanly on top of upstream 0.20.4
(which is what nixpkgs ships).
- home/profiles/gui.nix: include a flare-signal override that appends
the patches via overrideAttrs. None of them touch Cargo.lock so the
cargoDeps hash stays valid; signal-desktop stays alongside it.
agenix activation runs from initrd-nixos-activation-start, which fires
right after /sysroot/persistent is mounted but before impermanence's
stage-2 bind mounts. The TPM identity at /var/lib/agenix/tpm-identity
was therefore unreadable at activation time, and every secret silently
failed to decrypt: 'no readable identities found'. Visible downstream
fallout was pull-update-apply hitting HTTP 401 against the binary cache
because nix-cache-netrc was never written to /run/agenix.
Mark /var/lib/agenix as neededForBoot via a bare fileSystems entry,
mirroring the existing /home/${username} bind. Drop the now-redundant
environment.persistence directory entry to avoid two competing units.
`bun2nix.hook` (used by upstream omp's package.nix) sets
patchPhase = bunPatchPhase
at the end of its setup-hook unless `dontUseBunPatch` is already set.
`bunPatchPhase` only runs `patchShebangs` plus a HOME mktemp; it never
iterates over `$patches`. The standard nixpkgs `patches` attribute
therefore went into the derivation env but was silently ignored at
build time, leaving the deployed omp binary unpatched.
Switch to applying the two patches via `prePatch` (which `bunPatchPhase`
does call). Verified with strings(1) over the rebuilt binary that both
patch hunks land:
/wrong_api_format|...|invalid tool parameters/ (patch 0001)
stubsReasoningContent ... thinkingFormat == "openrouter" (patch 0002)
DeepSeek V4 Pro (and similar reasoning models reached via OpenRouter) reject
multi-turn requests in thinking mode with:
400 The `reasoning_content` in the thinking mode must be passed back
to the API.
omp's existing kimi placeholder injection (`requiresReasoningContentForToolCalls`)
covered this requirement only for `thinkingFormat == "openai"`. OpenRouter
sets `thinkingFormat == "openrouter"`, so the gate never fired even though
the underlying providers behind OpenRouter (DeepSeek, Kimi, etc.) all enforce
the same invariant.
This patch:
1. Extends `requiresReasoningContentForToolCalls` detection: any
reasoning-capable model fronted by OpenRouter now sets the flag.
2. Extends the placeholder gate in `convertMessages` to accept
`thinkingFormat == "openrouter"` alongside `"openai"`.
Cross-provider continuations are the dominant trigger: a conversation
warmed up by Anthropic Claude (whose reasoning is redacted/encrypted on
the wire) followed by a switch to DeepSeek V4 Pro via OpenRouter. omp
cannot synthesize plaintext `reasoning_content` from Anthropic's
encrypted blocks, so the placeholder satisfies DeepSeek's validator
without fabricating a reasoning trace. Real captured reasoning, when
present, short-circuits the placeholder via `hasReasoningField` and
survives intact.
Side benefit: also closes a latent gap where Kimi-via-OpenRouter
(`thinkingFormat == "openrouter"`) had the compat flag set but the
placeholder gate silently rejected it.
Applies cleanly on top of patch 0001.
Steam interprets exit 0 from 'steamos-update check' as 'update applied
successfully' and shows a persistent 'update available' notification.
The SteamOS convention is exit 7 = no update available.