docs(plans): record the tiennm99bot rebrand plan and cutover

This commit is contained in:
tiennm99 committed 2026-10-07 16:22:32 +07:00
1 parent f0ca083421
commit be46d4c19c
5 files changed
+374

No files matched your search

@@ -0,0 +1,85 @@
---
phase: 1
title: "Code rebrand"
status: done
owner: agent
---
# Phase 1 — Code rebrand
## Context
Every in-repo `miti99bot` occurrence, listed in the
[scout report](../reports/scout-261007-1423-rebrand-tiennm99bot.md). The bot's
own username is already runtime-resolved (`BOT_USERNAME` or getMe), so nothing
here depends on the new Telegram account.
## Steps
1. **Go module path.** In `go.mod`, change it to `github.com/tiennm99/tiennm99bot`,
then rewrite every import:
`git ls-files '*.go' | xargs sed -i 's#github.com/tiennm99/miti99bot#github.com/tiennm99/tiennm99bot#g'`.
`util/help.go` `repoURL` and `util/help_test.go` follow from the same sed.
2. **Runtime strings** → `tiennm99bot`:
- `internal/server/health.go` health body, plus the `compose.yml` and
`docs/deploy-coolify-selfhosted.md` text that quotes it.
- `internal/deploynotify/deploy_notify.go` DM text, plus its test.
- User-Agents in `coin/price_providers.go`, `gold/vnappmob_client.go` (×2),
`stock/prices_ssi.go`, `lol/api_client.go` (`userAgentProduct`), plus
`stock/prices_test.go` and `lol/api_client_test.go`.
- `monkeyd/export_job.go` `cacheDirName`.
- `renderer/src/gacha/page/page.js` edition label.
3. **Sticker slug.** Set `sticker/sticker_pack.go` `defaultStickerPackSlug` to the
confirmed slug (proposed `stickers`). Update the comment example and the tests
(`addsticker_command_test.go`, `sticker_pack_test.go`), plus the examples in
`docs/sticker-packs.md`, `.env.example` and `compose.yml`.
4. **Test fixtures.** Change `/cmd@miti99bot` to `@tiennm99bot` in
`modules/dispatcher_test.go` and `alias/fallback_test.go`, and the comment in
`stats/views.go`. Change the test DB prefixes `miti99bot_*` to
`tiennm99bot_*` in four `*_mongo*_test.go` files. Update the
`sticker_pack_test.go` username fixture. Leave `misc/handlers_test.go`
`@miti99` alone, because it is a user handle.
5. **loldle stickers.** Update the `loldle/stickers.go` comment to name
@tiennm99bot. The file_ids are replaced in phase 2, because they need the
new bot.
6. **Build/deploy config.**
- `.github/workflows/ci.yml` image tags `tiennm99bot`, `tiennm99bot-renderer`.
- `compose.yml`: the commented GHCR image and the DB example.
- `.env.example`: the header and `MONGO_DATABASE=tiennm99bot`.
- `renderer/package.json` name `tiennm99bot-renderer`. Regenerate the lock
file with `npm install --package-lock-only` in `renderer/`; do not edit it
by hand.
7. **Docs.**
- `README.md` (title, local mongo container name, `_dev` DB), `AGENTS.md`,
`CLAUDE.md`, `docs/deploy-coolify-selfhosted.md`.
- `renderer/README.md`, `renderer/docs/deployment.md`.
- `git mv renderer/docs/miti99bot-integration.md renderer/docs/tiennm99bot-integration.md`,
then fix its links (`git grep -n miti99bot-integration`).
8. **Sweep.** `git grep -n -i miti99bot -- ':!plans'` must be empty. Review any
remaining `miti99` hits by hand.
## Validation
```sh
gofmt -l . && go vet ./... && go test -race -count=1 ./... && go build ./...
(cd renderer && npm ci && npm run lint && npm run typecheck && npm test)
docker build -t tiennm99bot . && docker build -t tiennm99bot-renderer renderer
```
## Commit
Use two focused conventional commits on `main`:
- `feat(config): resolve the bot username from BOT_USERNAME or getMe` (the existing uncommitted change)
- `refactor!: rebrand miti99bot to tiennm99bot`
The body notes that the default sticker pack and the module path changed.
Delay the push to the cutover in phase 2 if the old bot should keep its old strings.
## Risk and rollback
- Go module path change: purely mechanical, and the build and tests catch any miss.
- Pushing deploys to Coolify. If it is pushed before cutover, the only visible
effects are new strings and a new default pack name on the *old* bot, where
`/addsticker` would create `stickers_by_miti99bot`. To avoid that, set
`STICKER_PACK_NAME=miti99_by_miti99bot` in Coolify until cutover, or hold the push.
- Rollback: `git revert` the rebrand commit.
@@ -0,0 +1,140 @@
---
phase: 2
title: "Cutover and manual steps"
status: in-progress
owner: user + agent
blockedBy: [phase-01]
---
# Phase 2 — Cutover and manual steps
Legend: **[you]** only you can do it (BotFather, Atlas UI, Coolify secrets).
**[agent]** I can run it once you approve that step.
Verified facts (2026-10-07):
- The Coolify app `miti99bot` is on **miti-sg** (uuid `ofo63lqv73huw1hce24ntg9i`).
- It has no `STICKER_PACK_NAME` and no `BOT_USERNAME` set.
- The name `tiennm99/tiennm99bot` is free on GitHub.
- `mongodump`/`mongorestore` are not installed here, but the local `mongo:8`
image ships them.
## A. Prepare (no downtime)
1. **[you] Create the bot.** In BotFather, run `/newbot` → username `tiennm99bot`
and keep the token. Then:
- `/setinline` on @tiennm99bot. The alias inline picker needs it
([docs/aliases.md](../../docs/aliases.md)).
- Optionally set `/setdescription`, `/setabouttext`, `/setuserpic`, and
`/setjoingroups` (keep enabled).
- The command menu needs nothing here: the bot registers it at startup.
2. **[you] Start the new bot.** Open @tiennm99bot from the `OWNER_ID` account
and press Start. Without that, the deploy DM fails with 403. Admins should
do the same.
3. **[you] Create the Atlas DB user.** Make a user with `readWrite` on database
`tiennm99bot` only, and build the new `MONGO_URL` with it. Keep the old user
until step D.
4. ✅ **Done 2026-10-07.** **[agent] Rename the repo.** Run `gh repo rename tiennm99bot -R tiennm99/miti99bot`.
GitHub keeps a redirect from the old URL. Then set the local `origin` to
`https://github.com/tiennm99/tiennm99bot.git`.
5. ✅ **Done 2026-10-07.** **[agent] Move the checkout.** Move `/workspace/tiennm99/miti99bot` to
`/workspace/tiennm99/tiennm99bot`. `/tiennm99/` is already ignored at the
workspace root. Restart the Claude session from the new path, because
project memory is keyed by path.
## B. Cutover window (bot offline about 10–15 min)
1. **[agent] Stop the app.** Use `control stop` on the Coolify app (confirm
required) so nothing writes during the copy.
2. **[agent] Back up and copy the database**, using the `mongo:8` image, with
the URL passed via env and never echoed:
- `mongodump --uri "$OLD_URL" --db miti99bot --archive=miti99bot-<date>.archive --gzip`
Keep this archive outside the repo as the backup.
- `mongorestore --uri "$NEW_URL" --archive=... --gzip --nsFrom 'miti99bot.*' --nsTo 'tiennm99bot.*'`
This restores indexes too.
- Compare `countDocuments` for every collection in both DBs with `mongosh`.
Any mismatch means stop and fix before going further.
- A first copy already ran on 2026-10-07 15:10 from `.env` `OLD_MONGO_URL`
/ `OLD_MONGO_DATABASE` (249 docs, counts and indexes match; backup
`~/backups/mongo/miti99bot-20261007-1510.archive.gz`). The old bot kept
writing after it, so at cutover use `--drop` on the restore to re-sync.
- Docker bind mounts land on the daemon host, not this workspace: stream
with `--archive` to stdout/stdin instead of `--out`.
3. **[you] Update the Coolify app env** in the dashboard (the MCP never writes
secret values):
- `TELEGRAM_BOT_TOKEN` = the new token
- `MONGO_URL` = the new user's URL
- `MONGO_DATABASE=tiennm99bot`
- Optionally `BOT_USERNAME=tiennm99bot`, which skips getMe.
- Do **not** set `STICKER_PACK_NAME`, so the default `stickers_by_tiennm99bot`
applies.
- Apply the same values to the preview copies, or delete those.
4. **[you] Rename and repoint the app.** Rename the Coolify app to `tiennm99bot`
and set its git repository to `tiennm99/tiennm99bot`, branch `main`. Check
that the GitHub App source still sees the repo after the rename.
5. **[agent] Deploy.** Push the phase 1 commits to `main` if they are held, or
trigger `deploy`. Then watch `get_deployment` until it is running:healthy.
## C. Verify (agent checks plus you in Telegram)
1. **[agent]** The logs show `bot username ... source getMe|BOT_USERNAME` = `tiennm99bot`,
`webhook cleared`, `telegram long polling started`, and no Mongo errors.
2. **[you]** The owner receives "🚀 tiennm99bot deployed: <sha>" from @tiennm99bot.
3. **[you]** Smoke-test in DM and in one group:
- `/help`
- `/stats` (old counts present, which proves the data moved)
- `/lol`, `/stock`, `/gold`, `/coin`
- `@tiennm99bot` inline
- `/wheelofnames`
4. **[you]** Run `/addsticker` replying to a sticker. It creates
`stickers_by_tiennm99bot`. The old `miti99_by_miti99bot` pack stays with the
old bot. Re-adding its stickers to the new pack is manual, one `/addsticker`
each.
5. **[you] Recapture the loldle stickers.** Send each wanted sticker to
@tiennm99bot and capture its file_id with `/stickerid`. **[agent]** puts
them in `internal/modules/loldle/stickers.go`, then commits and deploys.
Until then, loldle simply sends no sticker, because the errors are already
ignored.
## D. Migration window and cleanup
1. **[you] Move users and groups:**
- Add @tiennm99bot to every group that used @miti99bot.
- Users must Start the new bot in DM.
- Stored subscriptions (lol daily push and others) are keyed by chat ID, so
they stay valid. They deliver once the new bot is in that chat; until
then, the fan-out logs 403s for those chats.
- Announce the move from @miti99bot. Since its token is unused, send the
announcement manually from your account, or post a message in each group.
2. **[you] Retire the old bot** after the window (suggested 2–4 weeks).
Options: `/revoke` the old token in BotFather, `/deletebot`, or keep the
name parked to stop impersonation (recommended: keep it parked and revoke
the token).
3. **[agent] Drop the old database** after verification and the window. Run
`db.getSiblingDB('miti99bot').dropDatabase()` only after a fresh count
check, and keep the dump archive. **[you]** then delete the old Atlas user.
4. **[agent] Clean up.** Delete the local `miti99bot` and `miti99bot-renderer`
docker images if any remain. Update workspace memory or notes that mention
the old name.
## Rollback
Before D.3, rollback is quick:
1. Restore the old `TELEGRAM_BOT_TOKEN`, `MONGO_URL` and `MONGO_DATABASE`.
2. `git revert` the rebrand commit.
3. Redeploy.
The old DB is untouched until D.3. Any writes made to the new DB after cutover
would be lost on rollback.
## File_id migration (done 2026-10-07 16:10)
- Sticker file_ids turned out to work across bots: the 6 sticker aliases and
all 6 loldle stickers send from @tiennm99bot unchanged, so C.5 needs no code
change. Photo and animation file_ids do not transfer.
- The 9 photo/animation aliases were downloaded with the old token, re-uploaded
through the new bot to the owner DM (messages deleted), send-tested, and
their `fileId` updated only where unchanged. Three GIFs were stored without
a file extension and had to be uploaded as `.mp4` to stay animations.
- The 8 stickers of `miti99_by_miti99bot` were added to
`stickers_by_tiennm99bot` by file_id (pack now 9 with the /addsticker test).
- Backup before the update: `~/backups/mongo/tiennm99bot-20261007-pre-fileid-migration.archive.gz`.
@@ -0,0 +1,73 @@
---
title: "Rebrand miti99bot to tiennm99bot"
description: "Rename the code, repo, image, Coolify app, Mongo database and Telegram bot from miti99bot to tiennm99bot."
status: in-progress
priority: P2
effort: 1d (2h code, rest is a cutover window plus manual Telegram/Atlas steps)
branch: main
tags: [rebrand, deploy, mongo, telegram]
blockedBy: []
blocks: []
created: 2026-10-07
---
# Rebrand miti99bot → tiennm99bot
## Outcome
The project, the GitHub repo, the Coolify app, the Mongo database and the
Telegram bot are all named `tiennm99bot`. The bot runs as the new @tiennm99bot
account with all existing data. Old @miti99bot is retired after a migration
window.
Scout: [scout report](../reports/scout-261007-1423-rebrand-tiennm99bot.md).
## Decisions (user, 2026-10-07)
| Topic | Decision |
|---|---|
| Telegram bot | New @tiennm99bot account (new token). Bot usernames cannot be renamed. |
| Mongo database | Rename `miti99bot` → `tiennm99bot` by dump/restore, with a backup kept. |
| Sticker pack | New slug `stickers` → `stickers_by_tiennm99bot` (confirmed). |
| Push timing | Hold every push to `main` until the phase 2 cutover window. |
| Local checkout | Move to `/workspace/tiennm99/tiennm99bot`. |
| Coolify app | Rename the app on miti-sg and repoint it to the new repo. |
## Constraints and non-goals
- `plans/**` stays untouched: those are historical records.
- `@miti99` in `misc/handlers_test.go` is a user handle in a fixture, not the brand.
- Owner/admin IDs are Telegram *user* IDs and do not change.
- No data model changes. Chat IDs stored in Mongo stay valid under the new bot.
- Prerequisite: the uncommitted `BOT_USERNAME` change lands first as its own commit.
## Phases
| # | Phase | Who | Status |
|---|---|---|---|
| 1 | [Code rebrand](phase-01-code-rebrand.md) | agent | done (79104ef, 7008a57; not pushed) |
| 2 | [Cutover and manual steps](phase-02-cutover-and-manual-steps.md) | user + agent | B, C done 2026-10-07; D (retire old bot, drop old DB) after the migration window |
Phase 1 can merge to `main` any time, because nothing in it depends on the new
bot, repo or DB. Its deploy only changes branding strings and the default
sticker pack name, though. Hold the push until the phase 2 cutover window if
the old bot should keep its old strings until the switch.
## Acceptance criteria
- `git grep -i miti99bot -- ':!plans'` returns nothing.
- `go vet ./...`, `go test -race ./...`, `go build ./...`, the renderer
`npm run lint && npm run typecheck && npm test`, and both docker builds pass.
- Coolify app `tiennm99bot` is running:healthy from `github.com/tiennm99/tiennm99bot`.
- The logs show `bot username ... tiennm99bot`, and the owner receives
"🚀 tiennm99bot deployed: <sha>" from @tiennm99bot.
- Every collection in DB `tiennm99bot` has the same document count as in `miti99bot` at cutover.
- `/addsticker` creates or extends `stickers_by_tiennm99bot`, the loldle win/lose
stickers send, and the inline `@tiennm99bot` alias picker works.
## Open questions
- Should old @miti99bot stay alive during the migration window to answer
"moved to @tiennm99bot"? That would need a tiny separate process, so this
plan leaves it idle instead. Telegram allows only one `getUpdates` consumer
per token, so the old token is simply unused.
@@ -0,0 +1,18 @@
---
title: Plan rebrand to tiennm99bot
date: 2026-10-07
summary: "Scouted and planned the miti99bot to tiennm99bot rebrand across code, repo, Coolify, Mongo and Telegram"
---
# Plan rebrand to tiennm99bot
## What happened
Scouted 159 files with `miti99bot`; most are the Go module path (315 import lines). External surfaces: GitHub repo, Coolify app on miti-sg (uuid ofo63lqv73huw1hce24ntg9i), Atlas DB, Telegram bot account.
## Decision
New @tiennm99bot account (bot usernames cannot be renamed), Mongo DB renamed by dump/restore, new sticker slug (proposed `stickers`), checkout moved, Coolify app renamed. Plan: plans/261007-1423-rebrand-tiennm99bot/.
## Next steps
Commit the pending BOT_USERNAME change, run phase 1 (code), then the phase 2 cutover with the user's BotFather/Atlas/Coolify steps.
> Historical work record — not durable authority. Prefer docs/specs/ADRs for current decisions.
@@ -0,0 +1,58 @@
# Scout Report: rebrand miti99bot → tiennm99bot
Baseline: `main` @ c18006f plus the uncommitted `BOT_USERNAME` change (username
is now runtime-resolved; sticker default = `miti99_by_<bot username>`).
## In-repo occurrences (159 files)
### Go module path — 315 import lines, ~150 files
- `go.mod:1` `module github.com/tiennm99/miti99bot`
- Every `internal/...` import in `cmd/` and `internal/`. Mechanical rewrite.
- `internal/modules/util/help.go:16` `repoURL`; asserted in `util/help_test.go:62,165`.
### Runtime branding strings
- `internal/server/health.go:20` — `"miti99bot ok\n"` (health body; docs quote it).
- `internal/deploynotify/deploy_notify.go:74` — `"🚀 miti99bot deployed: %s"`; test `deploy_notify_test.go:89`.
- User-Agent `Mozilla/5.0 (miti99bot)`: `coin/price_providers.go:261`, `gold/vnappmob_client.go:127,233`, `stock/prices_ssi.go:152`; asserted in `stock/prices_test.go:66-67`.
- `lol/api_client.go` `userAgentProduct = "miti99bot/0.1"`; asserted in `lol/api_client_test.go` (`TestClientUserAgent`).
- `monkeyd/export_job.go:42` — cache dir `miti99bot-monkeyd-cache` (temp dir; rename is harmless, old dir orphaned).
- `renderer/src/gacha/page/page.js:281` — gacha recap edition label `'miti99bot'`.
### Sticker pack slug `miti99`
- `sticker/sticker_pack.go:29` `defaultStickerPackSlug = "miti99"`, comment at `:79`.
- Tests: `sticker/addsticker_command_test.go:108,136`, `sticker/sticker_pack_test.go:24`.
- Prod sets no `STICKER_PACK_NAME`, so the live pack is the derived default `miti99_by_miti99bot`.
### Test fixtures (bot-agnostic, rename for consistency only)
- `/cmd@miti99bot`: `modules/dispatcher_test.go:92,98,110,140`, `alias/fallback_test.go:43,45`, `stats/views.go:82` (comment).
- Test DB names `miti99bot_*_test_%d`: `storage/mongo_doc_store_test.go:38`, `lol/startup_mongo_test.go:32`, `stats/startup_mongo_test.go:129`, `stock/startup_mongo_test.go:79`.
- `sticker/sticker_pack_test.go:22-23`, `sticker/addsticker_command_test.go`.
- `misc/handlers_test.go:257-263` uses `@miti99` as a *user* handle — not the brand; leave.
### Bot-scoped data
- `loldle/stickers.go` — sticker file_ids valid only for the @miti99bot account (comment line 5).
### Build / deploy config
- `.github/workflows/ci.yml:65,102` — local image tags `miti99bot`, `miti99bot-renderer`.
- `compose.yml:6` (`ghcr.io/tiennm99/miti99bot:latest`, commented), `:12` DB example, `:53` health text.
- `.env.example:1,12` header and `MONGO_DATABASE=miti99bot`.
- `renderer/package.json:2`, `renderer/package-lock.json:2,8` — `miti99bot-renderer`.
### Docs
- `README.md:1,289,293,295`, `AGENTS.md:5`, `CLAUDE.md:1`.
- `docs/deploy-coolify-selfhosted.md:3,33,118,184,249`, `docs/sticker-packs.md:27,55`.
- `renderer/README.md:3,180,181`, `renderer/docs/deployment.md:3`, `renderer/docs/miti99bot-integration.md` (file name + 3 lines).
- `plans/**` — historical records; leave untouched.
## External surfaces (outside the repo)
- GitHub repo `tiennm99/miti99bot` (git `origin`). Renaming keeps a redirect.
- Coolify app `miti99bot` on **miti-sg** (uuid `ofo63lqv73huw1hce24ntg9i`, project "Applications", running:healthy). Env keys: `TELEGRAM_BOT_TOKEN`, `MONGO_URL`, `MONGO_DATABASE`, `OWNER_ID`, `ADMIN_IDS`, `MODULES`, `LOL_PANDASCORE_TOKEN` (+ preview copies). No `STICKER_PACK_NAME`, no `BOT_USERNAME`.
- MongoDB Atlas database (value of `MONGO_DATABASE`; docs suggest `miti99bot`) and its least-privilege user scoped to that DB.
- Telegram bot account @miti99bot. Bot usernames cannot be renamed; a new @tiennm99bot means a new bot + token.
- Local checkout path `/workspace/tiennm99/miti99bot` (workspace rule: `<owner>/<repo>`).
- No GHCR publish workflow exists; the image ref is only a comment.
## Unresolved Questions
- Is the Telegram bot itself moving to a new @tiennm99bot account, or only the code/repo?
- Should the Mongo database be renamed (requires dump/restore; Mongo has no DB rename)?
- Should the sticker pack slug change (`tiennm99_by_…`), creating a new pack?