FluentLoop is a Telegram bot for an owner-curated admitted-user audience. The operational surface is still small: one bot, one VPS, one Docker container, and one set of secrets. The sensitive part is the learning data, which may contain real names of colleagues, clients, and projects. This file documents what is protected, what is sent to third parties, and what to do when something goes wrong.
| Asset | Storage | Sensitivity | Notes |
|---|---|---|---|
TELEGRAM_BOT_TOKEN |
.env (local), VPS env, gitignored |
Critical | Compromise = full bot impersonation, ability to message the user as "the bot". |
AI provider API key (OPENAI_API_KEY / ANTHROPIC_API_KEY / DEEPSEEK_API_KEY) |
.env (local), VPS env, gitignored |
Critical | Compromise = billing fraud + leak of any text sent through it. |
| User lesson data (notes, mistakes, answers) | data/ directory, SQLite, gitignored |
High | Contains real names, client info, internal project topics. |
| Bot session / state files | data/, state/, gitignored |
Medium | Re-creatable but losing them resets progress. |
data/backups/ daily SQLite snapshot |
Local, gitignored | High | Same sensitivity as the live DB. |
- Admitted Telegram users, single VPS, single Docker container. Low attack surface, but per-user lesson progress and private uploads must stay isolated.
- No public web endpoint in MVP (Telegram is the only interface).
- Realistic risks:
- Accidental commit of
.envor a leaked token in a log line. - AI provider data retention — anything sent to OpenAI / Anthropic / DeepSeek is governed by their terms.
- VPS compromise via SSH (mitigated by key-only auth, fail2ban — handled in a deployment epic later).
- Accidental commit of
- Not in scope for MVP: DDoS, advanced threat actors, sophisticated exfiltration. This is a personal tool.
The bot sends user-generated text to the configured AI provider for three purposes:
- Extraction (PRD §25.1) — uploaded lesson notes, word lists, teacher feedback are sent verbatim to the AI to identify candidate learning items.
- Exercise generation (PRD §25.2) — approved learning items, progress state, and weakness signals are sent so the AI can generate exercises.
- Answer checking (PRD §25.3) — exercise prompts and the user's answers are sent so the AI can judge them and produce feedback.
What this means in practice:
- The offline roadmap editor makes no network requests. Its public syllabus
contains no learner data; personal order and notes stay in browser storage or
downloaded JSON until explicitly imported. CLI exports use mode 600. Personal
exports belong outside tracked files, preferably under
data/. Roadmap settings/notes are not sent to AI providers and cannot grant assessed mastery. - Simple choice questions from the reviewed pack and existing approved cards are selected and checked locally. An optional written bonus uses the existing AI answer-checking path and sends its prompt and submitted sentence to the configured provider. Attempts and personal progress stay in the private DB.
- Bounded simple-bank expansion sends curated question prompts, choices, and target constructions to the configured provider to draft and independently check new variants. Raw learner answers are not sent in those prompts. A reported question is excluded from that learner's selection while its report remains in the private DB.
- Lesson notes may contain colleague names, client names, internal project names, and informal commentary. All of that is transmitted to the chosen AI provider.
- Provider data retention follows the published terms for the configured AI provider.
- The user must consciously decide they accept this. There is no way to build the product without it.
Optional mitigation — redaction list. A simple regex-based redactor can
replace user-maintained sensitive tokens (real names, project codenames)
with placeholders like [COLLEAGUE_1], [PROJECT_X] before sending text to
the AI. This is captured as a P1 enhancement, not MVP-blocking. See
docs/architecture.md (TODO section) when it is filled in.
- Real values live only in
.env(local), in the VPS environment, or in a password manager. Never in git, commit messages, logs, or example files. .env.exampleis the only env file tracked. It contains placeholders only.- Confidential deploy-only values may live in
secrets/deploy.env(gitignored, mode 600). Seedocs/runbooks/secrets-management.md. - Pre-commit checklist:
python3 scripts/secret_scan.pymust returnsecret-scan: ok.- No real Telegram user IDs (numeric IDs are personally identifying).
- No email addresses.
- If a secret leaks: rotate immediately (BotFather
/revoke, AI provider dashboard), force-push a clean history (with explicit user permission), audit logs.
| Scenario | Recovery |
|---|---|
| Bot token rotated by user | Update .env on VPS, restart container. |
| AI key rotated by user | Update .env on VPS, restart container. |
data/fluentloop.sqlite corrupted |
Restore from latest data/backups/db-YYYY-MM-DD.sqlite (14-day rotation, see EPIC-08). |
| VPS lost / wiped | Re-deploy from git, re-add secrets, restore DB from off-VPS backup if you keep one. Off-VPS backup is a future enhancement. |
| Token leaked publicly | Rotate token, audit recent bot activity via Telegram update history, rebuild commit history if leaked through git. |
Before pushing to a remote (when there is one):
git status— no.env, nodata/, nosecrets/, no*.session.python3 scripts/secret_scan.pyreturnssecret-scan: ok.- No real numeric Telegram user IDs in tracked files.
- PRD / epic / ADR docs reflect any behavior change in this commit.