mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 10:24:02 +00:00
feat(bot): add multi-household setup flow
This commit is contained in:
118
docs/decisions/ADR-003-multi-household-runtime-configuration.md
Normal file
118
docs/decisions/ADR-003-multi-household-runtime-configuration.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# ADR-003: Database-Backed Multi-Household Telegram Configuration
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
Decision Date: 2026-03-09
|
||||
Owners: Stanislav Kalishin
|
||||
|
||||
## Context
|
||||
|
||||
The current runtime assumes one household per deployment. `HOUSEHOLD_ID`,
|
||||
`TELEGRAM_HOUSEHOLD_CHAT_ID`, `TELEGRAM_PURCHASE_TOPIC_ID`, and
|
||||
`TELEGRAM_FEEDBACK_TOPIC_ID` are injected as environment variables and then used
|
||||
globally by the bot.
|
||||
|
||||
That model is not viable for the intended product:
|
||||
|
||||
- one bot should support multiple Telegram groups
|
||||
- onboarding should not require Terraform edits or redeploys
|
||||
- topic ids should be captured from real Telegram updates, not copied manually
|
||||
- mini app and bot features must resolve household context per chat/member
|
||||
|
||||
## Decision
|
||||
|
||||
Move household Telegram configuration out of environment variables and into the
|
||||
application database.
|
||||
|
||||
Keep environment variables only for deployment-global concerns:
|
||||
|
||||
- `TELEGRAM_BOT_TOKEN`
|
||||
- `TELEGRAM_WEBHOOK_SECRET`
|
||||
- `DATABASE_URL`
|
||||
- scheduler auth settings
|
||||
- logging and infrastructure settings
|
||||
|
||||
Persist household-specific Telegram configuration as data:
|
||||
|
||||
- Telegram group/supergroup chat id
|
||||
- topic bindings by role (`purchase`, `feedback`, later `reminders`)
|
||||
- household state and setup status
|
||||
- member-to-household Telegram identity linkage
|
||||
|
||||
Bootstrap household setup through bot interactions:
|
||||
|
||||
- bot added to a Telegram group
|
||||
- admin runs `/setup`
|
||||
- admin runs topic binding commands inside target topics
|
||||
- members DM `/start` to link their Telegram identity
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
- Domain stays unaware of Telegram ids and setup flows.
|
||||
- Application owns setup use-cases and authorization rules.
|
||||
- Ports expose household configuration and membership repositories.
|
||||
- Telegram-specific extraction of chat ids, topic ids, and admin checks remains
|
||||
in adapters/app entrypoints.
|
||||
|
||||
## Data Model Direction
|
||||
|
||||
Add database-backed configuration entities around the existing `households`
|
||||
table, likely including:
|
||||
|
||||
- `telegram_households` or equivalent mapping from Telegram chat to household
|
||||
- `household_topics` keyed by household + role
|
||||
- richer `members` onboarding/link status fields if needed
|
||||
|
||||
Exact table shapes remain implementation work, but the model must support:
|
||||
|
||||
- many Telegram groups per deployment
|
||||
- unique chat id ownership
|
||||
- unique topic role per household
|
||||
- idempotent setup commands
|
||||
|
||||
## Rationale
|
||||
|
||||
- Removes deploy-time coupling between infrastructure and household onboarding.
|
||||
- Matches real Telegram behavior, where chat and topic identifiers are only
|
||||
known after bot interaction.
|
||||
- Keeps the production architecture aligned with a multi-tenant SaaS model.
|
||||
- Simplifies future mini app settings screens because configuration is already
|
||||
stored as data.
|
||||
|
||||
## Consequences
|
||||
|
||||
Positive:
|
||||
|
||||
- one deployed bot can support many households
|
||||
- onboarding is self-serve through Telegram commands and later mini app UI
|
||||
- infrastructure configuration becomes smaller and safer
|
||||
|
||||
Negative:
|
||||
|
||||
- requires schema changes and migration from the current single-household model
|
||||
- setup authorization rules become a real application concern
|
||||
- finance/reminder flows must resolve household context dynamically
|
||||
|
||||
## Risks and Mitigations
|
||||
|
||||
Risk:
|
||||
|
||||
- Mixing old env-based household logic with new DB-backed logic creates an
|
||||
inconsistent runtime.
|
||||
|
||||
Mitigation:
|
||||
|
||||
- Introduce an explicit migration phase with fallback rules documented in the
|
||||
spec.
|
||||
- Remove household-specific env usage after setup flows are shipped.
|
||||
|
||||
Risk:
|
||||
|
||||
- Unauthorized users could bind topics or hijack setup.
|
||||
|
||||
Mitigation:
|
||||
|
||||
- Require Telegram group admin privileges for setup and topic binding commands.
|
||||
- Persist an owning admin/member relation and audit setup actions.
|
||||
@@ -63,6 +63,25 @@ Exit criteria:
|
||||
- Purchase messages are ingested and persisted.
|
||||
- Monthly statement can be produced via command.
|
||||
|
||||
## Phase 2.5 - Multi-Household Setup
|
||||
|
||||
Goal: remove single-household deploy assumptions and support real Telegram group
|
||||
onboarding.
|
||||
|
||||
Deliverables:
|
||||
|
||||
- Database-backed Telegram group and topic configuration.
|
||||
- Group bootstrap command (`/setup`).
|
||||
- Topic binding commands executed inside the target topic.
|
||||
- Member DM onboarding and household linkage flow.
|
||||
- Removal of household-specific runtime env requirements.
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- One bot deployment can support multiple household groups.
|
||||
- New households can be configured without Terraform edits or redeploy.
|
||||
- Purchase and anonymous feedback topics are bound from real Telegram updates.
|
||||
|
||||
## Phase 3 - Reminders and Scheduling
|
||||
|
||||
Goal: automate key payment reminders.
|
||||
|
||||
154
docs/specs/HOUSEBOT-070-multi-household-telegram-setup.md
Normal file
154
docs/specs/HOUSEBOT-070-multi-household-telegram-setup.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# HOUSEBOT-070: Multi-Household Telegram Setup and Configuration
|
||||
|
||||
## Summary
|
||||
|
||||
Replace the current single-household env configuration with database-backed
|
||||
household registration, topic binding, and member onboarding so one deployed bot
|
||||
can serve multiple Telegram groups.
|
||||
|
||||
## Goals
|
||||
|
||||
- Register a household from a real Telegram group without redeploying
|
||||
- Bind purchase and feedback topics from in-topic admin commands
|
||||
- Link real Telegram users to household members through DM onboarding
|
||||
- Resolve household context dynamically in bot and mini app flows
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Full settings UI in the mini app
|
||||
- Multi-household reminders customization beyond topic role binding
|
||||
- Cross-household user accounts beyond Telegram identity linkage
|
||||
|
||||
## Scope
|
||||
|
||||
- In:
|
||||
- group bootstrap command
|
||||
- topic binding commands
|
||||
- persistent Telegram chat/topic configuration
|
||||
- member DM onboarding and pending linkage flow
|
||||
- migration away from global household/topic env vars
|
||||
- Out:
|
||||
- advanced role management UI
|
||||
- invite links and QR onboarding
|
||||
- reminders topic configuration UI
|
||||
|
||||
## Interfaces and Contracts
|
||||
|
||||
Telegram commands:
|
||||
|
||||
- `/setup`
|
||||
- `/bind_purchase_topic`
|
||||
- `/bind_feedback_topic`
|
||||
- `/status`
|
||||
- `/start`
|
||||
|
||||
Expected command behavior:
|
||||
|
||||
- `/setup` in a group:
|
||||
- creates or reuses a household bound to `chat.id`
|
||||
- records setup initiator
|
||||
- returns current setup state
|
||||
- `/bind_purchase_topic` in a topic:
|
||||
- stores `message.chat.id` + `message.message_thread_id` as purchase topic
|
||||
- `/bind_feedback_topic` in a topic:
|
||||
- stores `message.chat.id` + `message.message_thread_id` as feedback topic
|
||||
- `/start` in DM:
|
||||
- records Telegram identity
|
||||
- lists pending household memberships or onboarding status
|
||||
|
||||
Mini app/API implications:
|
||||
|
||||
- session resolution must locate the caller’s household membership from stored
|
||||
membership data, not a deployment-global `HOUSEHOLD_ID`
|
||||
- household dashboard endpoints must accept or derive household context safely
|
||||
|
||||
## Domain Rules
|
||||
|
||||
- One Telegram group chat maps to exactly one household
|
||||
- Topic role binding is unique per household and role
|
||||
- Only Telegram group admins can run setup and topic binding commands
|
||||
- Topic binding commands must be executed inside a topic message thread
|
||||
- Setup commands are idempotent
|
||||
- Member linkage must use the caller’s actual Telegram user id
|
||||
|
||||
## Data Model Changes
|
||||
|
||||
Add tables or equivalent structures for:
|
||||
|
||||
- household-to-Telegram chat mapping
|
||||
- topic bindings by household and role
|
||||
- member onboarding/link status if current `members` shape is insufficient
|
||||
|
||||
Indexes/constraints should cover:
|
||||
|
||||
- unique Telegram chat id
|
||||
- unique `(household_id, role)` for topic bindings
|
||||
- unique `(household_id, telegram_user_id)` for members
|
||||
|
||||
Migration direction:
|
||||
|
||||
- keep current `households` and `members`
|
||||
- backfill the existing demo household into the new config model if useful for
|
||||
development
|
||||
- remove runtime dependency on household/topic env vars after cutover
|
||||
|
||||
## Security and Privacy
|
||||
|
||||
- Verify group admin status before setup mutations
|
||||
- Reject topic binding attempts outside the target group/topic
|
||||
- Log setup and binding actions with actor Telegram id
|
||||
- Do not expose household membership data across households
|
||||
- Keep anonymous feedback sender privacy unchanged
|
||||
|
||||
## Observability
|
||||
|
||||
Required logs:
|
||||
|
||||
- household setup started/completed
|
||||
- topic binding created/updated
|
||||
- member onboarding started/linked
|
||||
- rejected setup attempts with reason
|
||||
|
||||
Useful metrics:
|
||||
|
||||
- setup command success/failure count
|
||||
- topic binding count by role
|
||||
- unlinked member count
|
||||
|
||||
## Edge Cases and Failure Modes
|
||||
|
||||
- Bot added to a group without admin permissions
|
||||
- Bot present in a group with privacy mode still enabled
|
||||
- Topic binding command sent in main chat instead of a topic
|
||||
- Duplicate `/setup` on an already configured household
|
||||
- Member DMs `/start` before the household exists
|
||||
- Same Telegram user belongs to multiple households
|
||||
|
||||
## Test Plan
|
||||
|
||||
- Unit:
|
||||
- setup authorization rules
|
||||
- topic binding validation
|
||||
- member link resolution rules
|
||||
- Integration:
|
||||
- repository operations for chat/topic binding persistence
|
||||
- Telegram command handlers with realistic update payloads
|
||||
- E2E:
|
||||
- group setup -> topic binding -> member DM onboarding -> command success
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Bot can create or load household config from a group `/setup` command
|
||||
- [ ] Admin can bind the purchase topic without manual id lookup
|
||||
- [ ] Admin can bind the feedback topic without manual id lookup
|
||||
- [ ] Member DM onboarding stores real Telegram user identity for later linkage
|
||||
- [ ] Existing finance and feedback flows can resolve household context from DB
|
||||
- [ ] Household-specific env vars are no longer required in deployed runtime
|
||||
|
||||
## Rollout Plan
|
||||
|
||||
- Add new schema and repositories first
|
||||
- Ship setup and topic binding commands behind the existing bot deployment
|
||||
- Migrate bot runtime reads from env vars to DB-backed config
|
||||
- Remove household/topic env vars from Terraform examples and runbooks after
|
||||
cutover
|
||||
Reference in New Issue
Block a user