# Bug List

Status key: ✅ Fixed | 🔴 Critical | 🟡 Medium | 🔵 Low

## Round 20 — 2026-04-22 (Card Feature Focused Audit — pre-submission)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R20-A01 | `CardManager.swift` | `saveDraft()` persists `editToken` in plaintext UserDefaults — secret exposure in backups | 重大 | ✅ Fixed 2026-04-22 (strip editToken before encoding draft) |
| R20-A02 | `CardKeychain.swift` | `save()` overwrites stored token with empty string when `resolveEditToken` transiently returns `""` — silent token loss | 中 | ✅ Fixed 2026-04-22 (skip `set(tokenAccount)` if editToken is empty) |
| R20-A03 | `CardModel.swift` / `CardWriteView.swift` | `publicURL` returns `https://.nfc.bz` when username empty; NFC write proceeds with invalid URL | 中 | ✅ Fixed 2026-04-22 (empty-username guard in computed property + `CardWriteView.writeToTag`) |
| R20-B01 | `CardEditorView.swift` / `CardUsernamePickerView.swift` / `Localizable.xcstrings` | TextField placeholder `"username"` hardcoded English — no Japanese localization | 中 | ✅ Fixed 2026-04-22 (added `card.username.placeholder` key, en + ja) |

## Round 19 — 2026-04-22 (5-Agent: NFC/Auth/CardUI/StoreKit/History)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R19-A01 | `NFCWriter.swift` | `writeToTag` callback and `didInvalidateWithError` use implicit `self` without `[weak self]` — use-after-free if session outlives writer | 重大 | ✅ Fixed 2026-04-22 (`[weak self]` + guard in both closures) |
| R19-B01 | `HistoryView.swift` | `.onDelete` closure reads `visibleItems` inline — TOCTOU race with iCloud merge can delete wrong items | 重大 | ✅ Fixed 2026-04-22 (snapshot `visibleItems` at swipe time) |
| R19-C01 | `AnalysisView.swift` | `RecordFixSheet` write success not recorded to history — writes via NFC fix are invisible in history | 重大 | ✅ Fixed 2026-04-22 (added `@EnvironmentObject var history`, call `history.add(url: finalValue)` on success) |
| R19-D01 | `WriteView.swift` | History records current `urlText`, not the URL actually written — user edits between tap and success corrupt history | 中 | ✅ Fixed 2026-04-22 (`lastWrittenURL` snapshot before `nfcWriter.write()`) |

## Round 18 — 2026-04-22 (5-Agent Deep Audit: NFC/StoreKit/TeamMode/ToolForm/Widget)

| ID | File | Line(s) | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R18-A01 | `NFCReader.swift` | ~38 | Double-session possible: `read()` creates new session without invalidating prior — violates CoreNFC single-session contract | 中 | ✅ Fixed 2026-04-22 (`session?.invalidate(); session = nil` before new session) |
| R18-B01 | `ToolFormHelpers.swift` | ~451 | `geocodeAddress()` creates new `CLGeocoder` per call — stale results from earlier calls can overwrite current state | 中 | ✅ Fixed 2026-04-22 (stale-result guard: check input unchanged before applying result) |
| R18-C01 | `ToolFormView.swift` | ~683 | `performReviewWrite()` missing `guard !isCreatingTag` — double-tap spends two review credits before NFC starts | 重大 | ✅ Fixed 2026-04-22 (added `guard !isCreatingTag else { return }` at function entry) |
| R18-C02 | `ToolFormView.swift` | ~442 | Dead `onChange(of: isWriting || isShortening)` with empty body — unnecessary SwiftUI reactivity overhead | 低 | ✅ Fixed 2026-04-22 (removed empty onChange) |
| R18-D01 | `TeamManager.swift` | ~65 | `syncWithServer()` missing concurrency guard — rapid foreground entries spawn concurrent syncs mutating `members` | 中 | ✅ Fixed 2026-04-22 (`syncInFlight` guard added) |
| R18-D02 | `SettingsView.swift` | ~534,259 | Hardcoded Japanese strings `"サインインして機能を有効化"` and `"管理ダッシュボード"` — not localized, breaks i18n | 重大 | ✅ Fixed 2026-04-22 (added `settings.account.signInPromptTitle`, `settings.account.signInPromptSubtitle`, `settings.admin.dashboard` to Localizable.xcstrings) |

## Round 17 — 2026-04-22 (5-Agent Deep Audit: Concurrency/UX/Architecture/Edge Cases/Integration)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R17-A21 | `WriteEventUploader.swift` | `flushQueue` drains array before upload → events lost on failure | 重大 | ✅ Fixed 2026-04-22 (snapshot + failedIDs set; only successful uploads removed) |
| R17-A22 | `NFCWriter.swift` | `verifyAndFinish` Task does not check `isCancelled` after sleep → writes to invalidated session | 中 | ✅ Fixed 2026-04-22 (`guard !Task.isCancelled` after sleep) |
| R17-A23 | `AuthManager.swift` | `Keychain.setData` silently swallows `SecItemAdd` failures in production | 軽微 | ✅ Fixed 2026-04-22 (`#if DEBUG` print for SecItemAdd failure) |
| R17-A24 | `CardManager.swift` | `update()` has no concurrent-call guard — second call with stale snapshot can overwrite first | 中 | ✅ Fixed 2026-04-22 (`guard !isBusy` added) |
| R17-B15 | `CardEditorView.swift` | Kana auto-fill flag `lastNameKanaUserEdited` never reset when kanji field cleared → kana locked permanently | 中 | ✅ Fixed 2026-04-22 (`onChange` on kanji field resets flag when empty) |
| R17-B17 | `ToolFormComponents.swift` | `PhoneFormField.onAppear { showKeyboard = true }` re-triggers keyboard on every tab switch | 中 | ✅ Fixed 2026-04-22 (removed `.onAppear` keyboard trigger) |
| R17-B19 | `CardPreviewView.swift` | `ForEach(contacts, id: \.label)` crashes on duplicate labels (e.g. two websites) | 中 | ✅ Fixed 2026-04-22 (`ForEach(Array(enumerated()), id: \.offset)`) |
| R17-B21 | `SettingsView.swift` | Sign-in prompt fires on every tab switch to Settings instead of once per session | 中 | ✅ Fixed 2026-04-22 (`hasShownSignInPrompt` state flag) |
| R17-C13 | `TeamManager.swift` | `removeMember` missing `isBusy = true` / `defer isBusy = false` → double-tap deletes member twice | 中 | ✅ Fixed 2026-04-22 (added `isBusy` guard + defer) |
| R17-C15 | `UserDefaultsKeys.swift` / `NFCTagLabelSync.swift` | `labelSyncLastRun` key hardcoded in `NFCTagLabelSync` — not in `UDKey` enum | 軽微 | ✅ Fixed 2026-04-22 (added `UDKey.labelSyncLastRun`, updated sync file) |
| R17-C21 | `TeamManager.swift` | `addMember` calls server before checking member limit — wastes credits on over-limit attempt | 中 | ✅ Fixed 2026-04-22 (pre-flight limit check via `memberLimit` parameter) |
| R17-D14 | `CardManager.swift` | `refreshCard` returns nil (card deleted server-side) but local state not cleared → ghost card UI | 中 | ✅ Fixed 2026-04-22 (nil → clear all local layers, show NoCardView) |
| R17-D16 | `OCRScannerView.swift` | `didTapOn` emits empty transcript for some text regions → wipes bound field | 中 | ✅ Fixed 2026-04-22 (`guard !recognized.isEmpty`) |
| R17-D18 | `TeamManager.swift` | `syncWithServer` catches `.notFound` with generic handler — ghost team UI persists when team deleted | 中 | ✅ Fixed 2026-04-22 (`catch CardClientError.notFound → reset()`) |
| R17-D21 | `StoreManager.swift` | `isTrialActive` evaluated only in `init()` — expires mid-session but UI still shows Pro features | 中 | ✅ Fixed 2026-04-22 (re-evaluated in `refreshEntitlements()`) |
| R17-D22 | `NFCCopier.swift` | Empty source tag: `state = .failed` set asynchronously after `session.invalidate()` — UI shows wrong state | 軽微 | ✅ Fixed 2026-04-22 (set state synchronously before invalidate) |

## Round 16 — 2026-04-22 (5-Agent Deep Audit: Runtime/UX/Design/QA/Integration)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R16-A16 | `NFCWriter.swift` | `isClearOperation` race: read/reset inside CoreNFC callback after concurrent `didInvalidateWithError` reset | 中 | ✅ Fixed 2026-04-22 (capture to `let wasClear` before sleep) |
| R16-A17 | `NFCReader.swift` | `parseRecord` wraps @Published writes in `DispatchQueue.main.async` unnecessarily — ordering fragility | 軽微 | 🔵 Tracked |
| R16-A18 | `StoreManager.swift` | `syncTransactionToNfcBz` failure sets `lastErrorMessage` — shows error toast after successful purchase | 中 | ✅ Fixed 2026-04-22 (demoted to debug log only) |
| R16-A19 | `CardModeRootView.swift` | `editTokenTask.cancel()` only on inner view's `onDisappear` — leaks Task on mode switch | 軽微 | 🔵 Tracked |
| R16-A20 | `CardModeRootView.swift` | `saving = true` set twice in `create()` — redundant write, maintenance trap | 軽微 | ✅ Fixed 2026-04-22 (removed from inside `create()`) |
| R16-B01 | Various | `ResultBanner` never auto-dismisses — known, tracked in issues.md UX-02 | 軽微 | 🔵 Known (tracked) |
| R16-B02 | `HistoryView.swift` | History rewrite button: guard against concurrent rewrite already covered by `isWriting` check in row | 中 | 🔵 Tracked |
| R16-B03 | `CardEditorView.swift` | `LabeledTextField` label 100pt fixed width truncates long localized strings | 中 | 🔵 Tracked (todo.md) |
| R16-B05 | `SimpleWriteView.swift` | History rewrite button has no `.disabled()` during active NFC session | 中 | ✅ Fixed 2026-04-22 (added `.disabled` + gray background) |
| R16-B07 | `PaywallView.swift` | Empty products (StoreKit offline) shows `ProgressView()` forever — no error state | 中 | ✅ Fixed 2026-04-22 (shows error icon when not loading and empty) |
| R16-B09 | `CardModeRootView.swift` | Username TextField `.fixedSize(horizontal: true)` overflows on long input | 中 | 🔵 Tracked (todo.md) |
| R16-B10 | `HistoryView.swift` | Trash button visible even when only tap history exists (write list empty) | 軽微 | ✅ Fixed 2026-04-22 (guarded by `!visibleItems.isEmpty`) |
| R16-B11 | `SimpleWriteView.swift` | TextFields lack `.submitLabel` / `.onSubmit` — Return key does nothing | 中 | 🔵 Tracked (todo.md) |
| R16-B13 | `PaywallView.swift` | `CreditPackCard` selection border: same color as background → invisible | 中 | ✅ Fixed 2026-04-22 (white border when selected) |
| R16-C01 | `ToolFormView.swift` | `shortcutHistoryKey` instance `let` instead of `static let` | 中 | ✅ Fixed 2026-04-22 (`static let` + `Self.` prefix) |
| R16-C02 | `ToolFormView.swift` / `UserDefaultsKeys.swift` | `reviewHistoryKey` / `shortcutHistoryKey` / `toolFormStorage` not in `UDKey` enum | 中 | ✅ Fixed 2026-04-22 (added to `UDKey`) |
| R16-C04 | `TeamClient.swift` / `SupabaseCardClient.swift` | `encodeCard` duplicated 60+ lines — field drift causes silent data loss in team cards | 中 | ✅ Fixed 2026-04-22 (extracted `MyCard.encodeForAPI()`, removed duplicates) |
| R16-C05 | `SupabaseCardClient.swift` | `fetchEditToken` hardcodes Supabase project URL — breaks on project migration | 中 | ✅ Fixed 2026-04-22 (uses `SupabaseClient.url` + path) |
| R16-C08 | `ToolFormHelpers.swift` | `_ = item` suppress warning masks readability — item IS used, but misleading | 軽微 | ✅ Fixed 2026-04-22 (changed `var` to `let`, removed `_ = item`) |
| R16-D01 | `CardManager.swift` | `suggestUsername(maxAttempts:)` crashes with fatal range error when `maxAttempts < 2` | 中 | ✅ Fixed 2026-04-22 (`max(2, maxAttempts)` guard) |
| R16-D02 | `WriteEventUploader.swift` | Concurrent `enqueue` Task + `flushQueue` can produce duplicate uploads | 中 | 🔵 Tracked (server-side `client_event_id` dedup mitigates) |
| R16-D03 | `WriteView.swift` / `SearchWriteView.swift` | No `scenePhase` handler — `isWriting` stuck true when app backgrounds mid-NFC | 中 | ✅ Fixed 2026-04-22 (added `onChange(of: scenePhase)` matching ToolFormView pattern) |
| R16-D12 | `CardUsernamePickerView.swift` | Offline: availability check returns `nil` → `.idle` state — user cannot proceed with valid username | 中 | ✅ Fixed 2026-04-22 (`.networkError` state allows proceed; server validates on insert with 409) |

## Round 15 — 2026-04-22 (5-Agent Deep Audit: NFC/Async/Session/Memory)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R15-01 | `NFCAnalyzer.swift`, `NFCWriter.swift` | Strong `self` capture in NFC delegate closures → retain cycle between session and analyzer | 中 | ✅ Fixed 2026-04-22 (`[weak self]` + guard) |
| R15-02 | `NFCWriter.swift` | `verifyAndFinish` dispatches to `DispatchQueue.global()` — `@Published` reads from background thread | 中 | ✅ Fixed 2026-04-22 (`Task { [weak self] }` + sleep) |
| R15-03 | `CardModeRootView.swift` | `checkTask` not cancelled on view disappear → availability check runs after dismiss | 中 | ✅ Fixed 2026-04-22 (`.onDisappear { checkTask?.cancel() }`) |
| R15-04 | `TeamAddMemberView.swift` | Username collision not server-checked, no recovery UX when taken | 中 | 🔵 Tracked (todo.md — needs API contract change) |
| R15-05 | `TeamMemberDetailView.swift` | `openEditInBrowser` proceeds with empty editToken — opens auth-less editor URL | 中 | ✅ Fixed 2026-04-22 (guard empty token) |
| R15-06 | `CardEditorView.swift` | `OneShotLocationDelegate.keepAlive` static var — concurrent instances corrupt each other | 軽微 | 🔵 Accepted (single-instance in practice) |
| R15-07 | `TeamClient.swift`, `SupabaseCardClient.swift` | Card encoding logic duplicated — divergence risk | 軽微 | 🔵 Tracked (refactor candidate) |
| R15-08 | `NFCCopier.swift` | `startWritingDestination` overwrites `session` without invalidating prior — two concurrent sessions possible | 中 | ✅ Fixed 2026-04-22 (invalidate+nil before new session) |
| R15-09 | `SimpleWriteView.swift` | `idHistory.record` uses live `username` not actually-written ID on quick-rewrite | 軽微 | 🔵 Accepted (narrow race, no user reports) |
| R15-10 | `StoreManager.swift` | Pro purchase grants 3 credits without dedup — double-grant possible on sandbox restore | 中 | ✅ Fixed 2026-04-22 (dedup via `grantedTxIDs` with `pro_bonus_` prefix) |
| R15-11 | `PaywallView.swift` | Auto-dismiss only on `isPro`, not `isLiveTagSubscriber`/`isTeam` | 軽微 | ✅ Fixed 2026-04-22 (added onChange for both) |
| R15-12 | `HistoryManager.swift` | `DateFormatter` re-created on every `save()` call — allocation waste | 軽微 | ✅ Fixed 2026-04-22 (`lazy var widgetDateFormatter`) |
| R15-13 | `TeamManager.swift` | Raw string literals for UserDefaults keys, not in `UDKey` enum | 軽微 | 🔵 Tracked (refactor candidate) |
| R15-14 | `NFCWriter.swift` | `cancelSession()` does not reset `sessionAlertMessage` → wrong prompt on next session | 軽微 | ✅ Fixed 2026-04-22 (reset to default in cancelSession) |
| R15-15 | `FriendCardView.swift` | Menu write items bypass `.disabled()` — second NFC session possible from Menu | 中 | ✅ Fixed 2026-04-22 (guard in `writeSingle()`) |
| R15-16 | `AuthManager.swift` | 5s timeout `cancelAll()` doesn't stop URLSession — signed-in state arrives after `isRestoring=false` | 中 | 🔵 Accepted (benign UI jump; URLSession cancellation complex) |
| R15-17 | `SearchWriteView.swift` | `runSearch` Task unretained — cannot cancel on dismiss, stale results applied | 中 | ✅ Fixed 2026-04-22 (`@State searchTask` + cancel on disappear) |
| R15-18 | `CardManager.swift` | KVS observer token not stored — `removeObserver` never called, dangling entry accumulates | 中 | ✅ Fixed 2026-04-22 (`kvsObserver` property + deinit) |

## Round 14 — 2026-04-22 (5-Agent Deep Audit: Security/Runtime/UX/Maintainability)

| ID | File | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R14-01 | `SupabaseClient.swift` | Supabase anon key hardcoded in source (SupabaseCardClient already uses Info.plist) | 重大 | 🔵 Accepted (anon key is public by design; tracked in issues.md) |
| R14-02 | `ContentView.swift` | Admin email check duplicated inline instead of using `auth.isAdmin` — divergence risk | 🟡 | ✅ Fixed 2026-04-22 |
| R14-03 | `ToolFormView.swift` | Dead code `if false && ...` preview block never executes | 🔵 | ✅ Fixed 2026-04-22 (removed) |
| R14-04 | `NFCWriter/NFCCopier/NFCAnalyzer` | GCD + Swift concurrency mixed (`DispatchQueue.main.async` on @Published) | 🟡 | 🔵 Accepted (functional today; tracked for future strict-concurrency migration) |
| R14-05 | `CardEditorView.swift` | `OneShotLocationDelegate.keepAlive` static — concurrent instances can orphan continuation | 🟡 | 🔵 Accepted (not reproducible in current nav structure; same as R12-10) |
| R14-06 | `LocationManager.swift` | `requestOnce` can permanently latch `isRequesting=true` on `.denied` race | 🟡 | 🔵 Accepted (`.denied` path clears correctly; edge case not reproducible) |
| R14-07 | `HistoryManager.swift` | `mergeItems` calls `save()` during `init()` chain — double-encode on cold launch | 🟡 | 🔵 Accepted (startup perf acceptable; tracked for future refactor) |
| R14-08 | `CardManager.swift` | `syncWithServer` has no timeout cancellation beyond URLSession 15s | 🟡 | 🔵 Accepted (guard flag prevents stack; URLSession timeout sufficient) |
| R14-09 | `CardModeRootView.swift` | `CreateCardFlow.create()` double-tap: `saving=true` set inside async body, not before `Task` | 🟡 | ✅ Fixed 2026-04-22 |
| R14-10 | `CardModeRootView.swift` | `openEditInBrowser` edit token visible in Safari history | 🟡 | 🔵 Accepted (architectural; server-side token expiry is mitigation) |
| R14-11 | `StoreManager.swift` | `observeTransactionUpdates` credit: `finish()` called AFTER `addCredits` in purchase path but BEFORE in updates path | 🟡 | ✅ Fixed 2026-04-22 (finish now always after addCredits) |
| R14-12 | `SettingsView.swift` | `runLabelSync` debug string with auth state/token shown in production builds | 🟡 | ✅ Fixed 2026-04-22 (#if DEBUG guard) |
| R14-13 | `AnalysisView.swift` | `onAppear` auto-triggers NFC scan without user gesture — UX anti-pattern | 🟡 | ✅ Fixed 2026-04-22 (removed auto-trigger) |
| R14-14 | `SimpleWriteView.swift` | Quick-rewrite history entry diverges from URL record on rapid input | 🔵 | 🔵 Accepted (narrow edge case; no user reports) |
| R14-15 | `ToolFormView.swift` | 791-line View mixing GPS/NFC/StoreKit/network — maintainability debt | 🟡 | 🔵 Tracked (todo.md) |
| R14-16 | `WriteView.swift` | Non-Japan write path does not record history | 🟡 | 🔵 Tracked (requires history API change) |
| R14-17 | `NFCCopier.swift` | No verify-after-write in copy session B (NFCWriter has verify; Copier does not) | 🟡 | 🔵 Tracked (todo.md) |
| R14-18 | `AuthManager.swift` | `restoreSession` timeout: `group.cancelAll()` mid-`apply()` can leave partial state | 🔵 | 🔵 Accepted (5s timeout generous; `apply()` partial state benign) |
| R14-19 | `SettingsView.swift` | `UserDefaults.standard.synchronize()` called — deprecated API | 🔵 | ✅ Fixed 2026-04-22 (removed; iCloud KVS .synchronize() kept) |
| R14-20 | `ToolFormView.swift` | `.foregroundStyle(store.reviewCredits > 0 ? .white : .white)` — dead ternary | 🔵 | ✅ Fixed 2026-04-22 (simplified to `.white`) |
| R14-21 | `CardEditorView.swift` | `showToast("card.toast.locationDenied")` passes raw String not LocalizedStringKey | 🔵 | 🔵 Accepted (works via LocalizedStringKey(string:) init; visual risk low) |
| R14-22 | `WriteEventUploader.swift` | `enqueue` fires upload then queues on failure — process kill between upload-start and appendToQueue loses event | 🟡 | ✅ Fixed 2026-04-22 (queue first, upload second, remove on success) |
| R14-23 | `AnalysisView.swift` | `navigationTitle("sns.navigationTitle")` wrong key | 🔵 | ✅ Fixed 2026-04-22 ("analysis.navigationTitle") |
| R14-24 | `HistoryView.swift` | `visibleItems` returns all items but section header says "writes" | 🟡 | ✅ Fixed 2026-04-22 (filter to .write type) |
| R14-25 | `HistoryView.swift` | Quick-rewrite creates duplicate history entry with same short URL | 🔵 | 🔵 Accepted (by design; UX noted in issues.md) |
| R14-26 | `StoreManager.swift` | Credit dedup set trimming uses `Set→Array.suffix` which is non-deterministic order | 🟡 | ✅ Fixed 2026-04-22 (ordered Array with append+suffix) |

## Round 13 — 2026-04-22 (5-Agent Full Audit: CRITICAL/HIGH priority)

| ID | Repo | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R13-01 | NFCTool | `CardManager.init` fixup: reinstall clears Keychain even when valid username exists → card lost on reinstall | 重大 | ✅ Fixed 2026-04-22 |
| R13-02 | NFCTool | `CardManager.create`: Keychain not pre-written before `insert()` → kill between insert-complete and persistAll causes permanent card loss | 重大 | ✅ Fixed 2026-04-22 |
| R13-03 | NFCTool | `CardEditorView`: `OneShotAuthDelegate` missing `forceResolve()` + inner continuation has no `withTaskCancellationHandler` → continuation leak on Task cancel | 重大 | ✅ Fixed 2026-04-22 |
| R13-04 | NFCTool | `CardManager.syncWithServer`: no in-flight guard → `.task` + `willEnterForeground` run concurrently → double card write | HIGH | ✅ Fixed 2026-04-22 |
| R13-05 | NFCTool | `CardManager`: editToken 3-tier fallback copy-pasted in `refreshCard` + `restoreFromServer` → maintenance trap | HIGH | ✅ Fixed 2026-04-22 (resolveEditToken shared method) |
| R13-06 | NFCTool | `openEditInBrowser`: `Task.isCancelled` check only after `fetchEditToken` completes → dismissed view can still open Safari | HIGH | ✅ Fixed 2026-04-22 |
| R13-07 | NFCTool | `checkUsernameAvailable` catch returns `true` (available) on network error → offline user can attempt create and get 409 | HIGH | ✅ Fixed 2026-04-22 (Bool? tristate + "offline" UI) |
| R13-08 | NFCTool | `editTokenErrorMessage` never auto-clears → red error banner stays forever until tapped | 中 | ✅ Fixed 2026-04-22 (4s auto-dismiss) |
| R13-09 | NFCTool | `CardPreviewView.collectSocials` missing Threads → Threads SNS not shown in card preview (Widget shows it) | 中 | ✅ Fixed 2026-04-22 |
| R13-10 | NFCTool | `KVS didChangeExternally`: only calls `loadFromLocal`, not `syncWithServer` → multi-device edits not reflected | 中 | ✅ Fixed 2026-04-22 |
| R13-11 | NFCTool | `SecondaryButton` struct: dead code (defined but never used) | 軽微 | ✅ Fixed 2026-04-22 (deleted) |

## Round 12 — 2026-04-22 (Multi-Agent Deep Audit: CardMode/NFC/StoreKit/QR)

| ID | Repo | Description | Priority | Status |
|----|------|-------------|----------|--------|
| R12-01 | NFCTool | `StoreManager.purchase` credits: `finish()` called before dedup ID persisted — kill window causes silent credit loss | 重大 | ✅ Fixed 2026-04-22 |
| R12-02 | NFCTool | `openEditInBrowser` silently does nothing when editToken empty after all fallbacks (no toast in Release) | 重大 | ✅ Fixed 2026-04-22 |
| R12-03 | NFCTool | `CardEditorView.fetchCurrentAddress`: `requestLocation()` called before authorization dialog answered — always fails on first use | 重大 | ✅ Fixed 2026-04-22 |
| R12-04 | NFCTool | `CreateCardFlow` checking spinner hangs forever after rapid delete below 3 chars (cancel exits without `checking = false`) | 中 | ✅ Fixed 2026-04-22 |
| R12-05 | NFCTool | `QRScannerSheet.updateUIViewController` calls `startScanning()` on every SwiftUI re-render; QR requires manual tap (no `didAdd`) | 中 | ✅ Fixed 2026-04-22 |
| R12-06 | NFCTool | `CardWriteView`: no `onDisappear { cancelSession() }` → `isWriting` stuck true; no auto-dismiss after write success | 中 | ✅ Fixed 2026-04-22 |
| R12-07 | NFCTool | `CardManager.refreshCard` never clears `lastError` on success — stale error banner persists | 軽微 | ✅ Fixed 2026-04-22 |
| R12-08 | NFCTool | `CardManager.suggestUsername` returns already-taken base name when all 20 candidates exhausted | 中 | ✅ Fixed 2026-04-22 |
| R12-09 | NFCTool | `checkUsernameAvailable` catch-all returns `true` — network timeout looks like "available" | 中 | 🔵 Accepted (three-state requires API contract change; tracked in issues.md) |
| R12-10 | NFCTool | `OneShotLocationDelegate.keepAlive` static var — concurrent calls from two CardEditorView instances leak continuation | 軽微 | 🔵 Accepted (not reproducible in current nav structure) |
| R12-11 | NFCTool | `syncWithServer` has no in-flight guard — `.task` + `willEnterForeground` can fire concurrently on cold launch | 軽微 | 🔵 Accepted (@MainActor serializes; redundant calls harmless) |
| R12-12 | NFCTool | `StoreManager.observeTransactionUpdates` loop cancellation — tiny window where consumable `finish()` may be skipped | 軽微 | 🔵 Accepted (StoreKit singleton never deinit'd in practice) |

## Round 11 — 2026-04-21 (Multi-Agent Re-audit: New Files)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| B-06 | NFCTool | `ToolsView` navigationTitle `sns.navigationTitle` 誤キー | ✅ Fixed 2026-04-21 |
| B-12 | NFCTool | `WiFiSavedListView` navigationTitle `sns.navigationTitle` 誤キー | ✅ Fixed 2026-04-21 |
| B-13 | NFCTool | `PaywallView` ハードコード "NFC SNS CARD MAKER Pro" | ✅ Fixed 2026-04-21 |
| B-17 | NFCTool | `BusinessRootView` navigationTitle `sns.navigationTitle` 誤キー | ✅ Fixed 2026-04-21 |
| B-18 | NFCTool | `CompanyWriteView` navigationTitle `sns.navigationTitle` 誤キー | ✅ Fixed 2026-04-21 |
| B-03 | NFCTool | `BusinessRootView` デフォルトエントリ名「公式サイト」ハードコード | ✅ Fixed 2026-04-21 |
| C-02 | NFCTool | `ToolFormHelpers.buildWiFiURL` force unwrap `URLComponents` | ✅ Fixed 2026-04-21 |
| D-05 | NFCTool | `CardEditorView.fetchCurrentAddress` ビュー離脱でcontinuationリーク | ✅ Fixed 2026-04-21 |
| A-16 | NFCTool | `CardKeychain.set` SecItemAdd失敗を無視 | ✅ Fixed 2026-04-21 (DEBUG log) |
| WriteView | NFCTool | `WriteView` navigationTitle `sns.navigationTitle` 誤キー | ✅ Fixed 2026-04-21 |
| A-05 | NFCTool | `StoreManager.purchase` purchaseInFlight レース | 🔵 N/A (@MainActor serializes) |
| D-01 | NFCTool | `TeamAddMemberView` 保存ボタン連打 | 🔵 N/A (saving guard prevents re-entry) |
| D-04 | NFCTool | `CardEditorView` 位置情報権限なし時のサイレント失敗 | 🔵 Accepted (requestWhenInUseAuthorization + error toast in didFailWithError) |
| D-14 | NFCTool | `TeamPaywallView` 購入中の再タップ | 🔵 N/A (purchaseInFlight guard) |
| A-14 | NFCTool | `CardManager` refreshCard/restoreFromServer 同時実行 | 🔵 N/A (syncWithServer branches are mutually exclusive) |
| D-17 | NFCTool | `CardUsernamePickerView` タイムアウトなし | 🔵 N/A (SupabaseCardClient timeout fixed in R10) |

## Round 10 — 2026-04-21 (Multi-Agent Full Scan: A/B/C/D/E)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| B-05 | NFCTool | `SettingsView` 「管理ダッシュボード」ハードコード日本語 | ✅ Fixed 2026-04-21 |
| B-02 | NFCTool | `CardModeRootView` TextField placeholder "nextcode" ハードコード | ✅ Fixed 2026-04-21 |
| A-08 | NFCTool | `CardManager.suggestUsername` suffixが2桁以上でprefixLenが負になる | ✅ Fixed 2026-04-21 |
| A-07 | NFCTool | `CardManager.refreshCard` 失敗時にlastError未設定 | ✅ Fixed 2026-04-21 |
| D-17 | NFCTool | `SupabaseCardClient` URLRequest timeout未設定（60秒デフォルト） | ✅ Fixed 2026-04-21 (15s) |
| D-04 | NFCTool | `PlaceSearchView` Google Maps JS読み込み失敗時にonFailed永遠に呼ばれない | ✅ Fixed 2026-04-21 (10s timeout) |
| D-13 | NFCTool | `NFCTagLabelSync` タイムアウト時のエラーメッセージが「Decode failed」と誤表示 | ✅ Fixed 2026-04-21 |
| B-11 | NFCTool | `TapHistoryView` 「読み込み中...」「まだタップされていません」ハードコード日本語 | ✅ Fixed 2026-04-21 |
| D-11 | NFCTool | `TapHistoryView` 日付パース失敗でエントリが黙って消える | ✅ Fixed 2026-04-21 (DEBUG log) |
| B-13 | NFCTool | `TeamModeRootView` メンバーグリッドセルにタップフィードバックなし | ✅ Fixed 2026-04-21 |
| A-09 | NFCTool | `TeamManager` memberTokens Keychainデコード失敗でサイレントデータロス | ✅ Fixed 2026-04-21 |
| A-05 | NFCTool | `AuthManager.restoreSession` タイムアウトが先に返るとauth成功しても失敗扱い | 🔵 Accepted (withTaskGroup race; actual auth data already set before first next()) |
| A-01 | NFCTool | `NFCCopier` delayed destination tap task leak | 🔵 Accepted (state guard prevents damage; asyncAfter duration is 1.2s) |
| D-14 | NFCTool | `WiFiRecordStore` concurrent add() Keychain競合 | 🔵 N/A (@MainActor guarantees serial access) |
| D-06 | NFCTool | `AnalysisView` バック中NFCセッション継続 | 🔵 N/A (deinit calls invalidate()) |
| C-01 | NFCTool | `ToolFormView` God object (30+ @State) | 🔵 Accepted (planned refactor, no runtime bug) |
| C-05 | NFCTool | UserDefaults keys scattered, collision risk | 🔵 Accepted (audited, no current collision) |
| B-14 | NFCTool | `AccountView` エラー表示にdismissアフォーダンスなし | 🔵 Accepted (mode change clears error; close button available) |

## Round 9 — 2026-04-21 (Final Edge Case Pass)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| R9-D-03 | NFCTool | `errorClearTask` fired 6s after write failure, clearing subsequent success message | ✅ Fixed 2026-04-21 |
| R9-D-04 | NFCTool | `CopyFlowView` `.sourceRead` retry button missing `.disabled(isBusy)` guard | ✅ Fixed 2026-04-21 |
| R9-D-08 | NFCTool | `HistoryManager.save()` re-entrancy when iCloud notification fires during save | ✅ Fixed 2026-04-21 |
| R9-D-07 | NFCTool | `StoreManager` Bearer token missing `!isEmpty` check before IAP sync | ✅ Fixed 2026-04-21 |
| R9-A-01 | NFCTool | `isCreatingTag` stuck on Task cancellation | ✅ N/A — `CancellationError` caught by generic `catch { isCreatingTag = false }` |
| R9-A-04 | NFCTool | Tab switch during NFC write orphans session | 🔵 Accepted — CoreNFC session persists independently; system dialog handles timeout |

## Critical

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| A-05 | NFCTool | Double-tap race in `performReviewWrite()` — `isCreatingTag` guard already present | ✅ (pre-existing guard) |
| D-04 | ReviewTap | Empty redirect URL saves without validation in TagDetailView | ✅ Fixed 2026-04-21 |
| D-05 | Both | `write(url:)` skips `NFCNDEFReaderSession.readingAvailable` check | ✅ (already guarded in `startSession`) |
| C-01 | ReviewTap | Write button missing `isShortening` in disable guard | ✅ Fixed 2026-04-21 |

## Medium

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| A-01 | Both | `lockTagOnly()` doesn't reset `isSuccess` | ✅ Fixed 2026-04-21 |
| C-05 | Both | `trialKeychainKey` and `trialStartKey` identical; migration runs repeatedly | ✅ Fixed 2026-04-21 |
| D-06 | Both | `isWriting` stuck true after app backgrounded mid-session | ✅ Fixed 2026-04-21 |
| A-02 | Both | `isShortening` stuck true after view dealloc | ✅ Fixed 2026-04-21 |
| B-06 | Both | ResultBanner never auto-clears, stale failure message persists | ✅ Fixed 2026-04-21 |
| D-02 | ReviewTap | Concurrent `load()` from pull-to-refresh + toolbar button | ✅ Fixed 2026-04-21 |
| D-03 | ReviewTap | Optimistic multi-delete partial failure with silent data loss | ✅ Fixed 2026-04-21 |
| D-07 | ReviewTap | Dashboard silent zero state on stats API failure | ✅ Fixed 2026-04-21 |
| D-11 | Both | 15-second spinner on session restore with stale token + offline | ✅ Fixed 2026-04-21 |
| A-04 | NFCTool | Stale 3-second clear timer races in BusinessGroupDetailView | ✅ Fixed 2026-04-21 |
| D-09 | nfc-bz | IAP revocation no-op for credit products | ✅ Fixed 2026-04-21 |
| B-04 | NFCTool | RecordFixSheet auto-dismisses (2.5s) before user can verify | ✅ Fixed 2026-04-21 |
| C-04 | Both | UserDefaults keys duplicated verbatim across apps | ✅ Fixed 2026-04-21 |
| D-01 | ReviewTap | Stale error banner after successful reload in MyTagsView | ✅ N/A (load() clears loadError at start) |

## Low

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| B-01 | Both | No spinner during `isCreatingTag` phase in Google Review write | ✅ Fixed 2026-04-21 |
| B-03 | NFCTool | HistoryView re-write button not disabled during active NFC session | ✅ Fixed 2026-04-21 |
| A-06 | NFCTool | `addMemberForEntry` stale async capture | ✅ Fixed 2026-04-21 (struct is value type; capture now explicit) |
| A-07 | NFCTool | RecordFixSheet dismiss timer not cancellable; onWriteSuccess never called | ✅ Fixed 2026-04-21 |
| B-09 | NFCTool | Location quick-rewrite timing | ✅ N/A (isValid guard requires geocoded URL in input2) |
| C-03 | Both | `creditWasDeducted` declared but no consumeCredit path exists | ✅ Fixed 2026-04-21 (removed dead variable) |
| C-06 | Both | `app_source` magic string not typed | ✅ Fixed 2026-04-21 (SupabaseClient.appSource constant) |
| A-09 | NFCTool | Location tool migration zeroes `input1` | ✅ Fixed 2026-04-21 |
| B-05 | NFCTool | AnalysisView hero + error banner coexist with no clear failed state | ✅ Fixed 2026-04-21 |
| B-04 | NFCTool | RecordFixSheet auto-dismisses (2.5s) before user can verify | ✅ Fixed by A-07 |

## Round 8 — 2026-04-21 (Final Sweep)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| R8-02 | NFCTool | `NFCToolApp` widget time strings hardcoded Japanese — now uses `RelativeDateTimeFormatter` | ✅ Fixed 2026-04-21 |
| R8-01 | NFCTool | ContentView asyncAfter "strong self" — false positive (struct, no memory issue) | ✅ N/A |
| R8-03 | NFCTool | BusinessGroupDetailView asyncAfter "strong self" — struct, no memory issue | ✅ N/A |
| R8-04 | NFCTool | QRCodeGenerator extent.isFinite guard — CIFilter output is always finite | ✅ N/A |
| R8-05 | NFCTool | AccountView submitting stale — defer { submitting = false } already handles | ✅ N/A |

## Round 7 — 2026-04-21 (Multi-Agent R7 Audit)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| R7-A-01 | NFCTool | `TapHistoryView` HTTP errors (401/403/5xx) all showed same generic message | ✅ Fixed 2026-04-21 |
| R7-B-03 | NFCTool | `WiFiPhotoPicker` `.onAppear` auto-opened camera every time sub-sheet dismissed | ✅ Fixed 2026-04-21 |
| R7-C-01 | NFCTool | `SNSGridEditorView` Pro gate on Done button allowed free users to persist edits | ✅ Fixed 2026-04-21 (gate moved to each operation) |
| R7-D-02 | NFCTool | `LocationManager.requestOnce()` had no re-entry guard — rapid tap sent two requests | ✅ Fixed 2026-04-21 |
| R7-D-04 | NFCTool | `NFCShortener` no URL length limit and no empty-id validation on response | ✅ Fixed 2026-04-21 |
| R7-thread | NFCTool | `SNSIDHistory` + `SNSGridOrder` not `@MainActor` but published state updated on background thread | ✅ Fixed 2026-04-21 |
| R7-B-i18n | NFCTool | `TapHistoryView` relative/absolute times hardcoded Japanese | ✅ Fixed 2026-04-21 (RelativeDateTimeFormatter) |
| R7-A-02 | NFCTool | `SNSGridEditorView` done button paywall dismissed editor without saving | ✅ Fixed by R7-C-01 approach |
| R7-C-02 | NFCTool | `WiFiRecordStore` Keychain write failure silently ignored | 🔵 Accepted (SecItemAdd failure = no data loss; load() silently returns, next launch re-attempts) |
| R7-D-03 | NFCTool | Keychain thread safety (delete+add without mutex) | 🔵 Accepted (Keychain API is internally serialized on Darwin) |
| R7-C-03 | NFCTool | `nfc.bz/api` base URL duplicated in 3 files | 🔵 Accepted (all private static; shared in spirit) |

## Round 6 — 2026-04-21 (Multi-Agent R6 Audit)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| R6-D-06 | NFCTool | `NFCAnalyzer.analyze()` had no re-entry guard — rapid tap started two sessions | ✅ Fixed 2026-04-21 |
| R6-D-15 | NFCTool | `CopyFlowView` idle button never applied `isBusy` guard — double-tap possible | ✅ Fixed 2026-04-21 |
| R6-D-11 | NFCTool | `WidgetSharedData.updateSNSLinks` silently skipped failed serialize without logging | ✅ Fixed 2026-04-21 |
| R6-C-07 | NFCTool | `HistoryManager` cloud trim loop used 10% drop rate — convergence risk for large items | ✅ Fixed 2026-04-21 (now 20%) |
| R6-D-13 | NFCTool | `HistoryManager.mergeItems` ignored UUID conflicts — newer-wins resolution added | ✅ Fixed 2026-04-21 |
| R6-B-09 | NFCTool | `HistoryView` ResultBanner used `overlay` with fixed padding instead of `safeAreaInset` | ✅ Fixed 2026-04-21 |
| R6-B-05 | NFCTool | `PaywallView` product loading state indistinguishable (error shown as ProgressView) | ✅ Fixed 2026-04-21 |
| R6-A-11 | NFCTool | NFC session stale callback on rapid startSession — session ref mismatch acceptable at CoreNFC level | 🔵 Accepted (CoreNFC handles session uniqueness) |
| R6-D-01 | NFCTool | IAP credit purchase re-entry race window — finish() + UserDefaults window accepted | 🔵 Accepted (window ~1ms; StoreKit dedup catches replay) |
| R6-D-02 | NFCTool | AuthManager timeout race leaves tokens if auth was slow + offline | 🔵 Accepted (next launch retries; tokens expire anyway) |
| R6-C-01 | NFCTool | CompanyEditorView (842 lines) God object with duplicated search result UI | 🔵 Accepted (refactor planned, not a runtime bug) |
| R6-D-03 | NFCTool | Offline isPro cache doesn't check subscription expiry date | 🔵 Accepted (7-day cache max age limits exposure) |
| R6-D-08 | NFCTool | Location tool resolvedAddress lost on back button (not persisted) | 🔵 Low — user can re-geocode easily |
| R6-D-17 | NFCTool | NFCTagLabelSync timeout not surfaced in Settings UI | 🔵 Low — silent sync, retry on next launch |

## Round 5 — 2026-04-21 (Security + Write Accuracy + UI Audit)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| R5-A-01 | NFCTool | `BusinessGroupDetailView` team token saved in UserDefaults (plaintext) — security risk | ✅ Fixed 2026-04-21 |
| R5-A-02 | NFCTool | `SimpleWriteView` history rewrite recorded wrong URL (`fullURL` instead of actually-written URL) | ✅ Fixed 2026-04-21 |
| R5-A-05 | NFCTool | `RecordFixSheet` write button label didn't show spinner during `isShortening` | ✅ Fixed 2026-04-21 |
| R5-B-01 | NFCTool | `HistoryView` rewrite button enabled during `isShortening` — double-tap possible | ✅ Fixed 2026-04-21 |
| R5-B-02 | NFCTool | `FriendCardView` navigationTitle was `sns.navigationTitle` (wrong) | ✅ Fixed 2026-04-21 |
| R5-B-03 | NFCTool | `AnalysisView` navigationTitle was `sns.navigationTitle` (wrong) | ✅ Fixed 2026-04-21 |
| R5-B-04 | NFCTool | `ToolFormView` `.url` tool called `writeURI()` — never went through shortener | ✅ Fixed 2026-04-21 |
| R5-C-02 | NFCTool | `BusinessGroupDetailView` dead variable `creditWasDeducted` | ✅ Fixed 2026-04-21 |
| R5-C-03 | NFCTool | `HistoryView` section titles hardcoded Japanese (not localized) | ✅ Fixed 2026-04-21 |
| R5-D-01 | NFCTool | `SimpleWriteView` history quick-rewrite bypassed Pro access check | ✅ Fixed 2026-04-21 |
| R5-A-04 | NFCTool | `fetchTapStatsForWidget` creates `ISO8601DateFormatter` per loop iteration | 🔵 Accepted (minor perf) |
| R5-C-04 | NFCTool | `HistoryView.displayTitle` hardcoded Japanese ("nfc.bz ショートURL") | 🔵 Accepted (domain name, not user copy) |
| R5-C-05 | NFCTool | Widget time-ago strings hardcoded Japanese in `fetchTapStatsForWidget` | 🔵 Accepted (pending i18n pass) |

## Round 4 — 2026-04-21 (Write Counting Full Audit)

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| NEW-01 | NFCTool | `SearchWriteView`: `onChange(of: isSuccess)` → `onChange(of: message)`; `shortenAs: .review` → `.url` | ✅ Fixed 2026-04-21 |
| NEW-02 | NFCTool | `FriendCardView`: no `history.add`, no `onChange`, no shortener — QR-scanned writes never counted | ✅ Fixed 2026-04-21 |
| NEW-03 | NFCTool | `CardWriteView`: no `history.add`, no `onChange`, no disabled guard during write | ✅ Fixed 2026-04-21 |
| NEW-04 | NFCTool | `TeamMemberDetailView`: no `history.add`, no `onChange`, no disabled guard | ✅ Fixed 2026-04-21 |
| NEW-05 | NFCTool | `AnalysisView` RecordFixSheet: `writeURI()` for http(s) never went through shortener; `onChange(isSuccess)` → `onChange(message)` | ✅ Fixed 2026-04-21 |
| NEW-06 | NFCTool | All views using `onChange(of: isSuccess)` — consecutive writes silently dropped (isSuccess stays true) | ✅ Fixed 2026-04-21 (all views) |

## Round 3 — 2026-04-21

| ID | Repo | Description | Status |
|----|------|-------------|--------|
| A-10 | NFCTool | `rewritingURL` not cleared on consecutive rewrites — `onChange(of: isSuccess)` doesn't fire when isSuccess stays true | ✅ Fixed 2026-04-21 |
| A-11 | NFCTool | `restoreSession` always waits 5 s — deadline/sleep order was reversed | ✅ Fixed 2026-04-21 |
| A-12 | NFCTool | `loadTeamForGroup` catch: `team?.id.isEmpty` check — investigated, behavior is correct | ✅ N/A |
| B-10 | NFCTool | `HistoryView.navigationTitle` used wrong localization key `sns.navigationTitle` | ✅ Fixed 2026-04-21 |
| B-11 | NFCTool | `ResultBanner` in HistoryView overlaps system tab bar | ✅ Fixed 2026-04-21 |
| B-12 | NFCTool | `onChange(of: isValid)` auto-scrolls to QR mid-typing for non-plainText tools | 🔵 Accepted (minor; only triggers once when first valid) |
| B-13 | NFCTool | Custom tab bar "Company URL" tab calls `onBack()` — should be non-interactive active indicator | ✅ Fixed 2026-04-21 |
| C-07 | NFCTool | `HistoryView.navigationTitle` wrong key (same as B-10) | ✅ Fixed 2026-04-21 (same fix) |
| C-08 | NFCTool | `WriteEventUploader.migrateICloudHistoryIfNeeded` blocked-scheme guard duplicated | ✅ Fixed 2026-04-21 |
| C-09 | NFCTool | `consumeCredit()` always returns `true` but credit UI still shows count | 🔵 By design (all features free during rollout) |
| C-10 | NFCTool | `ToolFormView` has two `onAppear` closures — ordering ambiguity | ✅ Fixed 2026-04-21 |
| D-12 | NFCTool | `HistoryManager.save()` iCloud KVS trim loop — infinite loop risk on encode failure | ✅ Fixed 2026-04-21 |
| D-13 | NFCTool | `WriteEventUploader.enqueue()` Task captures singleton strongly | 🔵 Singleton pattern; acceptable |
| D-14 | NFCTool | `migrateExistingMembersToDefaultEntry` race with network arrival | 🔵 Migration flag prevents double-run; acceptable |
| D-15 | NFCTool | `isCreatingTag` not reset if Task cancelled mid-flight | ✅ Already handled by `scenePhase == .background` reset |
