@vailix/mask 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,211 @@
1
+ # @vailix/mask - Code Analysis Report
2
+
3
+ **Date:** January 7, 2026
4
+ **Reviewer:** AI Code Review
5
+ **Package Version:** 0.2.0
6
+ **Status:** Post-BLE Migration Review
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ The `@vailix/mask` package implementation follows the `core_framework_plan.md` specification. NFC pairing has been replaced with BLE-based proximity discovery. This analysis identified **1 bug** and **2 code issues** that were fixed, plus **1 remaining question**.
13
+
14
+ | Category | Count | Status |
15
+ |----------|-------|--------|
16
+ | Bugs | 1 | ✅ Fixed |
17
+ | Code Issues | 2 | ✅ Fixed |
18
+ | Questions | 1 | 🔵 Open |
19
+
20
+ ---
21
+
22
+ ## ✅ Fixed Issues
23
+
24
+ ### BUG-001: Binary parsing lacks bounds checking ✅ FIXED
25
+
26
+ **File:** `src/matcher.ts`
27
+ **Severity:** High - Would crash on malformed server response
28
+
29
+ **Problem:** The `_parseBinaryResponse` method read from the buffer without verifying there are enough bytes remaining.
30
+
31
+ **Fix Applied:** Added bounds checking before reading each key and during metadata extraction.
32
+
33
+ ---
34
+
35
+ ### ISSUE-001: QR expiry was hardcoded, not tied to RPI duration ✅ FIXED
36
+
37
+ **File:** `src/index.ts`
38
+ **Severity:** Medium
39
+
40
+ **Problem:** QR codes expired after 15 minutes regardless of configured `rpiDurationMs`.
41
+
42
+ **Fix Applied:** QR expiry now uses `this.rpiDurationMs` instead of hardcoded constant.
43
+
44
+ ---
45
+
46
+ ### ISSUE-003: UTF-8 metadata corruption with fallback decoder ✅ FIXED
47
+
48
+ **File:** `src/matcher.ts`
49
+ **Severity:** Medium
50
+
51
+ **Problem:** `String.fromCharCode()` doesn't handle multi-byte UTF-8 characters correctly.
52
+
53
+ **Fix Applied:** Replaced with `new TextDecoder('utf-8').decode(metaBytes)`.
54
+
55
+ ---
56
+
57
+ ## ❌ Removed Issues (No Longer Applicable)
58
+
59
+ The following issues were related to NFC and are no longer relevant after migration to BLE:
60
+
61
+ | Issue | Reason Removed |
62
+ |-------|----------------|
63
+ | ISSUE-002: NFC timestamp validation | NFC removed, replaced by BLE |
64
+ | ISSUE-004: NFC bidirectional exchange limitations | NFC removed, replaced by BLE |
65
+ | Q-002: NFC timestamp validation approach | NFC removed |
66
+ | Q-003: NFC bidirectional exchange flow | NFC removed |
67
+
68
+ ---
69
+
70
+ ## ✅ All Questions Resolved
71
+
72
+ ### Q-004: Type safety - `getMatchingScans` returns `any[]` ✅ FIXED
73
+
74
+ **File:** `src/storage.ts`
75
+ **Line:** 81
76
+
77
+ **Fix Applied:** Added `ScannedEvent` type alias using Drizzle's `$inferSelect` and updated method signature to `Promise<ScannedEvent[]>`.
78
+
79
+ ---
80
+
81
+ ## ✅ Verified Correct
82
+
83
+ | Component | Status | Notes |
84
+ |-----------|--------|-------|
85
+ | HMAC-SHA256 RPI generation | ✅ | 128-bit output, epoch-based |
86
+ | AES-256-GCM encryption | ✅ | Correct IV size (12 bytes), auth tag handling |
87
+ | SQLCipher database encryption | ✅ | Master key validated, key mismatch handled |
88
+ | Rescan protection | ✅ | Configurable interval, persisted to AsyncStorage |
89
+ | Memory-bounded scan history | ✅ | MAX_SCAN_HISTORY_SIZE = 10000 |
90
+ | Pagination handling | ✅ | Cursor-based, 500 batch size for SQLite |
91
+ | 14-day cleanup | ✅ | Automatic on SDK init |
92
+ | Event handler cleanup | ✅ | Returns unsubscribe function for React |
93
+ | Config validation | ✅ | rescanInterval ≤ rpiDuration enforced |
94
+ | Binary format parsing | ✅ | Bounds checking added |
95
+ | BLE discovery | ✅ | Service UUID filtering, RSSI proximity |
96
+ | BLE pairing exchange | ✅ | GATT read/write, bidirectional |
97
+ | Display name generation | ✅ | Deterministic from RPI prefix |
98
+ | Stale user cleanup | ✅ | Configurable timeout |
99
+ | Explicit consent mode | ✅ | `autoAcceptIncomingPairs` config |
100
+
101
+ ---
102
+
103
+ ## BLE Implementation Summary
104
+
105
+ ### New Files
106
+
107
+ | File | Lines | Purpose |
108
+ |------|-------|---------|
109
+ | `src/ble.ts` | 539 | BLE discovery and pairing service |
110
+
111
+ ### Removed Files
112
+
113
+ | File | Reason |
114
+ |------|--------|
115
+ | `src/nfc.ts` | Replaced by BLE |
116
+
117
+ ### New Types
118
+
119
+ ```typescript
120
+ interface NearbyUser {
121
+ id: string;
122
+ displayName: string;
123
+ rssi: number;
124
+ discoveredAt: number;
125
+ paired: boolean;
126
+ hasIncomingRequest: boolean;
127
+ }
128
+
129
+ interface PairResult {
130
+ success: boolean;
131
+ partnerRpi?: string;
132
+ partnerMetadataKey?: string;
133
+ error?: string;
134
+ }
135
+
136
+ interface VailixConfig {
137
+ // Backend & Auth
138
+ reportUrl: string;
139
+ downloadUrl: string;
140
+ appSecret: string;
141
+ // Storage
142
+ keyStorage?: KeyStorage;
143
+ reportDays?: number;
144
+ // Contact Tracing
145
+ rpiDurationMs?: number;
146
+ rescanIntervalMs?: number;
147
+ // BLE
148
+ bleDiscoveryTimeoutMs?: number;
149
+ proximityThreshold?: number;
150
+ autoAcceptIncomingPairs?: boolean;
151
+ }
152
+ ```
153
+
154
+ ### New SDK Methods
155
+
156
+ | Method | Description |
157
+ |--------|-------------|
158
+ | `VailixSDK.isBleSupported()` | Check BLE availability |
159
+ | `sdk.startDiscovery()` | Start BLE scanning |
160
+ | `sdk.stopDiscovery()` | Stop BLE scanning |
161
+ | `sdk.getNearbyUsers()` | Get nearby user list |
162
+ | `sdk.onNearbyUsersChanged(cb)` | Subscribe to updates |
163
+ | `sdk.pairWithUser(userId)` | Pair with user |
164
+ | `sdk.unpairUser(userId)` | Unpair/reject user |
165
+
166
+ ### Removed SDK Methods
167
+
168
+ | Method | Replacement |
169
+ |--------|-------------|
170
+ | `VailixSDK.isNfcSupported()` | `VailixSDK.isBleSupported()` |
171
+ | `sdk.pairViaNfc()` | `sdk.pairWithUser(userId)` |
172
+
173
+ ---
174
+
175
+ ## Action Items
176
+
177
+ ### Completed
178
+ - [x] **BUG-001:** Add bounds checking to binary response parser
179
+ - [x] **ISSUE-001:** Tie QR expiry to RPI duration
180
+ - [x] **ISSUE-003:** Use TextDecoder instead of String.fromCharCode
181
+ - [x] **ISSUE-002:** NFC timestamp validation — N/A (NFC removed)
182
+ - [x] **ISSUE-004:** NFC bidirectional exchange — N/A (NFC removed)
183
+ - [x] **Q-001:** QR expiry approach — Tied to RPI duration
184
+ - [x] **Q-002:** NFC timestamp validation — N/A (NFC removed)
185
+ - [x] **Q-003:** NFC bidirectional exchange — N/A (NFC removed)
186
+
187
+ ### Open
188
+ - [x] **Q-004:** Add proper return type to `getMatchingScans` ✅ FIXED
189
+
190
+ ---
191
+
192
+ ## Appendix: File Inventory
193
+
194
+ | File | Lines | Purpose |
195
+ |------|-------|---------|
196
+ | `src/index.ts` | 321 | SDK entry point, VailixSDK class |
197
+ | `src/identity.ts` | 81 | Master key & RPI generation |
198
+ | `src/storage.ts` | 99 | SQLite storage, rescan protection |
199
+ | `src/matcher.ts` | 176 | Server sync, binary parsing, decryption |
200
+ | `src/ble.ts` | 539 | BLE discovery and pairing service |
201
+ | `src/transport.ts` | 21 | QR code format/parse |
202
+ | `src/db.ts` | 58 | SQLCipher database initialization |
203
+ | `src/types.ts` | 96 | TypeScript interfaces |
204
+ | `package.json` | 47 | Dependencies + scripts |
205
+ | `tsconfig.json` | 15 | TypeScript config |
206
+ | `README.md` | 366 | Comprehensive documentation |
207
+ | `BLE_IMPLEMENTATION_PLAN.md` | 704 | BLE architecture and design decisions |
208
+
209
+ ---
210
+
211
+ *Report updated after NFC → BLE migration. January 7, 2026.*