# Changelog

> **This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.**

## Score

- CAI 63 → 66 (+2.6)
- Rubric changed (rubric-2026.08.18 → rubric-2026.08.19) — scores are not directly comparable.

## Lenses

- Code Health 96 → 93 (-2.9)
- Architecture 90 → 93 (+3.1)
- Maturity 59 → 67 (+7.6)
- Readiness 57 → 55 (-1.6)
- Security 60 → 69 (+8.8)
- Domain Modelling 100 → 100 (+0.0)

## Resolved (9)

- Change coupling: BitchatApp.swift ↔ ChatViewModel.swift (bitchat/BitchatApp.swift)
- Change coupling: GeoRelayDirectory.swift ↔ NostrRelayManager.swift (bitchat/Nostr/GeoRelayDirectory.swift)
- High: security finding (details withheld)
- Medium advisory (unsound): RUSTSEC-2026-0097 (localPackages/Arti/Cargo.lock)
- No build provenance
- Off-boarding risk: anonymized user #1
- The BLE announcement metadata section lists 'Nickname' but does not explain what is exposed (e.g. persistent Noise key) or the security impact. (docs/privacy-assessment.md)
- The dual-transport architecture description mentions Bluetooth mesh but does not explain how Nostr integration works or the role of third-party relays in public content exposure. (README.md)
- complexity unreadable for .rs, .swift — churn × complexity hotspots could not be measured

## New (27)

- Change coupling: BLEOutboundPacketPolicy.swift ↔ SyncTypeFlags.swift (bitchat/Services/BLE/BLEOutboundPacketPolicy.swift)
- Change coupling: TextMessageView.swift ↔ MediaMessageView.swift (bitchat/Views/Components/TextMessageView.swift)
- FileTooLong: BLE/BLEIncomingFileStore.swift (bitchat/Services/BLE/BLEIncomingFileStore.swift)
- FileTooLong: BLE/BLEPrivateMediaReceiptStore.swift (bitchat/Services/BLE/BLEPrivateMediaReceiptStore.swift)
- FileTooLong: Noise/NoiseSessionManager.swift (bitchat/Noise/NoiseSessionManager.swift)
- FileTooLong: Nostr/NostrProtocol.swift (bitchat/Nostr/NostrProtocol.swift)
- FileTooLong: Services/KeychainManager.swift (bitchat/Services/KeychainManager.swift)
- FileTooLong: Services/NoiseEncryptionService.swift (bitchat/Services/NoiseEncryptionService.swift)
- FileTooLong: ViewModels/ChatMediaTransferCoordinator.swift (bitchat/ViewModels/ChatMediaTransferCoordinator.swift)
- FileTooLong: ViewModels/ChatPrivateConversationCoordinator.swift (bitchat/ViewModels/ChatPrivateConversationCoordinator.swift)
- FileTooLong: Views/AppInfoView.swift (bitchat/Views/AppInfoView.swift)
- FileTooLong: Views/ContentSheetViews.swift (bitchat/Views/ContentSheetViews.swift)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- LLM evaluation failed
- Medium advisory (unsound): RUSTSEC-2026-0097 (localPackages/Arti/Cargo.lock)
- Medium advisory (unsound): RUSTSEC-2026-0097 (localPackages/Arti/Cargo.lock)
- Medium advisory (unsound): RUSTSEC-2026-0221 (localPackages/Arti/Cargo.lock)
- …and 7 more

## Changes since last survey

- 33 commits — 24 feature/other, 9 fixes

## By area

- bitchat/Services — 10 commits
- bitchat/Views — 5 commits
- bitchat/Localizable.xcstrings — 3 commits
- (root) — 2 commits
- bitchat/App — 2 commits
- bitchat/ViewModels — 2 commits
- bitchatTests/Simulation — 2 commits
- bitchat/Features — 1 commit
- bitchat/Identity — 1 commit
- bitchat/Noise — 1 commit
- bitchat/Nostr — 1 commit
- bitchatTests/Protocols — 1 commit
- bitchatTests/VoiceRecorderTests.swift — 1 commit
- localPackages/BitFoundation — 1 commit

## Notable commits

- fix: Fix #1538: release stale bindings on rotation instead of leaving a ghost identity (#1554)
- fix: Fix $$ escaping that broke every Xcode just recipe (#1525)
- fix: Fix built-in relay actor isolation (#1528)
- fix: Fix the SimulatedMesh announce-loss flake (#1564)
- fix: Fix the retire↔reconnect oscillation: redundant-link survivor is the newest connection (#1566)
- fix: Link layer slice 4: deterministic multi-node mesh simulation (and the panic-announce bug it caught) (#1548)
- fix: fix(ble): don't spend the fragment scheduler's slot budget on blocked requests (#1530)
- fix: fix: show verified seal next to sender names in chat (#1506)
- fix: fix: stop EnvironmentObject crash in the people sheet (#1567)
- change: Add macOS camera QR scanning for peer verification (#1477)
- change: BLE transport architecture V3: one engine domain, capability ports, feature-owned state (#1498)
- change: Defer alert-binding dismissal writes out of the view update (#1537)
- change: Deflake VoiceRecorderTests: replace timed semaphores with async events (#1572)
- change: Don't suggest blocked people in @-mentions (#1543)
- change: Extract the central-role radio policy into BLERadioController (#1539)
- change: Give media the explicit file-protection class other stores use (#1552)
- change: Keyboard navigation for @-mention suggestions (#1542)
- change: Link layer slice 2: cohere link-auth state and split bindings from the physical store (#1540)
- change: Link layer slice 3: bindings and link-auth become engine-owned (the option-B domain flip) (#1547)
- change: Link layer slice 5: BLELinkEvent — the port has a name, the delegates have their own files (#1551)
- …and 13 more

## Architecture

- Containers 0 added · 0 removed · contexts 1 added · 0 removed · edges 0 added · 0 removed

## Added bounded contexts (1)

- python
