Skip to content

Commit 5e514f0

Browse files
authored
Point vendor claims, routing, and the release gate at carelink-api-research (#102)
* Point vendor claims, routing, and the release gate at carelink-api-research Medtronic publishes no API documentation, so every claim this bridge makes about CareLink rests on the sibling research repo. That repo was well linked in a few places (README, docs/vendor-api, ARCHITECTURE) and unlinked everywhere else, which left contributors with no route from the docs they actually read. Docs: - ROADMAP: cite the research map for the reports-API host/gateway evidence, the carepartner identity namespace, and the discovery pin; add a Tracking footnote pointing at the research repo as the vendor-surface source of truth. - ARCHITECTURE: link the discovery-pin and reports-API sections to the research pages that carry their evidence. - ADR 0002: add a Notes pointer to the canonical version matrix. The ADR is authoritative for the pin; the matrix is re-verified there. - CHANGELOG: the 2026-10-08/09 research pass narrates ~10 findings whose evidence lives in the sibling repo — link it once. - README: link "drift sweep" to the workflow that does it. Contributor routing (issue triage was the real gap — both repos had zero cross-mentions, so misfiled reports had nowhere to go): - CONTRIBUTING: is it a bridge bug or a vendor observation? The test is "if Medtronic did nothing, would it still be broken?". Adds a release step running the vendor suite before tagging. - bug.yml and PR template: vendor-moved triage and a vendor-surface impact checkbox. - SECURITY.md: split the channels — client vulnerabilities here via private advisory, vendor exposures to the research repo redacted. Automation: - `npm run drift:check` runs the research repo's regression suite from a sibling clone; non-zero blocks a release. - `npm run links:check` + a CI job verify every cross-repo link still resolves. Those links float on `main`, so a docs/ renumber there would otherwise 404 silently — exactly the rot this repo's own findings-log documents. Verified: npm run typecheck clean; 323/323 tests pass; links:check exit 0 (and exit 1 on an injected broken link); drift:check wrapper corrected to honour run.sh's bash shebang, full sweep 44/44 pass. * Fix the link gate's false pass and the release-gate ordering Two defects found reviewing the cross-linking pass. Both would have shipped silently, which is worse than the bugs they were meant to catch. check-links.mjs — CI was a no-op for the links it exists to protect. --online only fetched URLs with no file path (the repo root), so every blob/tree link fell through to the sibling-clone branch. CI checks out this repo alone, so 17 of 19 links were skipped and the tool still printed PASSED. Injected a guaranteed 404: exit 0. Now --online verifies every URL. Offline mode additionally requires the target to be git-tracked, so a file that exists in a working tree but is untracked (or gitignored) no longer passes — that is the exact class of breakage that 404s on GitHub while resolving fine locally. Unverified links now report as unverified rather than good, and the misleading "skip … only checked with --online" message printed while --online was active is gone. CONTRIBUTING — the release gate ran after the release. Steps were: tag, gh release create, then drift:check, described as blocking the release and as running "before tagging anything". The release was already published by the time the check ran. Moved to step 3, ahead of the merge and tag. Verified after the fix: offline and --online both exit 1 on an injected 404 and exit 0 clean; typecheck clean; 323/323 tests pass. * Harden the link gate; correct a stale matcher note Review of the previous commit found the link gate had a false pass in the exact configuration CI uses, plus several smaller defects. check-links.mjs: - `?template=` URLs were folded into a normal HTTP check, and GitHub returns 200 for a template that does not exist (it falls back to a blank form or a login redirect). Every contributor-funnel link — five of them — was being reported good regardless of whether the issue form was real. Now the template name is resolved against the sibling clone and required to exist, and online mode reports those links as unverified rather than ok. - A `blob/main/...#section` link failed the offline check with a message blaming the research side for a rename, while passing online, because the fragment was left in the path. Fragments and query strings are now stripped before the path is resolved. - The repo name had no boundary assertion, so a link to a `carelink-api-research-archive` was truncated to `…research`, which resolves — a silent false pass. Added `(?![\w.-])`. - fetch had no try/catch and no timeout: one DNS blip failed CI with an unhandled rejection indistinguishable from a broken link, and a hung connection would hold the job for GitHub's 6-hour default. Now bounded at 20s, with network errors counted separately and labelled, because the sister repo's own rule is that a network failure looks exactly like vendor drift. - SCAN_DIRS listed '.' alongside its own subdirectories, so the tree was walked ~1.85x and the reported file count was inflated. Scanning also skipped extensionless files — including .gitignore, which carries a live cross-repo URL in a comment and is exactly the file you'd edit alongside a rename. - Failure output now names the files that reference the broken URL. drift:check: - Missing `hurl` made run.sh exit 1, which CONTRIBUTING described as "Medtronic moved something under us" — a maintainer on a clean machine would have blocked a release over a missing binary. Now preflights `hurl` and `jq`, exits 2 with install hints, and says plainly that a missing tool is not vendor drift. - CONTRIBUTING did not disclose that this sends ~60 live read-only requests to Medtronic's production servers, nor that a network failure is not drift. Both now stated, with the two-consecutive-reds rule the sister repo uses. docs: - docs/vendor-api/README.md said the bridge matches on model prefix "rather than family token". That is stale — it predates the CC880 family-token match in src/carelink/client.ts and contradicts it. The sister repo had started citing it as endorsement of its own corrected note, so a stale doc was laundering a false claim into two places. Corrected to describe the actual matcher. - ROADMAP quoted a heading ("What a client must use") that does not exist; the real one is "What a client must actually use". Deep-linked. - SECURITY.md routed vendor exposures to a blob URL for a repo whose own security page insists private advisories are the only tracked channel, and pre-suppressed by saying the findings "already track these" when F1 is deliberately held back. Now routes to their advisory intake. - PR template asked outside contributors to run drift:check, which needs a second repo and two binaries. Now scoped to maintainers with an explicit n/a. - CONTRIBUTING gained the dual-cause tiebreaker: when a problem is both vendor motion and a client weakness, file both. Verified: typecheck clean; 323/323 tests; links:check exits 0 clean and 1 on an injected 404, in both offline and --online modes. * Complete the link gate's reporting; sync the two runbooks Final review round. The remaining defects were mostly reporting gaps and copy-paste damage from the previous commit's edits. check-links.mjs: - Offline failures computed the "referenced by" list and then never used it. Every failure message except the --online one omitted it, which is the worst mode to lose it: "no such path" and "not git-tracked" are precisely the cases where you need to know which of 93 files carries the stale link. All five offline paths now include it. - The --online summary told the user to "Run with --online" while the user was already running --online, because the message hardcoded the offline reason. It now distinguishes the two causes — unverified because there is no sibling clone, versus unverified because GitHub answers 200 for a template that does not exist — and gives advice matching the mode. - The repo-root fallback printed "(repo root, checked via origin remote)" for URLs like security/advisories/new that are not repo roots, while reporting every link verified. It now says the page itself is not verifiable offline. - Comment said 1,176 files where .gitignore says 1,170. Aligned. PR template: the drift:check line ended in a colon with nothing after it, a visible truncation artifact. Now has the input block, matching the sibling repo's research-gate exit convention. docs/vendor-api/README.md documented running the suite with none of the caveats CONTRIBUTING now carries for the same thing — no hurl/jq prerequisite, no mention that it sends live traffic to Medtronic's production servers, and no warning that a network failure is not drift. The README is where the release docs send someone, so it needs the same caveats, not fewer. SECURITY.md: routed vendor exposures to carelink-api-research's private advisory intake. Checked — that repo does not have private vulnerability reporting enabled, so this pointed the most sensitive possible report at a channel that does not exist. Now routes to their SECURITY.md and says explicitly never to report an exposure here, redacted or otherwise. Verified: typecheck clean; 323/323 tests; links:check exits 0 clean and 1 on an injected 404 offline and online. * Correct the probe host count and verb claim; minor formatting Counted the actual hosts the suite touches: nine, not seven (eight appear in the .hurl suites, and 05-public-config.check.sh adds carelink.medtronic.eu). The "seven" figure came from the research repo's own drift-sweep.yml and was never right; it should not propagate into this repo's runbook as fact. "read-only" was also imprecise — run.sh sends two pinned POSTs in 04-deep-surface.hurl. Both are expected to be refused server-side and are documented in the research repo, but describing vendor traffic needs to be exact. Also: missing EOF newline on scripts/check-links.mjs, and a 95-column prose line in docs/vendor-api/README.md reflowed to the file's ~78.
1 parent 8fb3df7 commit 5e514f0

13 files changed

Lines changed: 428 additions & 13 deletions

File tree

‎.github/ISSUE_TEMPLATE/bug.yml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ body:
77
value: |
88
Thanks for filing a bug. Please fill in the sections below so we can reproduce and fix it.
99
**Do not include credentials, tokens, or `logindata.json` content in this issue.**
10+
11+
**Is this Medtronic's fault, or ours?** If Medtronic changed something — a
12+
route now 404s or 405s, the version list moved, a country appeared, a status
13+
code changed — that is a *vendor observation*, not a bridge bug. Check the
14+
map first ([NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/00-summary-the-map.md))
15+
and file it there via its
16+
[new-finding form](https://github.com/NovaLux12/carelink-api-research/issues/new?template=01-new-finding.yml);
17+
its drift sweep is what notices. File it here if the vendor surface is
18+
unchanged and this bridge still misbehaves.
1019
- type: input
1120
id: version
1221
attributes:

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ The fork should only carry changes that landed in or were submitted upstream.
3838
- [ ] No divergence — the change is also applicable to (or already submitted to) upstream
3939
- [ ] Diverges from upstream — see explanation above
4040

41+
## Vendor-surface impact
42+
43+
<!--
44+
Medtronic publishes no API documentation, so every claim about it rests on
45+
[NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research).
46+
If this PR changes, adds, or re-verifies a vendor claim — a route, a status code,
47+
the discovery pin, the version list, device vocabulary, an error class — say so.
48+
-->
49+
50+
- [ ] No vendor-surface change (pure bridge logic)
51+
- [ ] Vendor claim checked against the [research map](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/00-summary-the-map.md)
52+
- [ ] Vendor change observed — filed upstream as a [finding](https://github.com/NovaLux12/carelink-api-research/issues/new?template=01-new-finding.yml): <link>
53+
54+
`npm run drift:check` (maintainer release step only — needs a sibling clone of
55+
the research repo plus `hurl` and `jq`; write `n/a` if not applicable):
56+
57+
```
58+
drift:check exit: __
59+
```
60+
4161
## Checklist
4262

4363
- [ ] My change matches the contribution guidelines in CONTRIBUTING.md

‎.github/workflows/ci.yml‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,15 @@ jobs:
2121
- run: npm ci
2222
- run: npm run typecheck
2323
- run: npm test
24+
25+
cross-links:
26+
# Every vendor claim in this repo cites NovaLux12/carelink-api-research.
27+
# Those links float on `main`, so a rename on that side would silently
28+
# 404 them. This makes the breakage loud at PR time.
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v7
32+
- uses: actions/setup-node@v7
33+
with:
34+
node-version: 22
35+
- run: npm run links:check -- --online

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ A research pass into CareLink's live API surface, followed by the fixes
152152
it produced. The branch is one squashed commit carrying both the code and
153153
the documentation changes, so this entry covers both.
154154

155+
The underlying evidence for this pass — and every claim in it — is filed in
156+
the sister research repo,
157+
**[NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research)**
158+
([start with the map](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/00-summary-the-map.md),
159+
dated findings in
160+
[`findings-log/`](https://github.com/NovaLux12/carelink-api-research/tree/main/findings-log)).
161+
That repo is re-verified continuously, so a drift found after this entry
162+
should be reported there, not here.
163+
155164
Every CareLink fact below was verified live on 2026-10-08 unless it is
156165
labelled **INFERRED** (from a third-party client or Medtronic's own
157166
published assets) or **UNVERIFIED** (needs a real CareLink credential).

‎CONTRIBUTING.md‎

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ dependency), write an ADR in `docs/adr/` first. The
2222

2323
1. Open an issue first for anything non-trivial (small typo
2424
fixes don't need an issue).
25+
26+
**Is it a bridge bug or a vendor observation?** This bridge is a
27+
*client*; most interesting problems are not its bugs. If Medtronic
28+
changed something — a route exists/doesn't, a version list moved, a
29+
new country, a changed status code, a renamed field — file it in
30+
**[NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research)**,
31+
the research repo that maps and continuously re-verifies this
32+
surface, using its
33+
[new-finding form](https://github.com/NovaLux12/carelink-api-research/issues/new?template=01-new-finding.yml).
34+
Its weekly drift sweep is what catches a change before it becomes a
35+
bridge outage. Issues on this repo are for bridge behaviour. The test:
36+
*if Medtronic did nothing, would it still be broken?* Yes → bridge
37+
issue. No → research finding.
2538
2. Fork the repo, create a branch.
2639
3. Make the change.
2740
4. Make sure `npm test` and `npm run typecheck` pass. (`npx tsc --noEmit`
@@ -106,6 +119,16 @@ most useful thing you can do is:
106119
That gives the next maintainer something to test against
107120
without needing their own real pump.
108121

122+
**If the real-data probe taught you something about the vendor
123+
surface** — not just about this bridge — that belongs in the research
124+
repo too. File it via its
125+
[new-finding form](https://github.com/NovaLux12/carelink-api-research/issues/new?template=01-new-finding.yml)
126+
and cite the `findings-log/` path it lands in from your PR, so the
127+
finding is pinned rather than only described. The bridge's own
128+
vendor claims live in
129+
[`docs/vendor-api/README.md`](./docs/vendor-api/README.md), which records
130+
which finding each source comment rests on.
131+
109132
## Releasing (maintainers)
110133

111134
Version metadata must stay in sync — v0.1.1 through v0.1.3
@@ -118,15 +141,34 @@ happened. For every release:
118141
2. Move the `[Unreleased]` items in CHANGELOG.md into a new
119142
dated version section and update the compare links at the
120143
bottom.
121-
3. Merge those changes via PR like any other.
122-
4. Tag the merge commit: `git tag vX.Y.Z && git push origin vX.Y.Z`.
123-
5. Cut the release: `gh release create vX.Y.Z --title vX.Y.Z --notes "..."`
144+
3. **Run the vendor-surface regression suite: `npm run drift:check`.**
145+
It executes
146+
[`regression/hurl/run.sh`](https://github.com/NovaLux12/carelink-api-research/blob/main/regression/hurl/run.sh)
147+
from a sibling clone of the research repo, and needs `hurl` and `jq`
148+
installed. **Do this before you tag** — a non-zero exit means Medtronic
149+
moved something under us, and tagging a release that is already broken
150+
would make the tag the published record of it.
151+
152+
Two things to know before you run it. It **sends live traffic to
153+
Medtronic's production servers** — around 60 requests across nine
154+
hosts, two seconds apart, read-only apart from two pinned POSTs. That
155+
is the research repo's deliberate probing budget, and running it more
156+
than once per release is not free politeness. And it needs a network
157+
round trip, so a **network failure is not drift**: the sweep's own
158+
rule is that only two consecutive reds count, because CI network
159+
failures look exactly like vendor drift.
160+
If it fails, re-run once; if it fails again, read
161+
[`docs/vendor-api/README.md`](./docs/vendor-api/README.md), decide with
162+
the evidence, and only then proceed.
163+
4. Merge those changes via PR like any other.
164+
5. Tag the merge commit: `git tag vX.Y.Z && git push origin vX.Y.Z`.
165+
6. Cut the release: `gh release create vX.Y.Z --title vX.Y.Z --notes "..."`
124166
— the notes should match the CHANGELOG entry
125167
(security-relevant changes get a clear callout per
126168
[SECURITY.md](./SECURITY.md)).
127-
6. Check ROADMAP.md — a phase marked "shipped" must have
169+
7. Check ROADMAP.md — a phase marked "shipped" must have
128170
a matching tag and release.
129-
7. If a new architectural decision was made in this
171+
8. If a new architectural decision was made in this
130172
release, the ADR should already exist in `docs/adr/`.
131173
Confirm the index table is up to date.
132174

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ uploading what it gets.
1919
> [`docs/vendor-api/README.md`](./docs/vendor-api/README.md) records which finding
2020
> each one rests on. **Go there first** when debugging a fetch failure, checking
2121
> whether a route still exists, or changing how this bridge talks to CareLink —
22-
> and report what you find there, where a drift sweep will notice it.
22+
> and report what you find there, where a
23+
> [drift sweep](https://github.com/NovaLux12/carelink-api-research/blob/main/.github/workflows/drift-sweep.yml)
24+
> will notice it.
2325
2426
> **How close is this to the official app?** The **data** path is the
2527
> same one the official CareLink app uses — the bridge takes its login

‎ROADMAP.md‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ refusal). If it is ever wired in it must stay **opt-in and
202202
off by default**: it is a second, much larger data surface
203203
than the fetch loop. Details in
204204
[docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md#live-carelink-api-surface)
205-
("Reports API").
205+
("Reports API"); the vendor-side host and gateway evidence is in
206+
[NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/07-admin-portal-and-reporting.md).
206207

207208
## v0.3.0 — reliability (shipped 2026-09-09, #58)
208209

@@ -285,6 +286,8 @@ this bridge actually uses is **unverified**, and a second
285286
identity is not buildable on top of an unverified one. That
286287
is the second of the two cheapest authenticated checks in
287288
[Pre-pump authenticated checks](#pre-pump-authenticated-checks-cheapest-first).
289+
The namespace comparison itself is mapped in
290+
[carelink-api-research docs/02 §4 "What a client must actually use"](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/02-auth-tenants-and-flows.md#4-what-a-client-must-actually-use).
288291
The multi-patient fan-out fixture item is also one of the
289292
things the reports API might unblock — see the v0.2.0
290293
maintenance note above.
@@ -299,7 +302,9 @@ cheapest checks that need a real account token, in order:
299302
flow still work at all? It exercises discovery → PKCE → token
300303
exchange → refresh, and it is the only check that catches an Auth0
301304
drift before it becomes a November emergency. It needs no data fetch
302-
and no pump.
305+
and no pump. The pin's evidence and the family fallback
306+
(`3.7`/`3.8`) are in
307+
[carelink-api-research docs/03](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/03-discovery-and-versions.md).
303308
2. **`GET /api/carepartner/v2/users/me` vs `GET /patient/users/me`.**
304309
Both answer `401` without a token, so **which one actually returns
305310
data with a valid token is unknown** — and that is the open question
@@ -337,6 +342,17 @@ blocked on a real pump or a real capture.
337342

338343
Active open work, cross-referenced from issues:
339344

345+
> **Vendor-surface source of truth.** Facts about CareLink itself
346+
> (which routes exist, which versions answer, what changed since
347+
> this roadmap was written) live in
348+
> **[NovaLux12/carelink-api-research](https://github.com/NovaLux12/carelink-api-research)** —
349+
> [start with the map](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/00-summary-the-map.md),
350+
> pick future work from
351+
> [docs/11 suggested areas](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/11-suggested-research-areas.md).
352+
> Its weekly drift sweep opens issues there when the surface
353+
> moves; bridge issue #76 mirrors the reports-API lead, and
354+
> #12 tracks what a real token settles.
355+
340356
| Item | Issue | Status |
341357
|------|-------|--------|
342358
| Pre-pump operator checklist | [#7](https://github.com/NovaLux12/carelink-bridge/issues/7) | open |

‎SECURITY.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ vulnerabilities. GitHub Security Advisories are the only
1010
channel that guarantees a private, tracked response for
1111
this repo.
1212

13+
**What goes where.** This advisory channel is for vulnerabilities
14+
in *this bridge's code* — the token handling, the file writes,
15+
the fetch loop. Two related things live elsewhere:
16+
17+
- **An exposure in Medtronic's own surface** — a published key,
18+
an internal hostname in a public artefact, an auth gap — is a
19+
research finding, not a bridge bug. **Never** report it here,
20+
redacted or otherwise. Their intake and redaction rules are in
21+
[NovaLux12/carelink-api-research's `SECURITY.md`](https://github.com/NovaLux12/carelink-api-research/blob/main/SECURITY.md);
22+
follow those, not this page. They maintain
23+
[security findings](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/08-security-findings.md)
24+
on the vendor surface — and whether an exposure is already known,
25+
publishable, or held back is their call, so please still report it
26+
rather than assuming it is covered.
27+
- **A login, upload, or crash failure** with an unchanged vendor
28+
surface is a plain bug — use the [bug form](https://github.com/NovaLux12/carelink-bridge/issues/new?template=bug.yml).
29+
1330
## Threat model
1431

1532
This bridge handles:

‎docs/ARCHITECTURE.md‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,10 @@ The full 23-cell matrix, the two orthogonal axes of the discovery URL,
273273
and the guard that must check the cumulus track rather than the mere
274274
presence of the config key are in
275275
[ADR 0002](./adr/0002-discovery-app-version-pin.md). The verification
276-
date is in the constant's own header comment.
276+
date is in the constant's own header comment. The wider matrix, and the
277+
evidence that probing a newer cell re-derives a known document rather than
278+
revealing a new API, is maintained continuously in the research repo's
279+
[discovery & versions page](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/03-discovery-and-versions.md).
277280

278281
### Discovery-document tripwires (issue #77)
279282

@@ -593,6 +596,13 @@ portal's public JS bundle also ships a hardcoded key present in the
593596
vendor's public bundle, tracked privately; that value is **not**
594597
reproduced in this repository.
595598

599+
Vendor-side detail — the brokers, the AWS gateways behind them, and the
600+
CloudFront origin failure on the metadata broker — is mapped in the
601+
research repo's
602+
[admin portal & reporting page](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/07-admin-portal-and-reporting.md),
603+
with the credential-handling posture in its
604+
[security findings page](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/08-security-findings.md).
605+
596606
If it is ever integrated it must stay **opt-in and off by default** —
597607
this is a second, much larger data surface than the fetch loop and
598608
should not be pulled on every cycle.

‎docs/adr/0002-discovery-app-version-pin.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ journald and points the operator at the constant to inspect.
205205

206206
## Notes
207207

208+
- **Canonical version-matrix map lives in the research repo.** This ADR's
209+
table is authoritative *for the bridge's pin*, but the wider cell-by-cell
210+
matrix, the "what does probing a new version re-derive" result, and the
211+
live re-verification history are maintained continuously in
212+
[NovaLux12/carelink-api-research — `docs/03` discovery & versions](https://github.com/NovaLux12/carelink-api-research/blob/main/docs/03-discovery-and-versions.md)
213+
and pinned by its regression suite. If a future probe contradicts the
214+
table above, check there first and **file the discrepancy there** (its
215+
weekly drift sweep is what notices) rather than editing this ADR in place.
208216
- Source: `src/discovery.ts` (the file's own header comment records
209217
a summary of the version matrix and the verification date).
210218
- **Re-probed live on 2026-10-08** (23 cells, unauthenticated, both

0 commit comments

Comments
 (0)