You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prevent future regressions where new migrations aren't added to the
entrypoint.sh stamping logic, causing crash-loops on pre-Alembic DBs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2. Use the naming convention: `git worktree add -b ai/[task-description] ../Telegram-Archive-ai-[task-description]`
5
+
1.Check existing worktrees with `git worktree list` and create a new one for this task if needed
6
+
2. Use the naming convention: `git worktree add -b ai/<task> .worktrees/<task>`
7
7
3. Navigate to the worktree directory before making any changes
8
8
4. Commit changes when the task is finished. Merge to main, and clean the worktree.
9
9
10
-
<!--
11
-
This file is synced with LynxPrompt (Blueprint: bp_cmk483at3000001pdq0ohz0t5)
12
-
13
-
Sync Commands:
14
-
15
-
# Using LynxPrompt CLI (recommended):
16
-
lynxp push # Upload local changes to cloud
17
-
lynxp pull # Download cloud changes to local
18
-
lynxp diff # Compare local vs cloud versions
19
-
20
-
# Install CLI: npm install -g lynxprompt
21
-
# Login: lynxp login
22
-
23
-
Docs: https://lynxprompt.com/docs/api
24
-
-->
25
-
26
-
> **Project Context:** This is an open-source project. Consider community guidelines and contribution standards.
27
-
28
10
## Persona
29
11
30
-
You assist developers working on Telegram-Archive.
31
-
32
-
Project description: Own your Telegram history. Automated, incremental backups with a local web viewer that feels just like the real app. Docker-ready and supports public chat sharing
12
+
You assist developers working on telegram-archive.
33
13
34
14
## Tech Stack
35
15
36
-
- Python 3.11
37
-
- Telethon (Telegram MTProto client)
38
-
- FastAPI + uvicorn (web viewer)
39
-
- SQLAlchemy async (ORM)
40
-
- aiosqlite / asyncpg (database drivers)
41
-
- APScheduler (cron scheduling)
42
-
- Alembic (database migrations)
43
-
- Jinja2 (HTML templates)
44
-
- PostgreSQL / SQLite
16
+
- Python
17
+
- FastAPI
18
+
- sqlalchemy
45
19
46
20
> **AI Assistance:** Let AI analyze the codebase and suggest additional technologies and approaches as needed.
47
21
48
22
## Repository & Infrastructure
49
23
50
-
-**Host:** github
51
-
-**License:** gpl-3.0
52
-
-**Architecture:** Dual-image Docker (shared codebase, separate entrypoints for backup and viewer)
24
+
-**License:** mit
25
+
-**CI/CD:**
53
26
-**Commits:** Follow [Conventional Commits](https://conventionalcommits.org) format
-`src/config.py` — All environment variables and their handling
152
-
-`src/telegram_backup.py` — Core backup logic
153
-
-`.env.example` — Configuration reference
154
-
-`docker-compose.yml` — Deployment patterns
155
-
156
-
## Self-Improving Blueprint
157
-
158
-
> **Auto-update enabled:** As you work on this project, track patterns and update this configuration file to better reflect the project's conventions and preferences.
42
+
-**Workflow:** Create feature branches and submit pull requests
43
+
- Create a descriptive branch name (e.g., `feat/add-login`, `fix/button-styling`)
44
+
- Open a PR for review before merging
45
+
- Do NOT commit directly to main/master branch
159
46
160
47
## Boundaries
161
48
162
49
### ✅ Always (do without asking)
163
50
164
-
- Create new files
165
-
- Rename/move files
166
-
- Rewrite large sections
167
-
- Change dependencies
168
-
- Touch CI pipelines
169
-
- Modify Docker config
170
-
- Change environment vars
171
-
- Update docs automatically
172
-
- Edit README
173
-
- Handle secrets/credentials
174
-
- Modify auth logic
51
+
- Read any file in the project
52
+
- Modify files in src/ or lib/
53
+
- Run build, test, and lint commands
54
+
- Create test files
55
+
- Fix linting errors automatically
175
56
176
57
### ⚠️ Ask First
177
58
178
-
-Delete files
179
-
- Modify database schema
180
-
-Update API contracts
181
-
-Skip tests temporarily
59
+
-Add new dependencies to package.json
60
+
- Modify configuration files at root level
61
+
-Create new modules or directories
62
+
-Refactor code structure significantly
182
63
183
64
### 🚫 Never
184
65
@@ -190,7 +71,7 @@ Always read these files first to understand the project context:
190
71
## Code Style
191
72
192
73
-**Naming:** follow idiomatic conventions for the primary language
193
-
-**Logging:**Python logging with `logger = logging.getLogger(__name__)`
74
+
-**Logging:**[90m⏭ Skip[39m
194
75
195
76
Follow these conventions:
196
77
@@ -201,114 +82,19 @@ Follow these conventions:
201
82
- Add comments for complex logic only
202
83
- Keep functions focused and testable
203
84
204
-
## ⚠️ Data Consistency Rules (CRITICAL)
205
-
206
-
These rules exist because of bugs that reached production. **Always verify these when modifying DB code.**
207
-
208
-
### Chat ID Format (Marked IDs)
209
-
210
-
Telegram uses "marked" IDs that differ from raw entity IDs:
211
-
212
-
| Entity Type | Format | Example |
213
-
|-------------|--------|---------|
214
-
| Users | Positive |`123456789`|
215
-
| Basic groups | Negative |`-123456789`|
216
-
| Supergroups/Channels | -1000000000000 - id |`-1001234567890`|
217
-
218
-
**Rules:**
219
-
- Always use `telethon.utils.get_peer_id(entity)` to get the marked ID
220
-
- Never use `entity.id` directly for database operations
221
-
- The `_get_marked_id()` method in `telegram_backup.py` wraps this
222
-
- User config (`GROUPS_INCLUDE_CHAT_IDS`, etc.) uses marked format
223
-
224
-
### DateTime Timezone Handling
225
-
226
-
Telethon returns timezone-aware datetimes, but PostgreSQL uses `TIMESTAMP WITHOUT TIME ZONE`.
227
-
228
-
**Rules:**
229
-
- Always strip timezone before DB insert/update using `_strip_tz(dt)` in `adapter.py`
230
-
- Apply to ALL datetime fields: `date`, `edit_date`, `created_at`, etc.
231
-
- Check both INSERT and UPDATE operations (v4.0.6 bug: insert used `_strip_tz`, update didn't)
232
-
233
-
### Consistency Checklist
234
-
235
-
When modifying database code, verify:
236
-
-[ ] All chat_id values use marked format (via `_get_marked_id()`)
237
-
-[ ] All datetime values pass through `_strip_tz()` before DB operations
238
-
-[ ] INSERT and UPDATE operations handle the same fields identically
239
-
-[ ] Tests exist in `tests/test_db_adapter.py` for data type handling
240
-
241
-
## Alembic Migrations (CRITICAL)
242
-
243
-
### Architecture
244
-
245
-
- Migrations live in `alembic/versions/` with format `YYYYMMDD_REV_slug.py`
246
-
- Sequential integer revisions: `001`, `002`, ..., `006`, etc.
247
-
-`alembic/env.py` runs migrations via async SQLAlchemy (`asyncpg` for PG, `aiosqlite` for SQLite)
248
-
-`scripts/entrypoint.sh` calls `alembic upgrade head` on container start (backup container only, not viewer)
249
-
- The entrypoint also handles **pre-Alembic stamping** for databases that existed before migrations were added
2. Set `revision = "NNN"` and `down_revision = "NNN-1"`
255
-
3. Use `op.add_column()`, `op.create_table()`, `op.create_index()`, etc.
256
-
4. Both SQLite and PostgreSQL must be supported -- check `conn.dialect.name` when behavior differs
257
-
5. Update the pre-Alembic stamping logic in `entrypoint.sh` if the new migration adds detectable schema (table, index, column) so existing databases get stamped correctly
258
-
259
-
### Advisory Lock Rule (v6.2.14 bugfix)
260
-
261
-
**NEVER execute SQL on the Alembic connection before `context.configure()`.**
262
-
263
-
Any `connection.execute()` before `configure()` triggers SQLAlchemy's autobegin. Alembic then detects `_in_external_transaction=True` and returns `nullcontext()` from `begin_transaction()`, skipping its own commit. DDL runs but is silently rolled back when the connection closes.
264
-
265
-
The correct pattern in `env.py`:
266
-
267
-
```python
268
-
defdo_run_migrations(connection):
269
-
context.configure(connection=connection, ...) # FIRST — no SQL before this
270
-
271
-
with context.begin_transaction():
272
-
# Advisory lock INSIDE the transaction, using xact variant (auto-releases on commit)
`entrypoint.sh` detects pre-Alembic databases and stamps them at the correct version by checking for schema artifacts (tables, columns, indexes). When adding migration `NNN`, add a detection check for it in the stamping logic so fresh installs and upgrades from any version work correctly.
281
-
282
85
## Testing Strategy
283
86
284
87
### Test Levels
285
88
286
-
-**Smoke:** Quick sanity checks for critical paths
287
89
-**Unit:** Unit tests for individual functions and components
288
90
-**Integration:** Integration tests for component interactions
289
-
-**E2e:** End-to-end tests for full user flows
290
91
291
92
### Frameworks
292
93
293
94
Use: pytest
294
95
295
96
### Coverage Target: 80%
296
97
297
-
### CI Requirements
298
-
299
-
**All PRs MUST pass tests before merge.** The `Tests` workflow runs on every PR:
300
-
-`tests/test_db_adapter.py` — Data type consistency (timezone, chat IDs)
4. Adding new features — test the happy path and error cases
311
-
312
98
## 🔐 Security Configuration
313
99
314
100
### Secrets Management
@@ -320,10 +106,6 @@ Add tests when:
320
106
- Dependabot (dependency updates)
321
107
- Renovate (dependency updates)
322
108
323
-
### Authentication
324
-
325
-
- Basic Authentication
326
-
327
109
### Data Handling & Compliance
328
110
329
111
- Encryption at Rest
@@ -337,6 +119,13 @@ Add tests when:
337
119
338
120
**🔍 Security Audit Recommendation:** When making changes that involve authentication, data handling, API endpoints, or dependencies, proactively offer to perform a security review of the affected code.
339
121
122
+
## Alembic Migrations — Critical Reminders
123
+
124
+
-**`Base.metadata.create_all(checkfirst=True)`** creates ALL tables from SQLAlchemy models at once, including tables that should be created by future Alembic migrations. This means pre-Alembic databases can have schema objects from migrations that haven't "run" yet.
125
+
-**`scripts/entrypoint.sh`** stamps pre-Alembic databases by detecting which schema objects exist. **Every time you add a new migration, you MUST update the stamping logic in entrypoint.sh** — both the PostgreSQL block and the SQLite block — to detect the new migration's artifacts (tables, columns, indexes). If you forget, existing databases that were created via `create_all()` will be stamped at a lower version, and Alembic will try to re-create objects that already exist, causing crash-loops.
0 commit comments