diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..7f54a51a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# GitHub's funding config only accepts URLs, not raw wallet addresses, so the +# "Sponsor" button points at DONATE.md where the BTC/EVM addresses live. +custom: + - https://github.com/OpenStrap/edge/blob/main/DONATE.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..dce06bc6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,94 @@ +name: Bug report +description: Something in the app is broken or wrong +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for reporting. A couple of things make bugs much faster to fix: + the app version, and whether the number is *wrong* or *missing* — those + are usually different causes. + + - type: textarea + id: what + attributes: + label: What happened? + description: What you saw, and what you expected instead. + placeholder: | + Readiness showed "—" all morning even though the band synced overnight. + I expected a score by the time I woke up. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: If you can. "It just happens every morning" is a valid answer. + placeholder: | + 1. Wear the band overnight + 2. Open the app in the morning + 3. Today screen shows "—" + validations: + required: false + + - type: input + id: version + attributes: + label: App version + description: Profile → scroll to the bottom, or the release you installed. + placeholder: "0.9.20" + validations: + required: true + + - type: dropdown + id: platform + attributes: + label: Platform + options: + - iOS (TestFlight) + - iOS (sideloaded IPA) + - Android (APK) + validations: + required: true + + - type: input + id: device + attributes: + label: Phone model and OS version + placeholder: "Pixel 8, Android 15 / iPhone 15 Pro, iOS 18.5" + validations: + required: false + + - type: dropdown + id: band + attributes: + label: Which band? + options: + - WHOOP 4.0 + - WHOOP 5.0 / MG (experimental — expect breakage) + - Not sure + validations: + required: true + + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: >- + Very helpful for anything visual. Note this issue is PUBLIC and stays + public — please redact health data, dates, names, and any device or + account identifiers before uploading. Blurring the numbers is fine; + we usually only need the layout and the state of the screen. + validations: + required: false + + - type: checkboxes + id: checks + attributes: + label: Quick checks + options: + - label: The official WHOOP app is not also connected to this band + required: false + - label: I've searched existing issues for this + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..987f63b5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,31 @@ +blank_issues_enabled: true +contact_links: + - name: Protocol / byte-level finding + url: https://github.com/OpenStrap/protocol/issues/new + about: >- + A new record type, opcode, event, or a field we decode wrongly. Those live + in the protocol repo, not here. + + - name: A new metric, or how one is computed + url: https://github.com/OpenStrap/analytics/issues/new + about: >- + The math lives in the analytics repo. Open it there if you're proposing a + method rather than reporting an app bug. + + - name: Questions and general discussion + url: https://github.com/OpenStrap/edge/discussions + about: >- + Not sure whether something's a bug? Want to ask how a metric works, or + show what you built? Start here. + + - name: Installing on iOS + url: https://github.com/OpenStrap/edge/blob/main/guides/IOS_SIDELOAD.md + about: >- + Install trouble is usually covered by the guide — TestFlight is the easy + path now. + + - name: Report a security vulnerability (private) + url: https://github.com/OpenStrap/edge/security/advisories/new + about: >- + Please don't open a public issue for a security problem — this reports it + privately instead. See SECURITY.md for what's in scope. diff --git a/.github/ISSUE_TEMPLATE/wrong_number.yml b/.github/ISSUE_TEMPLATE/wrong_number.yml new file mode 100644 index 00000000..6a45bf3f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/wrong_number.yml @@ -0,0 +1,85 @@ +name: A metric looks wrong +description: A number is displayed, but you think it's incorrect +labels: ["analytics", "needs-triage"] +body: + - type: markdown + attributes: + value: | + Worth saying up front, so nobody wastes time: **OpenStrap's numbers are + not meant to match WHOOP's.** Different algorithms, published methods, + computed from a reverse-engineered byte stream. "It doesn't match the + WHOOP app" on its own isn't a bug. + + What *is* a bug: a number that's physiologically implausible, one that + contradicts the app's own raw data, one that jumps around without + cause, or one that's confidently wrong when the underlying data is + clearly missing. + + - type: input + id: metric + attributes: + label: Which metric? + placeholder: "Readiness / RHR / Sleep stages / Strain / Steps / …" + validations: + required: true + + - type: textarea + id: shown + attributes: + label: What it showed, and why you think it's wrong + description: >- + Include the value, the day, and what you'd have expected. If another + screen in the app disagrees with it, that's a strong signal — say so. + placeholder: | + Readiness 100 after about 10 minutes of wear. There's no overnight data + yet, so it shouldn't be able to produce a confident score at all. + validations: + required: true + + - type: dropdown + id: kind + attributes: + label: What kind of wrong? + options: + - Physiologically implausible (impossible value) + - Contradicts other screens in this app + - Confident number where the data is missing (should show "—") + - Shows "—" where there clearly is data + - Jumps or changes without new data + - Other + validations: + required: true + + - type: input + id: version + attributes: + label: App version + placeholder: "0.9.20" + validations: + required: true + + - type: dropdown + id: band + attributes: + label: Which band? + description: >- + Matters more than it looks — WHOOP 5.0 / MG feeds a thinner record than + 4.0 does, so a metric can be wrong on one and fine on the other. + options: + - WHOOP 4.0 + - WHOOP 5.0 / MG (experimental — expect breakage) + - Not sure + validations: + required: true + + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: >- + The metric screen plus its trend view is ideal. This issue is PUBLIC and + stays public — redact health values, dates, names, and any device or + account identifiers first. The shape of a chart is usually enough; we + don't need your actual numbers to debug this. + validations: + required: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..3b31bb16 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,67 @@ +name: test + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +concurrency: + group: test-${{ github.ref }} + cancel-in-progress: true + +# Read-only: this job only builds and tests. Nothing here needs write access, +# and it executes code from pull requests. +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # Don't leave GITHUB_TOKEN in .git/config where PR-authored test code + # could read it. Nothing in this job pushes back to the repo. + persist-credentials: false + + # PINNED, not `channel: stable`. Two reasons, both found the hard way when + # this workflow first ran: + # + # 1. The repo does NOT currently build on Flutter 3.44.x. phosphor_flutter + # 2.1.0 extends IconData, which became a `final class` in 3.44, so + # every widget test fails to compile: + # "The class 'IconData' can't be extended outside of its library + # because it's a final class." + # Upgrading past 3.41.x needs phosphor_flutter bumped or dropped first. + # 2. CupertinoPageTransitionsBuilder moved between cupertino.dart and + # material.dart across those versions, so theme.dart's imports are + # version-sensitive too. + # + # A floating channel means the toolchain changes underneath an already + # reviewed commit — the same reasoning as the commit-SHA pins for sibling + # packages in pubspec.yaml. Bump this deliberately, with the phosphor + # dependency sorted out in the same change. + - uses: subosito/flutter-action@v2 + with: + flutter-version: 3.41.6 + channel: stable + cache: true + + # Sibling packages resolve from their pinned commit SHAs in pubspec.yaml. + # There is no pubspec_overrides.yaml here — that file is gitignored and + # local-dev only — so CI tests exactly the pins a release would ship. + - name: Install dependencies + run: flutter pub get + + - name: Analyze + run: flutter analyze + + # --concurrency=1: the suite uses sqflite_common_ffi against real database + # files, and parallel workers race on them. + # + # The golden capture (whoop_hist.jsonl) is a real band recording kept + # beside the repo rather than committed to it, so the two derivation-replay + # tests SKIP here and run locally. + - name: Test + run: flutter test --concurrency=1 --reporter=expanded diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..a1f22989 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,116 @@ +# Contributing + +Thanks for looking. This is a small project and PRs genuinely get read. + +## Which repo does my change go in? + +This is the one thing worth getting right before you start, because it decides +where the code lives. OpenStrap is three packages and the split is strict: + +| Your change | Repo | +|---|---| +| A new record type, opcode, event, or anything about the bytes on the wire | [**protocol**](https://github.com/OpenStrap/protocol) | +| A new metric, or a change to how an existing number is computed | [**analytics**](https://github.com/OpenStrap/analytics) | +| Bluetooth reliability, storage, background sync, UI, anything app-shaped | [**edge**](https://github.com/OpenStrap/edge) (here) | + +If you're not sure, open an issue first and ask — it's cheaper than moving code +between repos afterwards. + +## Ground rules + +**Never fabricate a number.** If an input isn't there, the metric returns +`null`, not a plausible-looking guess. Every metric carries a confidence and a +tier (`AUTH` / `HIGH` / `ESTIMATE` / `RELATIVE`), and those need to stay honest. +A metric that quietly invents a value when the data is missing is worse than no +metric. + +**Cite the method.** Anything in analytics implements a published, peer-reviewed +algorithm, and the citation goes in a comment next to the code. If nothing in +the literature fits what you want to do, that's fine — mark it `ESTIMATE`, give +it low confidence, and say so. Don't invent constants and present them as +science. + +**Some ceilings are real, not bugs.** HRV here is PRV derived from 1 Hz beat +timing. Deep sleep is a low-confidence HR-flatness overlay. SpO2 and skin +temperature are relative ADC values, never absolute. These are properties of +what the band actually hands over. Please don't "fix" them by making the output +look more confident than the input justifies. + +**Bump `kAlgoVersion`** (in `lib/compute/derivation_engine.dart`) whenever a +change alters any analytics output. Stored day results are versioned and +immutable; without a bump, devices keep serving stale values. If your bump's +changelog entry cites an analytics change, check that the pinned analytics SHA +in `pubspec.yaml` actually contains it — that mismatch has shipped a bug before. + +**Put logic in the pure policy classes.** Bluetooth decisions belong in +`lib/ble/ble_state.dart` or `lib/sync/sync_policy.dart` as small, testable +classes; the engine wires them together and the policies decide. That's what +makes any of this testable without a band on your wrist. + +## Running it + +```bash +git clone https://github.com/OpenStrap/edge.git +cd edge +cp .env.example .env +flutter pub get +flutter run --dart-define-from-file=.env +``` + +Quit the official WHOOP app before pairing — Bluetooth only lets one app own the +band at a time. + +For local work across all three packages at once, create a `pubspec_overrides.yaml` +(it's gitignored) pointing at your sibling checkouts: + +```yaml +dependency_overrides: + openstrap_protocol: + path: ../protocol + openstrap_analytics: + path: ../analytics +``` + +## Tests + +```bash +flutter analyze +flutter test --concurrency=1 +``` + +`--concurrency=1` matters: the suite runs against real database files and +parallel workers race on them. + +A few tests replay `whoop_hist.jsonl`, a real band capture kept *beside* the +repo rather than committed to it. If you don't have it those tests skip +automatically — that's expected, and CI runs the same way. Everything else runs +everywhere. + +CI runs `flutter analyze` and the full suite on every PR. Please make sure both +are green locally first. + +## Pull requests + +- Branch off `main`. One logical change per PR. +- Explain *why*, not just what. If it fixes an issue, link it. +- If it changes anything a user sees, say what it looked like before and after. +- Protocol changes: say how you verified it. "Decoded N real records off my own + band and the values were plausible" is a perfectly good answer, and honestly + more useful than a unit test alone. +- No `Co-Authored-By` trailers. + +## Reporting protocol findings + +If you've worked out a field, an opcode, or an event we don't decode yet, that's +one of the most valuable things you can contribute. Open an issue in +[protocol](https://github.com/OpenStrap/protocol/issues) with the raw bytes, what +you think the field is, and how you convinced yourself. A lot of the current +event table is empirical guesswork by one person — more eyes genuinely helps. + +## A note on scope + +This project talks to hardware people already own, using their own data, on +their own device. Please keep contributions within that: no scraping WHOOP's +services, no redistributing their code, firmware, or assets, and no vendored +material from other reverse-engineering projects whose licences don't permit it. +Facts about a protocol are fine. Someone else's source code is not. diff --git a/DONATE.md b/DONATE.md new file mode 100644 index 00000000..3ae09b4b --- /dev/null +++ b/DONATE.md @@ -0,0 +1,46 @@ +# Support OpenStrap + +OpenStrap is free, MIT-licensed, and has no company, no subscription, and no +revenue behind it. It exists because a perfectly good sensor turned into a +bracelet and that seemed like a stupid reason to throw hardware away. + +If it gave your band a second life and you'd like to chip in, these are the only +addresses. There is no other donation channel, no token, and nothing for sale. + +### Bitcoin + +``` +bc1qvtcch38dcwp967ar764uu6eetw7tf907844wfq +``` + +### EVM — Ethereum, Base, Arbitrum, Optimism, Polygon + +``` +0x8310C89393366b7eBCD47ABa82e1dfB5ECeFFbD9 +``` + +--- + +**Please don't feel obliged.** The genuinely valuable contributions are free: + +- **Open an issue** when a number looks wrong. Bug reports from real bands on + real wrists are worth more than money — there's only one person's physiology + in the test data otherwise. +- **Decode something.** A lot of the event table is empirical guesswork. If you + work out a field we don't understand, that helps everyone with one of these + bands. See [protocol](https://github.com/OpenStrap/protocol/issues). +- **Tell someone** whose strap is in a drawer. + +### What donations do and don't buy + +They don't buy priority, features, or support. This isn't a paid product and +turning it into one would defeat the point. What they realistically cover is the +Apple Developer Program membership that keeps the TestFlight build alive, test +hardware (a second band is the main thing that would speed up WHOOP 5 support), +and coffee. + +Nothing is gated behind paying, and nothing ever will be. + +--- + +*Not affiliated with, endorsed by, or connected to WHOOP.* diff --git a/README.md b/README.md index 4970c997..b0a61526 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,28 @@ An app that makes a WHOOP 4.0 useful without a WHOOP subscription. Connects to the band over Bluetooth, computes everything on your phone locally iOS and Android. +[![test](https://github.com/OpenStrap/edge/actions/workflows/test.yml/badge.svg)](https://github.com/OpenStrap/edge/actions/workflows/test.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +[![TestFlight](https://img.shields.io/badge/iOS-TestFlight-0D96F6?logo=apple&logoColor=white)](https://testflight.apple.com/join/2BVSwq65) +[![APK](https://img.shields.io/github/v/release/OpenStrap/edge?label=Android%20APK&logo=android&logoColor=white)](https://github.com/OpenStrap/edge/releases/latest) + > Not affiliated with WHOOP. Not a clone of their app or their scores — see below. image +## Install + +| | | +|---|---| +| **iOS** | **[Join the TestFlight beta →](https://testflight.apple.com/join/2BVSwq65)** — normal TestFlight install, no sideloading, no computer needed. | +| **Android** | **[Download the APK →](https://github.com/OpenStrap/edge/releases/latest)** — allow installs from unknown sources and open it. | + +Quit the official WHOOP app before you pair. Bluetooth only lets one app own the +band at a time. + +Prefer to sideload the unsigned IPA instead of using TestFlight? That still +works — see [`guides/IOS_SIDELOAD.md`](guides/IOS_SIDELOAD.md). + ## What made me build this app My subscription lapsed and a perfectly good sensor turned into a bracelet. The hardware @@ -53,23 +71,37 @@ spot-check, real-time breathing coherence. **Activity** — auto-detected workouts, live workout tracking with GPS routes, heart-rate zones. +**Your data, elsewhere** — writes to **Apple Health** (HealthKit) and **Google Health +Connect**: sleep stages, resting HR, HRV, respiratory rate, active energy and workouts. +Only things the band actually measures — never the derived scores, which have no native +type and would be fabricated. Exports are idempotent, so a day re-deriving never +duplicates samples. You can also export the entire local SQLite database to a file +whenever you like — it's your data, in a format anything can open. + +**Background sync** — the band drains without you opening the app. Android runs a +foreground service with a 15-minute watchdog worker and re-attaches via +CompanionDeviceManager. iOS uses a background processing task plus a light refresh task, +and a separate restore Bluetooth central that relaunches the app when the band +reconnects. + **Everything else** — trends/history, a journal with on-device correlation insights ("what actually moves your numbers"), cycle tracking, a deterministic coach, a shareable weekly recap, a BYOK AI assistant, home-screen widgets, iOS Live Activities, Siri -shortcuts. +shortcuts, a smart alarm that buzzes the band. ## What doesn't work (yet, or maybe ever) -- iOS background sync is best-effort. Apple doesn't give third-party apps a real - background-service option, so syncing while you haven't opened the app in a while is - "usually," not "always." +- iOS background sync is best-effort. It genuinely works (see above), but Apple doesn't + give third-party apps a real background-service option, so the OS decides when those + tasks actually run. Syncing while you haven't opened the app in a while is "usually," + not "always." Android has no such limit. - Metrics are approximations off published research — not medical-grade, not validated against a lab, don't treat any of it as a diagnosis. -- Sideload only right now — not on the App Store or Play Store. You're installing an APK - or an unsigned IPA straight off Releases. Android's just "allow unknown sources" and - you're done. iOS needs one extra tool — see - [`guides/IOS_SIDELOAD.md`](guides/IOS_SIDELOAD.md) if you just want the app and aren't - planning to build it yourself. +- Not on the App Store or Play Store yet. iOS is a public TestFlight beta, which is a + normal install but still a beta; Android is an APK straight off Releases. +- WHOOP 5.0 / MG support is in progress and **experimental** — the band is detected and + spoken to, but it hasn't been validated against real 5.0 hardware. WHOOP 4.0 is the + only one that's actually tested. ## Run it @@ -114,10 +146,27 @@ you're into this kind of thing. ## Your data stays on your phone Everything's computed and stored locally. No cloud account required, no backend this -needs to work day to day. The only network calls this app ever makes are three narrow, -optional things — a one-time legacy-account import if you had an old cloud account, an -OTA/announcement pointer, and a BYOK LLM proxy for the AI assistant. None of them are -required for the app to work. +needs to work day to day. **Your health data never leaves the device unless you +explicitly send it somewhere.** + +Being precise about the network, since "no cloud" gets said too loosely. Nothing below +is required for the app to work, and none of it carries health data except the two you +turn on yourself: + +- **Anonymous diagnostics** (Firebase crash/performance). **On by default in GitHub + release builds** — switch it off in your profile and collection stops immediately. + **Not present at all** in App Store / Play Store builds. Never includes health data. +- **OTA/announcement pointer** — checks whether there's a newer build. +- **Legacy account import** — one-time, only if you had an old OpenStrap cloud account. +- **BYOK AI assistant** — only if you configure a provider. Your key, your account. Be + aware that **the prompts contain your health data**: to answer "why is my recovery + low", the assistant is given your metrics to read. That data goes to whichever + provider you chose, under their policies, not ours. +- **Health-data contribution** — opt-in, off by default, GitHub builds only. Uploads + your local database wholesale, which is the entire point of it. It's the only thing + here that sends the whole database rather than a slice. + +Full detail in [PRIVACY.md](PRIVACY.md). ## Repo layout @@ -139,3 +188,18 @@ Found something broken? Open an issue. Found something broken and fixed it? Even send the PR. Protocol-level stuff (new record types, opcodes) belongs in the protocol repo, metric/formula changes belong in analytics, anything about the app itself — Bluetooth, storage, UI — belongs here. + +[**CONTRIBUTING.md**](CONTRIBUTING.md) has the details: which repo a change belongs in, +how to run the three packages together locally, and the two rules that matter most — +never fabricate a number when the data isn't there, and cite the published method you're +implementing. + +Security problems shouldn't go in a public issue — see [SECURITY.md](SECURITY.md) for +private reporting. + +## Support the work + +Free, MIT, no company behind it. If it gave your band a second life: +[**DONATE.md**](DONATE.md) has BTC and EVM addresses. Bug reports from real bands are +worth more than money, though — there's only one person's physiology in the test data +otherwise. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..4fad16c8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,59 @@ +# Security Policy + +## Reporting a vulnerability + +Please **don't** open a public issue for a security problem. + +Use GitHub's private reporting instead: +[**Report a vulnerability →**](https://github.com/OpenStrap/edge/security/advisories/new) + +That goes straight to the maintainer and stays private until there's a fix. + +Rough expectations, set honestly — this is a one-maintainer project, not a +company with an on-call rota: + +- Acknowledgement within about a week. +- An assessment, and a fix or a clear "won't fix and here's why", within 30 days + for anything that puts user data at risk. +- Credit in the release notes if you want it. + +## What's in scope + +- Anything that discloses a user's health data off their device. +- Anything that lets a third party read, write to, or hijack the Bluetooth + session with someone's band. +- Local data-at-rest problems: the database, exports, the App Group container, + widget snapshots. +- The optional companion worker in + [backend](https://github.com/OpenStrap/backend): auth, the import endpoints, + the opt-in telemetry and health-upload paths. +- Anything that causes the app to send data anywhere the user did not agree to. + +## What's out of scope + +- The band's own firmware. We don't ship it, can't patch it, and won't publish + attacks against it. +- WHOOP's own apps and services. Please report those to WHOOP. +- The fact that sideloaded builds are unsigned, or that a rooted/jailbroken + device can read app storage. Both are known properties of the distribution + model, documented in the README. +- Metric accuracy. Wrong numbers are bugs — open a normal issue. + +## Where your data actually is + +Worth knowing before you go looking: OpenStrap computes and stores your health +data on-device, and there's no account or server holding it. Two qualifications, +so the boundary is exact: + +- **Anonymous diagnostics** (Firebase crash/performance, never health data) are + **on by default in GitHub release builds** and absent from App Store / Play + Store builds. Switchable off in-app. +- **Health-data contribution** uploads the local database, but is opt-in, off by + default, and compiled out of store builds entirely. + +Everything else the companion worker does — legacy import, an update pointer — +is optional and carries no health data. See [PRIVACY.md](PRIVACY.md). + +That means the realistic attack surface is the phone, the Bluetooth link, and +the local database — not a cloud backend. Reports focused there are the most +useful. diff --git a/docs/index.html b/docs/index.html index 9a68c7d4..29c1fb39 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,8 +3,14 @@ -Edge — Legal - +OpenStrap Edge — use your WHOOP 4.0 without a subscription + + + + + + + @@ -12,35 +18,165 @@
Edge
-

Legal

-

Edge (OpenStrap) is an independent, open-source, local-first fitness and wellness - companion application. This page links the legal documents for the app.

- - +
+

Your WHOOP 4.0 doesn’t stop working when the subscription does.

+

+ Only the app goes dark. Edge pairs with the band over Bluetooth, decodes what it + recorded, and works out your sleep, recovery, strain and the rest — + entirely on your phone. No account, no subscription, and no server that ever + receives your health data. +

+ + + +

+ Free and MIT licensed. Not affiliated with WHOOP. + Tested on WHOOP 4.0 — 5.0 / MG support is experimental. +

+
+ +
+
+ The Today screen, showing a readiness ring and the day's headline metrics +
Today
+
+
+ The Sleep screen, showing a hypnogram and sleep stage breakdown +
Sleep
+
+
+ The Heart screen, showing heart rate and HRV trends +
Heart
+
+
+ The weekly Recap screen +
Recap
+
+
+

Every screenshot is real output from a WHOOP 4.0.

+ +
+
+

It runs on your phone

+

+ The band talks to the app, the app decodes the bytes and computes every metric + locally, and the results are stored on the device. There’s no server that + sees your health data — that isn’t a setting, it’s the + architecture. +

+

+ Precisely, because “no cloud” gets said too loosely: GitHub Release + builds send anonymous crash diagnostics by default (switchable off); store + builds send none. Neither ever includes health data. + Detail → +

+
+
+

Published methods, cited

+

+ Banister TRIMP, Cole–Kripke, Lomb–Scargle, van Hees and friends. + Nothing invented, no neural net guessing at WHOOP’s formulas. You can go + read the paper and decide whether you trust the number. +

+
+
+

It admits what it doesn’t know

+

+ Every metric carries a confidence and a tier. When the data isn’t there + you get a dash, not a plausible-looking guess. SpO2 and skin + temperature are relative-only, because that’s what the band actually + gives up. +

+
+
+

Not a WHOOP clone

+

+ Different algorithms, different numbers. They have years of research and a + team; this is textbook methods over a reverse-engineered byte stream. It trends + correctly and it’ll tell you when you’re under-recovered. It + isn’t their secret sauce and never claims to be. +

+
+
+ +
+

Before you install

+ +
+ +
+

How it’s put together

+

band → Bluetooth → protocol decoder → local storage → analytics → the UI

+ +
+ +
+

Support the work

+

+ Free, MIT licensed, no company behind it. Bug reports from real bands are worth + more than money — but if you’d like to chip in: +

+
+
BTC
+
bc1qvtcch38dcwp967ar764uu6eetw7tf907844wfq
+
EVM
+
0x8310C89393366b7eBCD47ABa82e1dfB5ECeFFbD9
+
+

+ Nothing is gated behind paying, and nothing ever will be. +

+
diff --git a/docs/legal.html b/docs/legal.html new file mode 100644 index 00000000..6ac325ec --- /dev/null +++ b/docs/legal.html @@ -0,0 +1,48 @@ + + + + + +Edge — Legal + + + + +
+
+ Edge + +
+ +
+

Legal

+

Edge (OpenStrap) is an independent, open-source, local-first fitness and wellness + companion application. This page links the legal documents for the app.

+ + +
+ + +
+ + diff --git a/docs/notice.html b/docs/notice.html index 0117aed9..eb4286f8 100644 --- a/docs/notice.html +++ b/docs/notice.html @@ -12,6 +12,7 @@
Edge