stitchkit 0.100.3 → 0.101.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/dist/browser/chunked-upload.d.ts +80 -0
- package/dist/browser/chunked-upload.d.ts.map +1 -0
- package/dist/browser/client-executors.d.ts.map +1 -1
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http.d.ts +3 -0
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/upload-progress.d.ts +26 -0
- package/dist/browser/upload-progress.d.ts.map +1 -0
- package/dist/contract/client-types.d.ts +19 -0
- package/dist/contract/client-types.d.ts.map +1 -1
- package/dist/entrypoints/application.js +2 -1
- package/dist/entrypoints/contract.d.ts +1 -1
- package/dist/entrypoints/contract.d.ts.map +1 -1
- package/dist/entrypoints/files.d.ts +1 -0
- package/dist/entrypoints/files.d.ts.map +1 -1
- package/dist/entrypoints/files.js +230 -0
- package/dist/entrypoints/index.d.ts +1 -0
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +90 -2
- package/dist/entrypoints/observability.js +2 -1
- package/dist/entrypoints/react.js +1 -1
- package/dist/entrypoints/remote.js +2 -2
- package/dist/entrypoints/telegram/screens.js +1 -1
- package/dist/entrypoints/telegram.d.ts +8 -4
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +277 -49
- package/dist/entrypoints/testing.js +2 -2
- package/dist/entrypoints/tools.js +2 -1
- package/dist/entrypoints/tracking.js +1 -1
- package/dist/files/chunk-spool.d.ts +66 -0
- package/dist/files/chunk-spool.d.ts.map +1 -0
- package/dist/{index-aaj97r4y.js → index-65jwqhcf.js} +27 -10
- package/dist/{index-6k1svmjh.js → index-e05cjgtf.js} +16 -13
- package/dist/{index-kzz6rq0w.js → index-e6c2spsd.js} +56 -18
- package/dist/{index-qjeggp8w.js → index-h43cepag.js} +139 -11
- package/dist/index-sznqf8fx.js +20 -0
- package/dist/internal/secret-shapes.d.ts +21 -0
- package/dist/internal/secret-shapes.d.ts.map +1 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/telegram/bot-api.d.ts +7 -4
- package/dist/telegram/bot-api.d.ts.map +1 -1
- package/dist/telegram/init-data.d.ts +3 -44
- package/dist/telegram/init-data.d.ts.map +1 -1
- package/dist/telegram/operator-channel.d.ts +1 -18
- package/dist/telegram/operator-channel.d.ts.map +1 -1
- package/dist/telegram/operator-dedupe.d.ts +44 -0
- package/dist/telegram/operator-dedupe.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +6 -0
- package/dist/telegram/send-failure.d.ts.map +1 -1
- package/dist/telegram/update-intake.d.ts +5 -1
- package/dist/telegram/update-intake.d.ts.map +1 -1
- package/dist/telegram/update-store-check.d.ts +22 -0
- package/dist/telegram/update-store-check.d.ts.map +1 -0
- package/dist/telegram/update-store-postgres.d.ts +33 -0
- package/dist/telegram/update-store-postgres.d.ts.map +1 -0
- package/dist/telegram/user.d.ts +51 -0
- package/dist/telegram/user.d.ts.map +1 -0
- package/llms/files.txt +3 -0
- package/llms/observability.txt +13 -1
- package/llms/server.4.txt +16 -0
- package/llms/stitchkit.2.txt +157 -2
- package/llms/stitchkit.3.txt +5 -2
- package/llms/stitchkit.txt +3 -3
- package/llms/telegram.txt +91 -13
- package/llms/{upgrading-0.74.0-0.100.0.txt → upgrading-0.74.0-0.101.0.txt} +39 -3
- package/llms/upgrading.txt +1 -1
- package/llms-full.txt +324 -21
- package/llms.txt +6 -6
- package/package.json +1 -1
package/llms/stitchkit.txt
CHANGED
|
@@ -79,12 +79,12 @@ own, recorded as an ADR.
|
|
|
79
79
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
80
80
|
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
81
81
|
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
82
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the
|
|
82
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 2 of the 46 minors since 0.56.2, most recently 0.92.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
83
83
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the managed-resource conformance kit |
|
|
84
84
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
85
85
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
86
86
|
| `stitchkit/react/keyboard` | browser | evolving | which part of a screen gets a key — ordered layers, one Escape per level, list zones with real focus; see [keyboard guide](keyboard.md) |
|
|
87
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 22 of the
|
|
87
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 22 of the 46 minors since 0.56.2, most recently 0.97.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
88
88
|
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
89
89
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults, deterministic race controls and the agent-store conformance kit |
|
|
90
90
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
@@ -94,7 +94,7 @@ own, recorded as an ADR.
|
|
|
94
94
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
95
95
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
96
96
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
97
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 10 of the
|
|
97
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 10 of the 46 minors since 0.56.2, most recently 0.100.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
98
98
|
| `stitchkit/application/grammy` | server | evolving | a grammY bot as application resources — configuration, then polling with updates admitted by batch — and the webhook adapter |
|
|
99
99
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
100
100
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
package/llms/telegram.txt
CHANGED
|
@@ -42,16 +42,21 @@ output, in pino's shape — numeric `level` (`debug` 20, `info` 30, `warn` 40,
|
|
|
42
42
|
`error` 50), `time` in epoch milliseconds, `msg` — so `pino-pretty` reads it on
|
|
43
43
|
a terminal and a supervisor matching `"level":50` sees errors. Unlike pino, an
|
|
44
44
|
`Error` under *any* key is written with its name, message, stack and cause; an
|
|
45
|
-
error logged as `{ error }` does not become `"error":{}
|
|
45
|
+
error logged as `{ error }` does not become `"error":{}`, and its own fields —
|
|
46
|
+
a `TelegramBotApiError`'s `error_code` and `parameters.retry_after` — are on the
|
|
47
|
+
line beside them.
|
|
48
|
+
|
|
49
|
+
A bot token is masked wherever it appears — a request URL in an error message,
|
|
50
|
+
a local Bot API file path — with no configuration: `123456:[redacted]` keeps the
|
|
51
|
+
bot's id, which is public and is what tells two bots apart in one journal. So is
|
|
52
|
+
the password in an address and a query parameter named as a secret (`?token=`).
|
|
46
53
|
|
|
47
54
|
```ts
|
|
48
55
|
import { createJsonLogger } from 'stitchkit/observability'
|
|
49
|
-
import { TELEGRAM_BOT_TOKEN_PATTERN } from 'stitchkit/telegram'
|
|
50
56
|
|
|
51
57
|
export const logger = createJsonLogger({
|
|
52
58
|
level: env.LOG_LEVEL,
|
|
53
59
|
fields: { service: 'my-bot' },
|
|
54
|
-
sensitiveUrlPatterns: [TELEGRAM_BOT_TOKEN_PATTERN],
|
|
55
60
|
})
|
|
56
61
|
|
|
57
62
|
logger.error('Application startup failed', { error })
|
|
@@ -67,11 +72,13 @@ query values inside any URL variable (`DATABASE_URL`), and each URL-encoded:
|
|
|
67
72
|
import { createJsonLogger, secretValuesFromEnv } from 'stitchkit/observability'
|
|
68
73
|
|
|
69
74
|
export const logger = createJsonLogger({
|
|
70
|
-
sensitiveUrlPatterns: [TELEGRAM_BOT_TOKEN_PATTERN],
|
|
71
75
|
sensitiveValues: secretValuesFromEnv(process.env),
|
|
72
76
|
})
|
|
73
77
|
```
|
|
74
78
|
|
|
79
|
+
A string of your own — a message for a person, a report — masks bot tokens with
|
|
80
|
+
`redactTelegramBotToken(text)` from `stitchkit/telegram`.
|
|
81
|
+
|
|
75
82
|
A key added to the environment is masked from its first line; a URL's user name
|
|
76
83
|
is left alone, since it names a role that appears in ordinary text.
|
|
77
84
|
|
|
@@ -128,7 +135,21 @@ const operators = createTelegramOperatorChannel<'errors'>({
|
|
|
128
135
|
})
|
|
129
136
|
```
|
|
130
137
|
|
|
131
|
-
Held-back messages reach `onDropped` as `repeated` or `over-budget`.
|
|
138
|
+
Held-back messages reach `onDropped` as `repeated` or `over-budget`.
|
|
139
|
+
|
|
140
|
+
A bot that already sends its alerts itself — its own bot instance, its own retry
|
|
141
|
+
— takes the window alone instead of switching the channel off with parameters:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { createTelegramOperatorDedupe } from 'stitchkit/telegram'
|
|
145
|
+
|
|
146
|
+
const admit = createTelegramOperatorDedupe<'errors'>({ windowMs: 10 * 60_000 })
|
|
147
|
+
|
|
148
|
+
const verdict = admit(text, 'errors')
|
|
149
|
+
if (verdict.send) await sendAlert(verdict.text) // the text carries the held-back counts
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
What to post stays the bot's. On the way down, drain it within the grace period
|
|
132
153
|
and close it: `drain: (context) => operators.drain(context.signal)`,
|
|
133
154
|
`close: () => operators.close()` in a resource.
|
|
134
155
|
|
|
@@ -249,6 +270,14 @@ itself be a secret — and says what to pass: set the takeover for one start and
|
|
|
249
270
|
remove it. `checkTelegramWebhook` on a timer notices a webhook that moved
|
|
250
271
|
elsewhere, which this process cannot see any other way.
|
|
251
272
|
|
|
273
|
+
**Moving to it from a claim of your own.** A bot that tagged its webhook itself
|
|
274
|
+
holds an address this one does not recognise, so the first claim is refused —
|
|
275
|
+
`other-secret` when the address is the same, `owned-elsewhere` otherwise — and
|
|
276
|
+
names its own host. Start once with `takeoverFrom` set to that host, then remove
|
|
277
|
+
it. The tag is derived from the secret with a fixed context, so it is the same
|
|
278
|
+
across stitchkit releases: that takeover is needed once per bot, not per
|
|
279
|
+
upgrade. A secret rotation is a new owner, and takes a takeover too.
|
|
280
|
+
|
|
252
281
|
**The update is recorded before Telegram is answered.** A handler that runs
|
|
253
282
|
longer than Telegram waits — a large file from a local Bot API server — gets the
|
|
254
283
|
same update again while it still works, and a process that answers and then
|
|
@@ -263,10 +292,55 @@ fix (a refused message, a blocked user) is abandoned; `maxAttempts` (5) ends
|
|
|
263
292
|
the rest. Delivery is at least once: a handler that finished but could not be
|
|
264
293
|
recorded as finished runs again.
|
|
265
294
|
|
|
295
|
+
With grammY the handler is `bot.handleUpdate`, which wraps a middleware's error
|
|
296
|
+
in a `BotError`; the intake unwraps it, so `retry`, `onFailure` and the error
|
|
297
|
+
stored with the update are what the middleware threw — a `retry` that returns
|
|
298
|
+
`false` for the bot's own terminal error sees that error.
|
|
299
|
+
|
|
266
300
|
The store is an interface of six atomic steps (`TelegramUpdateStore`), so the
|
|
267
|
-
bot's own database
|
|
268
|
-
|
|
269
|
-
|
|
301
|
+
bot's own database holds it:
|
|
302
|
+
|
|
303
|
+
| Store | Takes |
|
|
304
|
+
|---|---|
|
|
305
|
+
| `sqliteTelegramUpdateStore` | a `bun:sqlite` `Database` or `node:sqlite` `DatabaseSync` as it is |
|
|
306
|
+
| `postgresTelegramUpdateStore` | one `query(text, parameters)` over the client the bot already holds |
|
|
307
|
+
| `memoryTelegramUpdateStore` | nothing — tests, or a bot that accepts losing unhandled updates to a restart |
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
import { postgresTelegramUpdateStore } from 'stitchkit/telegram'
|
|
311
|
+
|
|
312
|
+
// Bun
|
|
313
|
+
postgresTelegramUpdateStore({ query: (text, parameters) => sql.unsafe(text, [...parameters]) })
|
|
314
|
+
// Prisma
|
|
315
|
+
postgresTelegramUpdateStore({
|
|
316
|
+
query: (text, parameters) => prisma.$queryRawUnsafe(text, ...parameters),
|
|
317
|
+
createTable: false, // the migration below owns the table
|
|
318
|
+
})
|
|
319
|
+
// pg
|
|
320
|
+
postgresTelegramUpdateStore({
|
|
321
|
+
query: (text, parameters) => pool.query(text, [...parameters]).then((result) => result.rows),
|
|
322
|
+
})
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Each rule is one conditional statement, so a claim is atomic across every
|
|
326
|
+
process sharing the table. By default the table is created on first use; where
|
|
327
|
+
migrations own the schema, `postgresTelegramUpdateStoreSchema(table)` is the
|
|
328
|
+
statement to put in one.
|
|
329
|
+
|
|
330
|
+
A store of your own — over an ORM, another database — is put through the same
|
|
331
|
+
rules the shipped ones are, concurrent claims included:
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
import { checkTelegramUpdateStore } from 'stitchkit/telegram'
|
|
335
|
+
|
|
336
|
+
test('our update store keeps the rules', async () => {
|
|
337
|
+
expect(await checkTelegramUpdateStore(() => ourStore(freshTable()))).toEqual([])
|
|
338
|
+
})
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
A store that reads and then writes in two statements passes every test with one
|
|
342
|
+
process and runs one update twice in production; the check races eight claims
|
|
343
|
+
against each other to catch it.
|
|
270
344
|
|
|
271
345
|
## Files from a local Bot API server
|
|
272
346
|
|
|
@@ -313,23 +387,24 @@ injected grammY bot. → ADR 0143, ADR 0201 — [guide](../guide/telegram.md)
|
|
|
313
387
|
| `verifyTelegramInitData` | function | verify a Mini App `initData` signature against the bot token in constant time, before reading anything out of it |
|
|
314
388
|
| `VerifyTelegramInitDataOptions` | _type_ | raw `initData`, bot token, optional `maxAgeSeconds` bound and injected clock |
|
|
315
389
|
| `TelegramInitDataVerification` | _type_ | `{ valid: true, data }` or a refusal carrying its reason |
|
|
316
|
-
| `TelegramInitData` | _type_ | verified `user`/`receiver`, `authDate`, `ageSeconds`, `queryId`, `startParam`, `chatType`, `chatInstance` and every signed pair in `raw` |
|
|
317
|
-
| `
|
|
390
|
+
| `TelegramInitData` | _type_ | verified `user`/`receiver` as `TelegramUser`, `authDate`, `ageSeconds`, `queryId`, `startParam`, `chatType`, `chatInstance` and every signed pair in `raw` |
|
|
391
|
+
| `parseTelegramUser` / `TelegramUser` | function / _type_ | Telegram's `snake_case` user — grammY's `ctx.from`, a Bot API `User`, a Mini App `user` — as the one camelCase record initData returns too; `undefined` when it is not a user |
|
|
318
392
|
| `TelegramInitDataRefusal` | _type_ | `missing-hash` / `signature-mismatch` / `malformed` / `expired` — an expired string is not a forged one |
|
|
319
393
|
| `classifyTelegramSendFailure` | function | name a refused Bot API send and separate "retry this send" from "stop addressing this recipient" |
|
|
320
394
|
| `TelegramSendFailure` | _type_ | reason, `status`, Telegram-stated `retryAfterSeconds`, `retryable`, `recipientUnreachable` and which evidence produced the answer |
|
|
321
|
-
| `TelegramSendFailureReason` | _type_ | `blocked-by-user` / `user-deactivated` / `chat-not-found` / `not-started` / `rate-limited` / `message-invalid` / `server-error` / `unknown` |
|
|
395
|
+
| `TelegramSendFailureReason` / `TELEGRAM_SEND_FAILURE_REASONS` | _type_ / constant | `blocked-by-user` / `user-deactivated` / `chat-not-found` / `not-started` / `rate-limited` / `message-invalid` / `server-error` / `unknown`, and the same as a list; a `Record<TelegramSendFailureReason, …>` over them fails to compile when a reason is added |
|
|
322
396
|
| `runTelegramBroadcast` | function | a resumable broadcast by `name` under a state `directory`: audience written once, an append-only journal, pacing at `ratePerSecond` (25), 429 waits `retry_after`, unreachable recipients never addressed again, a `message-invalid` or unreachable Telegram halts without charging the recipient, a send in flight at a crash is `uncertain` and not repeated, `dryRun`, one runner per name |
|
|
323
397
|
| `TelegramBroadcastConfig` / `TelegramBroadcastSend` / `TelegramBroadcastReport` / `TelegramBroadcastRunOutcome` / `TelegramBroadcastOutcome` / `TelegramBroadcastRecipient` | _type_ | `name`, `directory`, `recipients()`, `send({ recipient, attempt })`, `maxAttempts`, `signal`, `onProgress`; counts `delivered` / `unreachable` / `failed` / `uncertain` / `pending` and `finished` / `stopped` / `halted` / `dry-run` |
|
|
324
398
|
| `telegramBroadcastSender` / `TelegramBroadcastSenderConfig` / `TelegramBroadcastMessage` | function / _type_ | the standard `send`: `sendMessage` with a text or `copyMessage` of a prepared message, through the Bot API |
|
|
325
399
|
| `createTelegramOperatorChannel` | function | the operator chat, apart from the journal: `post(text, topic?)` returns at once and never throws; paced sends into forum topics, 429 honoured, oldest dropped on overflow, `drain(signal)` and `close()` for the way down |
|
|
326
400
|
| `TelegramOperatorChannelConfig` / `TelegramOperatorChannel` / `TelegramOperatorMessage` / `TelegramOperatorDrop` / `TelegramChatId` | _type_ | `chatId`, `topics`, `send`, `maxQueued`, `minIntervalMs`, `maxAttempts`, `onDropped`, `sensitivePatterns` and `sensitiveValues` (a bot token is always masked), `dedupe`; a drop is `overflow` / `refused` / `attempts` / `closed` / `repeated` / `over-budget` with its classification |
|
|
401
|
+
| `createTelegramOperatorDedupe` / `TelegramOperatorDedupeVerdict` | function / _type_ | the channel's dedupe window alone, for a sender with its own bot and retry: `(text, topic?)` → `{ send: true, text }` with the held-back counts, or `{ send: false, reason: 'repeated' \| 'over-budget' }` |
|
|
327
402
|
| `TelegramOperatorDedupe` | _type_ | `windowMs` (10 min): one message per `fingerprint` per window, the next one sent carries `repeatedLine(count)`; `maxPerWindow` (20) across fingerprints, the overflow counted onto the next one sent with `overBudgetLine(count)`; `now` |
|
|
328
403
|
| `telegramOperatorSender` / `TelegramOperatorSenderConfig` | function / _type_ | the standard `send`: `sendMessage` into the chat and topic, plain text unless `parseMode`; with `'HTML'` the markup is cleaned and cut by what it shows, so the channel's cut never leaves a tag open |
|
|
329
404
|
| `createTelegramLocalFiles` | function | files the local Bot API server wrote under `<root>/<token>/`: `resolve(file_path)` and `remove(file_path)` only inside the bot's directory, judged on real paths so a link is judged by where it leads; `check()` for readiness. Recommended root variable: `BOT_API_FILES_ROOT` |
|
|
330
405
|
| `TelegramLocalFilesConfig` / `TelegramLocalFiles` / `TelegramLocalFilesCheck` / `TelegramLocalFileError` / `TelegramLocalFileRefusal` | _type_ / class | `root`, `token`; refusals `root-not-absolute` / `bot-directory-unavailable` / `outside-bot-directory` / `missing` / `not-a-file`, never carrying the path or the token |
|
|
331
406
|
| `callTelegramBotApi` / `TelegramBotApiCall` / `TelegramBotApiError` | function / _type_ / class | one Bot API method over `fetch`; a refusal keeps `error_code`, `description` and `parameters` for the classifier, and no error names the URL |
|
|
332
|
-
| `TELEGRAM_BOT_TOKEN_PATTERN` | constant | the
|
|
407
|
+
| `TELEGRAM_BOT_TOKEN_PATTERN` / `redactTelegramBotToken` | constant / function | the secret half of a bot token — the bot's id before the colon is not matched; `redact` and every logger on it mask it already, `redactTelegramBotToken(text)` masks every token in a string to `123456:[redacted]` |
|
|
333
408
|
| `claimTelegramWebhook` | function | set the webhook only where it already points here, or by naming the host it is taken from; confirm Telegram holds it; pending updates kept unless `dropPendingUpdates` |
|
|
334
409
|
| `ClaimTelegramWebhookConfig` / `TelegramWebhookConfig` / `TelegramWebhookClaim` | _type_ | `token`, `url`, `secret`, `apiRoot`, `fetch`, `signal`; `takeoverFrom` (a host, or `'none'`), `allowedUpdates`, `maxConnections`, `dropPendingUpdates`; the claim's tagged `url`, `takenFrom`, `pendingUpdates` |
|
|
335
410
|
| `TelegramWebhookClaimError` / `TelegramWebhookRefusal` / `TELEGRAM_WEBHOOK_NONE` | class / _type_ / constant | `owned-elsewhere` / `other-secret` / `not-confirmed` with `ownerHost` — a host, never a path; `'none'` names no webhook |
|
|
@@ -337,9 +412,12 @@ injected grammY bot. → ADR 0143, ADR 0201 — [guide](../guide/telegram.md)
|
|
|
337
412
|
| `checkTelegramWebhook` / `TelegramWebhookState` | function / _type_ | whether the webhook still points here: `owned`, `ownerHost`, `pendingUpdates`, Telegram's `lastError` |
|
|
338
413
|
| `receiveTelegramWebhook` / `ReceiveTelegramWebhookOptions` / `TelegramUpdateAcceptance` | function / _type_ | one webhook `Request`: 403 without the secret (compared in constant time), 405 for another method, 400 for no update, 200 once `accept` recorded it |
|
|
339
414
|
| `createTelegramUpdateIntake` | function | webhook updates recorded before Telegram is answered and handled after: chat order kept, other chats alongside up to `maxConcurrent`, a renewed lease per attempt, a sweep that takes over what a restart or a dead process left, retries, `maxAttempts`, finished updates remembered `retainMs` to refuse repeats; at least once |
|
|
340
|
-
| `TelegramUpdateIntakeConfig` / `TelegramUpdateIntake` / `TelegramUpdateEnvelope` / `TelegramUpdateFailure` / `TelegramUpdateStoreStep` | _type_ | `store`, `handle`, `retry`, `maxAttempts` (5), `leaseMs` (120 000), `pendingGraceMs` (60 000), `sweepEveryMs` (30 000), `retainMs` (24 h), `maxConcurrent` (32), `onFailure`, `onStoreError`, `now`; `accept(body)`, `start()`, `sweep()`, `idle()`, `close()` |
|
|
415
|
+
| `TelegramUpdateIntakeConfig` / `TelegramUpdateIntake` / `TelegramUpdateEnvelope` / `TelegramUpdateFailure` / `TelegramUpdateStoreStep` | _type_ | `store`, `handle` (a grammY `BotError` is unwrapped: `retry`, `onFailure` and the stored error see what the middleware threw), `retry`, `maxAttempts` (5), `leaseMs` (120 000), `pendingGraceMs` (60 000), `sweepEveryMs` (30 000), `retainMs` (24 h), `maxConcurrent` (32), `onFailure`, `onStoreError`, `now`; `accept(body)`, `start()`, `sweep()`, `idle()`, `close()` |
|
|
341
416
|
| `TelegramUpdateStore` / `StoredTelegramUpdate` / `TelegramUpdateState` / `TelegramUpdateSettlement` / `TelegramUpdateClaimOptions` / `TelegramUpdateDueQuery` | _type_ | the store an intake runs on: `add`, `claim`, `renew`, `settle`, `due`, `prune`, each atomic on one record — a claim takes `pending`, a due `failed` or a lapsed `processing`; renew and settle only by the attempt holding it |
|
|
342
417
|
| `memoryTelegramUpdateStore` | function | the store in this process's memory — tests, or a bot that accepts losing unhandled updates to a restart |
|
|
343
418
|
| `sqliteTelegramUpdateStore` / `SqliteTelegramUpdateStoreConfig` / `TelegramSqliteDatabase` | function / _type_ | the store in SQLite over the handle the application opened — `bun:sqlite` `Database` or `node:sqlite` `DatabaseSync`; `table` (default `telegram_updates`) created when missing |
|
|
419
|
+
| `postgresTelegramUpdateStore` / `PostgresTelegramUpdateStoreConfig` / `TelegramPostgresQuery` | function / _type_ | the store in Postgres over the client the application holds, as one `query(text, parameters)` returning rows — Bun `sql.unsafe`, Prisma `$queryRawUnsafe`, `pg` `pool.query`; each rule one conditional statement; `table`, `createTable` (default `true`) |
|
|
420
|
+
| `postgresTelegramUpdateStoreSchema` | function | the table and its index as a statement for a migration, safe to run twice |
|
|
421
|
+
| `checkTelegramUpdateStore` | function | put any store through every rule, each on a fresh store from `make`, concurrent claims included; resolves with the violations, empty when it keeps them |
|
|
344
422
|
|
|
345
423
|
---
|
|
@@ -1,14 +1,50 @@
|
|
|
1
|
-
# Upgrading 0.74.0 → 0.
|
|
1
|
+
# Upgrading 0.74.0 → 0.101.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.74.0 → 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.74.0 → 0.101.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.74.0 → 0.
|
|
9
|
+
# Guide: Upgrading, 0.74.0 → 0.101.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.101.0
|
|
13
|
+
|
|
14
|
+
### `TelegramInitDataUser` is `TelegramUser`
|
|
15
|
+
|
|
16
|
+
**Who must act:** code that names the type `TelegramInitDataUser` from
|
|
17
|
+
`stitchkit/telegram`. The record is the same; its name now says it is any
|
|
18
|
+
Telegram user, since `parseTelegramUser(ctx.from)` returns it for a Bot API user
|
|
19
|
+
too.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// Before
|
|
23
|
+
import type { TelegramInitDataUser } from 'stitchkit/telegram'
|
|
24
|
+
function ensureAccount(user: TelegramInitDataUser) {}
|
|
25
|
+
// After
|
|
26
|
+
import type { TelegramUser } from 'stitchkit/telegram'
|
|
27
|
+
function ensureAccount(user: TelegramUser) {}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### `TELEGRAM_BOT_TOKEN_PATTERN` matches the secret half only
|
|
31
|
+
|
|
32
|
+
**Who must act:** code that uses `TELEGRAM_BOT_TOKEN_PATTERN` to find or cut a
|
|
33
|
+
whole token. It now matches what follows `<bot id>:`, so a masking replace keeps
|
|
34
|
+
the bot's id — `123456:[redacted]`. Masking needs nothing any more: `redact` and
|
|
35
|
+
every logger on it mask bot tokens by shape; remove the pattern from
|
|
36
|
+
`sensitiveUrlPatterns`, and use `redactTelegramBotToken(text)` for a string of
|
|
37
|
+
your own.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// Before
|
|
41
|
+
createJsonLogger({ sensitiveUrlPatterns: [TELEGRAM_BOT_TOKEN_PATTERN] })
|
|
42
|
+
text.replace(new RegExp(TELEGRAM_BOT_TOKEN_PATTERN.source, 'g'), '[redacted]')
|
|
43
|
+
// After
|
|
44
|
+
createJsonLogger({})
|
|
45
|
+
redactTelegramBotToken(text)
|
|
46
|
+
```
|
|
47
|
+
|
|
12
48
|
## Released migration: 0.100.0
|
|
13
49
|
|
|
14
50
|
### watch capacity and session/live/delivery adoption
|
package/llms/upgrading.txt
CHANGED
|
@@ -11,7 +11,7 @@ Contains: Guide: Upgrading, general (docs/guide/upgrading.md)
|
|
|
11
11
|
|
|
12
12
|
Load this slice, then every range slice between your installed version and the target:
|
|
13
13
|
|
|
14
|
-
- 0.74.0 → 0.
|
|
14
|
+
- 0.74.0 → 0.101.0: `llms/upgrading-0.74.0-0.101.0.txt`
|
|
15
15
|
- 0.61.0 → 0.73.0: `llms/upgrading-0.61.0-0.73.0.txt`
|
|
16
16
|
- 0.44.0 → 0.60.0: `llms/upgrading-0.44.0-0.60.0.txt`
|
|
17
17
|
- 0.37.0 → 0.37.0: `llms/upgrading-0.37.0.txt`
|