Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Code of Conduct

Short version: be decent, assume good faith, and remember there's one person
maintaining this in their spare time.

## What's expected

- **Be civil.** Disagree with the code, the maths, or the decision — not the
person. Sharp technical criticism is welcome and useful; contempt isn't.
- **Assume good faith.** If a metric looks wrong or a decision looks strange,
there's usually a reason written down somewhere. Ask before concluding it's
carelessness.
- **Be patient.** Issues get read and answered, but not always quickly, and not
in the order they arrived. "Any update on this?" a day later doesn't speed
anything up.
- **Respect the honesty rules.** A recurring theme here is that numbers admit
what they don't know, and that the docs don't overclaim. Arguing for a change
is fine; pressuring for output that looks more confident than the data
supports isn't.

## What isn't acceptable

Harassment, personal attacks, discriminatory language, sexualised content,
deliberate intimidation, sustained disruption, publishing others' private
information, or posting someone else's health data.

## Health data

Issues and discussions are **public and stay public**. Please redact health
values, dates, names, and device or account identifiers from screenshots and
logs before posting. If someone forgets, don't quote or amplify it — flag it and
it'll be edited.

Don't ask anyone to share their raw health data publicly to debug something.
There's almost always a way to reproduce with a redacted screenshot or a
description.

## Medical claims

This project produces approximations from published research. It isn't a medical
device and nothing it outputs is a diagnosis. Please don't give other users
medical advice in issues or discussions, and don't present OpenStrap's numbers to
anyone as clinical measurements. If someone posts something that reads as a
health scare, point them at an actual clinician.

## Scope

Applies in all OpenStrap repos — issues, pull requests, discussions, commit
messages, and code review.

## Reporting

Email the maintainer at the address on the [organisation
profile](https://github.com/OpenStrap), or report the content to GitHub directly.
Reports are handled privately.

Consequences scale with severity and intent: usually a warning and an edit;
for repeated or deliberate behaviour, blocking from the org.
91 changes: 91 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Contributing to OpenStrap

This is the org-wide default. The three main repos — [protocol][p],
[analytics][a], [edge][e] — each have their own `CONTRIBUTING.md` with
repo-specific detail, and those override this one. Read theirs if you're working
there.

## First: which repo?

This is the thing that most often sends a PR to the wrong place, so it's worth
30 seconds up front.

| Your change | Repo |
|---|---|
| A record type, opcode, event — anything about the bytes on the wire | [**protocol**][p] |
| A metric, or how an existing number is computed | [**analytics**][a] |
| Bluetooth, storage, background sync, UI — anything app-shaped | [**edge**][e] |
| The optional companion worker (legacy import, update pointer, opt-in telemetry) | [**backend**][b] |
| Protocol notes, or the standalone Python client | [**research**][r] |

The separation is strict and it's load-bearing: protocol has zero dependencies,
analytics has zero runtime dependencies and no I/O, and edge is the only thing
that touches a device. If you're unsure, open an issue and ask — that's cheaper
than moving code between repos afterwards.

## The rules that apply everywhere

**Never fabricate a number.** If an input isn't there, the result is `null` — not
a default, not a last-known-good, not an interpolation that will look fine on a
chart. Every metric carries a confidence and a tier (`AUTH` / `HIGH` /
`ESTIMATE` / `RELATIVE`). A metric that quietly invents a value when the data is
missing is worse than no metric at all, because you can't tell the difference
from the outside.

**Cite the method.** Anything computing a physiological quantity implements a
published, peer-reviewed algorithm, cited in a comment next to the code. If
nothing in the literature fits, that's allowed — mark it `ESTIMATE`, give it low
confidence, and say so. What isn't allowed is inventing constants and presenting
them as science, or fitting to WHOOP's outputs to match their scores.

**Some limits are real, not bugs.** HRV here is PRV from 1 Hz beat timing. Deep
sleep is a low-confidence HR-flatness overlay. SpO₂ and skin temperature are
relative ADC values with no calibration to absolute units. These are properties
of what the band actually hands over. Please don't "fix" them by making output
look more confident than the input supports.

**Don't overclaim on privacy either.** The same honesty standard applies to what
we say about data. Everything health-related is computed and stored on-device;
where that's qualified — anonymous diagnostics in GitHub builds, opt-in
contribution, BYOK AI prompts that contain your metrics — say so plainly rather
than rounding it to "no cloud".

## Provenance

Facts about a wire protocol, worked out by observing a device you own, are fine
and are what this project is built on.

Vendor source code, firmware, decompiled binaries, and material from other
reverse-engineering projects whose licences don't permit reuse are **not** — in
code, comments, commit messages, or PR descriptions. Several projects in this
space are unlicensed (which means all rights reserved, not public domain) or
non-commercial-only. OpenStrap is MIT and stays cleanly MIT.

## Pull requests

- Branch off `main`. One logical change per PR.
- Explain *why*, not just what. Link the issue if there is one.
- Say how you verified it. For protocol work, "decoded N real records off my own
band and the values were plausible" is a genuinely good answer.
- If it changes any number a user sees, say so explicitly — that's the single
most important line in the PR, because stored results are versioned and a
change means `kAlgoVersion` has to be bumped in edge.
- CI runs analyze + the full test suite on every PR. Please get it green.
- No `Co-Authored-By` trailers.

## Reporting things

- **A bug, or a metric that looks wrong** — [edge issues][ei]. There's a form for
each; the metric one exists because "it doesn't match the WHOOP app" isn't by
itself a bug.
- **A protocol finding** — [protocol issues][pi]. Include the bytes and how you
convinced yourself.
- **A security problem** — privately, please. See `SECURITY.md`.

[p]: https://github.com/OpenStrap/protocol
[a]: https://github.com/OpenStrap/analytics
[e]: https://github.com/OpenStrap/edge
[b]: https://github.com/OpenStrap/backend
[r]: https://github.com/OpenStrap/research
[ei]: https://github.com/OpenStrap/edge/issues/new/choose
[pi]: https://github.com/OpenStrap/protocol/issues/new
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# GitHub funding config accepts URLs only, 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
29 changes: 29 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
blank_issues_enabled: true
contact_links:
- name: Bug or wrong metric in the app
url: https://github.com/OpenStrap/edge/issues/new/choose
about: >-
Anything you see in the app belongs in the edge repo, which has forms for
bugs and for metrics that look wrong.

- name: Protocol / byte-level finding
url: https://github.com/OpenStrap/protocol/issues/new
about: >-
A new record type, opcode, event, or a field decoded wrongly. Include the
raw bytes and how you convinced yourself.

- 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? Start here.

- 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. See SECURITY.md
for what's in scope.
61 changes: 61 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Security Policy

Org-wide default. [protocol][p], [analytics][a] and [edge][e] each have their own
`SECURITY.md`, which overrides this for those repos.

## Reporting a vulnerability

Please **don't** open a public issue for a security problem.

Use GitHub's private vulnerability reporting on the affected repo — the
**Security** tab → **Report a vulnerability**. That reaches the maintainer and
stays private until there's a fix.

Honest expectations, since this is a one-maintainer project rather than 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'd like it.

## Where the data actually is

Worth knowing before you go looking, because it determines what's worth
reporting: OpenStrap computes and stores health data **on the phone**. There's no
account and no 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**, switchable off in-app, and absent
entirely from App Store / Play Store builds.
- **Health-data contribution** does upload the local database, but is opt-in, off
by default, and compiled out of store builds.
- The **BYOK AI assistant**, if you configure one, sends your metrics to
whichever provider you chose, under their policies.

So 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.

## In scope

- Anything that discloses a user's health data off their device.
- Anything letting a third party read, write to, or hijack the Bluetooth session
with a band.
- Local data-at-rest problems: the database, exports, the iOS App Group
container, widget snapshots.
- The optional companion worker: auth, import endpoints, the opt-in telemetry and
health-upload paths.
- Anything causing data to go somewhere the user didn't agree to.

## Out of scope

- **The band's 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.
- Sideloaded builds being unsigned, or a rooted/jailbroken device reading app
storage. Both are known properties of the distribution model and documented.
- Metric accuracy. Wrong numbers are bugs — open a normal issue.

[p]: https://github.com/OpenStrap/protocol
[a]: https://github.com/OpenStrap/analytics
[e]: https://github.com/OpenStrap/edge
33 changes: 33 additions & 0 deletions .github/SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Support

**Something's broken, or a number looks wrong** →
[open an issue on edge](https://github.com/OpenStrap/edge/issues/new/choose).
There's a form for each; pick the metric one if the app is showing a value you
think is incorrect.

**A question, rather than a bug** →
[Discussions](https://github.com/OpenStrap/edge/discussions). Good place for
"how does this metric work", "is this expected", or showing what you built.

**Installing it**

- **iOS** — [TestFlight](https://testflight.apple.com/join/2BVSwq65). Normal
install, no computer needed. Sideloading the unsigned IPA still works if you
prefer: see [`guides/IOS_SIDELOAD.md`](https://github.com/OpenStrap/edge/blob/main/guides/IOS_SIDELOAD.md).
- **Android** — [the APK](https://github.com/OpenStrap/edge/releases/latest).

**Pairing trouble** — quit the official WHOOP app first. Bluetooth only lets one
app own the band at a time, and this is the cause of most "it won't connect"
reports.

**You found something in the protocol** →
[protocol issues](https://github.com/OpenStrap/protocol/issues). Include the raw
bytes and how you convinced yourself. This is one of the most useful things
anyone can contribute.

**A security problem** → privately, please. See `SECURITY.md`.

---

There's no support contract here and no SLA — one person maintains this. Issues
do get read.