@7365admin1/core 3.8.0 → 3.10.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.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +391 -11
- package/dist/index.js +2248 -516
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2226 -516
- package/dist/index.mjs.map +1 -1
- package/docs/hid-amico-diagram.md +201 -0
- package/docs/hid-amico-integration.md +491 -0
- package/docs/hid-amico-postman-api.md +614 -0
- package/docs/hid-amico-ui-design-scope.md +441 -0
- package/package.json +1 -1
|
@@ -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
|
+
```
|