Update .env.example and README.md for passkey authentication
- .env.example: Add WEBAUTHN_RP_ID, WEBAUTHN_RP_NAME, WEBAUTHN_ORIGIN, ENVIRONMENT, and UMBRA_URL with documentation comments - README.md: Full rewrite — remove outdated PIN/bcrypt references, document current auth stack (Argon2id + TOTP + passkeys), all 17 API route groups, security features, and Docker deployment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9234880648
commit
57d400c6de
@ -1,2 +1,14 @@
|
||||
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/umbra
|
||||
SECRET_KEY=your-secret-key-change-in-production
|
||||
ENVIRONMENT=development
|
||||
|
||||
# Public-facing URL (used for ntfy click links, CORS derivation)
|
||||
UMBRA_URL=http://localhost
|
||||
|
||||
# WebAuthn / Passkey authentication
|
||||
# RP_ID must be the eTLD+1 domain of the live site (e.g. umbra.ghost6.xyz)
|
||||
# ORIGIN must include the scheme (https://)
|
||||
# These defaults work for local development; override in production .env
|
||||
WEBAUTHN_RP_ID=localhost
|
||||
WEBAUTHN_RP_NAME=UMBRA
|
||||
WEBAUTHN_ORIGIN=http://localhost
|
||||
|
||||
@ -1,39 +1,37 @@
|
||||
# UMBRA Backend
|
||||
|
||||
A complete FastAPI backend for the UMBRA application with async SQLAlchemy, PostgreSQL, authentication, and comprehensive CRUD operations.
|
||||
FastAPI backend for the UMBRA life management application with async SQLAlchemy, PostgreSQL, multi-user RBAC, and comprehensive security.
|
||||
|
||||
## Features
|
||||
|
||||
- **FastAPI** with async/await support
|
||||
- **SQLAlchemy 2.0** with async engine
|
||||
- **PostgreSQL** with asyncpg driver
|
||||
- **Alembic** for database migrations
|
||||
- **bcrypt** for password hashing
|
||||
- **itsdangerous** for session management
|
||||
- **PIN-based authentication** with secure session cookies
|
||||
- **Full CRUD operations** for all entities
|
||||
- **Dashboard** with aggregated data
|
||||
- **CORS enabled** for frontend integration
|
||||
- **FastAPI** with async/await and Pydantic v2
|
||||
- **SQLAlchemy 2.0** async engine with `Mapped[]` types
|
||||
- **PostgreSQL 16** via asyncpg
|
||||
- **Alembic** database migrations (001-061)
|
||||
- **Authentication**: Argon2id passwords + signed httpOnly cookies + optional TOTP MFA + passkey (WebAuthn/FIDO2)
|
||||
- **Multi-user RBAC**: admin/standard roles, per-user resource scoping
|
||||
- **Session management**: DB-backed sessions, sliding window expiry, concurrent session cap
|
||||
- **Account security**: Account lockout (10 failures = 30-min lock), CSRF protection, rate limiting
|
||||
- **APScheduler** for background notification dispatch
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
backend/
|
||||
├── alembic/ # Database migrations
|
||||
│ ├── versions/ # Migration files
|
||||
│ ├── env.py # Alembic environment
|
||||
│ └── script.py.mako # Migration template
|
||||
├── alembic/versions/ # 61 database migrations
|
||||
├── app/
|
||||
│ ├── models/ # SQLAlchemy models
|
||||
│ ├── schemas/ # Pydantic schemas
|
||||
│ ├── routers/ # API route handlers
|
||||
│ ├── config.py # Configuration
|
||||
│ ├── database.py # Database setup
|
||||
│ └── main.py # FastAPI application
|
||||
├── requirements.txt # Python dependencies
|
||||
├── Dockerfile # Docker configuration
|
||||
├── alembic.ini # Alembic configuration
|
||||
└── start.sh # Startup script
|
||||
│ ├── models/ # 21 SQLAlchemy 2.0 models
|
||||
│ ├── schemas/ # 14 Pydantic v2 schema modules
|
||||
│ ├── routers/ # 17 API routers
|
||||
│ ├── services/ # Auth, session, passkey, TOTP, audit, recurrence, etc.
|
||||
│ ├── jobs/ # APScheduler notification dispatch
|
||||
│ ├── config.py # Pydantic Settings (env vars)
|
||||
│ ├── database.py # Async engine + session factory
|
||||
│ └── main.py # FastAPI app + CSRF middleware
|
||||
├── requirements.txt
|
||||
├── Dockerfile
|
||||
├── alembic.ini
|
||||
└── start.sh
|
||||
```
|
||||
|
||||
## Setup
|
||||
@ -41,160 +39,87 @@ backend/
|
||||
### 1. Install Dependencies
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2. Configure Environment
|
||||
|
||||
Create a `.env` file:
|
||||
Copy `.env.example` to `.env` and configure:
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/umbra
|
||||
SECRET_KEY=your-secret-key-change-in-production
|
||||
DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/umbra
|
||||
SECRET_KEY=generate-a-strong-random-key
|
||||
ENVIRONMENT=production
|
||||
|
||||
# WebAuthn / Passkeys (required for passkey auth)
|
||||
WEBAUTHN_RP_ID=your-domain.com
|
||||
WEBAUTHN_RP_NAME=UMBRA
|
||||
WEBAUTHN_ORIGIN=https://your-domain.com
|
||||
```
|
||||
|
||||
### 3. Create Database
|
||||
|
||||
```bash
|
||||
createdb umbra
|
||||
```
|
||||
|
||||
### 4. Run Migrations
|
||||
### 3. Run Migrations
|
||||
|
||||
```bash
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
### 5. Start Server
|
||||
### 4. Start Server
|
||||
|
||||
```bash
|
||||
# Using the start script
|
||||
chmod +x start.sh
|
||||
./start.sh
|
||||
|
||||
# Or directly with uvicorn
|
||||
uvicorn app.main:app --reload
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8000`
|
||||
## API Routes
|
||||
|
||||
## API Documentation
|
||||
All routes require authentication (signed session cookie) except `/api/auth/*` and `/health`.
|
||||
|
||||
Interactive API documentation is available at:
|
||||
- **Swagger UI**: http://localhost:8000/docs
|
||||
- **ReDoc**: http://localhost:8000/redoc
|
||||
| Prefix | Description |
|
||||
|--------|-------------|
|
||||
| `/api/auth` | Login, logout, register, setup, status, password, TOTP, passkeys |
|
||||
| `/api/admin` | User management, system config, audit logs (admin only) |
|
||||
| `/api/todos` | Task management with categories and priorities |
|
||||
| `/api/events` | Calendar events with recurrence support |
|
||||
| `/api/event-invitations` | Event invitation RSVP and management |
|
||||
| `/api/event-templates` | Reusable event templates |
|
||||
| `/api/calendars` | Calendar CRUD |
|
||||
| `/api/shared-calendars` | Calendar sharing with permission levels |
|
||||
| `/api/reminders` | Reminder management with snooze |
|
||||
| `/api/projects` | Projects with tasks, comments, and collaboration |
|
||||
| `/api/people` | Contact management |
|
||||
| `/api/locations` | Location management |
|
||||
| `/api/connections` | User connections (friend requests) |
|
||||
| `/api/notifications` | In-app notification centre |
|
||||
| `/api/settings` | User preferences and ntfy configuration |
|
||||
| `/api/dashboard` | Aggregated dashboard data |
|
||||
| `/api/weather` | Weather widget data |
|
||||
|
||||
## API Endpoints
|
||||
## Authentication
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/setup` - Initial PIN setup
|
||||
- `POST /api/auth/login` - Login with PIN
|
||||
- `POST /api/auth/logout` - Logout
|
||||
- `GET /api/auth/status` - Check auth status
|
||||
UMBRA supports three authentication methods:
|
||||
|
||||
### Todos
|
||||
- `GET /api/todos` - List todos (with filters)
|
||||
- `POST /api/todos` - Create todo
|
||||
- `GET /api/todos/{id}` - Get todo
|
||||
- `PUT /api/todos/{id}` - Update todo
|
||||
- `DELETE /api/todos/{id}` - Delete todo
|
||||
- `PATCH /api/todos/{id}/toggle` - Toggle completion
|
||||
1. **Password** (Argon2id) - Primary login method
|
||||
2. **TOTP MFA** - Optional second factor via authenticator apps
|
||||
3. **Passkeys** (WebAuthn/FIDO2) - Optional passwordless login via biometrics, security keys, or password managers
|
||||
|
||||
### Calendar Events
|
||||
- `GET /api/events` - List events (with date range)
|
||||
- `POST /api/events` - Create event
|
||||
- `GET /api/events/{id}` - Get event
|
||||
- `PUT /api/events/{id}` - Update event
|
||||
- `DELETE /api/events/{id}` - Delete event
|
||||
Passkey login bypasses TOTP (a passkey is inherently two-factor: possession + biometric/PIN).
|
||||
|
||||
### Reminders
|
||||
- `GET /api/reminders` - List reminders (with filters)
|
||||
- `POST /api/reminders` - Create reminder
|
||||
- `GET /api/reminders/{id}` - Get reminder
|
||||
- `PUT /api/reminders/{id}` - Update reminder
|
||||
- `DELETE /api/reminders/{id}` - Delete reminder
|
||||
- `PATCH /api/reminders/{id}/dismiss` - Dismiss reminder
|
||||
## Security
|
||||
|
||||
### Projects
|
||||
- `GET /api/projects` - List projects
|
||||
- `POST /api/projects` - Create project
|
||||
- `GET /api/projects/{id}` - Get project
|
||||
- `PUT /api/projects/{id}` - Update project
|
||||
- `DELETE /api/projects/{id}` - Delete project
|
||||
- `GET /api/projects/{id}/tasks` - List project tasks
|
||||
- `POST /api/projects/{id}/tasks` - Create project task
|
||||
- `PUT /api/projects/{id}/tasks/{task_id}` - Update task
|
||||
- `DELETE /api/projects/{id}/tasks/{task_id}` - Delete task
|
||||
|
||||
### People
|
||||
- `GET /api/people` - List people (with search)
|
||||
- `POST /api/people` - Create person
|
||||
- `GET /api/people/{id}` - Get person
|
||||
- `PUT /api/people/{id}` - Update person
|
||||
- `DELETE /api/people/{id}` - Delete person
|
||||
|
||||
### Locations
|
||||
- `GET /api/locations` - List locations (with category filter)
|
||||
- `POST /api/locations` - Create location
|
||||
- `GET /api/locations/{id}` - Get location
|
||||
- `PUT /api/locations/{id}` - Update location
|
||||
- `DELETE /api/locations/{id}` - Delete location
|
||||
|
||||
### Settings
|
||||
- `GET /api/settings` - Get settings
|
||||
- `PUT /api/settings` - Update settings
|
||||
- `PUT /api/settings/pin` - Change PIN
|
||||
|
||||
### Dashboard
|
||||
- `GET /api/dashboard` - Get dashboard data
|
||||
- `GET /api/upcoming?days=7` - Get upcoming items
|
||||
|
||||
## Database Schema
|
||||
|
||||
The application uses the following tables:
|
||||
- `settings` - Application settings and PIN
|
||||
- `todos` - Task items
|
||||
- `calendar_events` - Calendar events
|
||||
- `reminders` - Reminders
|
||||
- `projects` - Projects
|
||||
- `project_tasks` - Tasks within projects
|
||||
- `people` - Contacts/people
|
||||
- `locations` - Physical locations
|
||||
- CSRF protection via `X-Requested-With` header middleware
|
||||
- All Pydantic schemas use `extra="forbid"` (mass-assignment prevention)
|
||||
- Nginx rate limiting on auth, registration, and admin endpoints
|
||||
- DB-backed account lockout after 10 failed attempts
|
||||
- Timing-safe dummy hash for non-existent users (prevents enumeration)
|
||||
- SSRF validation on ntfy webhook URLs
|
||||
- Naive datetimes throughout (Docker runs UTC)
|
||||
|
||||
## Docker
|
||||
|
||||
Build and run with Docker:
|
||||
The backend runs as non-root `appuser` in `python:3.12-slim`:
|
||||
|
||||
```bash
|
||||
docker build -t umbra-backend .
|
||||
docker run -p 8000:8000 -e DATABASE_URL=... -e SECRET_KEY=... umbra-backend
|
||||
docker run -p 8000:8000 --env-file .env umbra-backend
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Create New Migration
|
||||
|
||||
```bash
|
||||
alembic revision --autogenerate -m "Description of changes"
|
||||
```
|
||||
|
||||
### Apply Migrations
|
||||
|
||||
```bash
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
### Rollback Migration
|
||||
|
||||
```bash
|
||||
alembic downgrade -1
|
||||
```
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Change `SECRET_KEY` in production
|
||||
- Use strong PINs (minimum 4 digits recommended)
|
||||
- Session cookies are httpOnly and last 30 days
|
||||
- All API endpoints (except auth) require authentication
|
||||
- PINs are hashed with bcrypt before storage
|
||||
In production, use Docker Compose (see root `docker-compose.yaml`).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user