@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.
- package/ANALYSIS_REPORT.md +211 -0
- package/BLE_IMPLEMENTATION_PLAN.md +703 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +365 -0
- package/dist/index.d.mts +347 -0
- package/dist/index.d.ts +347 -0
- package/dist/index.js +1095 -0
- package/dist/index.mjs +1058 -0
- package/package.json +62 -0
- package/src/ble.ts +504 -0
- package/src/db.ts +57 -0
- package/src/identity.ts +91 -0
- package/src/index.ts +375 -0
- package/src/matcher.ts +224 -0
- package/src/storage.ts +110 -0
- package/src/transport.ts +20 -0
- package/src/types.ts +100 -0
- package/src/utils.ts +20 -0
- package/tsconfig.json +15 -0
|
@@ -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.*
|