① Collect
Provider Overview
The data sources that actually ship with the engine: four theta providers, the Apple Health importer, what switches each one on, and which config keys have no provider behind them.
What ships with the repository
Section titled “What ships with the repository”Two platforms are registered at startup — theta and apple. The theta platform loads its providers from disk, one directory per source; the apple platform is a built-in importer that accepts no plugins. The list below is what the repository contains — no other source is wired in.
| Source | Slug | Platform | Link type | Scheduled pull |
|---|---|---|---|---|
| Garmin Connect | theta_garmin | theta | OAUTH1 | No — push only |
| Whoop | theta_whoop | theta | OAUTH2 | Every 24 hours |
| Oura | theta_oura | theta | OAUTH2 | Every 5 minutes |
| PostgreSQL | theta_pgsql | theta | CUSTOMIZED | No — validation only |
| Apple Health | apple_health | apple | NONE | No — the client uploads |
For the contract these implement — BasePullProvider, ProviderInfo, LinkType, the pull scheduler — see Pulse Provider System. To connect one, see Using Providers.
The theta providers
Section titled “The theta providers”Each lives in its own mirobody_<slug>/ directory under mirobody/pulse/providers/, holds exactly one provider_*.py, and is instantiated by its own create_provider(config) factory. A factory that returns None leaves the provider out of the registry entirely — which is how an unconfigured source disables itself.
| Directory | Class | Switched on by | Pull task |
|---|---|---|---|
mirobody_garmin_connect/ | GarminProvider | GARMIN_CLIENT_ID + GARMIN_CLIENT_SECRET | None — webhook only |
mirobody_whoop/ | WhoopProvider | WHOOP_CLIENT_ID + WHOOP_CLIENT_SECRET | inherits the base default — True |
mirobody_oura/ | OuraProvider | OURA_CLIENT_ID + OURA_CLIENT_SECRET | Scheduled |
mirobody_pgsql/ | PgsqlProvider | ENABLE_PGSQL_DEVICE — any non-empty value | None — validation only |
The metadata each one advertises is a plain ProviderInfo, built without touching the network.
The PostgreSQL provider is the odd one out in two ways. It is the only CUSTOMIZED source — it declares five connect_info_fields (username, password, host, port, database) rather than sending the user through a browser — and it is the only one gated by an explicit feature flag instead of by whether credentials exist.
It also stops at validation: it opens a connection, runs SELECT version(), closes it, and stores the credentials. Fetching and formatting are deliberate no-ops, so linking it produces no records — it exists so a deployment can record a database connection, not to import from one.
Apple Health
Section titled “Apple Health”Apple Health is not a plugin: the apple platform registers its provider itself, so nothing from PROVIDER_DIRS can be added to it.
Both of its providers declare auth_type NONE and report as permanently connected — there is no account to link, because the client pushes data in rather than the server pulling it out. Three routes accept those pushes:
| Route | Body | Notes |
|---|---|---|
POST /api/v1/pulse/apple/health | metaInfo + healthData[] | The main import; Content-Encoding: gzip accepted |
POST /api/v1/pulse/apple/statistics | metaInfo + statistics[] | Client-computed aggregates (sum / average / minimum / maximum / mostRecent) written through as summary indicators |
POST /api/v1/pulse/apple/cda | metaInfo + cdaData[] | Clinical Document Architecture documents |
All three require a JWT, and both /apple/* and /api/v1/pulse/apple/* answer, because an uploader may point at either mount. The type vocabulary this channel accepts is cross-platform rather than specific to Apple’s health store — see Data Flow.
Configuration keys without a provider
Section titled “Configuration keys without a provider”config.yaml and the pull scheduler both name sources this checkout does not contain. They are leftovers from a wider deployment, and setting the keys will not make a source appear:
| Leftover | Where it appears | Why nothing happens |
|---|---|---|
VITAL_API_KEY, VITAL_ENVIRONMENT | config.yaml | No vital platform is registered, so POST /api/v1/pulse/vital/generate-sign-in-token answers 503 Vital platform not available |
RENPHO_API_BASE_URL, RENPHO_APP_VERSION, RENPHO_PLATFORM, RENPHO_ENCRYPTION_KEY | config.yaml | There is no mirobody_renpho/ directory and no Renpho provider class anywhere in the tree |
FRONTIERX_CLIENT_ID, FRONTIERX_USER_POOL_ID | config.yaml, commented out | Not read by any provider |
theta_renpho, theta_vital, theta_cgm | the cadence tables in pull_task.py | Intervals and lock durations for slugs no shipped provider claims |
The providers that ship are the four theta providers above plus the apple platform’s own two. Anything else is not in this branch.
Next steps
Section titled “Next steps”Fill in the keys, connect an account, watch records arrive
One shipped implementation read end to end
The contract all of these implement
Add a fifth source of your own