Skip to content

fix(migration): close cooldown-key strand gap + allowlist guard test (W4)#247

Merged
JasonYeYuhe merged 1 commit into
mainfrom
fix/w4-migration-allowlist-hardening
Jun 28, 2026
Merged

fix(migration): close cooldown-key strand gap + allowlist guard test (W4)#247
JasonYeYuhe merged 1 commit into
mainfrom
fix/w4-migration-allowlist-hardening

Conversation

@JasonYeYuhe

Copy link
Copy Markdown
Owner

What & why

A 5-way adversarial verification of the W1-A..W3 changeset (#243/#244/#245/#246) confirmed MAS-safety (high), entitlement-verifier soundness (medium), and the reentrancy fix (high) all hold, and surfaced one real latent issue + two doc-comment drifts. (The bulk of W4 — the ship-config entitlement-invariant test — already shipped in W1-A as DevidEntitlementsInvariantTests.)

Fixes

  1. Migration-allowlist completenessClaudeCredentials.keychainReadCooldownKey ("claudeCodeKeychainReadCooldownUntil") is written to UserDefaults(suiteName:"group.yyh.CLI-Pulse") ?? .standard. The app-group store doesn't move on unsandbox, but the ?? .standard fallback would strand a non-cli_pulse_/non-privacy. key → falsifying UnsandboxedDataMigration's "every app-owned standard-defaults key is prefixed" invariant. Renamed → "cli_pulse_claude_keychain_read_cooldown_until" (orphans the old 30-min timestamp once — benign); made the constant internal for a guard test.
  2. Allowlist contract guardtest_appOwnedKeyPrefixes_coverEveryKnownStandardDefaultsKey asserts every audited app-owned standard-defaults key (incl. privacy.* + the cooldown constant) matches appOwnedKeyPrefixes; a future unprefixed revert fails here.
  3. Gate-semantics comments — clarified the omitted selfDeviceId (local helper pairing, NOT cloud Remote-Control) precondition in the canStartLocalManagedSession doc + W1-B menu comment. Predicate unchanged — it's intentional + test-locked (SessionControlIntegrationGapTests); dropping it would break row-ownership invariants.

Validation

swift test full: 1826 tests, 0 failures. Existing ClaudeKeychainCooldownTests still pass (they go through the renamed constant, transparent to the change).

🤖 Generated with Claude Code

…(W4)

Adversarial verification of the W1-A..W3 changeset confirmed MAS-safety,
entitlement-verifier soundness, and the reentrancy fix all hold, and surfaced one
real latent issue: ClaudeCredentials.keychainReadCooldownKey
("claudeCodeKeychainReadCooldownUntil") is written to
UserDefaults(suiteName:"group.yyh.CLI-Pulse") ?? .standard. The app-group store is
safe, but the .standard FALLBACK would strand a non-cli_pulse_/non-privacy. key on
the DEVID unsandbox transition — falsifying UnsandboxedDataMigration's "every
app-owned standard-defaults key is prefixed" invariant.

- Rename the key -> "cli_pulse_claude_keychain_read_cooldown_until" so the
  migration allowlist covers it even on the fallback (orphans the old 30-min
  timestamp once — benign). Make the constant internal for a guard test.
- Add UnsandboxedDataMigrationTests.test_appOwnedKeyPrefixes_coverEveryKnownStandardDefaultsKey
  asserting every audited app-owned standard-defaults key (incl. privacy.* and the
  cooldown constant) matches appOwnedKeyPrefixes.
- Clarify the omitted selfDeviceId precondition in the canStartLocalManagedSession
  doc + the W1-B menu comment (verifier: doc drift, NOT behavior — predicate
  unchanged; it's intentional + test-locked).

swift test full: 1826 tests, 0 failures (existing ClaudeKeychainCooldownTests
still pass via the constant).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@JasonYeYuhe JasonYeYuhe merged commit 743ec11 into main Jun 28, 2026
21 of 23 checks passed
@JasonYeYuhe JasonYeYuhe deleted the fix/w4-migration-allowlist-hardening branch June 28, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant