Files
duty-teller/docs/runbook.md
Nikolay Tatarinov e6bc60b436
Some checks failed
CI / lint-and-test (push) Failing after 23s
chore: update project configuration and documentation
- Added *.egg-info/ to .gitignore to prevent egg metadata from being tracked.
- Updated virtual environment instructions in CONTRIBUTING.md and README.md to use .venv for consistency.
- Revised mkdocs.yml to include a placeholder for the repository URL when publishing.
- Cleaned up pyproject.toml by removing unnecessary pylint configuration.
- Enhanced import-format.md and runbook.md documentation for clarity on user roles and health check endpoints.
2026-02-24 13:30:58 +03:00

84 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Runbook (operational guide)
This document covers running the application, checking health, logs, common errors, and database operations.
## Starting and stopping
### Local
- **Start:** From the repository root, with virtualenv activated:
```bash
python main.py
```
Or after `pip install -e .`: `duty-teller`
- **Stop:** `Ctrl+C`
### Docker
- **Dev** (code mounted; no rebuild needed for code changes):
```bash
docker compose -f docker-compose.dev.yml up --build
```
Stop: `Ctrl+C` or `docker compose -f docker-compose.dev.yml down`.
- **Prod** (built image; restarts on failure):
```bash
docker compose -f docker-compose.prod.yml up -d --build
```
Stop: `docker compose -f docker-compose.prod.yml down`.
On container start, `entrypoint.sh` runs Alembic migrations then starts the app as user `botuser`. Ensure `.env` (or your orchestrators env) contains `BOT_TOKEN` and any required variables; see [configuration.md](configuration.md).
## Health check
- **HTTP:** The FastAPI app exposes **`GET /health`**, which returns `{"status": "ok"}` with 200 when the app is up. Use it for readiness checks and in Docker `HEALTHCHECK`.
- Alternatively, open the interactive API docs at **`GET /docs`** (e.g. `http://localhost:8080/docs`) or call a lightweight API endpoint with valid auth.
## Logs
- **Local:** Output goes to stdout/stderr; redirect or use your process managers logging (e.g. systemd, supervisord).
- **Docker:** Use `docker compose logs -f` (with the appropriate compose file) to follow application logs. Adjust log level via Python `logging` if needed (e.g. environment or code).
## Common errors and what to check
### "hash_mismatch" (403 from `/api/duties` or Miniapp)
- **Cause:** The server that serves the Mini App (e.g. production host) uses a **different** `BOT_TOKEN` than the bot from which users open the Mini App (e.g. test vs production bot). Telegram signs initData with the bot token; if tokens differ, validation fails.
- **Check:** Ensure the same `BOT_TOKEN` is set in `.env` (or equivalent) on the machine serving `/api/duties` as the one used by the bot instance whose menu button opens the Miniapp.
### Miniapp "Open in browser" or direct link — access denied
- **Cause:** When users open the calendar via “Open in browser” or a direct URL, Telegram may not send `tgWebAppData` (initData). The API requires initData (or `MINI_APP_SKIP_AUTH` in dev).
- **Action:** Users should open the calendar **via the bots menu button** (e.g. ⋮ → "Calendar") or a **Web App inline button** so Telegram sends user data.
### 403 "Open from Telegram" / no initData
- **Cause:** Request to `/api/duties` or `/api/calendar-events` without valid `X-Telegram-Init-Data` header. The API returns 403 without initData; the only bypass is `MINI_APP_SKIP_AUTH=1` (dev only, insecure).
- **Check:** Ensure the Mini App is opened from Telegram (menu or inline button). For local dev without Telegram, use `MINI_APP_SKIP_AUTH=1` in `.env`.
### Mini App URL — redirect and broken auth
- **Cause:** If the Mini App URL is configured **without** a trailing slash (e.g. `https://your-domain.com/app`) and the server redirects `/app` → `/app/`, the browser can drop the fragment Telegram sends, breaking authorization.
- **Action:** Configure the bots menu button / Web App URL **with a trailing slash**, e.g. `https://your-domain.com/app/`. See README “Mini App URL”.
### User not in allowlist (403)
- **Cause:** Miniapp access is determined by **roles in the database** (see `can_access_miniapp_for_telegram_user` in the repository). If the user has no role in the DB, the app falls back to `ADMIN_USERNAMES` and `ADMIN_PHONES`. A 403 means the user has neither a role granting access nor a match in the admin allowlist.
- **Check:** Assign a role with `/set_role @username user` or `admin` (admin-only command), or add the user to `ADMIN_USERNAMES` / their phone to `ADMIN_PHONES` in [configuration.md](configuration.md). Ensure at least one admin exists via env so they can use `/set_role`.
## Database and migrations
- **Default DB path (SQLite):** `data/duty_teller.db` (relative to working directory when using default `DATABASE_URL=sqlite:///data/duty_teller.db`). In Docker, the entrypoint creates `/app/data` and runs migrations there.
- **Migrations (Alembic):** From the repository root:
```bash
alembic -c pyproject.toml upgrade head
```
Config: `pyproject.toml` → `[tool.alembic]`; script location `alembic/`; metadata and URL from `duty_teller.config` and `duty_teller.db.models.Base`.
- **Rollback:** Use with care; test in a copy of the DB first. Example to go back one revision:
```bash
alembic -c pyproject.toml downgrade -1
```
Always backup the database before downgrading.
For full list of env vars (including `DATABASE_URL`), see [configuration.md](configuration.md). For reverse proxy and Mini App URL details, see the main [README](../README.md).