fix(anthropic-subscription): repair a damaged seat salt and store it without hard links

Merged
CO
2d ago
+93-7

Part of code-yeongyu/oh-my-openagent#10304. Follow-up to #3947 (its two review LOWs).

What

anthropic-subscription/seat-digest.ts, the per-install salt behind the seat digests in continuity logs:

  1. A salt file of the wrong length is replaced. Before, a truncated or foreign file sent every later process to the process-only fallback forever, so digests stopped matching across restarts on that install. Now the file is removed (only if it is still the file that was read, by inode) and recreated through the same link-into-place path.
  2. Filesystems without hard links store the salt. When linkSync fails with EPERM, ENOTSUP or ENOSYS (FAT/exFAT, some network and FUSE mounts, sandboxes), the salt is written with an exclusive create instead of giving up. Failing to store it still never fails a turn, and the digest stays salted.

Tests (test/anthropic-subscription-seat-digest.test.ts, 7/7)

  • "replaces a salt file of the wrong length": RED on main (the file stays 5 bytes), GREEN here.
  • "stores the salt on a filesystem without hard links" (a Node child with linkSync throwing EPERM): RED before the fallback, GREEN here.
  • The 12-process convergence test now also asserts that no staged seat-digest-salt.* files are left behind (review nit).

tsc --noEmit passes; the changelog gate passes. Thanks to 욜로개발조아 for the original measured report.


Summary by cubic

Repairs a damaged seat-digest salt file so continuity digests keep matching across restarts, and stores the salt even on filesystems without hard links.

  • A salt file of the wrong length is now removed (only if it is still the file that was read, by inode) and recreated through the same link-into-place path, instead of being ignored in favour of a process-only salt on every launch.
  • When linkSync fails with EPERM, ENOTSUP, or ENOSYS (FAT/exFAT, some network and FUSE mounts, sandboxes), the salt is written with an exclusive create instead of giving up.
  • Both paths can diverge under concurrent first starts; since digests are diagnostics, that costs a mismatch, never secrecy.
  • Failing to store the salt still never fails a turn, and the digest stays salted.
  • Adds tests for both cases and asserts no staged seat-digest-salt.* files are left behind.