@7365admin1/core 3.77.1-staging.333 → 3.79.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 +43 -0
- package/dist/index.d.ts +53 -267
- package/dist/index.js +555 -1993
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +555 -1988
- package/dist/index.mjs.map +1 -1
- package/package.json +68 -68
- package/test/guard-invite-wiring.test.mjs +0 -48
- package/test/notification-category.util.test.mjs +0 -21
- package/.changeset/cctv-live-view-signed.md +0 -12
- package/.changeset/cctv-recorded-footage.md +0 -5
- package/.changeset/client-invite-owner-role-permissions.md +0 -5
- package/.changeset/client-invite-service365.md +0 -5
- package/.changeset/customer-sites-one-row-per-site.md +0 -19
- package/.changeset/daily-occurrence-book-startup.md +0 -36
- package/.changeset/hid-duplicate-enrollment.md +0 -22
- package/.changeset/hid-facial-error-wording.md +0 -20
- package/.changeset/hid-identity-user-link.md +0 -26
- package/.changeset/hid-objectid-across-driver-copies.md +0 -26
- package/.changeset/hid-profile-qr-backend.md +0 -31
- package/.changeset/hid-reader-user-search.md +0 -22
- package/.changeset/inventory-notification-category.md +0 -5
- package/.changeset/manpower-authenticated-namespace.md +0 -27
- package/.changeset/member-direct-role-org.md +0 -5
- package/.changeset/member-direct-self-enrol-role.md +0 -5
- package/.changeset/member-list-site-scope.md +0 -5
- package/.changeset/member-lookup-follows-site.md +0 -16
- package/.changeset/members-by-user-reach.md +0 -5
- package/.changeset/module-ceiling-site-owner.md +0 -5
- package/.changeset/module-gate-foundation.md +0 -20
- package/.changeset/module-gate-kill-switch-and-read.md +0 -26
- package/.changeset/module-gate-server.md +0 -35
- package/.changeset/notify-access-filter-on.md +0 -24
- package/.changeset/org-owner-membership-repair.md +0 -15
- package/.changeset/org-read-reach.md +0 -5
- package/.changeset/org-update-diagnosable-error.md +0 -14
- package/.changeset/patrol-email-scope-restore.md +0 -16
- package/.changeset/people-create-reach-enforce.md +0 -5
- package/.changeset/people-create-reach-gate.md +0 -31
- package/.changeset/people-occupied-structure.md +0 -5
- package/.changeset/real-estate-developer-app-type.md +0 -5
- package/.changeset/real-estate-developer-lookup-both-types.md +0 -5
- package/.changeset/resident-app-module-ceiling.md +0 -18
- package/.changeset/role-module-ceiling.md +0 -16
- package/.changeset/role-read-self-arm.md +0 -5
- package/.changeset/role-v2-platform-grant.md +0 -14
- package/.changeset/site-module-allowlist.md +0 -5
- package/.changeset/site-modules-client-admin.md +0 -5
- package/.changeset/site-save-resident-ceiling.md +0 -7
- package/.changeset/staff-platform-notifications.md +0 -5
- package/.changeset/user-email-allowlist-subscription-authz.md +0 -21
- package/.changeset/user-field-self-allowlist.md +0 -5
- package/.changeset/user-invite-dedupe.md +0 -5
- package/scripts/hid-backfill-enrolment-access.mjs +0 -198
- package/test/document-expiry-event.test.mjs +0 -146
- package/test/document-expiry-filter.test.mjs +0 -167
- package/test/document-expiry-reminder.test.mjs +0 -161
- package/test/document-type-resolution.test.mjs +0 -62
- package/test/e2e/document-expiry-event-link.e2e.test.mjs +0 -323
- package/test/hid-enrolment-grants-access.test.mjs +0 -162
- package/test/occupancy-tree.test.mjs +0 -128
- package/test/resident-login-account.test.mjs +0 -126
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @iservice365/core
|
|
2
2
|
|
|
3
|
+
## 3.79.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4592408: Seven365 staff notifications: tell the platform's own super-admin accounts when a client organisation is created and when an invited client owner accepts. Adds a staff-only "Seven365 platform" notification category (hidden from client roles, including wildcard ones), a `platform` notification module, and `listStaffUserIds()`.
|
|
8
|
+
|
|
9
|
+
## 3.78.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 06ce99b: Create the daily occurrence book on server startup as well as at midnight, and skip a site that already has today's book
|
|
14
|
+
|
|
15
|
+
`processCreateDOB` was reachable only from the `0 0 * * *` cron API-core registers. A cron pattern
|
|
16
|
+
does not fire when it is registered, so a server that was down, redeployed, or running outside
|
|
17
|
+
production at midnight skipped that day and nothing ever went back for it - one site's book list
|
|
18
|
+
stopped at 17/07/2026 while its guards kept logging entries.
|
|
19
|
+
|
|
20
|
+
The job is now idempotent by the Singapore day: it reads the site ids that already have a book dated
|
|
21
|
+
inside today's window (`getSiteIdsWithBookInWindow`) and inserts only for the rest, returning
|
|
22
|
+
`{ created, skipped, message }`. The unique `{ site, date }` index cannot stand in for that check,
|
|
23
|
+
because the stored `date` carries the hour of the run, so 00:00 and a 09:15 restart are two different
|
|
24
|
+
keys. The book counter is consumed only when there is something to insert. API-core can therefore
|
|
25
|
+
call it on boot as well as on the cron.
|
|
26
|
+
|
|
27
|
+
`closeOccurrenceBooks` no longer throws when nothing is due to be closed - the normal case on a quiet
|
|
28
|
+
night, and now on every restart - and logs instead.
|
|
29
|
+
|
|
30
|
+
Every run now logs its outcome from inside the service - created how many and skipped how many, or nothing to create, and how many books were closed - so the midnight cron reports the same way the startup pass does. Silence used to be the only evidence either way.
|
|
31
|
+
|
|
32
|
+
The book number is now PER SITE. It came from one global `occurrence-book` counter row bumped once per run, which held only while every site got a book on the same night: a site added mid-day, or one that later stops taking daily occurrence books, would have its next number jump by however many days it missed. `getHighestEntryCounterBySite` reads each site's own high-water mark (deleted books included, so an issued number is never handed out twice) and `nextEntryCounter` adds one, so a site with no books starts at No. 1. Existing sites are unaffected: their highest number today is the same value the shared counter last wrote, so the sequence continues where it left off. Manual creation through `POST /occurrence-books` is numbered the same way, and the counter row no longer decides any number.
|
|
33
|
+
|
|
34
|
+
A new book's `date` is now Singapore midnight of the day it is for, not the instant the run happened, so every run of a day writes the same `{ site, date }` key and the unique index can refuse a second book. While `date` carried the hour, the 00:00 cron wrote 16:00Z and a 09:04 restart wrote 01:00Z - two different keys - and staging ended up with two books dated 21/09/2026. `closedAt` follows the same midnight, so a book created by a restart no longer closes hours later than the same day's cron book would have. A duplicate-key refusal is reported and logged rather than thrown, since it means another instance created today's book between this run's check and its write.
|
|
35
|
+
|
|
36
|
+
Every book now carries `day`, its calendar day as `YYYY-MM-DD`, and "one book per site per day" is enforced by a unique partial index `unique_site_day` on `{ site, day }` rather than by each caller. `ensureOneBookPerSiteDay`, run by API-core as the server starts and in each timezone's midnight job, backfills `day` onto any book without one, deletes same-day duplicates that are provably empty (no entries, `totalInput` 0 - deleted rather than soft-deleted because the book list does not filter `deletedAt`; the book holding entries is always kept, and a group where more than one book holds entries is reported and left alone), and builds the index. A book written by an out-of-date server has no `day`; setting it collides with the index, and that collision is caught and settled as a duplicate, so such a book is gone by the next midnight job or restart. No collection validator is used: it would need the `collMod` privilege, which the application user does not hold. A duplicate refusal (11000) in the cron or start-up path is logged, not thrown; a manual `POST /occurrence-books` for a day that already has a book answers 400 with the day named. The integrity run logs at info only when it changed something, and at warn when something needs a person.
|
|
37
|
+
|
|
38
|
+
A book now belongs to its SITE's local day. `siteBookDay` reads `sites.timezone` (Singapore when a site has none or an invalid one - every site today, so nothing moves until a site is given another zone) and gives the site-local `day`, local midnight as `date`, and `closedAt` 72 hours later, all from an absolute instant and an explicit zone, so the result does not depend on where the server runs or what its clock zone is. `getAllSitesUnpaginated` now also returns `timezone`. `processCreateDOB` groups sites by zone - one existence query per zone - and creates only for sites whose own day has started; `getBookTimezones` returns the zones the sites actually use (`bookTimezones` over a `distinct` of `sites.timezone`; Singapore for sites with none, so today it is just `Asia/Singapore`), and API-core schedules one `0 0 * * *` job per zone, in that zone, instead of a single 00:00 that is midnight for one zone only. A run that creates or closes nothing logs at debug and no longer flushes the occurrence-book cache. The close cut-off is 72 hours of plain milliseconds rather than `setDate(getDate() - 3)`, which followed the server's local calendar. Books written before this change are backfilled with their Singapore day, the schedule they were created on.
|
|
39
|
+
|
|
40
|
+
A newly created site gets today's book immediately instead of waiting for its next local midnight or a restart. The three site-creation paths (`site`, `customer` and `customer-site` services) call `startTodaysBookForSite` right after their transaction commits, so a rolled-back site never gets an orphan book. It is fire-and-forget and never throws, not even synchronously, so a book problem can never make an already-committed site look like it failed. It runs through `processCreateDOB({ siteIds })`, so the book gets the site's own timezone, day and No. 1, with the same duplicate protection as the midnight job.
|
|
41
|
+
|
|
42
|
+
`startTodaysBookForSite` is also called after a site's timezone is edited (`PUT /api/sites/:id` with `timezone`), and it tells API-core the set of timezones may have changed through `onBookTimezonesChanged`, a listener API-core registers at start-up. So a zone no site used before gets its midnight job without any polling, and a site moved into a zone whose day has already begun gets that day's book. A server that misses the call re-reads the timezones on its next restart.
|
|
43
|
+
|
|
44
|
+
A site's timezone can now be set from the Add / Edit Site form, which saves through `/api/customer-sites`. `TCustomerSite` and `schemaCustomerSite` accept `timezone` (validated as an IANA zone); it is passed through to `sites.timezone` on create and on update and never stored on the customer-site row. On update an unknown zone is refused with 400, and a CHANGED zone calls `startTodaysBookForSite` after the commit, so a new zone gets its midnight job and the site gets a book for its new day if that day has begun. The customer-sites list now returns each row's live `timezone` from its site, so the form opens on the zone the site actually has.
|
|
45
|
+
|
|
3
46
|
## 3.77.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|