Wiki
猫Table of Contents
- DRAFT: Laniakea v2 Migration Plan
- Decisions already made
- Compatibility preparation in v1.2.0
- Proposed breaking changes
- 1. Make optional poll voters explicit
- 2. Make runner cancellation mandatory
- 3. Make invalid keyboards unrepresentable by default
- 4. Use strict and bounded defaults
- 5. Remove deprecated compatibility names
- Expected migration work
- Open design decisions
- Release gates
- Related pages
DRAFT: Laniakea v2 Migration Plan
Russian version: V2-Migration-Plan-RU
Status: DRAFT. This page describes a possible v2 direction, not an implemented or committed public API. Names, signatures, defaults, and release scope are subject to change.
Laniakea v1.2.0 preserves the v1 public API while adding compatibility bridges for stricter, context-aware, and bounded behavior. A future v2 can use those bridges to remove ambiguous contracts and legacy aliases through a mostly mechanical migration instead of mixing breaking cleanup into a minor release.
Decisions already made
v1.2.0must remain source-compatible with v1 wherever the existing feature works.- Breaking changes listed here are deferred to a new major version.
- New v1.2 code should prefer the compatibility APIs shown below to reduce future migration work.
- Telegram wire compatibility is not intentionally broken; corrected JSON field names are already a v1.2 bug fix.
- This draft does not define a v2 release date or guarantee that every proposal will ship.
Compatibility preparation in v1.2.0
| Area | Preferred v1.2 API | Compatibility retained in v1.2 |
|---|---|---|
| Poll voters | PollAnswer.VoterUser() and VoterChatInfo() |
User and VoterChat remain value fields |
| Runners | NewContextRunner(...) |
RunnerFn and NewRunner(...) remain available |
| Callback payloads | CallbackData.EncodeValidated(...) |
Encode(...) keeps its error-free signature |
| Keyboard construction | button Build()/Validate() and keyboard GetValidated()/Validate() |
Existing fluent builders and Get() remain available |
| Rich messages | UnmarshalRichMessageStrict(...) for untrusted input |
UnmarshalRichMessage(...) remains permissive for an empty root |
| File downloads | GetFileByLinkLimit(...) or OpenFileByLink(...) |
Unbounded GetFileByLink(...) remains available |
| Reaction cleanup | DeleteAllMessageReactionsWithContext(...) |
Misspelled singular alias remains deprecated |
| Telegram field names | Use the existing Go fields with corrected wire keys | Source-level field names remain unchanged |
Adopting the preferred column in v1.2 should make most v2 changes compile-time-visible and straightforward to apply.
Proposed breaking changes
1. Make optional poll voters explicit
Change PollAnswer.User and PollAnswer.VoterChat from value fields to pointers. Telegram sends exactly one voter variant, and pointers represent absence without relying on a zero ID.
Migration direction:
// v1.2-compatible preparation
user, ok := answer.VoterUser()
if ok {
use(user)
}
// possible v2 form
if answer.User != nil {
use(answer.User)
}
2. Make runner cancellation mandatory
Make context.Context part of the primary runner callback contract. Long-running and I/O-bound work should stop with polling or webhook runtime cancellation.
Illustrative API only:
runner := laniakea.NewRunner("sync", func(ctx context.Context, bot *laniakea.Bot[*App]) error {
return app.Sync(ctx)
})
The final names may instead retain NewContextRunner; this draft commits to context-aware behavior, not constructor spelling.
3. Make invalid keyboards unrepresentable by default
Move callback-data length checks, payload validation, and row-size validation into the normal construction path. Error-free fluent methods may be replaced or complemented by a builder that returns an error. Unlimited rows should require an explicit option rather than overloading maxRow <= 0.
The exact builder shape is still open. Existing v1.2 Build, Validate, EncodeValidated, and GetValidated methods are the migration bridge.
4. Use strict and bounded defaults
- Make
UnmarshalRichMessage(...)rejectnull,{}, and a missing or nullblocksfield by default. - Preserve unknown rich block objects losslessly instead of reducing them to a known text wrapper.
- Remove or replace unbounded
GetFileByLink(...); prefer a required byte limit or a streaming body.
These changes make untrusted input and remote downloads safer, but their exact error and fallback types remain open.
5. Remove deprecated compatibility names
- Remove
DeleteAllMessageReactionWithContext(...)in favor ofDeleteAllMessageReactionsWithContext(...). - Consider the following exported field renames:
ChatFullInfo.AvailableReaction→AvailableReactions;ReplyParameters.QuoteParsingMode→QuoteParseMode;InputChecklist.OtherCanAddTasks→OthersCanAddTasks;InputChecklist.OtherCanMarkTasksAsDone→OthersCanMarkTasksAsDone.
The wire keys are already correct in v1.2. These proposals affect Go source names only.
Expected migration work
| v1 call or field | Preferred preparation now | Possible v2 migration |
|---|---|---|
answer.User.ID != 0 |
answer.VoterUser() |
nil-check answer.User |
NewRunner(name, func(*Bot) error) |
NewContextRunner(name, func(context.Context, *Bot) error) |
use the primary context-aware constructor |
keyboard.Get() |
keyboard.GetValidated() |
handle construction error from the default path |
data.Encode(kind) |
data.EncodeValidated(kind) |
handle the returned validation error |
UnmarshalRichMessage(data) for external data |
UnmarshalRichMessageStrict(data) |
strict behavior becomes the default |
GetFileByLink(link) |
GetFileByLinkLimit(link, max) or OpenFileByLink(link) |
use bounded or streaming download only |
| singular reaction alias | plural method | no further source change |
Open design decisions
- What public type should preserve unknown rich objects for lossless round trips?
- Should buffered file downloads require a caller-provided limit, provide a documented default, or be removed in favor of streaming?
- Should any deprecated aliases survive one additional major cycle?
- Should keyboard validation use immutable builders, error-returning mutation, or a final validation step?
- Should renamed fields receive temporary accessors during v2 prereleases?
- Which proposals belong in the first v2 release rather than a later v2 minor release?
Release gates
Before the first stable v2 release:
- Freeze the proposed public API and publish paired English/Russian migration guidance.
- Generate and review a complete public API diff against the latest v1 release.
- Add compile-focused migration examples and regression tests for every removed compatibility path.
- Verify Telegram JSON fixtures and unknown rich-object round trips.
- Define bounded download defaults and ownership rules for streaming response bodies.
- Resolve or explicitly defer every open decision on this page.
- Mark completed framework backlog items consistently in
Framework-Backlogand the main repositoryCHANGELOG.md.
Related pages
Navigation
Start here
Runtime and Architecture
- Bot-Lifecycle
- Webhook-Runtime
- Middleware
- Runners
- Error-Handling
- Logging
- Update-Routing-Model
- Policies
- Scenes
Interaction and Telegram API
- Inline-Keyboards-and-Payloads
- Auto-Generated-Commands
- Drafts
- Rich-Messages
- Localization
- Rate-Limiting
- tgapi-Overview