FILE / ScuroNeko/Laniakea
CHANGELOG.md
Исходный файл и его история в репозитории.
(fix): runtime reliability (tests): regression coverage (doc): v1.1 release notes
495 lines
48 KiB
Markdown
495 lines
48 KiB
Markdown
# Changelog
|
|
|
|
## v1.1.0
|
|
|
|
### Breaking Changes
|
|
- Fixed `Uploader.SendLivePhoto` and `Uploader.SendLivePhotoWithContext` to require both the live-photo video and its static image. The previous one-file signatures could not produce a valid `sendLivePhoto` request.
|
|
|
|
### Bot API 10.1
|
|
- Added rich message receiving support: `tgapi.RichMessage` on `Message.RichMessage` (`rich_message`), the full set of `RichText*`/`RichBlock*` wire types with official API names, and `UnmarshalRichText`/`UnmarshalRichBlock`/`UnmarshalRichMessage` parsers. Unknown text-bearing types retain their nested text through fallback wrappers while unmodeled fields are discarded.
|
|
- Added rich message sending support: `tgapi.InputRichMessage`, `tgapi.SendRichMessage` params, and `API.SendRichMessage`/`API.SendRichMessageWithContext`.
|
|
- Added rich message draft streaming: `API.SendRichMessageDraft`/`API.SendRichMessageDraftWithContext` for ephemeral ~30-second previews of partially generated messages.
|
|
- Added rich message editing: `EditMessageText.RichMessage` (`InputRichMessage`); `Text` is now omitted from the request when empty so rich-only edits are valid.
|
|
- Added `tgapi.InputRichMessageContent` for rich content in inline query results.
|
|
- Added join request query support: `User.SupportsJoinRequestQueries`, `ChatFullInfo.GuardBot`, `ChatJoinRequest.QueryID`, `API.AnswerChatJoinRequestQuery` with `ChatJoinRequestQueryResult` constants (`JoinRequestApprove`/`JoinRequestDecline`/`JoinRequestQueue`), and `API.SendChatJoinRequestWebApp` (plus `WithContext` variants).
|
|
- Added poll link media: the `tgapi.Link` type, `PollMedia.Link`, and the "link" type with `URL` on `InputPollOptionMedia`.
|
|
|
|
### Bot API 10.2
|
|
- Added block-based rich-message sending with `InputRichMessage.Blocks`, including animation, audio, photo, video, and voice-note input blocks. The `tgrich` package provides matching media constructors with optional block captions.
|
|
- Added `InputRichMessage.Media` for media embedded in rich-message HTML or Markdown, with multipart `attach://` upload support.
|
|
- Added multipart rich-message uploads through `Uploader.SendRichMessage`. Use `UploaderFile.SetAttachName` to match an `attach://` media reference; rich-message draft helpers reject direct uploads as required by Telegram.
|
|
- Added ephemeral-message support: outgoing receiver and callback parameters, reply targets, message fields, edit and delete methods, and ephemeral bot commands. Added community service-message types and subscription update handling.
|
|
|
|
### Added
|
|
- Added documented `tgrich` constructors and block types for building input rich messages.
|
|
- Added `tgrich.BuildHTML` and `tgrich.ToHTML` to validate input block trees, convert them to HTML rich messages, and collect URL, `file_id`, or multipart media references.
|
|
- Added `MessageContext.RichAnswer(...)` and `MessageContext.RichAnswerKeyboard(...)` for validating and sending `tgrich` input blocks.
|
|
- Added `UpdateTypeSubscription` routing and normalized message, user, and chat context for guest messages, deleted business messages, anonymous poll answers, reaction counts, managed bots, chat boosts, and subscription updates.
|
|
- Added webhook secret-format validation and the exported `ErrBotWebhookOptsSecretTokenInvalid` sentinel.
|
|
|
|
### Changed
|
|
- `AutoGenerateCommandsForScope(nil)` now atomically replaces commands in Telegram's default scope without deleting the previous list first.
|
|
- API debug logging now records redacted request JSON and response metadata instead of complete response bodies.
|
|
- Scene updates sharing a user or chat session key are serialized, and duplicate scene names from later plugins are skipped with a warning.
|
|
- Inline keyboard button builders now keep URL and callback actions mutually exclusive, and `InlineKeyboard.Get` returns independent markup data.
|
|
- `NewBot` no longer aliases `BotOpts.Prefixes` or mutates `BotOpts.LoggerBasePath`.
|
|
- README requirements now match the module's Go 1.26 directive.
|
|
- Migrated the golangci-lint configuration to its v2 schema so the repository lint workflow runs again.
|
|
- Added missing Godoc for exported error methods, enum constants, and all public Bot API 10.1/10.2 fields introduced in this release.
|
|
|
|
### Fixed
|
|
- Fixed JSON BotOpts environment placeholders corrupting or injecting JSON when values contain quotes, backslashes, or control characters.
|
|
- Preserved checkbox state when converting list items to ordered lists and made generated HTML attribute ordering deterministic.
|
|
- Added validation for rich-block type discriminators, heading sizes, list fields, table cells, map parameters, and media values.
|
|
- Fixed generated webhook secrets using padded Base64 characters that Telegram rejects, stopped logging generated secrets, and added HTTP read and idle timeouts to the webhook server.
|
|
- Fixed negative group and channel IDs receiving global rather than per-chat `retry_after` cooldowns.
|
|
- Fixed rejected per-chat requests consuming global rate-limit capacity and draft construction consuming an extra rate-limit token before the API request.
|
|
- Fixed subscription updates being decoded as `UpdateTypeUnknown`.
|
|
- Fixed rich-text and rich-block decoding silently accepting malformed typed fields or a top-level `null` rich-text value.
|
|
- Fixed `tgrich.BuildHTML` disabling Telegram entity detection and accepting the draft-only thinking block; `BuildDraftHTML` now provides the explicit draft path.
|
|
- Fixed `tgrich.BuildHTML` silently losing explicit bank-card, mention, hashtag, cashtag, and bot-command values when their visible text differs.
|
|
- Fixed API debug logs exposing webhook, payment, callback, passport, and managed-bot secrets.
|
|
- Fixed panics and nil callbacks in asynchronous middleware terminating the process; failures now reach the logger and observer error stream.
|
|
- Fixed multipart helpers attempting direct file uploads for rich-message drafts, which Telegram does not support; they now return `ErrRichMessageDraftUploadUnsupported`.
|
|
- Fixed draft ID zero values and collisions overwriting tracked drafts, nil draft APIs panicking, and draft entity slices aliasing caller memory.
|
|
- Fixed scene session payloads and returned inline keyboard markup aliasing mutable internal slices.
|
|
- Recovered panics from runner callbacks so they are reported through normal runner and error observer events instead of terminating the process.
|
|
|
|
### Tests
|
|
- Added JSON regression coverage for rich-message embedded media and ephemeral send, edit, and delete parameters.
|
|
- Added regression coverage for escaped environment placeholders and both required `sendLivePhoto` multipart fields.
|
|
- Added regression coverage for API log redaction, same-session scene serialization, duplicate scene registration, async middleware failures, and rich entity preservation.
|
|
- Added rich HTML renderer coverage for all input block and media types, multipart references, field validation, and Telegram's text, block, nesting, media, and table-width limits.
|
|
- Added regression coverage for webhook token syntax, update context normalization, subscription routing, rate-limit capacity, draft ID collisions, runner panics, scene and keyboard aliasing, command replacement, and malformed rich JSON.
|
|
|
|
## v1.0.2
|
|
|
|
### Fixed
|
|
- Fixed long-polling stopping permanently when the HTTP client's internal timeout fired. The polling loop was checking `errors.Is(err, context.DeadlineExceeded)`, which matched HTTP client timeout errors (`*url.Error` wraps `context.DeadlineExceeded`), causing the goroutine to exit as if the bot context was canceled. The check is now `ctx.Err() != nil` so only a real context cancellation stops polling.
|
|
- Fixed the HTTP client timeout (45 s) being too close to the long-poll `getUpdates` timeout (30 s default), leaving insufficient margin for connection setup and response transfer. The client timeout is now derived from the configured `PollTimeout` plus a 60-second buffer.
|
|
|
|
## v1.0.1
|
|
|
|
### Fixed
|
|
- Fixed webhook always accepting unauthenticated requests when `SecretToken` is not configured. A cryptographically random 32-byte token is now generated automatically when `SecretToken` is empty, so the webhook endpoint is always authenticated. The generated token is logged as a warning so the operator can record it.
|
|
- Fixed `tgapi.NewAPI` and `tgapi.NewUploader` not installing token redaction on their managed loggers. The bot token is now masked as `<TOKEN>` in debug output even when the `tgapi` package is used standalone without the `laniakea.Bot` wrapper.
|
|
|
|
## v1.0.0
|
|
|
|
### Breaking Changes
|
|
- Renamed `MsgContext` to `MessageContext` across the public API, including handler signatures (`CommandExecutor`, `MiddlewareExecutor`, scene handler types), all reply/edit/scene helpers, embedded fields on `SceneContext`, and documentation.
|
|
- Removed the `NewPayload(...)` constructor. `NewCommand(...)` builds the underlying `Command[T]` for both `/-`commands and callback payloads; registration via `Plugin.AddPayload`/`Plugin.Payload` decides routing.
|
|
- `MessageContext.Error(...)` no longer sends unclassified errors to the user. Only errors marked with `AsUserError(...)` are surfaced through the centralized reply path; everything else stays internal-only and is logged.
|
|
- `Plugin.Close()` no longer closes a logger supplied through `Plugin.SetLogger(...)`. Only loggers created by the bot during `AddPlugins` registration are owned and closed; caller-supplied loggers remain the caller's responsibility.
|
|
- Renamed final public APIs to idiomatic names before the stable release: `RunWebhookWithContext(...)`, `RunWebhook(...)`, `CloseWebhook()`, `BotWebhookOpts`, `NewBotWebhookOpts()`, `SetWebhookLogger(...)`, and `GetWebhookLogger()`.
|
|
- Renamed plugin builder helpers from `NewCommand(...)` and `NewScene(...)` to `Command(...)` and `Scene(...)`; the surviving `NewCommand(...)` takes the command string before the executor.
|
|
- Renamed command argument value constants to `CommandValueString`, `CommandValueInt`, `CommandValueBool`, and `CommandValueAny`; `NewCommandArg(...)` now defaults to unvalidated `CommandValueAny`.
|
|
- Renamed runner builders from `Onetime(...)` and `Timeout(...)` to `Every(...)` and `Async(...)`; `Runner.Once()` is removed. Use the default configuration (every=0, async=true) for a fire-and-forget goroutine, or `Async(false)` for a synchronous blocking one-shot.
|
|
- Renamed remaining public acronym/casing outliers including `AnswerCallback...`, `ParseMarkdownV2`, `ParseMarkdown`, `GetChatMemberCount`, `DropRateLimitOverflow`, `SetDropRateLimitOverflow`, and inline keyboard builder APIs.
|
|
- Renamed `Observer` event delivery methods `OnReceiveUpdate` → `OnUpdateReceived` and `OnHandledUpdate` → `OnUpdateHandled` to match the `UpdateReceivedEvent`/`UpdateHandledEvent` names and the `OnX` pattern of all other observer methods.
|
|
- `Scene.PluginName` is now unexported; it is assigned by the framework during plugin registration and must not be set by callers.
|
|
- `SceneSession.Data` is now unexported; use the `Set`/`Get`/`HasData`/`ClearData`/`BindData`/`SaveData` helpers instead.
|
|
- `BotPayloadType*` sentinels are now `const` instead of `var`; code that assigned to them will no longer compile.
|
|
|
|
### Bot API 10.0
|
|
- Added full support for Telegram Bot API 10.0 types, methods, and update kinds.
|
|
|
|
### Added
|
|
- Added `MessageContext.IsCallback()` and `MessageContext.HasPhoto()` helpers for callback-aware handler code.
|
|
- Added `MessageContext.UpsertKeyboard(...)` and `MessageContext.UpsertKeyboardMarkdown(...)` helpers that edit callback messages, replace photo callback messages with a fresh chat message, and send a new chat message outside callback flow.
|
|
- Added `CommandGroup`, `NewCommandGroup(...)`, `Plugin.CommandGroup(...)`, and `Plugin.AddCommandGroup(...)` helpers for registering prefixed command groups with shared middleware.
|
|
- Added the `tgfmt` package with typed MarkdownV2, HTML, legacy Markdown formatting helpers, and a message entity builder.
|
|
- Added `InlineKeyboardButtonBuilder.SetPayloadType(...)`, `InlineKeyboardButtonBuilder.SetCallbackData(...)`, and `MessageContext.NewInlineKeyboardButton(...)` helpers for payload-aware button building.
|
|
- Added compact callback payload encoding through `BotPayloadCompact`, `BotPayloadCompactBase64`, compact inline keyboard builders, and matching `CallbackData` helpers.
|
|
- Added `BotOpts.PollTimeout`, `BotOpts.SetPollTimeout(...)`, and the `POLL_TIMEOUT` environment variable to configure the long-polling `getUpdates` timeout (default 30 seconds).
|
|
- Added `RateLimiter.Cleanup(idleThreshold)` to evict per-chat limiter state and expired chat cooldowns; the limiter now tracks per-chat last-seen time so long-running bots can bound memory through a periodic runner.
|
|
- Added cached bot identity (`Bot.userID`) populated at `NewBot` so chat-admin policies and similar lookups reuse it instead of issuing a fresh `GetMe` request.
|
|
- Added `tgapi.ResponseError` so Telegram API error codes, descriptions, and response parameters remain inspectable through returned errors.
|
|
- Added nine exported webhook error sentinels — `ErrSetWebhookFailed`, `ErrBotAPINil`, `ErrBotWebhookOptsEmptyPath`, `ErrBotWebhookOptsPathNoSlash`, `ErrBotWebhookOptsPathHasQueryOrFragment`, `ErrBotWebhookOptsPathCollidesStatus`, `ErrBotWebhookTLSFilesIncomplete`, `ErrBotWebhookTLSFilesTooMany`, and `ErrStatusPathSecretRequired` — replacing the previous inline `errors.New(...)` calls so callers can match webhook startup errors with `errors.Is`.
|
|
- Added `ErrInvalidPayload` for compact payload decoding failures so callers can distinguish malformed payload bytes from other decode errors.
|
|
- Panics inside `Bot.handle` and the polling goroutine now emit an `ErrorEvent` through the observer so instrumentation sees runtime panics in addition to normal handler errors.
|
|
|
|
### Changed
|
|
- Version metadata now reports the stable `v1.0.0` release instead of `v1.0.0-rc.16`.
|
|
- Compact callback payload encoding now escapes `,`, `|`, and `\` in command and arg bytes so payloads containing those bytes round-trip without ambiguity. Note: the format coalesces "no args" with "single empty arg" — both encode as `cmd|` and decode to nil args.
|
|
- `CallbackData.ToJSON()`, `ToBase64()`, `ToCompact()`, and `ToCompactBase64()` now all return an empty string on serialization failure; the previous `ToJSON()` fallback `{"cmd":""}` has been removed so encoder bugs surface visibly instead of routing to no handler.
|
|
- Bot-level middleware blocks now emit a final `UpdateHandledEvent` with `Handled=false`, keeping observer update lifecycles balanced.
|
|
- Plugin registration now warns when `AddCommand`, `AddPayload`, or `AddScene` overwrites an existing entry with the same name instead of silently replacing it.
|
|
- `BotOpts`, `tgapi.APIOpts`, logger utilities, README, and wiki pages now document the final stable API names and configuration options consistently.
|
|
- CI now checks formatting, tests, vet, and lint on both pushes and pull requests.
|
|
|
|
### Fixed
|
|
- Fixed the update worker pool returning before in-flight handlers completed. `startUpdateWorkers` now calls `pool.StopAndWait()` so the bot waits for already-submitted tasks before runtime exit.
|
|
- Fixed `RateLimiter.getChatLimiter` upgrading a held read lock to a write lock, which could deadlock under contention. The lookup now releases the read lock before acquiring the write lock and re-checks the map.
|
|
- Fixed `RateLimiter` per-chat limiter and lock maps growing unbounded for the lifetime of long-running bots that serve many distinct chats.
|
|
- Fixed `Draft.Push` mutating `Message` before validating the candidate length, leaving the draft in a half-mutated state when the candidate would exceed Telegram's limit. The candidate is now validated first; on failure the draft remains unchanged.
|
|
- Fixed background runners running one extra iteration after context cancellation when both `ctx.Done()` and the ticker were ready in the same `select`.
|
|
- Fixed `Plugin.Close()` double-closing a logger supplied by the caller through `SetLogger(...)`.
|
|
- Fixed compact callback payload corruption for arguments containing `,` or `|` bytes.
|
|
- Fixed `LoadOptsFromEnv` calling `os.Getenv("MAX_WORKERS")` twice when parsing the worker count.
|
|
- Fixed `sceneRuntime` interface carrying a delegating `buildSceneKey` method that just forwarded to a package-level helper; `MessageContext` scene helpers now call the helper directly.
|
|
- Fixed webhook startup so empty-secret warnings are logged only after the webhook logger is initialized.
|
|
- Fixed webhook startup so a logger configured through `SetWebhookLogger(...)` is preserved.
|
|
- Fixed long-polling 429 handling so `getUpdates` retries use Telegram `retry_after` directly and do not inflate later transient-error backoff.
|
|
- Fixed `BotOptsFileJSON` silently dropping `PollTimeout` on round-trip; the field is now encoded and decoded correctly.
|
|
- Fixed the `tgapi.Uploader` returning an ad-hoc error string on Telegram API failures; it now returns `*tgapi.ResponseError` matching the JSON API client, so `errors.As(err, &respErr)` works consistently for both upload and JSON paths.
|
|
- Fixed webhook secret validation to use `subtle.ConstantTimeCompare` instead of a plain string equality check, removing the timing side-channel.
|
|
- Fixed the `/status` handler returning HTTP 403 for a wrong secret, which disclosed endpoint existence; it now returns 404 uniformly for any unauthenticated request.
|
|
|
|
### Tests
|
|
- Added regression coverage proving bot-level middleware blocks still complete the observer update lifecycle.
|
|
- Added webhook runtime regression coverage for request enqueue through worker execution of a command handler.
|
|
- Added regression coverage for inline callback keyboard upserts and callback target detection.
|
|
- Added regression coverage for command group prefixing, middleware order, clone behavior, and plugin registration.
|
|
- Added formatting coverage for escaping, composition, link destinations, HTML attributes, and legacy Markdown code blocks.
|
|
- Added regression coverage for context-aware inline keyboard button payload encoding.
|
|
- Added regression coverage for compact and Base64-encoded compact callback payload decoding.
|
|
- Added regression coverage for long-polling `retry_after` handling on Telegram 429 responses.
|
|
- Added regression coverage for compact callback payload round-tripping through `,`, `|`, and `\` separator bytes and a missing-separator decode error.
|
|
- Added regression coverage for `Draft.Push` preserving the existing message when validation rejects the candidate.
|
|
- Added regression coverage for `RateLimiter.Cleanup` evicting idle chat limiters and expired chat locks while leaving active state in place.
|
|
- Updated `MessageContext.Error` tests so unclassified errors stay internal-only and only `AsUserError` reaches the user.
|
|
- Added regression coverage for `BotOptsFileJSON` `PollTimeout` round-trip.
|
|
- Added regression coverage proving the `tgapi.Uploader` surfaces `*tgapi.ResponseError` for Telegram 4xx responses.
|
|
- Added regression coverage proving a panic inside `Bot.handle` emits an `ErrorEvent` through the observer.
|
|
- Added regression coverage for the webhook `/status` endpoint rejecting wrong and same-length-but-different secrets with HTTP 404, and accepting the correct secret.
|
|
- Added table-driven regression coverage for `parseCommand` with `/cmd@botname` stripping, bare commands, commands with arguments, and empty input.
|
|
|
|
## v1.0.0-rc.16
|
|
|
|
### Breaking Changes
|
|
- Replaced `git.scuroneko.dev/scuroneko/slog` with `git.scuroneko.dev/scuroneko/sneklog/v2` across public logger APIs, including `AppDataLogger`, logger getters, and custom logger setters.
|
|
- Renamed exported `Json`, `Url`, and `Id` identifiers to idiomatic `JSON`, `URL`, and `ID` spellings, including `BotOpts.APIURL`, `BotOpts.SetAPIURL(...)`, `tgapi.APIOpts.SetAPIURL(...)`, `BotOptsFileJSONCodec`, `BotPayloadJSON`, and related README examples.
|
|
- Made the request logger field internal; use `Bot.SetRequestLogger(...)` and `Bot.GetRequestLogger()` instead of accessing `Bot.RequestLogger` directly.
|
|
|
|
### Added
|
|
- Added `Bot.UpdatesIter(...)` as an iterator wrapper around a single `Bot.Updates(...)` call, including error delivery through the iterator.
|
|
- Added scene-local callback payload handlers through `Scene.OnPayload(...)`, including observer lifecycle events for scene payload execution.
|
|
- Added configurable logger output through `BotOpts.LogFormat`, `BotOpts.SetLogFormat(...)`, `BotOpts.SetLogFormatter(...)`, `tgapi.APIOpts.SetLogFormat(...)`, and `tgapi.APIOpts.SetLogFormatter(...)`.
|
|
- Added JSON BotOpts file format versioning through `ConfigVersion`, `ErrConfigVersionMismatch`, and `BotOpts.FileConfigVersion`.
|
|
- Added `Bot.SetLogger(...)`, `Bot.SetRequestLogger(...)`, `Bot.SetWebHookLogger(...)`, `Bot.GetRequestLogger()`, and `Bot.GetWebHookLogger()` helpers for explicit logger customization.
|
|
|
|
### Changed
|
|
- Updated `pond/v2` to `v2.7.1`.
|
|
- `Bot.RunWithContext(...)` now closes an explicitly set request logger when `UseRequestLogger` is false and closes webhook loggers before long-polling startup.
|
|
- Bot loggers now apply the configured token replacer consistently across the main bot logger, request logger, internal API and uploader loggers, webhook logger, app-data logger writers, and auto-managed plugin loggers.
|
|
- JSON `BotOpts` files now write `version`, reject newer unsupported config versions, keep older unversioned files loadable, and preserve the loaded file version in `BotOpts.FileConfigVersion`.
|
|
- `Bot.RunWithContext(...)` treats `context.DeadlineExceeded` like `context.Canceled` and exits polling without retry logging.
|
|
- README and README_RU now use the current `JSON`, `URL`, and `ID` public API names.
|
|
|
|
### Fixed
|
|
- Fixed the go-lint workflow file to end with a newline.
|
|
|
|
### Tests
|
|
- Added regression coverage for `Bot.UpdatesIter(...)` error delivery and early iterator stop behavior.
|
|
- Added regression coverage proving `Bot.RunWithContext(...)` preserves polling retry attempts and backoff delays across repeated getUpdates failures.
|
|
- Added regression coverage proving polling startup preserves an enabled request logger.
|
|
- Updated file logger regression coverage for the current `sneklog` text prefix format.
|
|
- Added regression coverage proving token masking still applies after `initLoggers(...)` switches loggers to file-backed writers and that auto-managed plugin loggers inherit token masking.
|
|
- Added regression coverage for JSON config version handling and scene-local payload routing, including observer lifecycle events and callback fallthrough behavior.
|
|
- Updated logger helper tests for the explicit log format and formatter parameters.
|
|
|
|
## v1.0.0-rc.15
|
|
|
|
### Changed
|
|
- Added file-based `BotOpts` loading and saving through `LoadBotOptsFile(...)`, `SaveBotOptsFile(...)`, and the `BotOptsFileCodec` API, with built-in JSON support.
|
|
- Added plugin-level message fallback handlers for text messages and channel posts that do not match commands.
|
|
- Added godoc for the exported `BotOpts` file codec and load/save helpers.
|
|
- README, README_RU, and bot-configuration wiki pages now document file-based `BotOpts` loading, built-in JSON support, env placeholder expansion, and custom codec usage including the TOML example.
|
|
- Active scenes now let unmatched slash-commands continue into normal bot command routing instead of also executing the current scene step or scene message fallback.
|
|
|
|
### Tests
|
|
- Added regression coverage for JSON `BotOpts` file codecs, file load/save helpers, decode failures, and env placeholder expansion.
|
|
- Added regression coverage for plugin message fallback routing, observer lifecycle events, command precedence, and middleware blocking.
|
|
- Added regression coverage proving unmatched slash-commands do not trigger active scene step handlers before normal bot command routing.
|
|
|
|
## v1.0.0-rc.14
|
|
|
|
### Bot API 9.6
|
|
|
|
#### Managed Bots
|
|
- Added the field can_manage_bots to the class User.
|
|
- Added the class KeyboardButtonRequestManagedBot and the field request_managed_bot to the class KeyboardButton.
|
|
- Added the class ManagedBotCreated and the field managed_bot_created to the class Message.
|
|
- Added updates about the creation of managed bots and the change of their token, represented by the class ManagedBotUpdated and the field managed_bot in the class Update.
|
|
- Added the methods getManagedBotToken and replaceManagedBotToken.
|
|
- Added the class PreparedKeyboardButton and the method savePreparedKeyboardButton, allowing bots to request users, chats and managed bots from Mini Apps.
|
|
- Added the method requestChat to the class WebApp.
|
|
- Added support for https://t.me/newbot/{manager_bot_username}/{suggested_bot_username}[?name={suggested_bot_name}] links, allowing bots to request the creation of a managed bot via a link.
|
|
|
|
### Polls
|
|
- Added support for quizzes with multiple correct answers.
|
|
- Replaced the field correct_option_id with the field correct_option_ids in the class Poll.
|
|
- Replaced the parameter correct_option_id with the parameter correct_option_ids in the method sendPoll.
|
|
- Allowed to pass allows_multiple_answers for quizzes in the method sendPoll.
|
|
- Increased the maximum time for automatic poll closure to 2628000 seconds.
|
|
- Added the field allows_revoting to the class Poll.
|
|
- Added the parameter allows_revoting to the method sendPoll.
|
|
- Added the parameter shuffle_options to the method sendPoll.
|
|
- Added the parameter allow_adding_options to the method sendPoll.
|
|
- Added the parameter hide_results_until_closes to the method sendPoll.
|
|
- Added the fields description and description_entities to the class Poll.
|
|
- Added the parameters description, description_parse_mode, and description_entities to the method sendPoll.
|
|
- Added the field persistent_id to the class PollOption, representing a persistent identifier for the option.
|
|
- Added the field option_persistent_ids to the class PollAnswer.
|
|
- Added the fields added_by_user and added_by_chat to the class PollOption, denoting the user and the chat which added the option.
|
|
- Added the field addition_date to the class PollOption, describing the date when the option was added.
|
|
- Added the class PollOptionAdded and the field poll_option_added to the class Message.
|
|
- Added the class PollOptionDeleted and the field poll_option_deleted to the class Message.
|
|
- Added the field poll_option_id to the class ReplyParameters, allowing bots to reply to a specific poll option.
|
|
- Added the field reply_to_poll_option_id to the class Message.
|
|
- Allowed “date_time” entities in checklist title, checklist task text, TextQuote, ReplyParameters quote, sendGift, and giftPremiumSubscription.
|
|
|
|
**More info**: https://core.telegram.org/bots/api#april-3-2026
|
|
|
|
### Breaking Changes
|
|
- Exported `tgapi` request parameter structs were renamed from the `*P` suffix to their method names. Update code such as `tgapi.SendMessageP{...}` to `tgapi.SendMessage{...}`.
|
|
|
|
### Changed
|
|
- *Support for Bot API 9.6*
|
|
- Added missing godoc for recently introduced Telegram Bot API managed-bot, prepared-button, chat-owner, and video-quality exported declarations.
|
|
- Renamed exported `tgapi` request parameter structs from the `*P` suffix to their method names, for example `SendMessageP` -> `SendMessage` and `SetWebhookP` -> `SetWebhook`.
|
|
- Added missing godoc for the exported observer `Event` marker interface.
|
|
- Webhook execution now shares the bot's queued update-dispatch path with polling, including worker-pool delivery, runner startup, single-use run semantics, and default fallback to bot-level update type filters when webhook-specific filters are not set.
|
|
- Webhook godoc and the English and Russian READMEs now describe the bot-level webhook runtime, its single-use lifecycle, and the main `RunWebHookWithContext(...)` entry points more explicitly.
|
|
- `Bot.Close()` once again releases only local resources and no longer deletes remote webhook registrations implicitly; explicit remote webhook teardown remains opt-in through `CloseWebHook()`.
|
|
- Polling and webhook docs now explicitly state that a deployment must delete its webhook before switching from webhook delivery to long polling.
|
|
- Webhook startup now validates path shape and TLS file count before remote webhook setup, and the shared webhook mux now serves both HTTP and TLS runtime paths consistently.
|
|
- Webhook-related `tgapi` request params now use `int8` for `max_connections`, matching Telegram's `1..100` range and the higher-level webhook options API.
|
|
- Webhook startup now also requires a non-empty `SecretToken` when the optional `/status` endpoint is enabled, preventing anonymous exposure of webhook operational metadata.
|
|
- Webhook debug logging now records update metadata instead of dumping raw request bodies.
|
|
- Package docs, README guidance, and core wiki pages now align with the current public API and runtime model, including `NoData`, `SetAppData(...)`, `SetL10n(...)`, `AddAppDataLoggerWriter(...)`, shared runner startup semantics, and the webhook runtime entry points.
|
|
|
|
### Tests
|
|
- Added regression coverage for webhook queue delivery, webhook runtime single-use behavior, runner startup in webhook mode, and default webhook `allowed_updates` inheritance from bot-level update type configuration.
|
|
- Added regression coverage proving `Bot.Close()` does not make remote webhook delete requests.
|
|
- Added webhook regression coverage for path validation, TLS file-count validation, oversized-body rejection, status-endpoint secret checks, and invalid TLS startup arguments.
|
|
- Added webhook regression coverage proving `/status` cannot be enabled without a non-empty `SecretToken`.
|
|
- Added regression coverage for Bot API 9.6 poll decoding, `managed_bot` update decoding, and structured `setChatMenuButton(...)` request serialization.
|
|
- Added regression coverage for `MaybeInaccessibleMessage` accessible and inaccessible JSON decoding.
|
|
|
|
## v1.0.0-rc.13
|
|
|
|
### Added
|
|
- `AsUserError(...)`, `AsInternalError(...)`, `IsUserError(...)`, and `IsInternalError(...)` for explicitly marking centralized handler errors as user-visible or internal-only without breaking the existing default error flow.
|
|
- `Policy[T]`, `RequirePolicy(...)`, and built-in chat and callback policy helpers for expressing reusable authorization rules through the existing middleware pipeline.
|
|
- `Bot.UsePolicy(...)` and `Plugin.UsePolicy(...)` as shorthand for registering policies as middleware.
|
|
- `AllPolicies(...)`, `AnyPolicy(...)`, and `NotPolicy(...)` for composing reusable authorization rules without introducing a second execution pipeline.
|
|
|
|
### Changed
|
|
- Bot configuration mutators now treat the bot as configuration-frozen after the first run begins and ignore late mutation attempts for bot-level config such as prefixes, payload defaults, plugins, middleware, runners, localization, scene session wiring, and database context injection.
|
|
- `MsgContext` godoc and field comments now describe the normalized update contract more explicitly, including when `Msg`, `From`, callback target fields, `Text`, and `Args` are expected to be populated.
|
|
- `MsgContext` normalization now also carries `Chat` and `ChatID` for more Telegram update kinds, allowing policy and update handlers to rely on normalized chat identity outside message-only flows.
|
|
- `MsgContext.Error(...)` and returned handler errors now suppress the automatic user reply when the error is explicitly marked with `AsInternalError(...)`, while keeping the previous user-visible default for unclassified errors.
|
|
- Godoc, README examples, and regression-test naming now consistently describe the shared generic dependency model as app data, including `NoData` and `SetAppData(...)`.
|
|
- Observer configuration now treats `SetObserver(nil)` as clearing instrumentation instead of leaving the previous observer attached.
|
|
- Observer lifecycle events now cover generic update handlers and scene command, step, and message-fallback handlers with logical handler names and durations.
|
|
- `RequirePolicy(...)` now emits `PolicyCheckedEvent` for both passed and denied policy decisions.
|
|
- Scene command, step, and message-fallback flows now emit observer `ErrorEvent`s with scene-specific handler kinds and logical handler names.
|
|
- Scene transition observer events now use the same transition payload for scene command, step, and message-fallback flows.
|
|
- Observer error emission now also covers generic update handlers, callback payload decode failures, runner failures, and polling retries, including dedicated runner and polling handler kinds in `ErrorEvent`.
|
|
- `TODO.md` and the framework backlog pages now mark the observability model as completed for `v1.0.0-rc.13`.
|
|
- `tgapi.Chat.Type` now uses the typed `tgapi.ChatType` enum in public DTOs and tests instead of raw string casts.
|
|
|
|
### Tests
|
|
- Added regression coverage for the bot configuration freeze model, including ignored post-run mutations for core bot configuration methods and late registration paths.
|
|
- Added table-driven update-contract coverage for `prepareUpdateCtx(...)`, including message-backed, callback-backed, user-backed, and no-user update kinds.
|
|
- Added regression tests for policy middleware blocking, built-in private-chat policy decisions, normalized chat identity, and admin checks that use normalized `ChatID` and `FromID`.
|
|
- Added regression tests for policy composition semantics, including all-of, any-of, and deny inversion with preserved internal failures.
|
|
- Added regression tests for `SetObserver(...)`, `GetObserver()`, and clearing the observer with `SetObserver(nil)`.
|
|
- Added observer regression tests for generic update-handler errors, callback payload decode failures, runner failure events, and polling retry emission.
|
|
- Added observer regression tests for update and scene handler lifecycle events and `PolicyCheckedEvent` emission.
|
|
- Added regression tests proving that `edited_message` and `edited_channel_post` stay out of command routing and continue through generic update handlers.
|
|
- Added callback-routing regression tests for both chat-message and inline-message callback targets, including `CallbackQueryId`, `CallbackMsgId`, `InlineMsgId`, and payload-argument guarantees.
|
|
- Added regression tests for the new error-visibility model in both message and callback flows, including silent internal-only errors and explicit user-visible callback replies.
|
|
|
|
## v1.0.0-rc.12
|
|
|
|
### Added
|
|
- `AnswerLong(...)`, `AnswerLongf(...)`, `KeyboardLong(...)`, and `SplitMessageText(...)` for explicit plain-text splitting of long replies without changing the semantics of existing single-message helpers.
|
|
- Centralized library-level validation errors in `errors.go`, including `ErrEmptyMessage`, `ErrMessageTooLong`, `ErrCaptionTooLong`, and context/target validation sentinels.
|
|
- `Bot.GetPayloadType()`, `InlineKeyboard.GetPayloadType()`, and optional strict payload decoding via `BotOpts.StrictPayloadType` / `Bot.SetStrictPayloadType(...)`.
|
|
- `MsgContext.BindArgs(...)` for binding positional command arguments into exported struct fields.
|
|
- Binding sentinels `ErrBindArgsTargetNotPointer`, `ErrBindArgsTargetNotStruct`, `ErrBindArgsUnsupportedFieldType`, and `ErrBindArgsConversion`.
|
|
- Work-in-progress scene/session support, including plugin scene registration, scoped scene sessions, scene entry/exit APIs on `MsgContext`, default in-memory session storage, scene-local routing before normal command handling, and state helpers on `SceneContext`.
|
|
|
|
### Changed
|
|
- `CommandExecutor` now returns `error`, and command, payload, and non-command update handlers now use centralized bot error handling for returned errors.
|
|
- README and README_RU examples now use the new handler signature and document the long-message helpers.
|
|
- README and README_RU now link to the project wiki, and the wiki now includes a page-priority tracker while content is being filled in.
|
|
- README and README_RU now document scenes, session scopes, scene state helpers, and `SceneActionPass` semantics.
|
|
- `TODO.md` and the framework backlog pages now group the remaining framework work into explicit priority 1, 2, and 3 buckets.
|
|
- Payload-type comments and docs now distinguish between the bot's default payload type and keyboard-local overrides.
|
|
- Scene runtime sentinel errors now have explicit godoc comments.
|
|
- Public scene structs now document their exported fields more explicitly.
|
|
- `MsgContext.Context()` now safely falls back to `context.Background()` when no request-scoped context is attached.
|
|
- `MsgContext` reply, edit, callback, delete, action, and draft-limiter paths now use the context accessor instead of reaching into raw internal state.
|
|
- Version constants were bumped to `v1.0.0-rc.12`.
|
|
|
|
### Fixed
|
|
- Message and caption validation now runs before Telegram API calls, rejecting empty messages, oversized message text, and oversized captions with stable sentinel errors.
|
|
- Draft flushing and draft updates now reject oversized messages before sending invalid requests.
|
|
- Callback payload decoding now optionally enforces strict type matching, while the default tolerant mode logs Base64-to-JSON decoding in debug mode and still accepts keyboard-local payload overrides.
|
|
- Positional argument binding now leaves missing trailing struct fields at zero values, joins the remaining arguments into the final string field, and returns clearer binding errors.
|
|
- Request-scoped contexts are now created per update handler execution and safely reused through `MsgContext.Context()` even for manually constructed test contexts.
|
|
- Command and payload handlers now have regression coverage for end-to-end typed argument binding through the normal routing path.
|
|
|
|
### Breaking Changes
|
|
- `CommandExecutor[T]` changed from `func(ctx *MsgContext, db T)` to `func(ctx *MsgContext, db T) error`.
|
|
- `Plugin.NewCommand(...)`, `Plugin.NewPayload(...)`, and `Plugin.AddUpdateHandler(...)` now require handlers with the new error-returning signature.
|
|
|
|
### Tests
|
|
- Added regression tests for `MsgContext.BindArgs(...)`, including scalar conversion, tail-string binding, zero-value trailing fields, invalid targets, unsupported field types, and end-to-end command/payload binding.
|
|
- Added scene regression tests for runtime guards, scene-local command handling, and `SceneActionPass` preserving session state.
|
|
- Added scene regression tests for message fallback handling, user-scoped session lookup without `Msg`, and custom `SessionStore` error propagation.
|
|
|
|
## v1.0.0-rc.11
|
|
|
|
### Fixed
|
|
- `chat_boost` update decoding now accepts string `boost_id` values, matching the current Telegram Bot API schema and preventing polling failures on boosted-chat updates.
|
|
|
|
## v1.0.0-rc.10
|
|
|
|
### Added
|
|
- `Plugin.AddUpdateHandler` for routing non-command Telegram updates by `tgapi.UpdateType`.
|
|
- Derived `tgapi.Update.Type` assignment during JSON decoding, plus `tgapi.UpdateTypeUnknown` for unmatched payloads.
|
|
- `tgapi.API.OpenFileByLink(...)` and `OpenFileByLinkWithContext(...)` for streaming downloads from Telegram's file server.
|
|
- Regression tests for update dispatch, keyboard builders, localization fallback, runners, rate limiting, parse mode encoding, streaming downloads, and context isolation.
|
|
- Regression tests for bot single-run enforcement, nil plugin registration, `L10n` concurrent access, `API.Close()` idle-connection cleanup, and `tgapi` worker-pool edge cases.
|
|
- `SEMVER.md` documenting versioning expectations for the project.
|
|
|
|
### Changed
|
|
- `NewBot` now returns `(*Bot[T], error)` instead of terminating the host process on configuration or startup failures.
|
|
- `Run` and `RunWithContext` now return errors; `RunWithContext` returns `ErrNoPrefixes` and `ErrNoPlugins` for invalid bot configuration.
|
|
- Polling retries now use exponential backoff instead of busy-looping on repeated `getUpdates` failures.
|
|
- `Bot` is now explicitly single-use; repeated `Run()` or `RunWithContext(...)` calls return `ErrBotAlreadyRun`.
|
|
- Database context wiring now uses `T` consistently instead of forcing `*T`; shared dependencies should typically use pointer types such as `*sql.DB`.
|
|
- `DatabaseContext`, `GetDBContext`, and `DbLogger` were updated to the new `T`-based dependency model.
|
|
- `DatabaseContext(...)` now warns once when `T` is a value type, to highlight likely unintended copying of shared dependencies.
|
|
- `AddDatabaseLoggerWriter(...)` now skips unset and nil database contexts instead of calling the writer with invalid values.
|
|
- `L10n` is now safe for concurrent use and copies added dictionary entries to avoid external mutation after registration.
|
|
- Plugin registration now snapshots commands, payloads, middlewares, and update handlers so later mutations of the original `*Plugin` do not leak into the bot.
|
|
- `AddPlugins(...)` now skips nil plugin pointers instead of panicking.
|
|
- `GetUpdateTypes()` now returns a copy instead of exposing internal slice state.
|
|
- Update handling now normalizes `MsgContext` for more Telegram update kinds and routes plugin-level update handlers with isolated context copies.
|
|
- `message`, `channel_post`, and `callback_query` remain on the command/payload flow; non-command updates can be handled through plugin update handlers.
|
|
- Command auto-generation now validates Telegram command names with the correct character set and `1..32` length limit, and emits commands in deterministic sorted order.
|
|
- Builder-style APIs were normalized to value returns for `NewCommandArg`, `NewMiddleware`, `NewRunner`, and `NewCallbackData`.
|
|
- `MenuButton` replaced `BaseMenuButton`, and `GetChatMenuButton(...)` now returns the renamed type.
|
|
- Several Telegram DTOs were tightened for optionality and serialization correctness, including `InputPaidMedia`, `MenuButton`, optional gift fields, and message entity slices.
|
|
- `tgapi.NewRequest(...)`, `NewRequestWithChatID(...)`, `NewUploaderRequest(...)`, and `NewUploaderRequestWithChatID(...)` are now documented as low-level unsafe escape hatches rather than internal helpers.
|
|
- `tgapi.API.Close()` now closes idle HTTP connections before releasing logger resources.
|
|
- Multipart form encoding now writes scalar field bytes directly instead of converting through temporary strings.
|
|
- README, README_RU, package docs, and exported godoc were updated to match the current APIs and concurrency/lifecycle model.
|
|
- Version constants were bumped to `v1.0.0-rc.10`.
|
|
|
|
### Fixed
|
|
- Required command arguments are now enforced by declared argument index, not only by total required count.
|
|
- `ParseNone` now omits `parse_mode` from JSON requests instead of serializing `"None"`.
|
|
- Upload file type detection is now case-insensitive for file extensions.
|
|
- Draft creation no longer panics when no limiter is configured, and draft flushing now rejects zero chat IDs before sending invalid requests.
|
|
- Channel posts with `SenderChat` no longer panic in the command path and now preserve the expected `MsgContext` fields.
|
|
- File logger initialization now falls back to stdout loggers instead of terminating the process on logger setup failures.
|
|
- `GetChatMenuButton` and `SetChatMenuButton` now serialize `chat_id` correctly when omitted.
|
|
- Update decoding tests now match the canonical `deleted_business_messages` model and no longer rely on the removed singular alias.
|
|
|
|
### Breaking Changes
|
|
- `NewBot[T](opts)` now returns `(*Bot[T], error)`.
|
|
- `Run()` now returns `error`.
|
|
- `RunWithContext(ctx)` now returns `error`.
|
|
- `Run()` and `RunWithContext(ctx)` are now single-use per bot instance; create a new `Bot` after they return.
|
|
- Database context handlers now receive `T` instead of `*T`. For shared dependencies, instantiate the bot with a pointer type, for example `Bot[*sql.DB]`.
|
|
- `DatabaseContext(...)` now takes `T` instead of `*T`.
|
|
- `GetDBContext()` now returns `T` instead of `*T`.
|
|
- `DbLogger[T]` now receives `T` instead of `*T`.
|
|
- `NewCommandArg(...)`, `NewMiddleware(...)`, `NewRunner(...)`, and `NewCallbackData(...)` now return values instead of pointers.
|
|
- `BaseMenuButton` was renamed to `MenuButton`, and `GetChatMenuButton(...)` now returns `MenuButton`.
|
|
- `tgapi.Update` no longer exposes the deprecated `DeletedBusinessMessage` alias; use `DeletedBusinessMessages`.
|
|
|
|
### Tests
|
|
- Added coverage for polling backoff helpers, command sorting, database logger safety checks, update handler routing, update-context isolation, channel posts with `SenderChat`, parse mode encoding, streaming downloads, and rate limiter behavior.
|
|
|
|
## v1.0.0-rc.7
|
|
|
|
### Added
|
|
- Package-level logger helpers: `utils.CreateLogger(prefix, level)` and `utils.CreateFileLogger(prefix, level, filePath)`.
|
|
- `MsgContext.Logger`, populated from the matched plugin and falling back to the bot logger.
|
|
- Plugin lifecycle/configuration APIs: `SetLogger`, `RemoveLogger`, `SetOnClose`, and `Close`.
|
|
- `Bot.CloseRemote(ctx)` as the explicit wrapper for Telegram Bot API close.
|
|
|
|
### Changed
|
|
- Logger initialization is now unified across `Bot`, `tgapi.API`, and `tgapi.Uploader`.
|
|
- `Bot.Close()` now performs local resource teardown only and invokes `Plugin.Close()` for registered plugins.
|
|
- Local `tgapi.API` shutdown was renamed to `Close()`.
|
|
- Telegram Bot API close wrappers in `tgapi.API` were renamed to `CloseRemote()` and `CloseRemoteWithContext()`.
|
|
- `Bot.Debug()` now updates log levels for the bot logger, request logger, and already registered plugin loggers.
|
|
- `Bot.AddPlugins()` now creates a default plugin logger automatically when one is not provided.
|
|
- `Bot.AddDatabaseLoggerWriter()` now also attaches the writer to already registered plugin loggers.
|
|
- GoDoc was expanded for the new shutdown and logging APIs, and plugin registration is now documented as a configuration commit point.
|
|
|
|
### Breaking Changes
|
|
- `(*Bot).Close(ctx context.Context)` was replaced with `(*Bot).Close()`.
|
|
- `(*tgapi.API).CloseApi()` was renamed to `(*tgapi.API).Close()`.
|
|
- `(*tgapi.API).Close()` was renamed to `(*tgapi.API).CloseRemote()`.
|
|
- `(*tgapi.API).CloseWithContext()` was renamed to `(*tgapi.API).CloseRemoteWithContext(ctx)`.
|
|
|
|
### Migration
|
|
- Replace `bot.Close(ctx)` with `bot.Close()`.
|
|
- If you need Telegram Bot API close, use `bot.CloseRemote(ctx)`.
|
|
- Replace `api.CloseApi()` with `api.Close()`.
|
|
- Replace `api.Close()` with `api.CloseRemote()`.
|
|
- Replace `api.CloseWithContext(ctx)` with `api.CloseRemoteWithContext(ctx)`.
|
|
- Configure plugin loggers and `OnClose` hooks before calling `bot.AddPlugins(...)`.
|
|
|
|
### Tests
|
|
- Updated tests for the new shutdown and logging behavior.
|
|
|
|
### Notes
|
|
- Registering a plugin via `AddPlugins(...)` is a configuration commit point; the plugin should not be mutated through the original `*Plugin` afterward.
|
|
- If plugin loggers must receive a database writer, call `AddDatabaseLoggerWriter(...)` after registering plugins.
|
|
|
|
## v1.0.0-rc.4
|
|
|
|
### Added
|
|
- `WithContext` variants across `tgapi` API and uploader methods so callers can pass cancellation and deadline contexts consistently.
|
|
- `UploaderCertificateType`, `UploadSetWebhookP`, `Uploader.SetWebhook(...)`, and `Uploader.SetWebhookWithContext(...)` for multipart webhook certificate uploads.
|
|
- Missing media thumbnail fields where applicable.
|
|
|
|
### Changed
|
|
- GoDoc for context-aware methods was improved, and `See` references now point to method-specific Telegram Bot API anchors.
|
|
- `EditMessageTextP` now includes `entities` and `link_preview_options`.
|
|
- `EditMessageCaptionP` now includes `caption_entities` and `show_caption_above_media`.
|
|
- `StopPollP` now uses `reply_markup` and no longer carries `inline_message_id`.
|
|
- `SendStickerP` now includes reply and suggested-post related fields.
|
|
- `SendDocumentP` now includes `disable_content_type_detection`.
|
|
- `SendInvoiceP` no longer includes unsupported `business_connection_id`.
|
|
- `SetWebhookP` no longer carries `certificate`; GoDoc now points to uploader-based certificate upload.
|
|
- Existing non-context methods remain available, and the `Do(...)` call style is preserved.
|
|
|
|
### Breaking Changes
|
|
- Users sending webhook certificates through JSON `SetWebhookP.Certificate` must migrate to `Uploader.SetWebhook(...)`.
|
|
|
|
## v1.0.0-rc.3
|
|
|
|
### Fixed
|
|
- The update polling loop no longer logs or retries after `context.Canceled` during shutdown.
|
|
- Extra retry delay was removed from canceled polling requests so `RunWithContext` can exit immediately while stopping.
|
|
|
|
### Changed
|
|
- Shutdown behavior remains explicit: callers are still responsible for invoking `Close()` after `RunWithContext` returns.
|
|
|
|
## v1.0.0-rc.2
|
|
|
|
### Fixed
|
|
- Fixed a shutdown crash caused by `DatabaseWriter` calling `Close()` through an uninitialized embedded logger writer.
|
|
- Fixed bot shutdown hanging during Telegram long polling by making update polling use a cancelable context.
|
|
- Reduced the chance of container termination with exit code `137` during shutdown by allowing `getUpdates` to stop promptly on cancellation.
|
|
|
|
### Changed
|
|
- Switched the project to use the local `laniakea` replacement for the shutdown fix.
|
|
- Documentation now clarifies that `RunWithContext` does not close resources automatically and callers must invoke `Close()` explicitly.
|
|
- `Updates` documentation now describes context-driven cancellation behavior.
|
|
|
|
### Tests
|
|
- Added regression tests for database logger writer shutdown behavior.
|