Skip to content

Commit dc42537

Browse files
StuMasonclaude
andcommitted
feat: Initial release - PostgreSQL-backed health analytics server
Core Features: - Multi-user architecture with user_id on all tables - REST API scoped by user_id for self-hosted and SaaS - Polar Flow SDK integration for data sync - PostgreSQL database with async SQLAlchemy 2.0 - Litestar async web framework - Docker and docker-compose deployment Data Models: - Sleep (score, stages, HRV, heart rate, breathing, temperature) - Nightly Recharge (ANS charge, recovery metrics) - Daily Activity (steps, calories, zones) - Exercises (workouts with detailed metrics) API Endpoints: - GET /users/{user_id}/sleep - GET /users/{user_id}/sleep/{date} - POST /users/{user_id}/sync/trigger Infrastructure: - CI/CD: tests, lint, security, docs, publish - Dependabot with auto-merge for minor/patch - MkDocs Material documentation - Strict type checking with mypy - Ruff for linting and formatting Tech Stack: - Python 3.12+ - PostgreSQL 17 - Litestar 2.14+ - SQLAlchemy 2.0 (async) - polar-flow-api 1.1.0 - Polars for data processing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent d8fb7ab commit dc42537

37 files changed

+4570
-173
lines changed

.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Deployment mode: self_hosted or saas
2+
DEPLOYMENT_MODE=self_hosted
3+
4+
# API configuration
5+
API_HOST=0.0.0.0
6+
API_PORT=8000
7+
8+
# Database URL (PostgreSQL)
9+
# Self-hosted (docker-compose): postgres service
10+
DATABASE_URL=postgresql+asyncpg://polar:polar@postgres:5432/polar
11+
12+
# SaaS (Laravel shared database)
13+
# DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/dbname
14+
15+
# Security (required for SaaS mode, generates default for self-hosted)
16+
# ENCRYPTION_KEY=<base64-encoded-32-byte-key>
17+
# JWT_SECRET=<secret-key>
18+
19+
# Sync settings
20+
SYNC_INTERVAL_HOURS=1
21+
SYNC_ON_STARTUP=true
22+
SYNC_DAYS_LOOKBACK=30
23+
24+
# Logging
25+
LOG_LEVEL=INFO
26+
27+
# Self-hosted mode: path to Polar token file
28+
POLAR_TOKEN_PATH=/root/.polar-flow/token

.github/dependabot.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: 2
2+
updates:
3+
# Python dependencies
4+
- package-ecosystem: "pip"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
day: "monday"
9+
time: "06:00"
10+
timezone: "Europe/London"
11+
open-pull-requests-limit: 10
12+
assignees:
13+
- "StuMason"
14+
commit-message:
15+
prefix: "chore(deps)"
16+
include: "scope"
17+
groups:
18+
minor-and-patch:
19+
patterns:
20+
- "*"
21+
update-types:
22+
- "minor"
23+
- "patch"
24+
25+
# GitHub Actions
26+
- package-ecosystem: "github-actions"
27+
directory: "/"
28+
schedule:
29+
interval: "weekly"
30+
day: "monday"
31+
time: "06:00"
32+
timezone: "Europe/London"
33+
open-pull-requests-limit: 5
34+
assignees:
35+
- "StuMason"
36+
commit-message:
37+
prefix: "ci(deps)"
38+
include: "scope"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Dependabot Auto-Merge
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
11+
jobs:
12+
auto-merge:
13+
name: Auto-merge Dependabot PRs
14+
runs-on: ubuntu-latest
15+
if: github.actor == 'dependabot[bot]'
16+
17+
steps:
18+
- name: Fetch Dependabot metadata
19+
id: metadata
20+
uses: dependabot/fetch-metadata@v2
21+
with:
22+
github-token: "${{ secrets.GITHUB_TOKEN }}"
23+
24+
- name: Auto-merge minor and patch updates
25+
if: |
26+
steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
27+
steps.metadata.outputs.update-type == 'version-update:semver-minor'
28+
run: gh pr merge --auto --squash "$PR_URL"
29+
env:
30+
PR_URL: ${{ github.event.pull_request.html_url }}
31+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Comment on major updates
34+
if: steps.metadata.outputs.update-type == 'version-update:semver-major'
35+
run: |
36+
gh pr comment "$PR_URL" --body "**Major version update** - requires manual review and approval.
37+
38+
Please review:
39+
- [ ] Breaking changes in changelog
40+
- [ ] Update required in our code
41+
- [ ] Tests still pass
42+
- [ ] Documentation updated if needed"
43+
env:
44+
PR_URL: ${{ github.event.pull_request.html_url }}
45+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/docs.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
deploy:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- uses: astral-sh/setup-uv@v7
18+
with:
19+
enable-cache: true
20+
21+
- name: Set up Python
22+
run: uv python install 3.12
23+
24+
- name: Install dependencies
25+
run: |
26+
uv sync
27+
uv pip install mkdocs-material mkdocstrings[python]
28+
29+
- name: Build and deploy docs
30+
run: uv run mkdocs gh-deploy --force

.github/workflows/lint.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Lint and Type Check
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- name: Install uv
18+
uses: astral-sh/setup-uv@v7
19+
with:
20+
enable-cache: true
21+
22+
- name: Set up Python
23+
run: uv python install 3.12
24+
25+
- name: Install dependencies
26+
run: uv sync --all-extras
27+
28+
- name: Check formatting with Ruff
29+
run: uv run ruff format --check .
30+
31+
- name: Lint with Ruff
32+
run: uv run ruff check .
33+
34+
- name: Type check with mypy
35+
run: uv run mypy src/polar_flow_server

.github/workflows/security.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Security Check
2+
3+
on:
4+
schedule:
5+
- cron: '0 3 * * *' # 3am UTC daily
6+
workflow_dispatch:
7+
8+
jobs:
9+
security-audit:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
steps:
16+
- uses: actions/checkout@v6
17+
18+
- name: Install uv
19+
uses: astral-sh/setup-uv@v7
20+
with:
21+
enable-cache: true
22+
23+
- name: Set up Python
24+
run: uv python install 3.12
25+
26+
- name: Install dependencies
27+
run: uv sync --all-extras
28+
29+
- name: Install pip-audit
30+
run: uv pip install pip-audit
31+
32+
- name: Check for security vulnerabilities
33+
id: security
34+
run: |
35+
uv run pip-audit --format json > audit.json 2>&1 || true
36+
if [ -s audit.json ] && [ "$(cat audit.json | jq '.vulnerabilities | length')" -gt 0 ]; then
37+
echo "vulnerable=true" >> $GITHUB_OUTPUT
38+
echo "::warning::Security vulnerabilities found"
39+
cat audit.json | jq '.vulnerabilities'
40+
else
41+
echo "vulnerable=false" >> $GITHUB_OUTPUT
42+
echo "No security vulnerabilities found"
43+
fi

.github/workflows/tests.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
name: Test Python ${{ matrix.python-version }}
12+
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
python-version: ["3.12", "3.13"]
16+
17+
steps:
18+
- uses: actions/checkout@v6
19+
20+
- name: Install uv
21+
uses: astral-sh/setup-uv@v7
22+
with:
23+
enable-cache: true
24+
25+
- name: Set up Python ${{ matrix.python-version }}
26+
run: uv python install ${{ matrix.python-version }}
27+
28+
- name: Install dependencies
29+
run: uv sync --all-extras
30+
31+
- name: Run tests with coverage
32+
run: uv run pytest --cov --cov-report=xml --cov-report=term
33+
34+
- name: Upload coverage to Codecov
35+
if: matrix.python-version == '3.12'
36+
uses: codecov/codecov-action@v5
37+
continue-on-error: true
38+
with:
39+
files: ./coverage.xml
40+
fail_ci_if_error: false
41+
token: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
MANIFEST
23+
24+
# Virtual environments
25+
.env
26+
.venv
27+
env/
28+
venv/
29+
ENV/
30+
env.bak/
31+
venv.bak/
32+
33+
# IDEs
34+
.vscode/
35+
.idea/
36+
*.swp
37+
*.swo
38+
*~
39+
.DS_Store
40+
41+
# Testing
42+
.pytest_cache/
43+
.coverage
44+
coverage.xml
45+
*.cover
46+
.hypothesis/
47+
.tox/
48+
htmlcov/
49+
50+
# Type checking
51+
.mypy_cache/
52+
.dmypy.json
53+
dmypy.json
54+
.pytype/
55+
.ruff_cache/
56+
57+
# Database
58+
*.db
59+
*.db-shm
60+
*.db-wal
61+
*.duckdb
62+
*.duckdb.wal
63+
data/
64+
65+
# Logs
66+
*.log
67+
logs/
68+
69+
# Documentation
70+
site/
71+
.mkdocs_cache/
72+
73+
# Environment
74+
.env.local
75+
.env.*.local
76+
77+
# Polar tokens
78+
.polar-flow/

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
- Initial release of polar-flow-server
12+
- REST API with user-scoped endpoints
13+
- Database models with multi-user support
14+
- Polar Flow SDK integration for data sync
15+
- Support for Sleep, Nightly Recharge, Activity, and Exercise data
16+
- DuckDB support for self-hosted deployments
17+
- PostgreSQL support for SaaS deployments
18+
- Litestar async web framework
19+
- Structured logging with structlog
20+
- Comprehensive test suite
21+
- Type safety with mypy strict mode
22+
- CI/CD workflows (tests, lint, security, publish, docs)
23+
- Dependabot with auto-merge for minor/patch updates
24+
- MkDocs Material documentation
25+
- Docker support (planned)
26+
- HTMX admin panel (planned)
27+
- MCP server for Claude Desktop (planned)
28+
- Analytics engine for HRV baselines and recovery scores (planned)
29+
30+
[Unreleased]: https://github.com/StuMason/polar-flow-server/commits/main

0 commit comments

Comments
 (0)