Commit Graph
100 Commits
Author SHA1 Message Date
Ben WestandGitHub 7e0e77f88f Merge pull request #8444 from nightscout/dev
new dev area for 15.0.7
2026-04-29 13:25:53 -07:00
Ben WestandGitHub 4f0f9b284e Merge pull request #8475 from nightscout/wip/test-improvements
fix(websocket): dedup AAPS profile dbAdd by startDate; warn on insert…
2026-04-20 17:55:37 -07:00
Ben WestandCopilot c927be7a0d Revert "fix(api3): dedup AAPS profile-store edits via REST POST /v3/profile"
This reverts commit 3b786ab3.

On review the V3 (app, defaultProfile) collapse was too aggressive and
broke parity with how the rest of the ecosystem treats the profile
collection:

- Loop (NightscoutKit) and Trio (NightscoutAPI.swift:411) both POST
  /api/v1/profile without _id on every settings edit, accumulating one
  doc per upload via lib/server/profile.js:create(). They have done so
  for years.
- The Nightscout profile collection is historical/append-only by
  design; the NS UI profile editor lets users navigate prior
  snapshots, and lib/server/profile.js:last() picks the most recent
  for display.
- Collapsing AAPS V3 edits onto a single (app, defaultProfile) row
  diverged from Loop/Trio/AAPS-V1 behavior and erased the upload
  history that NS UI exposes.

The original 'AAPS edits not appearing' user complaint is sufficiently
addressed by:
  - the V1 websocket retry dedup (commit 85f7e6ac), which kills the
    60s ack-window race; and
  - the {startDate: -1, _id: -1} secondary sort in profile.last()
    (also 85f7e6ac), which deterministically picks the newest row
    when startDate ties.

Both of those help every uploader (Loop, Trio, AAPS V1, AAPS V3)
without changing the ecosystem-wide profile-as-history semantic. The
characterization tests added in ddabdc6c are restored by this revert
and continue to document V3's request-level (date-based) dedup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 17:49:43 -07:00
Ben WestandCopilot 3b786ab3c0 fix(api3): dedup AAPS profile-store edits via REST POST /v3/profile
Profile-store documents are singleton-per-(app, defaultProfile) by design:
each source (e.g. AAPS) has one current profile snapshot at a time. The
prior identifier scheme (uuidv5 of "undefined_<doc.date>") created a new
identifier on every edit because AAPS sends a new `date`
(LocalProfileLastChange) per save, accumulating duplicate profile docs in
MongoDB and causing 'AAPS profile edits not appearing' user reports.

Changes:
- operationTools.calculateIdentifier: special-case profile-store shape
  (has `defaultProfile` + `store`, no `eventType`) -> identifier =
  uuidv5("profilestore_<app>_<defaultProfile>"), so re-sends and edits
  collapse onto the same row.
- update/validate: relax immutability of `date`, `created_at`,
  `startDate` during deduplication when the storage doc is a
  profile-store, since those fields are expected to advance per edit.
- api3.aaps-patterns tests updated to assert post-fix behavior:
  edits return 200 + same identifier + single doc; distinct
  defaultProfile names still produce distinct docs.

This complements the V1 (websocket) profile dedup fix in 85f7e6ac so
both AAPS sync paths now converge on a single profile document per
source.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 12:25:00 -07:00
Ben WestandCopilot ddabdc6ca7 test(api3): characterize V3 profile dedup behavior with AAPS-shaped payloads
V3 POST /api/v3/profile uses uuid.v5("undefined_<doc.date>") as the
identifier (no device, no eventType in profile docs), so:
- Identical resends (retry) dedup in place (200) — request-level dedup works
- AAPS edits with a new LocalProfileLastChange produce a new identifier and
  insert a new doc (201) — edit-level dedup does not exist

This characterizes the V3 behavior alongside the V1 websocket fix in the
prior commit. Both V1 (post-fix) and V3 rely on profile.last() with
{startDate: -1, _id: -1} for deterministic ordering.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 12:20:59 -07:00
Ben WestandCopilot 85f7e6ac7c fix(websocket): dedup AAPS profile dbAdd by startDate; warn on insert errors
AAPS V1 NSClient sync only ever calls nsAdd("profile", ...) — there is no
nsUpdate path for profiles (DataSyncSelectorV1.processChangedProfileStore).
Every profile edit reaches the server's websocket dbAdd handler.

Previously the dbAdd handler had no dedup branch for the 'profile' collection
and fell through to the generic else, which called insertOne() unconditionally
and then silently swallowed any insertion error via console.log + return [].
Result: each AAPS edit either created a duplicate profile document or failed
silently if the source JSONObject still carried an _id (E11000 dup key), so
users perceived their profile updates as not taking effect.

Changes:
- websocket.js: add a profile dedup branch — match on NSCLIENT_ID if present,
  otherwise on startDate, and replaceOne in place rather than insertOne.
  Returns the existing _id so the AAPS ack worker sees a stable identifier.
- websocket.js: upgrade the silent 'insertion error' console.log to
  console.warn for both the profile branch and the generic fallback so
  MongoDB write failures are visible in server logs.
- profile.js: add _id as a secondary sort key in last() so duplicate
  startDate values resolve deterministically (newest insert wins) for any
  legacy duplicates already present.
- tests/websocket.shape-handling.test.js: regression coverage for the
  AAPS-shaped profile flow — first insert, repeated dbAdd with same
  startDate (expect replace, not duplicate), and distinct startDate
  (expect insert + last() returns newest).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 11:52:12 -07:00
Ben WestandGitHub b8d5c02d52 Merge pull request #8474 from nightscout/fix/mongo-save-hardening
Fix/mongo save hardening
2026-04-19 17:14:40 -07:00
Ben WestandGitHub e807e1a6b6 Merge pull request #8473 from nightscout/wip/test-improvements
Wip/test improvements
2026-04-19 12:47:59 -07:00
Ben WestandCopilot e35e7104bb fix(api3): restore /test endpoint for both development and test environments
PR #8465 replaced 'development' with 'test' instead of adding it,
breaking the /test endpoint when NODE_ENV=development.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-19 12:35:32 -07:00
Ben WestandGitHub d7412acaf2 Merge branch 'dev' into wip/test-improvements 2026-04-19 12:32:27 -07:00
Ben WestandGitHub 6dc8d4b7b7 Merge pull request #8465 from bniels707/apiv3_security_test_preflight_fix
Fix 404 errors when running tests with NODE_ENV=test
2026-04-19 12:32:07 -07:00
Ben WestandGitHub de0bf65ed8 Merge branch 'dev' into wip/test-improvements 2026-04-19 12:27:24 -07:00
Ben WestandCopilot 3b701222e2 fix: production safety allows testing when entries within threshold (#8464)
The DB name check now only blocks when entries EXCEED the threshold.
If the database has fewer entries than the threshold (default 100),
it's treated as safe to test regardless of DB name — the name check
becomes a warning suggesting you rename for best practice.

Logic: entry count is the primary safety signal. DB name is secondary.
Both must fail to block. Entry count alone blocks. Name alone warns.

Changes:
- Entry count checked first to determine safety baseline
- DB name check downgrades to warning when entries within threshold
- Contextual override hints (only show relevant suggestions)
- Clarify CUSTOMCONNSTR_mongo vs CUSTOMCONNSTR_mongo_collection

Tests (5 new):
- 0 entries + non-test name → passes with warning
- 50 entries (below threshold) + non-test name → passes with warning
- Entries above threshold + non-test name → blocks (both errors)
- Entries above threshold alone → blocks with 'real data' message
- Non-test name hint mentions correct env var

Fixes nightscout/cgm-remote-monitor#8464

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-19 12:13:48 -07:00
Ben WestandGitHub 6b59dfc5a6 Merge pull request #8463 from nightscout/wip/test-improvements
Wip/test improvements
2026-03-25 15:32:31 -07:00
Ben WestandCopilot 246e46adb3 fix: legacy UUID treatments findable via $or fallback (#6923)
updateIdQuery() and upsertQueryFor() now use
  {$or: [{identifier: UUID}, {_id: UUID}]}
instead of only {identifier: UUID}. This matches both:
- New documents (UUID in identifier field, ObjectId in _id)
- Legacy documents (UUID directly in _id, no identifier field)

Gated behind env.uuidHandling (UUID_HANDLING env var, default true).

All 30 treatment tests pass:
- 3 legacy UUID tests (issue-6923): DELETE, PUT, GET all work
- 12 gap-treat-012 tests: new data paths unaffected
- 15 uuid-handling tests: edge cases, UUID_HANDLING=false still works

Fixes #6923 (unable to edit/save/delete overrides for legacy data)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 15:20:51 -07:00
Ben WestandCopilot 98ee2bcb3e fix: restore debounce with concurrency guard for data-received events
Strategy C: leading-edge debounce + concurrency guard.

- First data-received fires dataloader immediately (zero delay)
- Rapid events (AAPS batch upload) coalesced by 1s debounce
- Concurrency guard prevents overlapping dataloader.update() on shared ddata
- maxWait: 5s ensures data appears within 5s under sustained load
- Pending flag guarantees one final re-run after burst completes

Without this, N uploads → N concurrent dataloader runs → N×9 MongoDB
queries racing on the same ddata object. With it: N uploads → 2-3 runs.

9 tests confirm: leading-edge, coalescing (50 events → 2 runs),
no overlapping runs, trailing edge, maxWait guarantee.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 14:21:30 -07:00
Ben WestandCopilot f4e686c1fb fix: cache filterForAge rejects ObjectId _id on MongoDB driver 5.x
_.isEmpty(new ObjectId()) returns true on driver 5.x because ObjectId
no longer has enumerable own properties (Object.keys returns []).
This caused filterForAge() to silently drop all entries with ObjectId
_id from the server cache.

check. This correctly accepts ObjectId instances and strings while
still rejecting null, undefined, and empty string.

16 tests confirm the fix:
- 3 root cause tests (_.isEmpty regression)
- 7 filterForAge logic tests (old vs fixed behavior)
- 6 integration tests (actual cache.js with data-update events)

Fixes AAPS backfill display bug where entries were in MongoDB but
invisible on the chart when using API V3 (mongoCachedCollection
emits data-update with raw ObjectId _id).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 14:05:28 -07:00
Ben WestandCopilot 95b4c5e277 test: confirm _.isEmpty(ObjectId) cache regression on driver 5.x
MongoDB driver 5.x ObjectId has no enumerable properties, so
_.isEmpty(new ObjectId()) returns true. This breaks cache.js

7 tests confirm:
- _.isEmpty(ObjectId) returns true (regression)
- filterForAge rejects ObjectId _id documents
- processRawDataForRuntime mitigates by converting to string
- Proposed fix (_id != null) works correctly

Currently mitigated in V1 paths by processRawDataForRuntime, but
unmitigated in API V3 mongoCachedCollection path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 13:30:58 -07:00
Ben WestandCopilot b8523430db test: add regression test proving #6923 legacy UUID data bug
Inserts a treatment directly into MongoDB with UUID as _id (no identifier
field) — the shape of overrides created before normalizeTreatmentId(). All 3
tests fail as expected:

- DELETE: responds 200 but deletedCount=0 (silent no-op)
- PUT: creates duplicate document instead of updating in place
- GET: returns 0 results (query rewrite misses legacy doc)

These tests document the legacy data gap and will pass once updateIdQuery()
is updated to use a $or fallback: {identifier: UUID} || {_id: UUID}.

Relates to: #6923, #8450

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-19 17:31:31 -07:00
Ben WestandGitHub 8cf4a1a041 Merge pull request #8460 from nightscout/wip/test-improvements
Wip/test improvements
2026-03-18 20:03:19 -07:00
Ben WestandGitHub c00fd37628 Merge branch 'dev' into wip/test-improvements 2026-03-18 20:00:56 -07:00
Ben WestandCopilot e46e8532d3 docs: improve production safety check messaging
- Change 'FAILED' to 'ACTIVATED' - this is protective, not a failure
- Explain that tests WILL DELETE data in the database
- Explain the purpose: preventing accidental production data loss
- List all override options clearly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 19:57:40 -07:00
Ben WestandCopilot b1ffeeeacf fix: use ctx.store.db for entry count check
The ctx.entries module isn't always available depending on boot context.
Access the entries collection directly via ctx.store.db.collection().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 19:54:40 -07:00
Ben WestandCopilot 6a681509f3 feat: add database-level production safety checks (GAP-SYNC-047)
Adds multi-layer protection against running destructive tests on production:

1. Pre-flight check (hooks.js): Verifies NODE_ENV=test before any DB connection
2. Database name check: Requires 'test' substring in database name
3. Entry count threshold: Refuses if database has >100 entries (configurable)

Environment Variables:
- TEST_SAFETY_MAX_ENTRIES: Max entries before refusing (default: 100)
- TEST_SAFETY_REQUIRE_TEST_DB: Require 'test' in DB name (default: true)
- TEST_SAFETY_SKIP: Emergency bypass for all checks (default: false)

Files:
- tests/lib/production-safety.js: Core safety check module
- tests/00_production-safety.test.js: Runs first to gate test suite
- tests/production-safety.test.js: Unit tests for safety module
- tests/hooks.js: Updated to use new module

This addresses concerns about users with 'test' in production DB names
by adding the entry count threshold as a secondary safety measure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 19:49:49 -07:00
Ben WestandGitHub 7e5c345e8c Merge pull request #8456 from nightscout/wip/test-improvements
Wip/test improvements - extends same fixes for data shape across all remaining api surface areas and includes test coverage across the test matrix spectrum.
2026-03-18 18:03:53 -07:00
Ben WestandCopilot 729a6f5234 Add single object and empty array tests for entries API
- Add test for single entry returns array with one item
- Add test for empty array returns empty result
- Validates response format consistency for entries API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 16:01:35 -07:00
Ben WestandCopilot eacb6fca91 Add single object and array tests for activity API
- Add test for single activity returns array with one item
- Add test for activity array returns array
- Add test for empty array returns empty array
- Rename test file to follow *.test.js convention

Validates array normalization behavior for activity API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 16:00:18 -07:00
Ben WestandCopilot c6c60af906 Add array input tests for food API
- Add tests for POST with array of foods
- Add tests for PUT with array of foods
- Add test for empty array returning empty array
- Fix PUT endpoint to normalize array input like POST
- Fix food.save() storage to handle arrays with bulkWrite
- Rename test file to follow *.test.js convention

Validates fix from ef7bff3d for complete array handling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 15:58:50 -07:00
Ben WestandCopilot 67d2099331 perf: optimize activity and food storage with bulkWrite
Replace sequential replaceOne calls with bulkWrite for batch upserts.
This improves performance when inserting multiple documents at once.

- activity.js: Use bulkWrite with replaceOne ops instead of forEach loop
- food.js: Same optimization for consistency

Both maintain exact same upsert behavior (query by _id+created_at or doc).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 14:49:25 -07:00
Ben WestandCopilot ef7bff3d53 fix(food): add array support to food API POST
Add array normalization to food API POST endpoint:
- API layer: normalize single object to array (like activity/profile)
- Storage layer: use replaceOne loop with upsert (same as activity pattern)
- Storage layer: accept both single object and array for backward compat

Previously POST /api/food/ with array input would crash:
  insertOne([{...}]) → MongoDB error

Now supports both single object and array input consistently.
Response format is now array (matching treatments pattern).

Fixes #8447

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 14:06:16 -07:00
Ben WestandCopilot 808b923e8e feat(api): add _id validation to activity and food APIs
Add validation for _id field in activity and food APIs:
- activity: POST, PUT, DELETE now validate _id format
- food: POST, PUT, DELETE now validate _id format

Accepts: undefined, null, or 24-character hex string
Rejects: UUIDs, short strings, numbers, objects with 400 Bad Request

Previously:
- activity: 500 crash on invalid _id in save/remove
- food: silently replaced invalid _id with new ObjectId (data loss)

Tests added covering all validation cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 11:05:40 -07:00
Ben WestandCopilot 8d44a04304 feat(devicestatus): return 400 for invalid _id format
Add validation for _id field in devicestatus API:
- POST: validates each document's _id before storage
- DELETE: validates _id parameter (allows wildcard '*')

Accepts: undefined, null, or 24-character hex string
Rejects: UUIDs, short strings, numbers, objects with 400 Bad Request

Previously, invalid _id values were silently stored as strings instead
of ObjectIds, causing inconsistent data and query issues.

Tests added for all validation cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 11:02:31 -07:00
Ben WestandCopilot 32b1d70074 feat(profile): return 400 for invalid _id format
Add validation for _id field in profile API:
- POST: validates each document's _id before storage
- PUT: validates _id format before update
- DELETE: validates _id parameter before removal

Accepts: undefined, null, or 24-character hex string
Rejects: UUIDs, short strings, numbers, objects with 400 Bad Request

This prevents 500 errors from BSONError when clients send
UUID-style _ids (e.g., NightscoutKit).

Tests added for all validation cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:57:20 -07:00
Ben WestandCopilot 5f5bf224a6 Add API array handling test matrix with NightscoutKit fixtures
Extends api.shape-handling.test.js with:

Profile API tests:
- Single profile object POST
- Single-element array POST (NightscoutKit format)
- Multi-element array POST (batch upload)
- Response count equals input count validation
- Empty array handling
- Response shape consistency (always returns array)

NightscoutKit Fixtures Integration tests:
- Bolus treatments with syncIdentifier
- Carb entries with absorption time
- Temp basal treatments
- Mixed batch arrays
- Loop devicestatus with IOB/COB
- Batch devicestatus arrays
- Loop profile with loopSettings
- Historical profile batch sync

Test matrix coverage per spec in profile-api-array-regression.md:
| API | Single | Array | Batch | Empty | Response=Array | _id present |
|-----|--------|-------|-------|-------|----------------|-------------|
| Treatments |  |  |  |  |  |  |
| DeviceStatus |  |  |  |  |  |  |
| Entries |  |  |  |  |  |  |
| Profile |  |  |  |  |  |  |

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:38:34 -07:00
Ben WestandCopilot 83248e7f1d Add NightscoutKit treatment fixtures for API testing
Extract treatment fixture patterns from NightscoutKit Swift source:
- BolusNightscoutTreatment (Correction Bolus)
- CarbCorrectionNightscoutTreatment (Carb Correction)
- TempBasalNightscoutTreatment (Temp Basal)
- OverrideTreatment (Temporary Override)
- MealBolusNightscoutTreatment (Meal Bolus)
- BGCheckNightscoutTreatment (BG Check)
- NoteNightscoutTreatment (Note)
- Site Change, Sensor Start

Includes:
- Individual treatment objects for each type
- Array-wrapped formats (what NightscoutKit actually sends)
- Batch upload arrays for testing
- Helper functions for generating unique fixtures
- syncIdentifier field handling (client-provided dedup ID)

Source files:
- externals/NightscoutKit/Sources/NightscoutKit/Models/Treatments/*.swift
- externals/NightscoutKit/Sources/NightscoutKit/NightscoutClient.swift

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:34:57 -07:00
Ben WestandCopilot 269170b970 fixtures: add NightscoutKit devicestatus fixtures for array testing
Extract devicestatus structure from NightscoutKit Swift source:
- DeviceStatus.swift: top-level structure with device, created_at, identifier
- LoopStatus.swift: name, version, iob, cob, predicted, enacted, failureReason
- PumpStatus.swift: pumpID, manufacturer, model, reservoir, battery
- IOBStatus.swift: iob, basaliob with timestamp
- COBStatus.swift: cob with timestamp
- PredictedBG.swift: startDate, values array, optional COB/IOB curves
- LoopEnacted.swift: rate, duration (minutes), received, bolusVolume
- UploaderStatus.swift: name, battery percentage
- BatteryStatus.swift: percent, voltage, status

Fixtures include:
- minimal: Just device and timestamp
- loopWithIOBCOB: Loop status with IOB/COB
- fullLoop: Complete status with pump, predictions, enacted
- withEnacted: Status with active temp basal
- withFailure: Status with failureReason
- withAutoBolus: Status with automatic dose recommendation
- withMultiplePredictions: COB and IOB prediction curves
- singleArray: Single status in array format
- batchArray: 3 statuses for batch upload testing
- helpers: Factory functions for building custom fixtures

NightscoutKit sends devicestatus as arrays (NightscoutClient.swift:646-647).

Sources:
  externals/NightscoutKit/Sources/NightscoutKit/Models/DeviceStatus.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/LoopStatus.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/PumpStatus.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/IOBStatus.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/COBStatus.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/PredictedBG.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/LoopEnacted.swift

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:32:03 -07:00
Ben WestandCopilot 9fd53e324a fixtures: add NightscoutKit profile fixtures for array testing
Extract profile structure from NightscoutKit Swift source:
- ProfileSet.swift: dictionaryRepresentation structure
- LoopSettings.swift: loopSettings with overrides, dosing params
- TemporaryScheduleOverride.swift: override presets format

Fixtures include:
- minimal: Minimal valid profile
- fullLoop: Full profile with loopSettings and schedules
- withActiveOverride: Profile with active schedule override
- mmol: mmol/L units variant
- singleArray: Single profile in array (most common case)
- batchArray: 3 profiles for batch upload testing
- generateUniqueProfile(): Helper for dedup testing

NightscoutKit always sends profiles as arrays (NightscoutClient.swift:404).

Sources:
  externals/NightscoutKit/Sources/NightscoutKit/Models/ProfileSet.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/LoopSettings.swift
  externals/NightscoutKit/Sources/NightscoutKit/Models/TemporaryScheduleOverride.swift

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:29:15 -07:00
Ben WestandCopilot 2e81ce07e5 fix(devicestatus): purify each item in array input
The API layer was calling purifyObject() on the raw req.body without
handling arrays. When NightscoutKit sends [status], only the outer
array would be purified (no-op), not the individual status objects.

Now normalizes to array and purifies each devicestatus object,
matching the treatments pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:26:16 -07:00
Ben WestandCopilot cbb6d06107 fix(profile): restore array handling for profile POST API
NightscoutKit (Loop) sends profiles wrapped in arrays: [profile].
The MongoDB driver migration changed insert() to insertOne(), breaking
array support.

Changes:
- API layer: normalize input to array, purify each item
- Storage layer: use insertMany() instead of insertOne()
- Tests: verify single, array, and empty array handling

This matches the proven pattern from treatments API.

Fixes array handling regression introduced in d46c5b41.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:24:48 -07:00
Ben WestandCopilot 22f325c132 fix(tests): add missing closing brace in uuid-handling.test.js
First describe block was missing its closing });

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 17:17:33 -07:00
Ben WestandGitHub 18c10565bc Merge pull request #8457 from nightscout/copilot/sub-pr-8456
fix: gate UUID_HANDLING on both write and read paths; fix doc accuracy
2026-03-17 17:11:40 -07:00
Ben WestandCopilot 095c9d0454 fix: remove scope creep from UUID handling (syncIdentifier/uuid dedup)
UUID_HANDLING should ONLY affect UUID values in the _id field.
Previous commit incorrectly added server-side dedup for syncIdentifier
and uuid fields, which was never part of the original behavior.

Changes:
- upsertQueryFor(): Remove syncIdentifier/uuid as dedup keys
- Batch POST: Only fetch existing IDs by identifier, not by
  syncIdentifier/uuid
- tests: Update TEST-CACHE-003/004 to document actual behavior
  (duplicates occur without ObjectIdCache - this is by design)
- docs: Correct treatments-schema.md (syncIdentifier/uuid preserved,
  not copied to identifier)
- docs: Remove external link from entries-schema.md

Loop carbs/doses rely on ObjectIdCache for dedup, not server-side logic.
This matches the original (pre-change) server behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 16:00:03 -07:00
Ben WestandCopilot a432b5cf8c docs(changelog): correct UUID handling scope description
syncIdentifier and uuid fields are used for dedup, not copied to
identifier. Only UUID values in _id field are extracted to identifier.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 15:37:00 -07:00
Ben WestandCopilot 8fc155aa48 fix(treatments): correct UUID handling scope (only _id field)
REQ-SYNC-072 scope correction: normalizeTreatmentId() should ONLY
handle UUID values in the _id field, not copy syncIdentifier or uuid
fields to identifier.

Changes:
- normalizeTreatmentId(): Only extract UUID from _id to identifier
- normalizeEntryId(): Same fix for entries collection
- upsertQueryFor(): Add syncIdentifier and uuid as dedup fallbacks
  (fields are preserved, not copied to identifier)
- Batch POST: Fetch _id for docs deduped by syncIdentifier/uuid

Test updates:
- TEST-ID-003, TEST-V1-ID-004: Updated to expect identifier NOT copied
  from syncIdentifier (scope fix)

Affected clients:
- Loop overrides (UUID _id → identifier): Still works
- Loop carbs/doses (syncIdentifier): Dedup works, no identifier copy
- xDrip+ (uuid): Dedup works, no identifier copy
- AAPS (identifier): Unchanged

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 15:21:25 -07:00
Ben WestandCopilot 013e7b6efd fix(tests): update UUID_HANDLING test for new default
UUID_HANDLING default changed to true in 15.0.7. Test now explicitly
sets UUID_HANDLING=false rather than deleting the env var.

742 passing, 1 pending.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:59:05 -07:00
Ben WestandCopilot c1bece1386 docs: clarify write vs read path in schema docs
- Write normalization (syncIdentifier/uuid → identifier) is ALWAYS on
- UUID_HANDLING flag only controls READ path (GET/DELETE by UUID)
- Fix default: UUID_HANDLING=true (not false)
- Remove incorrect xDrip+ mention from entries (doesn't use UUID _id)
- Clarify that flag only affects API calls with UUID as _id parameter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:45:52 -07:00
Ben WestandCopilot 86e0564694 docs: clarify UUID_HANDLING only affects _id field, not all UUIDs
The feature only handles the specific case where a UUID is sent as
the _id field itself. It does NOT affect:
- AAPS (uses 'identifier' field)
- xDrip+ (uses 'uuid' field)
- Loop carbs/doses (uses 'syncIdentifier' field)

Only affects:
- Loop overrides (_id: syncIdentifier.uuidString)
- Trio CGM entries (_id: UUID)

See docs/10-domain/client-id-handling-deep-dive.md for full analysis.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:40:37 -07:00
Ben WestandCopilot ca22e8d930 docs: fix MongoDB pool default values to match code
Actual defaults in lib/storage/mongo-storage.js:
- MONGO_POOL_SIZE: 5 (not 10)
- MONGO_MIN_POOL_SIZE: 0 (not 1)
- MONGO_MAX_IDLE_TIME_MS: 30000 (not 10000)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:36:34 -07:00
Ben WestandCopilot a2c6ce1e5a docs: use neutral wording for UUID handling description
Avoid implying all AID clients use the same pattern or that any
specific implementation is incorrect. Different clients have
divergent sync patterns - the feature accommodates this variety.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:32:05 -07:00
Ben WestandCopilot abb505b256 docs: add MongoDB pool settings and advanced test scripts
README.md:
- Add MONGO_POOL_SIZE, MONGO_MIN_POOL_SIZE, MONGO_MAX_IDLE_TIME_MS
  to Core section for production tuning

CONTRIBUTING.md:
- Add 'Advanced Test Scripts' section documenting:
  - test:stress for concurrent write testing
  - test:flaky variants for detecting flaky tests
  - test:timing for finding slow tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:28:02 -07:00
Ben WestandCopilot 3bb100836b fix: change UUID_HANDLING default to true
Update default from false to true to enable AID client compatibility
out of the box:

- lib/server/env.js: readENVTruthy('UUID_HANDLING', true)
- README.md: Document UUID_HANDLING in Features section
- docs/example-template.env: Update comments, show true as default

Rationale:
- Loop, Trio, AAPS, xDrip+ use UUID sync patterns by default
- Before MongoDB 5.x, UUID _id didn't crash (just didn't CRUD properly)
- ObjectID users completely unaffected (quirk only triggers on UUID)
- Can set UUID_HANDLING=false for strict mode if needed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:17:48 -07:00
Ben WestandCopilot 942263c4d3 docs: fix _id format in entries example (string, not Extended JSON)
API returns _id as plain string "507f1f77bcf86cd799439011", not
MongoDB Extended JSON format {"$oid": "..."}.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 14:11:47 -07:00
Ben WestandCopilot 113d27cc7e docs: add entries schema documentation with UUID handling
Document entries collection fields, sysTime+type dedup behavior,
and identifier normalization for Trio/xDrip+ UUID _id uploads.

Refs: DOC-API-002, REQ-SYNC-072, GAP-SYNC-045

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:44:31 -07:00
Ben WestandCopilot 551f6dfac6 docs: add test environment variables section to CONTRIBUTING.md
Document MongoDB pool settings and AUTH_FAIL_DELAY for test tuning.
Useful for CI or resource-constrained environments.

Refs: DOC-ENV-002

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:42:59 -07:00
Ben WestandCopilot f37f44e8c8 test: add UUID edge case tests
Add 7 edge case tests for UUID_HANDLING:
- UUID-EDGE-001: 23-char hex (invalid ObjectId)
- UUID-EDGE-002: 25-char hex (too long)
- UUID-EDGE-003: UUID without hyphens not recognized
- UUID-EDGE-004: Empty _id query
- UUID-EDGE-005: Same identifier upsert behavior
- UUID-EDGE-006: Uppercase UUID matching
- UUID-EDGE-007: Valid ObjectId still works

Refs: uuid-test-edge, REQ-SYNC-072

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:40:59 -07:00
Ben WestandCopilot f91837f874 test: add UUID_HANDLING feature flag tests
Add 6 tests verifying UUID_HANDLING env var behavior:
- UUID-OFF-001: GET by UUID returns empty (no crash)
- UUID-OFF-002: DELETE by UUID deletes nothing (no crash)
- UUID-ON-001: GET by UUID finds treatment via identifier
- UUID-ON-002: DELETE by UUID removes treatment via identifier
- UUID-ON-003: ObjectId still works normally
- UUID-ON-004: Non-matching UUID returns empty

Tests use clearModuleCache() to reload env.js with different flag values.

Refs: uuid-test-flag-off, uuid-test-flag-on, REQ-SYNC-072

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:39:03 -07:00
Ben WestandCopilot 358941bba2 fix(tests): use fixed timestamp in BWP test for determinism
Replace Date.now() with the pre-captured 'now' variable in the
'set a pill to BWP with infos' test. This prevents timing drift
between when test data timestamps are set and when the sandbox
is initialized, eliminating flaky failures in CI environments.

Refs: BWP-TIME-001, GAP-TEST-001

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:28:12 -07:00
Ben WestandCopilot d987e55cb1 docs: add UUID_HANDLING to example-template.env
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:21:29 -07:00
Ben WestandCopilot bf6cfb7730 feat: add UUID_HANDLING feature flag for GET/DELETE by identifier
- env.js: Add UUID_HANDLING env var (default: false)
- query.js: Add UUID detection in normalizeIdValue()
  - When UUID_HANDLING=true and _id is UUID, search by identifier field
  - Returns searchByIdentifier flag to redirect query
- treatments.js: Move queryOpts inside query_for() for env access
- entries.js: Same pattern for entries collection

When UUID_HANDLING=true:
- GET /treatments/{uuid} searches by identifier field
- DELETE /treatments/{uuid} deletes by identifier field
- Same behavior for entries collection

When UUID_HANDLING=false (default):
- UUID _id values return empty results (safe, no crash)
- Maintains backwards compatibility

Refs: uuid-feature-flag, uuid-query-impl from uuid-identifier-lookup.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:21:14 -07:00
Ben WestandCopilot 4e79654d9f docs: add identifier field documentation and CHANGELOG for 15.0.7
- docs/data-schemas/treatments-schema.md: Document REQ-SYNC-072 identifier normalization
  - Describe how Loop/AAPS/xDrip+ sync fields are unified into identifier
  - Add example showing UUID _id → identifier promotion
  - Update sync/reconciliation fields table
- CHANGELOG.md: Create changelog for 15.0.7 release
  - Document UUID/identifier handling (REQ-SYNC-072)
  - Document test infrastructure improvements (GAP-SYNC-046)
  - Document Node.js/MongoDB requirement changes
  - Document bug fixes and documentation updates

Addresses DOC-API-001 and DOC-CHANGELOG from release-15.0.7-documentation.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:04:13 -07:00
Ben WestandCopilot 81393a4c1f docs: update Node.js requirements and add test documentation
- README.md: Update from Node 14/16 to Node 20+ (v22, v24 supported)
- README.md: Update MongoDB from 4.2/4.4 to 4.4+ (5.0, 6.0 supported)
- CONTRIBUTING.md: Add 'Running Tests Locally' section
- Document NODE_ENV=test requirement for safety
- Document npm scripts: test:unit, test:integration

Addresses DOC-NODE-001 and DOC-ENV-001 from release-15.0.7-documentation.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 13:02:12 -07:00
Ben WestandCopilot 96f9697866 test: add retry to AAPS entry dedup test for CI flakiness
This test passes locally in ~50ms but occasionally times out at 30s
in constrained GitHub runners. Adding retries(2) allows it to recover
from transient CI resource contention.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-12 14:16:21 -07:00
Ben WestandCopilot b76fb3e18a test: remove completed MongoDB 5.x array investigation tests
The 'WebSocket dbAdd Array Handling Investigation' block was R&D to
understand insertOne behavior with arrays. The investigation concluded:
- MongoDB's insertOne([a,b]) creates single doc (not multiple)
- Fix: sequential processing via processNextItem() in websocket.js

Production tests now cover this behavior:
- 'dbAdd with array input for treatments - current behavior test'
- 'dbAdd with array input for devicestatus - current behavior test'
- 'dbAdd with array input for entries - current behavior test'

Removes 2 flaky investigative tests, keeps 729 production tests passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-12 14:09:36 -07:00
Ben WestandCopilot ee3e6af76e ci: temporarily allow Node 20 for branch protection compliance
GitHub deprecated Node 20 on runners (2025-09-19), but branch protection
rules still require Node 20 tests to pass. Set ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true
only for the test job, not publish.

Reverts node-version matrix to [20, 22] to match master.

Ref: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-12 12:49:43 -07:00
Ben WestandCopilot e12cf3d2e2 fix(tests): make NODE_ENV=test check a hard failure (GAP-SYNC-046)
Change from warning to process.exit(1) to prevent any possibility of
running destructive test operations against a production database.

Tests now fail immediately if NODE_ENV !== 'test', with clear instructions
on how to fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-12 12:39:01 -07:00
Ben WestandCopilot 61501cac3a feat(tests): add NODE_ENV=test safety check (GAP-SYNC-046)
SAFETY-001: Fix tests/ci.test.env to use NODE_ENV=test instead of production
SAFETY-002: Add NODE_ENV check to tests/hooks.js with warning
SAFETY-003: Create tests/fixtures/test-guard.js with guarded deleteMany/drop helpers

This prevents deleteMany({}) from accidentally running against production
databases if test environment is misconfigured.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-12 12:24:15 -07:00
Ben WestandCopilot b88155057c fix(entries): handle UUID _id in CGM entries (GAP-SYNC-045)
Trio/Loop upload CGM entries with UUID strings as _id field.
This caused MongoDB errors when re-uploading with different UUID
at same timestamp: "immutable field '_id'" error.

Fix:
- Add normalizeEntryId() to extract UUID from _id to identifier field
- Add upsertQueryFor() to strip non-ObjectId _id before $set
- Maintain sysTime+type as primary dedup key for CGM data integrity
- Add identifier to indexed fields

Tests:
- 3 baseline tests document current sysTime+type dedup behavior
- 6 UUID handling tests including the previously-failing scenario

Refs: GAP-SYNC-045, REQ-SYNC-072

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-11 14:36:23 -07:00
Ben West 3758b6e339 github deprecates node 20 on runners 2026-03-10 16:35:16 -07:00
Ben WestandCopilot abd89f7935 test: add v3 API identifier generation tests (REQ-SYNC-072)
TEST-V3-ID-001: Null identifier generates ObjectId, copies to identifier
TEST-V3-ID-002: ObjectId string as identifier uses it directly
TEST-V3-ID-003: UUID string identifier preserved as-is

Validates Option G behavior extends to v3 API endpoints.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 16:13:51 -07:00
Ben WestandCopilot 02eec1b5a7 test: add identifier field tests for AAPS pattern (REQ-SYNC-072)
Add 3 new tests for explicit identifier field handling:
- supports identifier field for AAPS-style treatments
- deduplicates by identifier on re-upload
- supports batch upload with identifiers

These complement existing UUID _id tests (Loop pattern) to cover
both AID client sync patterns.

Refs: REQ-SYNC-072, GAP-TREAT-012

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 15:26:39 -07:00
Ben WestandCopilot 595219f9c4 Add Loop SGV entry and DeviceStatus upload tests
SGV Entry Tests (TEST-SGV-001 to 005):
- Single SGV with required fields
- All direction values
- Loop device identifier preserved
- Dexcom device with filtered/unfiltered/noise
- SGV deduplication by date+device
- Different devices create separate entries
- MBG (manual BG check) entries

DeviceStatus Tests (TEST-DS-001 to 005):
- Loop status with IOB/COB
- Loop predicted values array
- Loop enacted temp basal
- Pump reservoir and battery
- Omnipod specific fields
- Override in deviceStatus
- Override with insulinNeedsScaleFactor
- Complete Loop deviceStatus

17 new tests, all passing (716 total).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 15:03:48 -07:00
Ben WestandCopilot 16191f9c99 Add Loop carb and dose upload tests
Carb Tests (TEST-CARB-001 to 004):
- Create carb with syncIdentifier and absorptionTime
- Create carb with fat/protein (Warsaw FPU method)
- Create carb with cached _id
- Update carb via cached _id
- Delete carb via cached _id

Dose Tests (TEST-DOSE-001 to 005):
- Bolus with syncIdentifier
- Meal bolus with carbs and insulin
- Temp basal with rate and duration
- Suspend (zero rate) temp basal
- Update dose via cached _id
- Hex string syncIdentifier (pump events)
- Mixed dose batch maintains order

13 new tests, all passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 15:00:16 -07:00
Ben WestandCopilot d12bebe303 Add identity field test matrix for AID clients
Client Pattern Tests:
- TEST-ID-001: Loop Override UUID _id → identifier
- TEST-ID-002: Loop Override identifier field
- TEST-ID-003: Loop Carb syncIdentifier
- TEST-ID-004: AAPS identifier: null
- TEST-ID-005: AAPS identifier: ObjectId
- TEST-ID-006: xDrip+ uuid + _id fields

v1 API Identity Tests:
- TEST-V1-ID-001: No id field
- TEST-V1-ID-002: Valid ObjectId
- TEST-V1-ID-003: UUID string (REQ-SYNC-072)
- TEST-V1-ID-004: syncIdentifier field

Deduplication Tests:
- Duplicate identifier handling
- Unique identifiers create separate docs

12 new tests, all passing.

Refs: REQ-SYNC-072, GAP-TREAT-012

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 14:58:05 -07:00
Ben WestandCopilot 8ba8bbb18e Add ObjectIdCache workflow tests for Loop sync patterns
TEST-CACHE-001: POST carb → cache syncIdentifier → PUT with id
TEST-CACHE-002: POST dose → cache syncIdentifier → DELETE with id
TEST-CACHE-003: Cache miss (24hr expiry) → POST same syncIdentifier
TEST-CACHE-004: App restart (cache empty) → POST existing syncIdentifier
TEST-CACHE-005: Batch POST → verify response order → cache mapping

7 new tests validating Loop's ObjectIdCache behavior:
- syncIdentifier → ObjectId mapping
- Response order for batch operations
- Deduplication by syncIdentifier
- Hex string syncIdentifier handling

All 7 tests passing.

Refs: Loop ObjectIdCache.swift analysis

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 14:56:01 -07:00
Ben WestandCopilot 4af34767c2 Add GAP-TREAT-012 test suite for Loop override UUID handling
TEST-GAP-001: Loop override POST with UUID _id
TEST-GAP-002: Loop override DELETE by UUID
TEST-GAP-003: Loop override UPDATE by UUID
TEST-GAP-004: Loop override re-POST (upsert)

12 new tests validating REQ-SYNC-072 behavior:
- UUID _id promoted to identifier field
- Server generates valid ObjectId for _id
- Updates/deletes work via identifier lookup
- Duplicate detection via identifier
- Batch and edge case handling

New fixtures:
- loop-override.js: Real Loop override payload patterns

All 12 tests passing.

Refs: GAP-TREAT-012, REQ-SYNC-072

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 14:54:00 -07:00
Ben WestandCopilot e78a5bc6e7 fix(treatments): implement REQ-SYNC-072 server-controlled ID with transparent promotion
Fixes #8450 - Loop Temporary Override sync breaks due to UUID _id handling

Option G Implementation:
- Extract client sync identity (identifier) from any source:
  - Loop overrides: UUID in _id field → moved to identifier
  - Loop carbs/doses: syncIdentifier → copied to identifier
  - AAPS: identifier already present
  - xDrip+: uuid → copied to identifier

- Server generates proper ObjectId for _id field
- Deduplication uses identifier (not _id) as primary key
- No database migration needed - gradual adoption

Changes:
- normalizeTreatmentId(): extracts client identity to identifier field
- upsertQueryFor(): identifier-first lookup, strips UUID _id for upsert
- create()/upsert()/save(): fetch _id from DB after update by identifier
- Added 'identifier' to indexedFields for efficient querying
- Updated UUID treatment test with full workflow coverage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-10 13:36:34 -07:00
Ben West 13d314119d new dev area for 15.0.7
This initializes development after releasing 15.0.6.
2026-03-03 15:07:43 -08:00
Ben WestandGitHub 9cd304f78a Merge pull request #8442 from nightscout/dev
release for 15.0.6
2026-03-03 14:57:48 -08:00
Ben West 797df9bdda Update bridge deps to 0.2.12/1.5.8
These changes remove shrinkwrap from including dev dependencies for production
use.  This is intended to solve errors in production environments like heroku
incorrectly pulling in darwin based chokidar and related mocha dependencies.
2026-03-03 12:20:47 -08:00
Ben West 6852e550a8 cut new dev for 15.0.6
Post release 15.0.5, we will develop branch for 15.0.6.
2026-03-03 11:32:05 -08:00
Ben WestandGitHub f988ed9869 Merge pull request #8436 from nightscout/dev
Release 15.0.5
2026-03-01 13:17:22 -08:00
Ben WestandGitHub 743506a6a0 Merge pull request #8438 from nightscout/fix/docker-force
Dockerfile: Add --force to bypass platform check
2026-03-01 12:56:59 -08:00
Ben West aa13913093 Dockerfile: Add --force to bypass platform check
npm ci fails with EBADPLATFORM when lockfile contains darwin-only
packages (fsevents), even with --omit=optional. The --force flag
bypasses this check.
2026-03-01 12:53:32 -08:00
Ben WestandGitHub ee2bfa4fe7 Merge pull request #8437 from nightscout/fix/heroku-fsevents
Fix/heroku fsevents
2026-03-01 12:40:30 -08:00
Ben West b8aec4429c CI: Test only Node 20 and 22
Node 16 EOL was September 2023. Docker image uses Node 22.
Reduces CI matrix from 9 to 6 jobs.
2026-03-01 12:30:27 -08:00
Ben West 4130f325c5 Update bridge deps to 0.2.11/1.5.7 (fsevents fix)
Both bridge packages now have clean shrinkwraps without devDependencies,
eliminating the fsevents (darwin-only) entries that caused Heroku build failures.
2026-03-01 12:28:29 -08:00
Ben West ecafd4782c Fix Docker/Heroku builds with --omit=optional
Use npm ci with --omit=optional to skip optional dependencies like
fsevents (darwin-only) that were causing build failures on Linux
platforms including Heroku and local Docker builds on Mac.
2026-03-01 12:25:55 -08:00
Ben West a5ada47d32 first commit to cut new 15.0.5 dev branch 2026-03-01 12:02:54 -08:00
Ben WestandGitHub b03c604643 Merge pull request #8352 from nightscout/dev
release 15.0.4
2026-02-28 09:00:37 -08:00
Ben WestandGitHub 7ae17b13f5 Merge pull request #8433 from nightscout/test/node22-pr
Test/node22 pr
2026-02-27 15:07:57 -08:00
Ben WestandCopilot 0fb628e1c4 Update CI matrix to test Node 16, 20, 22
- Remove lts/* (redundant with explicit versions)
- Add Node 16 for backwards compatibility testing
- Skip Node 18 (flaky tests, will be fixed in MongoDB PR)
- Keep MongoDB 4.4, 5.0, 6.0 matrix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-27 14:53:30 -08:00
Ben WestandCopilot e0cc9ff5df Relax Node version constraints to >=16.x
- Change engines.node from '^22.x || ^20.x' to '>=16.x'
- Change engines.npm from '>=10.x' to '>=8.x'
- Update runtime checkNodeVersion to allow Node 16+
- Creates overlap with previous release (^16.x || ^14.x)

This allows users on Node 16/18 to upgrade smoothly while
recommending Node 20 or 22 LTS for best support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-27 14:52:56 -08:00
Ben West 019fa51cff Merge PR #8357 (Node 22 upgrade) 2026-02-27 14:06:32 -08:00
Ben WestandGitHub 535b50e9e0 Merge pull request #8432 from nightscout/wip/bewest/update-bridge-deps
Wip/bewest/update bridge deps
2026-02-27 14:03:03 -08:00
Ben WestandCopilot d81d6854c0 Update bridge dependencies to final deprecated versions
- share2nightscout-bridge: 0.2.9 → 0.2.10 (Node 22 support)
- minimed-connect-to-nightscout: 1.5.5 → 1.5.6 (Node 22 support)

Both packages now allow Node 18/20/22+ in their engines field.
This is a prerequisite for the Node 22 upgrade (PR #8357).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-27 13:36:08 -08:00
Ben WestandCopilot 6a48ea89cf Update bridge dependencies to final deprecated versions
- share2nightscout-bridge: 0.2.9 → 0.2.10 (Node 22 support)
- minimed-connect-to-nightscout: 1.5.5 → 1.5.6 (Node 22 support)

Both packages now allow Node 18/20/22+ in their engines field.
This is a prerequisite for the Node 22 upgrade (PR #8357).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-27 13:16:04 -08:00
Ben West f441d6a6fa ensure AUTH_FAIL_DELAY for ci 2026-01-19 19:07:19 -08:00
Ben West 93945b749e ensure auth tests have a proper delay set
It needs a small delay to test with.
2026-01-19 18:50:11 -08:00
Ben West 7a2d345491 move workflow out of way 2026-01-20 02:40:50 +00:00
Ben West 231e50818a remov attached assets 2026-01-19 13:53:27 -08:00