Skip to content

fix(config): track recovery backups without suppressing recovery - #4572

Draft
luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:agent/backup-ownership-20260914
Draft

fix(config): track recovery backups without suppressing recovery#4572
luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:agent/backup-ownership-20260914

Conversation

@luvs01

@luvs01 luvs01 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Current author follow-up

Published head 2304ed4ef3a54dda8a3c99396fed4dbced5af2b3 is based on the fixed dev snapshot 43f4450a538d729f353144c029aa97de1c4f2483. This supersedes older head/behind/CI status statements below; older verification remains historical evidence. Required conflicts were resolved without dropping upstream contracts. No repeated tip chasing was performed.

  • bun run typecheck: passed.
  • bun run structure:check: passed.
  • bun run privacy:scan: passed.
  • git diff --check: passed.
  • bun test tests/config/config-ownership-uninstall.test.ts tests/oauth/oauth-store-multi.test.ts: passed (54 pass; 0 fail; 200 expect() calls).

Exact-head hosted verification is not yet complete; no older-head matrix is substituted.

Maintainer sponsorship, where required, remains a separate hold. Existing resolved review findings were not reopened.

Summary

New recovery copies were missing from the uninstall manifest, so an owned installation could leave invalid-config backups and the OAuth downgrade backup behind after uninstall.

Register those copies after creation. Ownership registration stays best-effort: legacy/shared homes intentionally refuse ownership, and a metadata-write failure must not suppress or invalidate an already-created recovery copy. Existing OAuth downgrade backups remain unchanged and are not retroactively claimed.

Unregistered copies still produce the existing partial/refused cleanup outcome. Copying and manifest registration are not an atomic transaction, so a process interruption between them can still leave a residual file.

Verification

  • Windows focused suites: 54 pass, 0 fail, 200 assertions across config-ownership-uninstall and oauth-store-multi.
  • With the production changes removed, both new owned-uninstall regressions fail; the unowned-home recovery case still passes.
  • Coverage includes actual uninstall deletion, preservation in unowned homes, registration exceptions, and a pre-existing unregistered OAuth backup.
  • Typecheck, structure:check, privacy:scan and git diff --check passed.
  • Independent scoped code review found no blocking defect; both suggested regression gaps were added.
  • The import-connected local run hit the repository runner's 900-second limit (exit 124), with timeout and ACL-related failures in the broader selection. It did not complete and is not reported green; these failures have not all been independently attributed.
  • Cross-platform CI 34801111365 completed on published head 6ab2a394009449e4b3ad7ec0b113b48c96aa5417. Linux 4/4, macOS 2/2, all static gates, packaging/smoke/keyring jobs, and Windows 2/3/5/6 passed. Windows 1/6 and 4/6 failed; this is not a fully green matrix.
  • Windows 4/6 reports the unchanged desktop-restart Windows defects handled separately by fix(codex): repair desktop restart membership and POSIX-only cases on Windows #4564 and the TOML-escaped catalog-path assertion handled by test(codex): compare the injected catalog path as a decoded TOML value #4568. Windows 1/6 reports EPERM removing the quota-prime test directory in teardown, rather than a failed quota assertion. Config/OAuth production files and that quota fixture are byte-identical between the clean baseline worktree and the pre-PR base; the selected baseline quota test passes locally, so the hosted teardown locking condition remains unreproduced.
  • Readiness uses the documented non-PR test-failure exception above; it does not certify those unrelated Windows fixtures as repaired or the matrix as green. This patch changes post-copy ownership bookkeeping, and its 54 focused tests remain green. No retry matrix or rebase was started.
  • The branch is one commit behind current dev, within the gate's allowance. There are no unresolved formal or inline review findings. Maintainer security review and maintainer-sponsored remain required for src/oauth/store.ts; the existing sponsorship request is still pending.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness checklist

  • All CI tests are green on my local testing.
  • I pushed my PR to the latest dev commit.
  • I resolved all correct Codex and CodeRabbit findings.
  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Sep 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/store.ts.

@github-actions github-actions Bot added the bug Something isn't working label Sep 14, 2026
@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • hygiene: unsponsored_surface.

What to do

  • Fix unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/store.ts.
  • Tick all four boxes in the PR description once you're done (currently 2/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

2/4 boxes ticked.

This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.
@luvs01 Tick the boxes once your local CI is green, your branch is on the latest dev commit, and every correct Codex and CodeRabbit finding is resolved.

@luvs01

luvs01 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

The current hygiene failure is unsponsored_surface for src/oauth/store.ts. The change there registers the recovery copy after it is created; registration exceptions emit a generic warning and leave the copy intact. It does not change credential selection, login/logout, or migration persistence.

The independent code review and 54 focused tests cover actual owned cleanup, unowned recovery, registration failure, and pre-existing backup preservation. The import-connected local run reached its 900-second deadline. Exact-head cross-platform CI has now finished; the PR body records the passing jobs and the unrelated Windows fixture-failure exceptions. The author readiness checklist is complete, while maintainer security review and sponsorship remain pending.

Please review this restricted-surface change and apply maintainer-sponsored if approved.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 52 / 80

지금 devbackupInvalidConfig(src/config.ts 약 4598행)와 backupLegacyOnce(src/oauth/store.ts 약 432행)는 복구 파일을 만든 뒤 recordOwnedConfigPath를 호출하지 않습니다. 그래서 소유된 홈에서 uninstall을 하면, 방금 만든 invalid-config 백업이나 auth.json.pre-multiauth가 매니페스트에 없어서 남거나 partial/refused로 남을 수 있습니다. 이 PR은 복사 직후에 ownership 등록을 넣고, 등록 실패는 복구 자체를 막지 않도록 try/catch + warn으로 처리합니다. 의도(복구 우선, 등록은 best-effort)는 dev의 ownership 계약과 잘 맞습니다.

테스트도 핵심을 잡았습니다. 등록 예외 시에도 백업이 살아 있는지, owned/unowned 홈에서 uninstall이 백업을 지울지 말지, 이미 있던 미등록 OAuth 백업은 소급 청구하지 않는지까지 있습니다. structure 문서에 백업 ownership 계약을 적어 둔 것도 후속 기여자에게 도움이 됩니다.

다만 지금 게이트 상태는 머지 준비가 아닙니다. PR이 draft이고, 라벨 intake: hygiene-blocked가 붙어 있으며, hygiene 실패 코드는 unsponsored_surface입니다. src/oauth/store.ts는 메인테이너 스폰서십이 필요한 면이라 본문에도 sponsorship 대기가 적혀 있습니다. enforce-target도 fail입니다. Windows 매트릭스 일부 실패는 이 패치와 무관하다고 본문에 적어 두었고, #4564/#4568을 가리킨 설명은 타당해 보이지만, draft+hygiene 차단이 먼저입니다.

src/config.ts backupInvalidConfig - 복사 후 recordOwnedConfigPath(getConfigDir(), backupPath) 추가는 맞습니다. 등록 실패 시에도 backupPath를 반환하는 흐름이 복구 우선 원칙과 일치합니다.

src/oauth/store.ts backupLegacyOnce - 같은 패턴입니다. 다만 이 파일은 unsponsored_surface라서, 스폰서 없이 머지하면 안 됩니다.

tests/config/config-ownership-uninstall.test.ts - spyOn(ownership, "recordOwnedConfigPath")로 등록 실패를 재현한 테스트가 좋습니다. owned/unowned 루프 테스트도 uninstall 결과를 직접 검증합니다.

structure/providers/xai-grok.md - OAuth 백업 문장을 넣었는데, 변경의 본질은 xAI 전용이 아니라 공통 backupLegacyOnce입니다. 문서 위치가 살짝 좁아 보일 수 있지만 차단 사유는 아닙니다.

메인테이너의 판단이 필요한 지점

  • src/oauth/store.tsmaintainer-sponsored를 줄지, 아니면 config 쪽만 남기고 OAuth 등록을 스폰서 PR로 나눌지.
  • draft를 ready로 올리기 전에 exact-head로 dev에 맞추고 hygiene/enforce-target을 통과시킬지(본문은 1커밋 behind라고 함).
  • 복사와 매니페스트 등록이 원자적이지 않다는 잔여 레이스는 문서로만 둘지, 후속 이슈로 추적할지.

너의 추천
방향은 좋고 dev와 충돌하는 큰 리팩터도 아닙니다. 지금 상태로는 머지하지 마세요. draft 해제 → dev 동기화 → hygiene 통과(필요하면 메인테이너 스폰서십) → exact-head CI 확인 순으로 게이트를 연 뒤 다시 랜딩하세요. 타입스플릿 때문에 닫을 대상은 아닙니다.

이 댓글은 grok-bot이 작성했습니다

@luvs01
luvs01 force-pushed the agent/backup-ownership-20260914 branch from 6ab2a39 to 2304ed4 Compare September 14, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants