@7365admin1/core 3.52.7-staging.255 → 3.52.8
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
CHANGED
|
@@ -1,5 +1,101 @@
|
|
|
1
1
|
# @iservice365/core
|
|
2
2
|
|
|
3
|
+
## 3.52.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8ef43c8: Scope `GET /api/customer-sites` to the sites the caller may actually reach
|
|
8
|
+
|
|
9
|
+
The endpoint authorised the caller at ORGANISATION level (`requireOrgAccess`)
|
|
10
|
+
and then returned every site that organisation has. One call fills the site
|
|
11
|
+
switcher in all seven vertical web apps' layouts, the MA and iSecure365 site
|
|
12
|
+
pickers and the resident app, so a user invited to a SINGLE site opened the
|
|
13
|
+
switcher and read the client's entire estate by name.
|
|
14
|
+
|
|
15
|
+
The list now applies the same rule the access side already applies
|
|
16
|
+
(`cameraGrant`, owner decision 2026-08-10), expressed as `orgSiteScope`: a
|
|
17
|
+
membership carrying no site is an org-wide role and keeps the whole list, and a
|
|
18
|
+
membership pinned to a site is offered that site alone. Seven365 staff are
|
|
19
|
+
answered before the question is asked, so the client console's
|
|
20
|
+
cross-organisation reads are unchanged.
|
|
21
|
+
|
|
22
|
+
The restriction is applied inside the query and is part of the cache key, so
|
|
23
|
+
paging counts describe what the caller can see and one caller's page is never
|
|
24
|
+
served to another.
|
|
25
|
+
|
|
26
|
+
Org-level roles are exempt from the narrowing. Owner decision, 2026-09-02: "Org
|
|
27
|
+
-level roles see all sites." A membership whose ROLE is organisation-level — the
|
|
28
|
+
`roles` document carries no `site` of its own — keeps the whole estate EVEN IF
|
|
29
|
+
the membership row also names a site, because that stray `siteId` is a data
|
|
30
|
+
artefact and not a demotion. On staging that is the difference between narrowing
|
|
31
|
+
204 and narrowing 109 `(user, org)` pairs: 95 pairs, overwhelmingly `Org Owner`,
|
|
32
|
+
sit on an org-level role attached to a site row. An unresolvable or soft-deleted
|
|
33
|
+
role is treated as site-level, so the exemption fails closed.
|
|
34
|
+
|
|
35
|
+
- 8ef43c8: Revoke each expired vehicle's plate only from its own site's cameras, and fail closed
|
|
36
|
+
|
|
37
|
+
The hourly expired-vehicle sweep declared its `siteCameras` array outside the
|
|
38
|
+
per-vehicle loop and only ever pushed to it, so the list grew as the run went
|
|
39
|
+
on: the second vehicle was revoked from its own site's cameras AND from the
|
|
40
|
+
first vehicle's. `recNo` is a per-device sequence number, so those extra calls
|
|
41
|
+
did not simply miss - they addressed whatever record carried that number on the
|
|
42
|
+
other site's camera and took an unrelated, still-valid plate off the barrier.
|
|
43
|
+
Cameras are now resolved per vehicle, cached by site id so each site is still
|
|
44
|
+
paged only once per run.
|
|
45
|
+
|
|
46
|
+
The sweep also marked every expired vehicle deleted with one blanket
|
|
47
|
+
`updateMany`, regardless of what the cameras answered, so a record could read
|
|
48
|
+
"deleted" while its plate still opened the gate. Only vehicles whose every
|
|
49
|
+
camera confirmed are now marked deleted; the rest are left expired, logged at
|
|
50
|
+
error level naming the vehicle, plate, site and camera, and retried on the next
|
|
51
|
+
hourly run. `deleteExpiredVehicles` now requires the list of ids.
|
|
52
|
+
|
|
53
|
+
Also: each camera is asked for its own record id before the removal (the same
|
|
54
|
+
thing manual delete does), the ANPR list is chosen from the vehicle's type
|
|
55
|
+
instead of always TRAFFIC_REDLIST, a site with no ANPR camera no longer aborts
|
|
56
|
+
the whole run, and the transaction that wrapped nothing - the only write was
|
|
57
|
+
issued without the session - has been removed.
|
|
58
|
+
|
|
59
|
+
- 8ef43c8: Fail closed in the visitor ANPR sweep, and remove the dead invitation transaction
|
|
60
|
+
|
|
61
|
+
`processTransactionDahuaStatus`, the hourly job that takes an expired or
|
|
62
|
+
checked-out visitor's plate off the site's ANPR camera, marked the transaction
|
|
63
|
+
`dahuaSyncStatus: "removed"` on the line after the camera call and only skipped
|
|
64
|
+
on a thrown error. `removePlateNumber` does not throw for a device failure - it
|
|
65
|
+
returns an outcome object - so a camera answering 401 or 500, or not answering
|
|
66
|
+
at all, still had the transaction recorded as removed while the visitor's plate
|
|
67
|
+
was still on the barrier. Nothing retried it either, because the query that
|
|
68
|
+
feeds the sweep skips anything already marked removed.
|
|
69
|
+
|
|
70
|
+
It now uses the same decision logic as the expired-vehicle sweep: only a
|
|
71
|
+
transaction every camera confirmed is marked removed, and the rest are logged at
|
|
72
|
+
error level naming the plate, the site and the camera, then retried on the next
|
|
73
|
+
run. Each camera is also asked for its own record id before the removal, which
|
|
74
|
+
is what the old "not found" message sniff was reaching for and what stops a
|
|
75
|
+
transaction whose record is already gone from being retried for ever.
|
|
76
|
+
|
|
77
|
+
`checkExpiredInvitation` opened a session and a transaction and then issued
|
|
78
|
+
every write without that session, never committing: the transaction protected no
|
|
79
|
+
write and the rollback rolled back nothing. Each invitation is independent, so
|
|
80
|
+
there is no invariant spanning them and nothing for a transaction to protect -
|
|
81
|
+
it is removed rather than wired up.
|
|
82
|
+
|
|
83
|
+
## 3.52.7
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- 4d8be2a: Scope the NFC patrol tag, route and settings endpoints to the caller's own estate.
|
|
88
|
+
|
|
89
|
+
`/api/nfc-patrol-tag`, `/api/nfc-patrol-route` and `/api/nfc-patrol-settings`
|
|
90
|
+
carried `requireAuth` and nothing more, and their three controllers held no
|
|
91
|
+
authorization identifier of any kind, so any signed-in account on the platform
|
|
92
|
+
could read and CHANGE another client's checkpoint register, patrol rounds and
|
|
93
|
+
patrol settings. They now ask the same `requireSiteReach` -> `entitleSite`
|
|
94
|
+
question the already-scoped `/api/nfc-patrol-log` and the rest of the
|
|
95
|
+
site-scoped modules ask, and answer `404 Site not found.` The five `/public`
|
|
96
|
+
mounts, which are reached without a credential while `ENFORCE_NFC_PUBLIC_AUTH`
|
|
97
|
+
is off, are unchanged.
|
|
98
|
+
|
|
3
99
|
## 3.52.6
|
|
4
100
|
|
|
5
101
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/core": patch
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Scope `GET /api/customer-sites` to the sites the caller may actually reach
|
|
6
|
-
|
|
7
|
-
The endpoint authorised the caller at ORGANISATION level (`requireOrgAccess`)
|
|
8
|
-
and then returned every site that organisation has. One call fills the site
|
|
9
|
-
switcher in all seven vertical web apps' layouts, the MA and iSecure365 site
|
|
10
|
-
pickers and the resident app, so a user invited to a SINGLE site opened the
|
|
11
|
-
switcher and read the client's entire estate by name.
|
|
12
|
-
|
|
13
|
-
The list now applies the same rule the access side already applies
|
|
14
|
-
(`cameraGrant`, owner decision 2026-08-10), expressed as `orgSiteScope`: a
|
|
15
|
-
membership carrying no site is an org-wide role and keeps the whole list, and a
|
|
16
|
-
membership pinned to a site is offered that site alone. Seven365 staff are
|
|
17
|
-
answered before the question is asked, so the client console's
|
|
18
|
-
cross-organisation reads are unchanged.
|
|
19
|
-
|
|
20
|
-
The restriction is applied inside the query and is part of the cache key, so
|
|
21
|
-
paging counts describe what the caller can see and one caller's page is never
|
|
22
|
-
served to another.
|
|
23
|
-
|
|
24
|
-
Org-level roles are exempt from the narrowing. Owner decision, 2026-09-02: "Org
|
|
25
|
-
-level roles see all sites." A membership whose ROLE is organisation-level — the
|
|
26
|
-
`roles` document carries no `site` of its own — keeps the whole estate EVEN IF
|
|
27
|
-
the membership row also names a site, because that stray `siteId` is a data
|
|
28
|
-
artefact and not a demotion. On staging that is the difference between narrowing
|
|
29
|
-
204 and narrowing 109 `(user, org)` pairs: 95 pairs, overwhelmingly `Org Owner`,
|
|
30
|
-
sit on an org-level role attached to a site row. An unresolvable or soft-deleted
|
|
31
|
-
role is treated as site-level, so the exemption fails closed.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/core": patch
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Revoke each expired vehicle's plate only from its own site's cameras, and fail closed
|
|
6
|
-
|
|
7
|
-
The hourly expired-vehicle sweep declared its `siteCameras` array outside the
|
|
8
|
-
per-vehicle loop and only ever pushed to it, so the list grew as the run went
|
|
9
|
-
on: the second vehicle was revoked from its own site's cameras AND from the
|
|
10
|
-
first vehicle's. `recNo` is a per-device sequence number, so those extra calls
|
|
11
|
-
did not simply miss - they addressed whatever record carried that number on the
|
|
12
|
-
other site's camera and took an unrelated, still-valid plate off the barrier.
|
|
13
|
-
Cameras are now resolved per vehicle, cached by site id so each site is still
|
|
14
|
-
paged only once per run.
|
|
15
|
-
|
|
16
|
-
The sweep also marked every expired vehicle deleted with one blanket
|
|
17
|
-
`updateMany`, regardless of what the cameras answered, so a record could read
|
|
18
|
-
"deleted" while its plate still opened the gate. Only vehicles whose every
|
|
19
|
-
camera confirmed are now marked deleted; the rest are left expired, logged at
|
|
20
|
-
error level naming the vehicle, plate, site and camera, and retried on the next
|
|
21
|
-
hourly run. `deleteExpiredVehicles` now requires the list of ids.
|
|
22
|
-
|
|
23
|
-
Also: each camera is asked for its own record id before the removal (the same
|
|
24
|
-
thing manual delete does), the ANPR list is chosen from the vehicle's type
|
|
25
|
-
instead of always TRAFFIC_REDLIST, a site with no ANPR camera no longer aborts
|
|
26
|
-
the whole run, and the transaction that wrapped nothing - the only write was
|
|
27
|
-
issued without the session - has been removed.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/core": patch
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Scope the NFC patrol tag, route and settings endpoints to the caller's own estate.
|
|
6
|
-
|
|
7
|
-
`/api/nfc-patrol-tag`, `/api/nfc-patrol-route` and `/api/nfc-patrol-settings`
|
|
8
|
-
carried `requireAuth` and nothing more, and their three controllers held no
|
|
9
|
-
authorization identifier of any kind, so any signed-in account on the platform
|
|
10
|
-
could read and CHANGE another client's checkpoint register, patrol rounds and
|
|
11
|
-
patrol settings. They now ask the same `requireSiteReach` -> `entitleSite`
|
|
12
|
-
question the already-scoped `/api/nfc-patrol-log` and the rest of the
|
|
13
|
-
site-scoped modules ask, and answer `404 Site not found.` The five `/public`
|
|
14
|
-
mounts, which are reached without a credential while `ENFORCE_NFC_PUBLIC_AUTH`
|
|
15
|
-
is off, are unchanged.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
"@7365admin1/core": patch
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
Fail closed in the visitor ANPR sweep, and remove the dead invitation transaction
|
|
6
|
-
|
|
7
|
-
`processTransactionDahuaStatus`, the hourly job that takes an expired or
|
|
8
|
-
checked-out visitor's plate off the site's ANPR camera, marked the transaction
|
|
9
|
-
`dahuaSyncStatus: "removed"` on the line after the camera call and only skipped
|
|
10
|
-
on a thrown error. `removePlateNumber` does not throw for a device failure - it
|
|
11
|
-
returns an outcome object - so a camera answering 401 or 500, or not answering
|
|
12
|
-
at all, still had the transaction recorded as removed while the visitor's plate
|
|
13
|
-
was still on the barrier. Nothing retried it either, because the query that
|
|
14
|
-
feeds the sweep skips anything already marked removed.
|
|
15
|
-
|
|
16
|
-
It now uses the same decision logic as the expired-vehicle sweep: only a
|
|
17
|
-
transaction every camera confirmed is marked removed, and the rest are logged at
|
|
18
|
-
error level naming the plate, the site and the camera, then retried on the next
|
|
19
|
-
run. Each camera is also asked for its own record id before the removal, which
|
|
20
|
-
is what the old "not found" message sniff was reaching for and what stops a
|
|
21
|
-
transaction whose record is already gone from being retried for ever.
|
|
22
|
-
|
|
23
|
-
`checkExpiredInvitation` opened a session and a transaction and then issued
|
|
24
|
-
every write without that session, never committing: the transaction protected no
|
|
25
|
-
write and the rollback rolled back nothing. Each invitation is independent, so
|
|
26
|
-
there is no invariant spanning them and nothing for a transaction to protect -
|
|
27
|
-
it is removed rather than wired up.
|