8000 Add CBIO GS1 sensor integration by shroominic · Pull Request #209 · shroominic/OpenGlucose · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
821f9a3
feat: land Libre 2 + Yuwell Anytime multi-sensor protocol base
shroominic Sep 8, 2026
02140e7
fix: avoid gated-selection deadlock in Libre cleanup test
shroominic Sep 8, 2026
3c47637
feat(cbio): add discovery and offline GS1 frame inspection
shroominic Sep 9, 2026
222a2c0
feat(cbio): preserve offline GS1 evidence and gates
shroominic Sep 14, 2026
fd4b7ee
feat(cbio): register fail-closed live GS1 driver
shroominic Sep 17, 2026
8f40390
test(cbio): add bounded device-backed GS1 live capture harness
shroominic Sep 17, 2026
a5749f1
test(cbio): expect the cbio driver in the production registry
shroominic Sep 17, 2026
1f71f6c
fix(cbio): match short-form platform UUIDs when locating FF31
shroominic Sep 17, 2026
fcb751c
test(cbio): keep the live link up for a bounded settle window
shroominic Sep 17, 2026
e24bc6c
fix(ble): complete nearby-sensor scans at a registry-owned deadline
shroominic Sep 17, 2026
ab52637
test(cbio): classify the live GS1 FF31 reply as unresolved
shroominic Sep 17, 2026
cfe69c0
fix(session): bound the sensor sync wait and fail closed
shroominic Sep 17, 2026
7f5888d
feat(cbio): send the vendor GS1 read queries and bound live/history sync
shroominic Sep 17, 2026
1a3273a
docs(cbio): record that the fixed FF31 payload is not command-specific
shroominic Sep 17, 2026
6592ee2
docs(cbio): record GS1 auth key source and runtime call sequence
shroominic Sep 17, 2026
36a0b2a
feat(cbio): authenticate the GS1 link and stream live glucose and his…
shroominic Sep 17, 2026
4702025
docs(cbio): point the live record at the sibling derivation branch
shroominic Sep 17, 2026
6fadcb0
merge: land frame-decode lane (#132, 1a3273a) into v0.4.0 aggregate
shroominic Sep 17, 2026
6cbc534
merge: land auth-material docs lane (#138, 6592ee2) into v0.4.0 aggre…
shroominic Sep 17, 2026
5fd9d13
merge: land bounded session-sync fix (#134, cfe69c0) into v0.4.0 aggr…
shroominic Sep 17, 2026
6d9a45f
merge: land nearby-sensor scan-deadline fix (#130, e24bc6c) into v0.4…
shroominic Sep 17, 2026
7541552
style(cbio): format the live query harness to the repository page width
shroominic Sep 17, 2026
17db5b4
feat(cbio): stream GS1 history and live readings into the app
shroominic Sep 17, 2026
1920c45
fix(ble): close the scan stream before plugin cleanup can block it
shroominic Sep 17, 2026
1aab143
fix(cbio): keep masked auth vectors out of key-shaped string form
shroominic Sep 18, 2026
de8a360
chore(cbio): format the lane integration harness
shroominic Sep 18, 2026
bc52c12
Merge remote-tracking branch 'origin/feature/cbio-gs1-app-live' into …
shroominic Sep 18, 2026
a1a36c3
Merge remote-tracking branch 'origin/fix/ble-scan-stream-close' into …
shroominic Sep 18, 2026
5f41ba9
fix(workspace): isolate host and device integration test roots
shroominic Sep 17, 2026
174ceeb
chore(ble): format the scan-close transport change
shroominic Sep 18, 2026
762c845
chore(cbio): format the app-live session tests
shroominic Sep 18, 2026
033b727
chore(release): append the app-live and scan-close lanes and carry th…
shroominic Sep 18, 2026
b1ac236
docs(deps): record the cgm_cbio vendor-derived material review
shroominic Sep 18, 2026
b13f240
docs(cbio): publish plaintext vectors only, never masked bytes
shroominic Sep 18, 2026
e81e335
fix(cbio): drop the unverified mg/dL claim from the raw record
shroominic Sep 18, 2026
a53b00f
fix(cbio): render the closed GS1 phase, not the driver's status text
shroominic Sep 18, 2026
4d9ee95
chore(release): align the 0.4.0 identity with main and the shipped cg…
shroominic Sep 18, 2026
a580afa
chore(release): carry the cgm_cbio version into the app lockfile
shroominic Sep 18, 2026
0dafd7a
docs(cbio): record that the fixture encoding is not a security control
shroominic Sep 18, 2026
f457b9c
Merge remote-tracking branch 'origin/fix/cbio-integration-test-format…
shroominic Sep 18, 2026
d03e791
Merge remote-tracking branch 'origin/fix/cbio-ble-transport-formattin…
shroominic Sep 18, 2026
3fb9da1
Merge remote-tracking branch 'origin/fix/cbio-app-test-formatting' in…
shroominic Sep 18, 2026
cdb13c2
Merge remote-tracking branch 'origin/fix/cbio-masked-vector-literals'…
shroominic Sep 18, 2026
2f65839
Merge remote-tracking branch 'origin/docs/cbio-vendor-material-review…
shroominic Sep 18, 2026
4812c87
Merge remote-tracking branch 'origin/docs/cbio-auth-material-redactio…
shroominic Sep 18, 2026
b31f724
Merge remote-tracking branch 'origin/fix/release-identity-metadata' i…
shroominic Sep 18, 2026
59b0a6d
Merge remote-tracking branch 'origin/fix/cbio-progress-copy' into rel…
shroominic Sep 18, 2026
e9d3eeb
style(cbio): format the app surface test after the progress-copy fix
shroominic Sep 18, 2026
8e3dcba
fix(ios): record the integration_test pod the sensor lane added
shroominic Sep 18, 2026
c397761
fix(session): bound automatic reconnect and stop retrying a refused c…
shroominic Sep 18, 2026
a719aab
fix(cbio): read private-bench evidence on the Linux runner
shroominic Sep 18, 2026
d86bba7
fix(cbio): give every closed failure its own code and its own sentence
shroominic Sep 18, 2026
f483880
fix(cbio): disclose the positions the stored history never received
shroominic Sep 18, 2026
6ec7ff2
fix(cbio): give the device harnesses a real verdict (#155)
shroominic Sep 18, 2026
e856f16
feat(cbio): record a durable redacted GS1 evidence artifact (#156)
shroominic Sep 18, 2026
0d873f6
Merge remote-tracking branch 'origin/fix/ios-podfile-lock-integration…
shroominic Sep 18, 2026
018dd90
Merge remote-tracking branch 'origin/fix/cbio-private-bench-linux' in…
shroominic Sep 18, 2026
a7c21bc
fix(cbio): require injected vendor material instead of compiled const…
shroominic Sep 18, 2026
05785b0
fix(cbio): resolve the live lane's vendor material from an injected s…
shroominic Sep 18, 2026
0dc7a57
test(cbio): pin the GS1 surface to the timestamp-free reading it publ…
shroominic Sep 18, 2026
7549756
chore(release): advance the app-live lane to its injected-credential tip
shroominic Sep 18, 2026
d255bc6
Merge remote-tracking branch 'origin/test/cbio-timestamp-guard' into …
shroominic Sep 18, 2026
a6a30ca
chore(release): absorb the bounded-reconnect fix onto the redacted cr…
shroominic Sep 18, 2026
2461f15
chore(release): absorb the GS1 failure taxonomy onto the aggregate
shroominic Sep 18, 2026
50fa6c7
chore(release): absorb the stored-history hole disclosure
shroominic Sep 18, 2026
ad1ec4e
chore(release): absorb the device-harness verdicts onto the redacted …
shroominic Sep 18, 2026
5297e28
Merge remote-tracking branch 'origin/feature/cbio-gs1-evidence-artifa…
shroominic Sep 18, 2026
94cb0be
Merge remote-tracking branch 'origin/fix/cbio-archive-unit-claim' int…
shroominic Sep 18, 2026
0490128
fix(security): prove and scope the cgm_cbio vendor-material guard
shroominic Sep 18, 2026
859ee1b
chore(release): format the absorbed lane and close two union resolutions
shroominic Sep 18, 2026
38c1d5f
chore(release): exclude the raw-record unit-claim removal from this c…
shroominic Sep 18, 2026
a084d8f
test(cbio): give the new failure-taxonomy cases injected material
shroominic Sep 18, 2026
27ffff6
test(capture): wait for the status condition, not a fixed event-loop …
shroominic Sep 18, 2026
92a1de2
Merge remote-tracking branch 'origin/fix/protocol-capture-status-flak…
shroominic Sep 18, 2026
4a865cd
docs(release): record the absorbed sensor-lane packaging in both chan…
shroominic Sep 18, 2026
ba9057f
test(cbio): pin the GS1 surface to the timestamp-free reading it publ…
shroominic Sep 18, 2026
9de5544
feat(cbio): anchor the GS1 record index to the clock the app set
shroominic Sep 18, 2026
c1aaa39
fix(cbio): judge the live surface by receipt time, not a sensor clock
shroominic Sep 18, 2026
48e4d81
fix(app): release the live session on dispose and stop background pol…
shroominic Sep 18, 2026
2a3168e
fix(session): bound automatic reconnect and stop retrying a refused c…
shroominic Sep 18, 2026
6ec9318
fix(cbio): give every closed failure its own code and its own sentence
shroominic Sep 18, 2026
77795f9
fix(cbio): disclose the positions the stored history never received
shroominic Sep 18, 2026
c19f68a
fix(cbio): drop the unverified mg/dL claim from the raw record
shroominic Sep 18, 2026
c85f827
Merge main into the GS1 sensor feature line
shroominic Sep 18, 2026
128d952
Merge the app-live lane tip into the GS1 feature consolidation
shroominic Sep 18, 2026
83df370
chore(security): allowlist the superseded masked-vector fixture
shroominic Sep 18, 2026
3eca4f4
chore(security): absorb the repository secret-scanning policy
shroominic Sep 18, 2026
bb2619d
fix(cbio): read the raw payload word, not the empty packed field (G1)
shroominic Sep 18, 2026
6355da4
docs(cbio): record the payload-word identity and the two-decoder comp…
shroominic Sep 18, 2026
f67aa89
fix(cbio): reconcile the payload-word rename across the session and i…
shroominic Sep 18, 2026
2175407
fix(cbio): grant the device harness its BLE permissions in the eviden…
shroominic Sep 18, 2026
65a927b
fix(cbio): keep the authenticated harness from stranding its GATT client
shroominic Sep 18, 2026
4254acf
fix(cbio): give the harness a scan pass that bounds and closes itself
shroominic Sep 18, 2026
be9b47a
fix(cbio): name the sensor counter a counter, not a clock
shroominic Sep 18, 2026
fe89da1
docs(cbio): audit which decode path reads which record word (#207)
shroominic Sep 18, 2026
b88ed02
docs(cbio): record why a GS1 scan finds nothing while the phone scree…
shroominic Sep 18, 2026
269578f
docs(cbio): cite the direct evidence for the screen-off failure window
shroominic Sep 18, 2026
ec83adc
fix(cbio): never read a declined scan as "no sensor nearby" (#211)
shroominic Sep 18, 2026
14626f6
fix(cbio): refuse and surface a restarted sensor counter
shroominic Sep 18, 2026
e6f6f35
test(cbio): bound and report both halves of the screen-off scan harness
shroominic Sep 18, 2026
7e58f86
fix(release): inject CBIO material into production builds
shroominic Sep 19, 2026
4cca7d1
fix(cbio): harden GS1 session I/O
shroominic Sep 19, 2026
c219345
fix(cbio): ignore queued terminal session timers
shroominic Sep 19, 2026
b0fc74b
test(cbio): cover terminal callback matrix
shroominic Sep 19, 2026
9b46082
fix(cbio): contain raw values outside glucose surfaces
shroominic Sep 19, 2026
8447528
fix(cbio): reconcile persisted counter witnesses
shroominic Sep 19, 2026
a597034
fix(cbio): preserve validated checkpoint on disconnect
shroominic Sep 19, 2026
83f2fcd
docs(cbio): record combined release readiness baseline
shroominic Sep 19, 2026
64dc0f6
docs(cbio): coordinate host and polling ownership
shroominic Sep 19, 2026
d5075a7
fix(cbio): simplify raw sensor dashboard presentation
shroominic Sep 19, 2026
221c2aa
docs(cbio): record reviewed dashboard integration
shroominic Sep 19, 2026
5f3a650
feat(cbio): expose confirmed resume witness binding
shroominic Sep 19, 2026
7057f68
fix(cbio): pace continuous polling without a lifetime cap
shroominic Sep 19, 2026
0c56123
docs(cbio): record reviewed polling integration
shroominic Sep 19, 2026
461698a
docs(cbio): track host review and release gates
shroominic Sep 19, 2026
c7fe61f
fix(cbio): persist proven raw history with atomic resume state
shroominic Sep 19, 2026
b60d805
fix(cbio): reject cross-driver snapshot side effects
shroominic Sep 19, 2026
dce71a0
fix(cbio): identify incomplete recovery history on home
shroominic Sep 19, 2026
6905e1f
test(cbio): add synthetic archive recovery preview
shroominic Sep 19, 2026
9b0d8c9
docs(cbio): distinguish raw support and configured artifact policy
shroominic Sep 19, 2026
1addf7a
docs(cbio): record combined fixture integration gate
shroominic Sep 19, 2026
4510b73
test(cbio): verify real host resume flow and align surface fixtures
shroominic Sep 19, 2026
dfaeaab
docs(cbio): record verified source and remaining release gates
shroominic Sep 19, 2026
3eb98a8
fix: hide glucose chart tips for raw CBIO sessions
shroominic Sep 19, 2026
ca552cd
test: preserve AiDEX chart tips for provisional readings
shroominic Sep 19, 2026
2de41ba
fix: explain CBIO history failures with safe support references
shroominic Sep 19, 2026
1f20607
test: assert retained CBIO error progress preconditions
shroominic Sep 19, 2026
8ae95aa
fix: separate sensor detail labels from values
shroominic Sep 19, 2026
ac016e3
fix: distinguish closed CBIO counter-confirmation failures
shroominic Sep 19, 2026
46e51ea
docs: pin GS1 shared UI restoration boundary
shroominic Sep 19, 2026
79cd522
docs: plan bounded private GS1 clock witness probe
shroominic Sep 19, 2026
09fc170
docs: clarify GS1 normalized progress and probe gates
shroominic Sep 19, 2026
f167da8
refactor(cbio): define private state store boundary
shroominic Sep 19, 2026
a16fc9e
refactor: extract canonical sensor state identity
shroominic Sep 19, 2026
fb078df
fix: preserve GS1 raw archives in private restricted state
shroominic Sep 19, 2026
9da2b3a
fix(cbio): retain raw acquisition behind private storage boundary
shroominic Sep 19, 2026
68e6925
fix(cbio): keep acquisition details out of public diagnostics
shroominic Sep 19, 2026
73863c6
fix(cbio): exclude unverified advertisement fallback
shroominic Sep 19, 2026
98e688e
fix(cbio): sanitize public acquisition events and terminal conflicts
shroominic Sep 19, 2026
2df240d
refactor: route private sensor handoff through shared controller hooks
shroominic Sep 19, 2026
1bc49ee
fix: preserve private sensor state across guarded controller handoffs
shroominic Sep 19, 2026
586607f
test: drain asynchronous cleanup before Yuwell confirmation settles
shroominic Sep 19, 2026
7272387
fix: include normalized vendor records in shared history analytics
shroominic Sep 19, 2026
53e59e3
fix: use normalized quality policy for visible wellness history
shroominic Sep 19, 2026
bce5dc1
test: specify shared normalized sensor presentation parity
shroominic Sep 19, 2026
ca9c58c
test: retain opt-in narrow shared-layout audit matrix
shroominic Sep 19, 2026
907ea62
test: require raw-value rejection independent of sensor identity
shroominic Sep 19, 2026
b9c2b0d
test: replace GS1 diagnostic surfaces with shared contract assertions
shroominic Sep 19, 2026
61392b1
fix: restore shared normalized sensor presentation for GS1
shroominic Sep 19, 2026
c831df9
fix: keep normalized controller lifecycle sensor neutral
shroominic Sep 19, 2026
816e8a6
fix: project private sensor metadata before shared snapshots
shroominic Sep 19, 2026
8733e96
docs: align GS1 compatibility with private driver boundary
shroominic Sep 19, 2026
5cca4d8
docs: plan private GS1 full-input preservation
shroominic Sep 19, 2026
228030d
fix: preserve complete GS1 input envelopes
shroominic Sep 19, 2026
cdfdde8
fix: atomically persist admitted GS1 inputs
shroominic Sep 19, 2026
9af6bbd
fix: retain first-observed GS1 reindex provenance
shroominic Sep 19, 2026
6fc01ae
fix: integrate restricted GS1 full-input storage
shroominic Sep 19, 2026
70b86b8
test: cover GS1 throwing cleanup boundaries
shroominic Sep 19, 2026
f68e4bf
docs: correct GS1 shared UI and normalized output claims
shroominic Sep 19, 2026
c008b6b
fix(cbio): add private closed failure trace
shroominic Sep 19, 2026
23ad7c8
fix(cbio): preserve one isolated recovery acquisition
shroominic Sep 19, 2026
ffa8f4d
fix(cbio): guard one successor acquisition after witness mismatch
shroominic Sep 19, 2026
4cd6198
docs(cbio): record reviewed acquisition recovery completion
shroominic Sep 19, 2026
7e81a73
chore(cbio): add allowlisted acquisition milestones
shroominic Sep 19, 2026
ddf0049
fix(cbio): keep reconnect acquisition read-only
shroominic Sep 21, 2026
e5ba765
docs(cbio): correct read-only session contract
shroominic Sep 21, 2026
d2ff49c
test(app): keep provisional restore fixture fresh
shroominic Sep 21, 2026
713224f
feat(cbio): add bounded private GS1 capture
shroominic Sep 21, 2026
ac558b9
fix(cbio): harden private capture admission
shroominic Sep 21, 2026
a7cbeed
fix(cbio): quarantine unsafe capture results
shroominic Sep 21, 2026
35b0d91
fix: run GS1 capture standalone
shroominic Sep 21, 2026
7bc307c
fix: accept modern Android package paths
shroominic Sep 21, 2026
28180aa
fix: harden GS1 READY parsing
shroominic Sep 22, 2026
d204f39
fix(gS1): support Owner first-install capture
shroominic Sep 22, 2026
df2e1c7
test: bind CBIO driver fixture package
shroominic Sep 22, 2026
c808951
fix: keep GS1 capture separate from normal app
shroominic Sep 23, 2026
a03e697
fix(cbio): accept producer capture IDs
shroominic Sep 23, 2026
bd8ed17
fix: record GS1 native disconnect diagnostics
shroominic Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
/packages/cgm_ble/ @shroominic
/packages/cgm_ble_flutter/ @shroominic
/packages/cgm_aidex/ @shroominic
/packages/cgm_libre2/ @shroominic
/packages/cgm_yuwell_anytime/ @shroominic
/.github/ @shroominic
/docs/ @shroominic
/SECURITY.md @shroominic
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ body:
- cgm_ble
- cgm_ble_flutter
- cgm_aidex
- cgm_libre2
- cgm_yuwell_anytime
- Build, tooling, or documentation
- Unsure
validations:
Expand Down
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,28 @@ updates:
labels:
- dependencies

- package-ecosystem: pub
directory: /packages/cgm_libre2
schedule:
interval: weekly
day: monday
time: "06:20"
timezone: Etc/UTC
open-pull-requests-limit: 3
labels:
- dependencies

- package-ecosystem: pub
directory: /packages/cgm_yuwell_anytime
schedule:
interval: weekly
day: monday
time: "06:25"
timezone: Etc/UTC
open-pull-requests-limit: 3
labels:
- dependencies

- package-ecosystem: gradle
directory: /openhealth/android
schedule:
Expand Down
35 changes: 33 additions & 2 deletions .github/workflows/release-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ jobs:
}
done

- name: Require CBIO vendor material for the release build
shell: bash
env:
CBIO_VENDOR_STREAM_KEY_HEX: ${{ secrets.CBIO_VENDOR_STREAM_KEY_HEX }}
CBIO_VENDOR_AUTH_MATERIAL_HEX: ${{ secrets.CBIO_VENDOR_AUTH_MATERIAL_HEX }}
CBIO_VENDOR_AUTH_TRIGGER_HEX: ${{ secrets.CBIO_VENDOR_AUTH_TRIGGER_HEX }}
run: |
set -euo pipefail
for secret_name in \
CBIO_VENDOR_STREAM_KEY_HEX \
CBIO_VENDOR_AUTH_MATERIAL_HEX \
CBIO_VENDOR_AUTH_TRIGGER_HEX; do
test -n "${!secret_name:-}" || {
printf 'Required android-release secret %s is missing.\n' "$secret_name" >&2
exit 1
}
done

- name: Set up Java
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
Expand All @@ -200,12 +218,16 @@ jobs:
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
CBIO_VENDOR_STREAM_KEY_HEX: ${{ secrets.CBIO_VENDOR_STREAM_KEY_HEX }}
CBIO_VENDOR_AUTH_MATERIAL_HEX: ${{ secrets.CBIO_VENDOR_AUTH_MATERIAL_HEX }}
CBIO_VENDOR_AUTH_TRIGGER_HEX: ${{ secrets.CBIO_VENDOR_AUTH_TRIGGER_HEX }}
run: |
set -euo pipefail
umask 077
keystore_path="$RUNNER_TEMP/openglucose-release.jks"
cbio_defines_path="$RUNNER_TEMP/openglucose-cbio-vendor.json"
cleanup() {
rm -f -- "$keystore_path"
rm -f -- "$keystore_path" "$cbio_defines_path"
}
trap cleanup EXIT
trap 'exit 130' INT
Expand All @@ -214,9 +236,18 @@ jobs:
> "$keystore_path"
test -s "$keystore_path"
unset ANDROID_KEYSTORE_BASE64
jq -n \
'{CBIO_VENDOR_STREAM_KEY_HEX: env.CBIO_VENDOR_STREAM_KEY_HEX,
CBIO_VENDOR_AUTH_MATERIAL_HEX: env.CBIO_VENDOR_AUTH_MATERIAL_HEX,
CBIO_VENDOR_AUTH_TRIGGER_HEX: env.CBIO_VENDOR_AUTH_TRIGGER_HEX}' \
> "$cbio_defines_path"
chmod 600 "$cbio_defines_path"
test -s "$cbio_defines_path"
unset CBIO_VENDOR_STREAM_KEY_HEX CBIO_VENDOR_AUTH_MATERIAL_HEX CBIO_VENDOR_AUTH_TRIGGER_HEX
export ANDROID_KEYSTORE_PATH="$keystore_path"
cd openhealth
flutter build apk --release --no-pub
flutter build apk --release --no-pub \
--dart-define-from-file="$cbio_defines_path"

- name: Verify signer, identity, version, and digest
id: verify
Expand Down
17 changes: 15 additions & 2 deletions .github/workflows/release-testflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ jobs:
ASC_API_ISSUER_ID: ${{ vars.ASC_API_ISSUER_ID }}
ASC_API_KEY_ID: ${{ vars.ASC_API_KEY_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
CBIO_VENDOR_STREAM_KEY_HEX: ${{ secrets.CBIO_VENDOR_STREAM_KEY_HEX }}
CBIO_VENDOR_AUTH_MATERIAL_HEX: ${{ secrets.CBIO_VENDOR_AUTH_MATERIAL_HEX }}
CBIO_VENDOR_AUTH_TRIGGER_HEX: ${{ secrets.CBIO_VENDOR_AUTH_TRIGGER_HEX }}
IOS_APP_STORE_PROFILE_BASE64: ${{ secrets.IOS_APP_STORE_PROFILE_BASE64 }}
IOS_DISTRIBUTION_CERTIFICATE_SHA1: ${{ vars.IOS_DISTRIBUTION_CERTIFICATE_SHA1 }}
IOS_DISTRIBUTION_P12_BASE64: ${{ secrets.IOS_DISTRIBUTION_P12_BASE64 }}
Expand Down Expand Up @@ -284,7 +287,7 @@ jobs:
chmod 600 "$2"
}

for name in APPLE_TEAM_ID APP_BUNDLE_ID APP_STORE_PROFILE_UUID ASC_API_ISSUER_ID ASC_API_KEY_ID ASC_API_KEY_P8_BASE64 IOS_APP_STORE_PROFILE_BASE64 IOS_DISTRIBUTION_CERTIFICATE_SHA1 IOS_DISTRIBUTION_P12_BASE64 IOS_DISTRIBUTION_P12_PASSWORD IOS_LIVE_ACTIVITY_PROFILE_BASE64 LIVE_ACTIVITY_APP_STORE_PROFILE_UUID LIVE_ACTIVITY_BUNDLE_ID TESTFLIGHT_GROUP TESTFLIGHT_GROUP_ID TESTFLIGHT_INTERNAL_TESTER_ID; do
for name in APPLE_TEAM_ID APP_BUNDLE_ID APP_STORE_PROFILE_UUID ASC_API_ISSUER_ID ASC_API_KEY_ID ASC_API_KEY_P8_BASE64 CBIO_VENDOR_STREAM_KEY_HEX CBIO_VENDOR_AUTH_MATERIAL_HEX CBIO_VENDOR_AUTH_TRIGGER_HEX IOS_APP_STORE_PROFILE_BASE64 IOS_DISTRIBUTION_CERTIFICATE_SHA1 IOS_DISTRIBUTION_P12_BASE64 IOS_DISTRIBUTION_P12_PASSWORD IOS_LIVE_ACTIVITY_PROFILE_BASE64 LIVE_ACTIVITY_APP_STORE_PROFILE_UUID LIVE_ACTIVITY_BUNDLE_ID TESTFLIGHT_GROUP TESTFLIGHT_GROUP_ID TESTFLIGHT_INTERNAL_TESTER_ID; do
require_value "$name"
done
if [[ "$RELEASE_AUDIENCE" == external ]]; then
Expand All @@ -309,6 +312,16 @@ jobs:
test ! -e "$material_dir" && test ! -e "$state_dir" && test ! -e "$keychain_path"
mkdir -m 700 "$material_dir" "$state_dir"

cbio_defines_path="$material_dir/cbio-vendor.json"
jq -n \
'{CBIO_VENDOR_STREAM_KEY_HEX: env.CBIO_VENDOR_STREAM_KEY_HEX,
CBIO_VENDOR_AUTH_MATERIAL_HEX: env.CBIO_VENDOR_AUTH_MATERIAL_HEX,
CBIO_VENDOR_AUTH_TRIGGER_HEX: env.CBIO_VENDOR_AUTH_TRIGGER_HEX}' \
> "$cbio_defines_path"
chmod 600 "$cbio_defines_path"
test -s "$cbio_defines_path"
unset CBIO_VENDOR_STREAM_KEY_HEX CBIO_VENDOR_AUTH_MATERIAL_HEX CBIO_VENDOR_AUTH_TRIGGER_HEX

asc_key_path="$material_dir/AuthKey_$ASC_API_KEY_ID.p8"
p12_path="$material_dir/distribution.p12"
app_profile_path="$material_dir/app.mobileprovision"
Expand Down Expand Up @@ -359,7 +372,7 @@ jobs:
cd openhealth
env -u GEM_HOME -u GEM_PATH \
"${phase_environment[@]}" \
APPLE_TEAM_ID="$APPLE_TEAM_ID" APP_BUNDLE_ID="$APP_BUNDLE_ID" APP_STORE_PROFILE_UUID="$APP_STORE_PROFILE_UUID" ASC_API_ISSUER_ID="$ASC_API_ISSUER_ID" ASC_API_KEY_ID="$ASC_API_KEY_ID" ASC_API_KEY_PATH="$asc_key_path" DISTRIBUTE_INTERNAL=yes LIVE_ACTIVITY_APP_STORE_PROFILE_UUID="$LIVE_ACTIVITY_APP_STORE_PROFILE_UUID" LIVE_ACTIVITY_BUNDLE_ID="$LIVE_ACTIVITY_BUNDLE_ID" RELEASE_APPROVED=yes RELEASE_COMMIT="$RELEASE_COMMIT" RELEASE_VERSION="$RELEASE_VERSION" TESTFLIGHT_CHANGELOG="$changelog" TESTFLIGHT_EXTERNAL_TESTER_COUNT="$TESTFLIGHT_EXTERNAL_TESTER_COUNT" TESTFLIGHT_EXTERNAL_TESTER_IDS_SHA256="$TESTFLIGHT_EXTERNAL_TESTER_IDS_SHA256" TESTFLIGHT_GROUP="$TESTFLIGHT_GROUP" TESTFLIGHT_GROUP_ID="$TESTFLIGHT_GROUP_ID" TESTFLIGHT_INTERNAL_TESTER_ID="$TESTFLIGHT_INTERNAL_TESTER_ID" TESTFLIGHT_MODE="$RELEASE_AUDIENCE" TESTFLIGHT_NOTIFICATION_RECEIPT_PATH="$state_dir/notification.json" TESTFLIGHT_UPLOAD_PROVENANCE_PATH="$state_dir/upload-provenance.json" \
APPLE_TEAM_ID="$APPLE_TEAM_ID" APP_BUNDLE_ID="$APP_BUNDLE_ID" APP_STORE_PROFILE_UUID="$APP_STORE_PROFILE_UUID" ASC_API_ISSUER_ID="$ASC_API_ISSUER_ID" ASC_API_KEY_ID="$ASC_API_KEY_ID" ASC_API_KEY_PATH="$asc_key_path" CBIO_DART_DEFINE_FROM_FILE="$cbio_defines_path" DISTRIBUTE_INTERNAL=yes LIVE_ACTIVITY_APP_STORE_PROFILE_UUID="$LIVE_ACTIVITY_APP_STORE_PROFILE_UUID" LIVE_ACTIVITY_BUNDLE_ID="$LIVE_ACTIVITY_BUNDLE_ID" RELEASE_APPROVED=yes RELEASE_COMMIT="$RELEASE_COMMIT" RELEASE_VERSION="$RELEASE_VERSION" TESTFLIGHT_CHANGELOG="$changelog" TESTFLIGHT_EXTERNAL_TESTER_COUNT="$TESTFLIGHT_EXTERNAL_TESTER_COUNT" TESTFLIGHT_EXTERNAL_TESTER_IDS_SHA256="$TESTFLIGHT_EXTERNAL_TESTER_IDS_SHA256" TESTFLIGHT_GROUP="$TESTFLIGHT_GROUP" TESTFLIGHT_GROUP_ID="$TESTFLIGHT_GROUP_ID" TESTFLIGHT_INTERNAL_TESTER_ID="$TESTFLIGHT_INTERNAL_TESTER_ID" TESTFLIGHT_MODE="$RELEASE_AUDIENCE" TESTFLIGHT_NOTIFICATION_RECEIPT_PATH="$state_dir/notification.json" TESTFLIGHT_UPLOAD_PROVENANCE_PATH="$state_dir/upload-provenance.json" \
./scripts/testflight.sh
)

Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

vendor-material-guard:
name: Vendor Material Guard
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install checksum-pinned quality tools
run: make tooling-bootstrap

- name: Reject vendor material and prove the rule with a canary
run: ./scripts/check-cbio-vendor-material.sh

dependency-review:
name: Dependency Review
if: github.event_name == 'pull_request'
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ app.*.map.json
*.log
*.swp

# Private physical-device captures (the harness also rejects Git-local output)
openglucose-protocol-captures/
.openglucose-passive-capture
bugreport-*.zip
btsnoop_hci.log
*.pcap
*.pcapng

# Apple credentials / certs (defense in depth — these should never be in repo)
*.p8
*.p12
Expand Down
39 changes: 39 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Secret scanning policy for the repository sweep.
#
# The default rule set is extended, never replaced, and no path is exempt: a
# secret introduced anywhere in the tree still fails the sweep. Every entry
# below either names a value that is already in this repository's history and is
# not a credential, records the single historical binding that holds a
# key-derived test vector, or scopes one obsolete commit that a release
# aggregate still reaches through a merge it later reverted.

title = "OpenGlucose secret scanning policy"

[extend]
useDefault = true

[allowlist]
description = "Known non-secret values, one recorded key-derived fixture binding, and one superseded commit."
regexTarget = "line"
regexes = [
# macOS self-test storage entry name: a local keychain label, not a credential.
'''^\s*const testKey = 'ct5[.]macos[.]selftest[.]v1';$''',
# App Store Connect issuer identifier: an identifier, not a credential. The
# credential for that API is a private key file that is not in this repository.
'''API_ISSUER_ID="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"''',
# Test-only fixture defaults in a Dart test helper, bounded to that shape.
'''^\s*String token = '[A-Za-z0-9_-]{24}',$''',
# RECORDED, NOT DISMISSED: this binding held a published synthetic masking
# vector, which is a function of the vendor stream key and therefore material
# rather than a false positive. It is already public and no scanner setting can
# un-publish it; the binding is removed from every tip and the tree guard in
# `security/gitleaks-vendor-material.toml` rejects it or any successor at the
# tip. Purging the history and rotating the material are decision requests, not
# something this policy can settle. Bounded to this one binding name.
'''const _authMasked = ''',
]
# The sensor lane's first redaction commit carried a synthetic, key-shaped test
# fixture. That commit has been rewritten and is no longer a tip, but
# `release/v0.4.0-lane-append` merged it and then reverted the merge, so it is
# still reachable. Bounded to that one commit; the tip guard covers every tip.
commits = ["3be16fc212b699d7e9be1852dcbbac8bec6e3ec0"]
73 changes: 73 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,79 @@ expectations are defined in [docs/compatibility.md](docs/compatibility.md).

## [Unreleased]

### Fixed

- Keep CBIO raw sensor values out of glucose charts, target ranges, native live
values, wellness summaries and glucose export columns, including restored
CBIO records with missing quality flags. Show the unscaled raw integer without
a glucose unit; preserve stored raw records and diagnostic export fields.

### Added

- Add the `cgm_cbio` GS1 live driver and app surface: `FF30` discovery mapping,
read-only `FF31` reply inspection, an authenticated, fail-closed read session
with bounded history sync, and live glucose rows. Vendor link material is
injected at build time, never compiled into the package. SiSensing UUID and
protocol evidence stay recorded. Record a separately authorized Mac bench
probe in the evidence document.
- Add a durable, redacted GS1 evidence artifact for device-backed runs:
`make cbio-gs1-evidence` records one `gs1-session-<utc>-<harness>.json` per run
with the session outcome, record counts and index ranges, closed error
taxonomy, and app/harness identity, and indexes it. Both device harnesses now
assert the record's invariants instead of printing lines for a human to read.
- Add a self-proving vendor-material guard (`make vendor-material-guard`, a
dedicated security workflow job): the rule rejects a synthetic canary and must
also clear the checked-out tree, so a rule that stops matching fails the check
rather than reporting a clean repository.
- Add a private Android Gen1 Libre 2 receiver path with an explicitly initiated
NFC streaming exchange, encrypted receiver state, durable login counters,
exact-target Bluetooth connection, and CRC-validated packet diagnostics.
A separate GPL reference decoder can display provisional current estimates
in the explicit private bench build. Neither path is enabled in normal builds.
- Keep sensor setup inline on the home screen with automatic Bluetooth
discovery. A `Can't find your sensor?` action opens model-specific help;
AiDEX/LinX stays on Bluetooth, while an explicit FreeStyle Libre 2 selection
opens guided NFC in debug capture builds. Move sample data to Settings.
- Add an identifier-free Libre NFC scan event bridge with an animated
listening state, neutral tag detection, verified model identification, and
generic retry states. Raw tag identifiers and protocol bytes stay in the
bounded app-private capture.
- Add a pure-Dart, target-unverified Libre 2-family offline protocol core for
UUID/topology classification, observation-only sequence validation, and
strict opaque fragment assembly. It contains no live sensor I/O, keys,
authentication, activation, decryption, or glucose decoding.
- Add a pure-Dart, target-unverified Yuwell Anytime CT5 offline protocol core
with synthetic checksum, framing, transform, authentication-arithmetic, and
record-parser tests. It contains no BLE transport, live driver, activation,
proprietary binary, real identifier, or vendor-native glucose algorithm.
- Add an app-owned multi-driver registry that routes one physical BLE scan by
stable vendor driver ID while preserving existing AiDEX identifiers, storage
keys, histories, and presentation behavior.

### Changed

- Keep the current NFC calibration patch separate from the frozen Libre 2
Bluetooth receiver patch. Verify the receiver binding and all FRAM CRCs
before saving calibration for the private debug decoder.
- Reuse a confirmed Libre receiver after a fresh, same-sensor NFC read instead
of repeating streaming setup. Failed or stale verification cannot start a
new NFC enable attempt.
- Restore the saved Libre receiver before discovery, and wait for a fresh
exact-target advertisement before one explicit Bluetooth connection attempt.
Preserve the completed NFC setup and login counters across app restarts.
- Show closed, user-readable Libre connection failures instead of raw internal
codes, and distinguish radio search from successful data reception.
- Full-product protocol capture builds can keep the existing AiDEX and LinX
driver available while passively recording Libre-family observations. The
strict capture-only entry point remains observation-only.
- The one-shot target-unverified Libre patch-information probe now requires an
exact eight-byte ISO 15693 identity, derives its manufacturer byte from that
identity, accepts only an exact successful seven-byte response, and rejects
unknown model signatures before publishing a UI result.
- The Libre NFC animation now starts only after the native reader confirms NFC
and capture readiness. Reader loss publishes a closed retry state; reopening
or retrying waits for a fresh native state instead of inventing readiness.

## [0.1.6] - 2026-08-31

### Added
Expand Down
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ SHELL := /bin/sh

.PHONY: help bootstrap tooling-bootstrap tooling-check hooks format \
format-check lint typecheck test-unit test-integration test-e2e test \
cbio-gs1-evidence \
cbio-gs1-decode-comparison \
build build-android build-web build-ios build-macos test-ios-native \
test-macos-native \
verify-android-release-signing check
verify-android-release-signing vendor-material-guard check

platform_checks :=
ifeq ($(shell uname -s),Darwin)
Expand All @@ -26,6 +28,9 @@ tooling-bootstrap: ## Install checksum-pinned repository quality tools.
tooling-check: tooling-bootstrap ## Run ShellCheck and actionlint with pinned versions.
@./scripts/check-tooling.sh

vendor-material-guard: tooling-bootstrap ## Reject vendor material and prove the guard with a canary.
@./scripts/check-cbio-vendor-material.sh

hooks: ## Install the pinned Lefthook Git hooks.
@./scripts/install-lefthook.sh

Expand All @@ -50,6 +55,12 @@ test-integration: ## Run every tagged or directory-based integration test.
test-e2e: ## Report the explicitly deferred device end-to-end lane.
@./scripts/flutter-workspace.sh test-e2e

cbio-gs1-evidence: ## Run one GS1 session on a device and record a redacted artifact.
@./scripts/cbio-gs1-evidence.sh

cbio-gs1-decode-comparison: ## Replay one captured GS1 log as a side-by-side decode.
@./scripts/cbio-gs1-decode-comparison.sh

test: test-unit test-integration ## Run all locally configured automated tests.

build: build-android build-web ## Build the portable Android and web targets.
Expand All @@ -75,4 +86,4 @@ test-macos-native: ## Run the macOS RunnerTests on this Mac.
verify-android-release-signing: ## Prove Android release signing fails closed without credentials.
@./scripts/flutter-workspace.sh verify-android-release-signing

check: tooling-check format-check lint test build verify-android-release-signing $(platform_checks) ## Run every required CI gate supported by this host.
check: tooling-check vendor-material-guard format-check lint test build verify-android-release-signing $(platform_checks) ## Run every required CI gate supported by this host.
Loading
Loading
0