Skip to main content

Known issues & current status

The single cross-system view of what's fixed, open, and noted — consolidated from the 2026-07-22 audit. Each component guide repeats the items relevant to it.

audit 2026-07-22 12 fixed 24 open 6 security

Consolidated from the 2026-07-22 audit (18 agents, two waves + three critical-focused passes, ~110 findings).

Legendfixed this session (build-verified) · open · security (real, but deprioritised behind features per the team's call).

Data-integrity red flags (highest priority)

These can lose or mismatch a patient's recording — the worst outcomes.

StatusIssueWhere
fixedDelete-during-upload could splice two takes into one WAV (3 s guard vs 60 s chunk) — now waits for the upload + trim tailSATE_Recorder.ino, connectivity.cpp
fixedReboot mid-renumber left a numbering hole → later takes invisible forever — now NVS-journaled + healed on bootSATE_Recorder.ino (recoverInterruptedDelete)
fixedRecorder didn't auto-resume after reboot (60 s flush window) — now ~5 s flush + restart-empty-part00SATE_Recorder.ino (maybeResumeRecording)
fixedUploader freed SD audio on a .synced marker alone — now server byte-verified before freeconnectivity.cpp (verifySessionStored) + device-api /sessions/verify
fixedBLE session pull could upload a truncated WAV as complete — now byte-reconciledsrc/ble/SateBle.ts
fixedDuplicate sessions + duplicate AI runs on a lost markSynced ACK — server dedup probe addeddevice-api storeSessionRecord
fixedPendant take contaminated by the previous take — buffers reset on start()/disconnect()src/pendant/PendantLink.ts
openPendant takeWav() clears the buffer before upload succeeds → failed upload loses the takesrc/pendant/PendantLink.ts
openPendant capture is memory-only → app kill/crash mid-record loses everythingsrc/pendant/PendantLink.ts
openStalled-but-loud pendant stream naps and wipes its ring → the "audio stuck" symptomSATE_Pendant.ino

Recorder

StatusIssueWhere
openOTA has no device-side rollback — a bad image bricks the fleet (server magic/semver/size validation added)connectivity.cpp (verifyOta not overridden)
openrenameSessionFiles ignores SD_MMC.rename() returns → new number + old audio on a glitchSATE_Recorder.ino
opensaveMetadataToSd() return ignored → flags + patient tag silently lost on a full cardSATE_Recorder.ino
openBLE notifyFramed drops a packet after 50 retries → short WAV accepted as completeconnectivity.cpp
openFlag markers truncated to ~37 in flagsCsv[300] → device/server count mismatchconnectivity.cpp
openpendDirty lost-update → a renumbered pending take stranded until an unrelated eventconnectivity.cpp
openSeveral millis()-wrap-unsafe deadlines (~49.7-day uptime)connectivity.cpp, SATE_Recorder.ino
lowRoster-full active-patient push overwrites a slot — low priority (standalone recording doesn't assign patients)SATE_Recorder.ino

Pendant

StatusIssueWhere
openNo onDisconnected handler → a dead link looks like a normal nap (UI still says recording)src/pendant/PendantLink.ts
openOverrun guard keeps the oldest audio → stale burst on link recoverySATE_Pendant.ino
openFirmware + app stack two tanh soft-clips (effective gain 104× not 40×) → harsh distortionsrc/pendant/PendantLink.ts
open~128 ms of every recording's onset dropped by a fixed "drain" readSATE_Recorder.ino (I2S drain)

Web app

StatusIssueWhere
fixedAnnotations couldn't be clicked (popup off-screen behind an invisible backdrop) — now position: fixedAnnotations/AnnotationPopup.tsx
fixedFirst Undo wiped the transcript (history seeded from empty) — now guarded re-seedhooks/useUndoRedo.ts
openInline SALT edit zeroes filler / mispronunciation / morpheme-omission countsConversationView/hooks/useSegmentOperations.ts
openSALT round-trip swaps repetitions ↔ revisions; split/merge desyncs word.index → inflated NDW/MLUservices/saltService.ts, utils/segmentOperations.ts
openStale fetch overwrites the current patient's PHI on fast switchCRM/PatientDetails/hooks/usePatientData.ts
openerrorRate counts correct morphemes + pauses as errors; examiner-speaker poolingservices/DataService/speechAnalysis.ts
openBilling page shows a fabricated next-billing/cancellation dateStripe/BillingPage.tsx

Backend

StatusIssueWhere
openprocess-device-session repo copy is NOT the deployed no-op — if deployed it races the container → duplicate recordingssupabase/functions/process-device-session/index.ts
openNo DB unique constraint backstops duplicate sessions (only the app-side probe)cloudflare/schema.sql
opendeleteRecording orphans the device session and can leak the audio objectDataService/recordingStorage.ts
openCloudflare port is a regression (no state machine, sync-AI in a Worker)cloudflare/src/functions/processDeviceSession.ts

Security (noted, deprioritised behind features)

StatusIssueWhere
securityPOST /firmware is above the /admin gate → any authenticated user can publish fleet firmware (image validation added; isAdmin gate still needed)device-api/index.ts
securityDevice key is derivable from the serial (key-dev-<serial>) → roster read + audio injectiondevice-api/index.ts
securityDevice heartbeat has no key validation → any key- string harvests active-patient PHIdevice-api/index.ts
security.env with a live service_role key is not git-ignoredrepo root
securityAccess + 30-day refresh tokens in plaintext AsyncStorage, not Keychainsrc/store.tsx
securityinvite_codes SELECT policy is cross-tenant readablecloudflare/src/policy.ts

Refuted (verified false positives)

The adversarial pass cleared two claims — kept here so they aren't re-raised:

  • Record-begin FATFS race — a fresh session file, no renumber, and the FATFS per-volume lock serialise the access; the delete-path quiesce exists specifically because delete renumbers, which record does not.
  • cf-processor watchdog requeuing a running take — the heartbeat guard exists, so an actively-processing job is not reclaimed.