@7365admin1/core 3.8.0 → 3.9.0

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,201 @@
1
+ # HID Amico Hardware Integration Diagrams
2
+
3
+ ## 1. Overall Architecture
4
+
5
+ ```mermaid
6
+ flowchart LR
7
+ Admin[Admin / Web App / Postman]
8
+
9
+ subgraph API[iService365 API Core]
10
+ Route[/api/access-management/hid]
11
+ end
12
+
13
+ subgraph Core[iService365 Core]
14
+ Controller[HID Controller<br/>validate + call service]
15
+ Service[HID Service<br/>business logic + HID HTTP client]
16
+ Repo[HID Repository<br/>MongoDB only]
17
+ Model[HID Model<br/>types + Joi schemas]
18
+ end
19
+
20
+ subgraph DB[(MongoDB)]
21
+ Readers[hid-amico-readers]
22
+ Events[hid-amico-events]
23
+ Identities[hid-amico-identities]
24
+ Existing[Existing iService365<br/>users/persons/members/visitors]
25
+ end
26
+
27
+ subgraph HID[HID Amico Reader]
28
+ HidWeb[HID Web Portal]
29
+ HidApi[HID HTTP API]
30
+ Face[Face / card scan]
31
+ end
32
+
33
+ Admin --> Route
34
+ Route --> Controller
35
+ Controller --> Model
36
+ Controller --> Service
37
+ Service --> Repo
38
+ Repo --> Readers
39
+ Repo --> Events
40
+ Repo --> Identities
41
+ Identities -. maps to .-> Existing
42
+ Service --> HidApi
43
+ HidWeb --> HidApi
44
+ Face --> HidApi
45
+ ```
46
+
47
+ ## 2. Reader Registration And Connection Test
48
+
49
+ ```mermaid
50
+ sequenceDiagram
51
+ participant Admin as Admin / Postman
52
+ participant API as iService365 API
53
+ participant Service as HID Service
54
+ participant DB as MongoDB
55
+ participant HID as HID Reader
56
+
57
+ Admin->>API: POST /readers
58
+ API->>Service: createReader()
59
+ Service->>Service: encrypt password
60
+ Service->>DB: insert hid-amico-readers
61
+ DB-->>API: readerId
62
+ API-->>Admin: created reader without password
63
+
64
+ Admin->>API: POST /readers/:readerId/test
65
+ API->>Service: testReader(readerId)
66
+ Service->>DB: get reader with password
67
+ Service->>HID: POST /hidlogin.fcgi
68
+ HID-->>Service: session
69
+ Service->>HID: POST /session_is_valid.fcgi?session=...
70
+ HID-->>Service: valid
71
+ Service->>HID: POST /logout.fcgi?session=...
72
+ Service->>DB: update lastSeenAt + add test event
73
+ API-->>Admin: connection result
74
+ ```
75
+
76
+ ## 3. Pull HID Users And Access Logs
77
+
78
+ ```mermaid
79
+ sequenceDiagram
80
+ participant Admin as Admin / Web App / Postman
81
+ participant API as iService365 API
82
+ participant Service as HID Service
83
+ participant DB as MongoDB
84
+ participant HID as HID Reader
85
+
86
+ Admin->>API: POST /readers/:readerId/objects<br/>operation=load, object=users
87
+ API->>Service: runObjectOperation(load)
88
+ Service->>DB: get active reader with password
89
+ Service->>HID: POST /hidlogin.fcgi
90
+ HID-->>Service: session
91
+ Service->>HID: POST /load_objects.fcgi?session=...
92
+ HID-->>Service: users[]
93
+ Service->>DB: add backend event objects_load
94
+ API-->>Admin: HID users
95
+
96
+ Admin->>API: POST /readers/:readerId/objects<br/>operation=load, object=access_logs
97
+ API->>Service: runObjectOperation(load)
98
+ Service->>HID: POST /load_objects.fcgi?session=...
99
+ HID-->>Service: access_logs[]
100
+ Service->>DB: add backend event objects_load
101
+ API-->>Admin: raw HID access logs
102
+ ```
103
+
104
+ ## 4. Face Scan Recognition And Pull-Based Review
105
+
106
+ ```mermaid
107
+ sequenceDiagram
108
+ participant Person as Resident / Staff / Visitor
109
+ participant HID as HID Reader
110
+ participant Portal as HID Web Portal
111
+ participant Admin as iService365 Admin
112
+ participant API as iService365 API
113
+
114
+ Person->>HID: Face scan
115
+ HID->>HID: Local biometric recognition
116
+ HID->>Portal: Shows access notification/log
117
+
118
+ Admin->>API: Load access_logs from reader
119
+ API->>HID: /load_objects.fcgi object=access_logs
120
+ HID-->>API: access_logs with user_id/time
121
+ API-->>Admin: Raw logs for mapping/review
122
+ ```
123
+
124
+ ## 5. Callback / Monitor Flow
125
+
126
+ ```mermaid
127
+ sequenceDiagram
128
+ participant Person as Resident / Staff / Visitor
129
+ participant HID as HID Reader
130
+ participant API as iService365 API
131
+ participant Service as HID Service
132
+ participant DB as MongoDB
133
+ participant App as Web / Mobile App
134
+
135
+ Person->>HID: Face/card scan
136
+ HID->>HID: Local match
137
+ HID->>API: POST /notifications/:readerId/:type
138
+ API->>Service: receiveNotification(readerId, type, payload)
139
+ Service->>DB: get reader
140
+ Service->>DB: find identity by hidUserId/registration/cardNo
141
+
142
+ alt Identity mapped
143
+ Service->>DB: save event with mapped identity
144
+ API-->>HID: 202 Accepted
145
+ App->>API: read backend HID logs
146
+ API-->>App: event linked to user/person/member/visitor
147
+ else Identity not mapped
148
+ Service->>DB: save event with identity=null and identityLookup
149
+ API-->>HID: 202 Accepted
150
+ App->>API: read backend HID logs
151
+ API-->>App: unmapped event
152
+ end
153
+ ```
154
+
155
+ ## 6. Identity Mapping
156
+
157
+ ```mermaid
158
+ flowchart TB
159
+ HidUser[HID user<br/>users.id / registration]
160
+ HidCard[HID card<br/>cardNo]
161
+ Mapping[hid-amico-identities]
162
+ User[iService365 user]
163
+ Person[Person]
164
+ Member[Member]
165
+ Visitor[Visitor]
166
+ Log[access_logs.user_id]
167
+ Event[hid-amico-events]
168
+
169
+ HidUser --> Mapping
170
+ HidCard --> Mapping
171
+ Mapping --> User
172
+ Mapping --> Person
173
+ Mapping --> Member
174
+ Mapping --> Visitor
175
+ Log --> HidUser
176
+ Mapping --> Event
177
+ ```
178
+
179
+ ## 7. Remote Network Access
180
+
181
+ ```mermaid
182
+ flowchart LR
183
+ VN[Developer / Backend<br/>Vietnam]
184
+ VPN[Tailscale / Site VPN]
185
+ Router[Philippines subnet route<br/>192.168.20.0/24]
186
+ HID[HID Reader<br/>192.168.20.123:80]
187
+ API[Deployed iService365 API]
188
+
189
+ VN --> VPN
190
+ VPN --> Router
191
+ Router --> HID
192
+ API -. production network route .-> HID
193
+ ```
194
+
195
+ ## Notes
196
+
197
+ - iService365 authentication uses `Authorization: Bearer <sid>`.
198
+ - Reader callback endpoint is unauthenticated so HID can call it.
199
+ - Face recognition happens on the HID reader.
200
+ - iService365 receives or pulls the resulting event, then maps it to an iService365 identity.
201
+ - Door-state support depends on firmware; the tested reader returned `Invalid command: door_state`.
@@ -0,0 +1,491 @@
1
+ # HID Amico Integration
2
+
3
+ This document explains the current iService365 backend integration for HID Amico VL35LF / VL70LF biometric readers.
4
+
5
+ ## Source Documents
6
+
7
+ - `HID Amico Biometric Reader API Guide.pdf`
8
+ - `PLT-07752 A.2 - HID Amico Biometric Readers VL35LF and VL70LF User Guide.pdf`
9
+
10
+ Important confirmed behavior:
11
+
12
+ - Face recognition is performed by the HID reader, not by iService365.
13
+ - The backend connects to the reader through the HID HTTP API.
14
+ - The backend can register readers, test connectivity, execute generic HID object operations, pull users/access logs, and receive notification callbacks.
15
+ - Raw HID users/access logs must be mapped to existing iService365 records before the product can show a known resident/staff/visitor.
16
+
17
+ ## Repositories And Packages
18
+
19
+ Core package: `iservice365-core`
20
+
21
+ ```text
22
+ src/models/hid-amico.model.ts
23
+ src/repositories/hid-amico.repo.ts
24
+ src/services/hid-amico.service.ts
25
+ src/controllers/hid-amico.controller.ts
26
+ src/index.ts
27
+ ```
28
+
29
+ API package: `iservice365-API-core`
30
+
31
+ ```text
32
+ src/routes/hid-amico.route.ts
33
+ src/routes/index.ts
34
+ ```
35
+
36
+ Route mount:
37
+
38
+ ```text
39
+ /api/access-management/hid
40
+ ```
41
+
42
+ ## Layer Responsibilities
43
+
44
+ ### Model
45
+
46
+ File: `src/models/hid-amico.model.ts`
47
+
48
+ Responsibilities:
49
+
50
+ - Type definitions for readers, events, and identities.
51
+ - Joi schemas for request validation.
52
+ - Model factories:
53
+ - `MHidAmicoReader`
54
+ - `MHidAmicoEvent`
55
+ - `MHidAmicoIdentity`
56
+
57
+ Joi schemas are kept in the model file to match the existing codebase convention.
58
+
59
+ ### Repository
60
+
61
+ File: `src/repositories/hid-amico.repo.ts`
62
+
63
+ Responsibilities:
64
+
65
+ - MongoDB access only.
66
+ - Reader CRUD.
67
+ - Event insert/list.
68
+ - Identity mapping CRUD.
69
+ - Reader password sanitization before returning data.
70
+ - Identity duplicate guard.
71
+
72
+ Repository should not call HID hardware APIs.
73
+
74
+ ### Service
75
+
76
+ File: `src/services/hid-amico.service.ts`
77
+
78
+ Responsibilities:
79
+
80
+ - Business logic.
81
+ - Reader password encryption/decryption.
82
+ - Active reader checks.
83
+ - HID hardware HTTP client.
84
+ - Reader connection test.
85
+ - Sync/object operations.
86
+ - Notification enrichment and identity lookup.
87
+
88
+ Reader passwords are encrypted with AES-256-GCM. The encryption key comes from:
89
+
90
+ ```text
91
+ HID_AMICO_SECRET
92
+ ```
93
+
94
+ Fallback:
95
+
96
+ ```text
97
+ ACCESS_TOKEN_SECRET
98
+ ```
99
+
100
+ ### Controller
101
+
102
+ File: `src/controllers/hid-amico.controller.ts`
103
+
104
+ Responsibilities:
105
+
106
+ - Validate `params`, `query`, and `body` using model schemas.
107
+ - Call service methods.
108
+ - Return API responses.
109
+
110
+ Controller should not call repository methods directly.
111
+
112
+ ### API Route
113
+
114
+ File: `iservice365-API-core/src/routes/hid-amico.route.ts`
115
+
116
+ Responsibilities:
117
+
118
+ - Mount authenticated admin APIs.
119
+ - Expose unauthenticated reader notification callback.
120
+
121
+ ## Data Collections
122
+
123
+ ### `hid-amico-readers`
124
+
125
+ Stores configured HID devices.
126
+
127
+ Key fields:
128
+
129
+ ```text
130
+ site
131
+ name
132
+ location
133
+ baseUrl
134
+ username
135
+ password
136
+ deviceId
137
+ monitorPath
138
+ enabled
139
+ status
140
+ lastSeenAt
141
+ lastSyncAt
142
+ lastSyncStatus
143
+ lastSyncMessage
144
+ createdAt
145
+ updatedAt
146
+ deletedAt
147
+ ```
148
+
149
+ Notes:
150
+
151
+ - `password` is encrypted.
152
+ - API responses do not return `password`.
153
+ - API responses include `passwordSet` so UI can show whether a password exists.
154
+
155
+ ### `hid-amico-identities`
156
+
157
+ Maps HID users/cards to iService365 records.
158
+
159
+ Key fields:
160
+
161
+ ```text
162
+ reader
163
+ site
164
+ hidUserId
165
+ registration
166
+ cardNo
167
+ person
168
+ user
169
+ member
170
+ visitor
171
+ type
172
+ status
173
+ metadata
174
+ ```
175
+
176
+ At least one of these is required:
177
+
178
+ ```text
179
+ hidUserId
180
+ registration
181
+ cardNo
182
+ ```
183
+
184
+ Supported identity types:
185
+
186
+ ```text
187
+ resident
188
+ staff
189
+ contractor
190
+ visitor
191
+ unknown
192
+ ```
193
+
194
+ ### `hid-amico-events`
195
+
196
+ Stores backend-side HID events.
197
+
198
+ Examples:
199
+
200
+ ```text
201
+ test
202
+ sync
203
+ sync_failed
204
+ objects_load
205
+ objects_create
206
+ objects_modify
207
+ objects_destroy
208
+ objects_load_failed
209
+ notification callback event types
210
+ ```
211
+
212
+ This collection is not the same as the raw HID `access_logs` table. Raw access logs live on the reader and can be pulled using the generic object API.
213
+
214
+ ## API Surface
215
+
216
+ Base path:
217
+
218
+ ```text
219
+ /api/access-management/hid
220
+ ```
221
+
222
+ Reader management:
223
+
224
+ ```text
225
+ GET /readers
226
+ POST /readers
227
+ PATCH /readers/:readerId
228
+ DELETE /readers/:readerId
229
+ ```
230
+
231
+ Reader operations:
232
+
233
+ ```text
234
+ POST /readers/:readerId/test
235
+ POST /readers/:readerId/sync
236
+ GET /readers/:readerId/door-state
237
+ POST /readers/:readerId/actions
238
+ POST /readers/:readerId/objects
239
+ GET /readers/:readerId/logs
240
+ ```
241
+
242
+ Identity mapping:
243
+
244
+ ```text
245
+ GET /readers/:readerId/identities
246
+ POST /readers/:readerId/identities
247
+ PATCH /identities/:identityId
248
+ DELETE /identities/:identityId
249
+ ```
250
+
251
+ Reader callback:
252
+
253
+ ```text
254
+ POST /notifications/:readerId/:type
255
+ ```
256
+
257
+ The notification endpoint is unauthenticated because the HID reader must be able to call it directly.
258
+
259
+ ## HID HTTP API Mapping
260
+
261
+ The service wraps these HID endpoints:
262
+
263
+ ```text
264
+ /hidlogin.fcgi
265
+ /session_is_valid.fcgi
266
+ /logout.fcgi
267
+ /create_objects.fcgi
268
+ /load_objects.fcgi
269
+ /modify_objects.fcgi
270
+ /destroy_objects.fcgi
271
+ /door_state.fcgi
272
+ /execute_actions.fcgi
273
+ ```
274
+
275
+ Observed working operations against the Philippines reader:
276
+
277
+ ```text
278
+ hidlogin.fcgi
279
+ session_is_valid.fcgi
280
+ load_objects.fcgi
281
+ logout.fcgi
282
+ ```
283
+
284
+ Known working object names:
285
+
286
+ ```text
287
+ users
288
+ access_logs
289
+ ```
290
+
291
+ Observed unsupported endpoint:
292
+
293
+ ```text
294
+ door_state.fcgi
295
+ ```
296
+
297
+ The tested reader returned:
298
+
299
+ ```json
300
+ {
301
+ "error": "Invalid command: door_state",
302
+ "code": 1
303
+ }
304
+ ```
305
+
306
+ Keep door/relay features optional in product UI.
307
+
308
+ ## Generic Object Operation
309
+
310
+ Backend endpoint:
311
+
312
+ ```text
313
+ POST /api/access-management/hid/readers/:readerId/objects
314
+ ```
315
+
316
+ Load users:
317
+
318
+ ```json
319
+ {
320
+ "operation": "load",
321
+ "object": "users",
322
+ "limit": 50,
323
+ "offset": 0
324
+ }
325
+ ```
326
+
327
+ Load access logs:
328
+
329
+ ```json
330
+ {
331
+ "operation": "load",
332
+ "object": "access_logs",
333
+ "limit": 50,
334
+ "offset": 0
335
+ }
336
+ ```
337
+
338
+ Filter access logs by HID user id:
339
+
340
+ ```json
341
+ {
342
+ "operation": "load",
343
+ "object": "access_logs",
344
+ "where": {
345
+ "access_logs": {
346
+ "user_id": 3
347
+ }
348
+ },
349
+ "limit": 20,
350
+ "offset": 0
351
+ }
352
+ ```
353
+
354
+ Important: for HID object operations, use a nested `where` object keyed by the table/object name when the reader requires it.
355
+
356
+ Create objects:
357
+
358
+ ```json
359
+ {
360
+ "operation": "create",
361
+ "object": "users",
362
+ "values": [
363
+ {
364
+ "name": "Example User"
365
+ }
366
+ ]
367
+ }
368
+ ```
369
+
370
+ Validation:
371
+
372
+ - `create` and `modify` require `values`.
373
+ - `destroy` requires `where`.
374
+ - `load` can be called without `where`.
375
+
376
+ ## Access Log Timestamp
377
+
378
+ HID `access_logs.time` is Unix time in seconds.
379
+
380
+ Example:
381
+
382
+ ```json
383
+ {
384
+ "user_id": 3,
385
+ "time": 1780561438
386
+ }
387
+ ```
388
+
389
+ This is:
390
+
391
+ ```text
392
+ 2026-06-04 16:23:58 Asia/Manila
393
+ ```
394
+
395
+ For Philippines sites, display times in `Asia/Manila`.
396
+
397
+ ## Identity Mapping Flow
398
+
399
+ 1. Pull HID users from the reader:
400
+
401
+ ```text
402
+ POST /readers/:readerId/objects
403
+ object = users
404
+ ```
405
+
406
+ 2. Create a mapping in iService365:
407
+
408
+ ```text
409
+ POST /readers/:readerId/identities
410
+ ```
411
+
412
+ 3. Pull access logs or receive callbacks.
413
+
414
+ 4. Backend attempts to match the event using:
415
+
416
+ ```text
417
+ hidUserId
418
+ registration
419
+ cardNo
420
+ ```
421
+
422
+ 5. If matched, the saved event payload includes the mapped iService365 identity.
423
+
424
+ 6. If not matched, the event is still saved with `identity: null` and `identityLookup`.
425
+
426
+ ## Callback / Monitor Flow
427
+
428
+ Callback endpoint:
429
+
430
+ ```text
431
+ POST /api/access-management/hid/notifications/:readerId/:type
432
+ ```
433
+
434
+ The reader must be able to reach the backend URL. `localhost` cannot work from the HID reader unless the reader is running on the same machine, which it is not.
435
+
436
+ For deployed backend:
437
+
438
+ ```text
439
+ https://<api-domain>/api/access-management/hid/notifications/:readerId/:type
440
+ ```
441
+
442
+ For private site network testing:
443
+
444
+ - Use VPN or subnet routing, such as Tailscale.
445
+ - Ensure the reader can reach the backend host and port.
446
+
447
+ Callback and pull logs are separate modes:
448
+
449
+ - Callback: HID pushes events to backend.
450
+ - Pull logs: backend calls `load_objects.fcgi` to read `access_logs`.
451
+
452
+ Support both because real deployment networks may differ by site.
453
+
454
+ ## Network Notes
455
+
456
+ The Philippines reader observed during testing:
457
+
458
+ ```text
459
+ IP: 192.168.20.123
460
+ Netmask: 255.255.255.0
461
+ Gateway: 192.168.20.1
462
+ Web Port: 80
463
+ ```
464
+
465
+ Remote access from Vietnam requires routing into the Philippines LAN, for example:
466
+
467
+ - Tailscale subnet route `192.168.20.0/24`
468
+ - Site VPN
469
+ - A deployed backend that has network access to the reader
470
+
471
+ ## Security Notes
472
+
473
+ - Do not log reader passwords.
474
+ - Do not return reader passwords in API responses.
475
+ - HID request errors redact the `session` query value.
476
+ - Use a stable `HID_AMICO_SECRET` in production; changing it will make existing encrypted reader passwords undecryptable.
477
+ - Callback endpoint is unauthenticated by design, so it should be treated as an ingestion endpoint and validated by `readerId`, network rules, and deployment controls.
478
+
479
+ ## Verification
480
+
481
+ Current local verification command:
482
+
483
+ ```bash
484
+ D:\HRM\iservice365-core\node_modules\.bin\tsc.cmd
485
+ ```
486
+
487
+ Status:
488
+
489
+ ```text
490
+ PASS
491
+ ```