approval-md 0.3.0 → 0.4.0
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/README.md +83 -914
- package/SPEC.md +98 -13
- package/cli.js +66 -7
- package/dist/src/adapters/smtp.d.ts +18 -0
- package/dist/src/adapters/smtp.js +24 -3
- package/dist/src/adapters/smtp.js.map +1 -1
- package/dist/src/channels/contract.d.ts +19 -0
- package/dist/src/channels/contract.js +105 -1
- package/dist/src/channels/contract.js.map +1 -1
- package/dist/src/channels/relay-server.d.ts +90 -0
- package/dist/src/channels/relay-server.js +295 -0
- package/dist/src/channels/relay-server.js.map +1 -0
- package/dist/src/channels/relay.d.ts +273 -0
- package/dist/src/channels/relay.js +564 -0
- package/dist/src/channels/relay.js.map +1 -0
- package/dist/src/channels/tagging.js +6 -1
- package/dist/src/channels/tagging.js.map +1 -1
- package/dist/src/channels/telegram-webhook.d.ts +273 -0
- package/dist/src/channels/telegram-webhook.js +536 -0
- package/dist/src/channels/telegram-webhook.js.map +1 -0
- package/dist/src/channels/telegram.d.ts +271 -1
- package/dist/src/channels/telegram.js +403 -45
- package/dist/src/channels/telegram.js.map +1 -1
- package/dist/src/cli/amend.js +350 -4
- package/dist/src/cli/amend.js.map +1 -1
- package/dist/src/cli/attest.js +43 -6
- package/dist/src/cli/attest.js.map +1 -1
- package/dist/src/cli/channel-relay.d.ts +108 -0
- package/dist/src/cli/channel-relay.js +334 -0
- package/dist/src/cli/channel-relay.js.map +1 -0
- package/dist/src/cli/channel-telegram-webhook.d.ts +273 -0
- package/dist/src/cli/channel-telegram-webhook.js +709 -0
- package/dist/src/cli/channel-telegram-webhook.js.map +1 -0
- package/dist/src/cli/channel-telegram.d.ts +272 -26
- package/dist/src/cli/channel-telegram.js +478 -41
- package/dist/src/cli/channel-telegram.js.map +1 -1
- package/dist/src/cli/channel.d.ts +1 -1
- package/dist/src/cli/channel.js +5 -1
- package/dist/src/cli/channel.js.map +1 -1
- package/dist/src/cli/daemon.js +37 -5
- package/dist/src/cli/daemon.js.map +1 -1
- package/dist/src/cli/doctor.d.ts +63 -0
- package/dist/src/cli/doctor.js +856 -111
- package/dist/src/cli/doctor.js.map +1 -1
- package/dist/src/cli/execute.d.ts +17 -1
- package/dist/src/cli/execute.js +341 -20
- package/dist/src/cli/execute.js.map +1 -1
- package/dist/src/cli/exit-codes.d.ts +12 -0
- package/dist/src/cli/exit-codes.js +13 -0
- package/dist/src/cli/exit-codes.js.map +1 -1
- package/dist/src/cli/gate.d.ts +2 -0
- package/dist/src/cli/gate.js +233 -2
- package/dist/src/cli/gate.js.map +1 -1
- package/dist/src/cli/help.d.ts +9 -1
- package/dist/src/cli/help.js +246 -38
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/hook.d.ts +371 -3
- package/dist/src/cli/hook.js +1926 -44
- package/dist/src/cli/hook.js.map +1 -1
- package/dist/src/cli/init.js +16 -7
- package/dist/src/cli/init.js.map +1 -1
- package/dist/src/cli/instructions.js +24 -3
- package/dist/src/cli/instructions.js.map +1 -1
- package/dist/src/cli/log-anchor.d.ts +55 -0
- package/dist/src/cli/log-anchor.js +199 -60
- package/dist/src/cli/log-anchor.js.map +1 -1
- package/dist/src/cli/main.d.ts +0 -12
- package/dist/src/cli/main.js +51 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/muse.d.ts +2 -0
- package/dist/src/cli/muse.js +62 -0
- package/dist/src/cli/muse.js.map +1 -0
- package/dist/src/cli/payload.js +79 -1
- package/dist/src/cli/payload.js.map +1 -1
- package/dist/src/cli/scaffold.js +6 -0
- package/dist/src/cli/scaffold.js.map +1 -1
- package/dist/src/cli/serve.d.ts +53 -0
- package/dist/src/cli/serve.js +270 -0
- package/dist/src/cli/serve.js.map +1 -0
- package/dist/src/cli/up.js +21 -2
- package/dist/src/cli/up.js.map +1 -1
- package/dist/src/cli/verb-registry.d.ts +2 -0
- package/dist/src/cli/verb-registry.js +337 -39
- package/dist/src/cli/verb-registry.js.map +1 -1
- package/dist/src/cli/wordmark.d.ts +2 -2
- package/dist/src/cli/wordmark.js +2 -2
- package/dist/src/core/attest-bootstrap.d.ts +95 -0
- package/dist/src/core/attest-bootstrap.js +135 -0
- package/dist/src/core/attest-bootstrap.js.map +1 -0
- package/dist/src/core/attest.d.ts +20 -3
- package/dist/src/core/attest.js +25 -0
- package/dist/src/core/attest.js.map +1 -1
- package/dist/src/core/audit.d.ts +55 -3
- package/dist/src/core/audit.js +52 -5
- package/dist/src/core/audit.js.map +1 -1
- package/dist/src/core/channel-lease.d.ts +322 -0
- package/dist/src/core/channel-lease.js +663 -0
- package/dist/src/core/channel-lease.js.map +1 -0
- package/dist/src/core/command-class.d.ts +51 -0
- package/dist/src/core/command-class.js +760 -8
- package/dist/src/core/command-class.js.map +1 -1
- package/dist/src/core/daemon-host.d.ts +178 -0
- package/dist/src/core/daemon-host.js +228 -0
- package/dist/src/core/daemon-host.js.map +1 -0
- package/dist/src/core/daemon-identity.d.ts +238 -0
- package/dist/src/core/daemon-identity.js +252 -0
- package/dist/src/core/daemon-identity.js.map +1 -0
- package/dist/src/core/gate.d.ts +306 -5
- package/dist/src/core/gate.js +772 -24
- package/dist/src/core/gate.js.map +1 -1
- package/dist/src/core/harness-version.d.ts +128 -4
- package/dist/src/core/harness-version.js +179 -12
- package/dist/src/core/harness-version.js.map +1 -1
- package/dist/src/core/harness-wait.d.ts +82 -3
- package/dist/src/core/harness-wait.js +89 -3
- package/dist/src/core/harness-wait.js.map +1 -1
- package/dist/src/core/log-subscribe.d.ts +21 -0
- package/dist/src/core/log-subscribe.js +16 -6
- package/dist/src/core/log-subscribe.js.map +1 -1
- package/dist/src/core/log-write-layer.d.ts +55 -0
- package/dist/src/core/log-write-layer.js +91 -0
- package/dist/src/core/log-write-layer.js.map +1 -0
- package/dist/src/core/log.d.ts +50 -21
- package/dist/src/core/log.js +197 -19
- package/dist/src/core/log.js.map +1 -1
- package/dist/src/core/payload-census.d.ts +51 -0
- package/dist/src/core/payload-census.js +125 -2
- package/dist/src/core/payload-census.js.map +1 -1
- package/dist/src/core/payload-store.d.ts +31 -0
- package/dist/src/core/payload-store.js +113 -8
- package/dist/src/core/payload-store.js.map +1 -1
- package/dist/src/core/payload.d.ts +18 -3
- package/dist/src/core/payload.js +20 -4
- package/dist/src/core/payload.js.map +1 -1
- package/dist/src/core/policy-diff.d.ts +10 -0
- package/dist/src/core/policy-diff.js +10 -2
- package/dist/src/core/policy-diff.js.map +1 -1
- package/dist/src/core/policy-explain.d.ts +7 -1
- package/dist/src/core/policy-explain.js +16 -1
- package/dist/src/core/policy-explain.js.map +1 -1
- package/dist/src/core/policy-load.d.ts +24 -0
- package/dist/src/core/policy-load.js.map +1 -1
- package/dist/src/core/policy-match.d.ts +38 -0
- package/dist/src/core/policy-match.js +35 -0
- package/dist/src/core/policy-match.js.map +1 -1
- package/dist/src/core/policy-proposal.d.ts +23 -0
- package/dist/src/core/policy-proposal.js +8 -2
- package/dist/src/core/policy-proposal.js.map +1 -1
- package/dist/src/core/read-scope.d.ts +10 -0
- package/dist/src/core/read-scope.js +4 -0
- package/dist/src/core/read-scope.js.map +1 -1
- package/dist/src/core/run-payload.d.ts +160 -0
- package/dist/src/core/run-payload.js +304 -0
- package/dist/src/core/run-payload.js.map +1 -0
- package/dist/src/core/sender-identity.d.ts +35 -10
- package/dist/src/core/sender-identity.js +48 -11
- package/dist/src/core/sender-identity.js.map +1 -1
- package/dist/src/core/state.d.ts +52 -1
- package/dist/src/core/state.js +52 -6
- package/dist/src/core/state.js.map +1 -1
- package/dist/src/core/telegram-config.d.ts +79 -0
- package/dist/src/core/telegram-config.js +108 -0
- package/dist/src/core/telegram-config.js.map +1 -1
- package/dist/src/core/verify.d.ts +23 -1
- package/dist/src/core/verify.js +20 -2
- package/dist/src/core/verify.js.map +1 -1
- package/dist/src/daemon/audit.d.ts +80 -5
- package/dist/src/daemon/audit.js +126 -6
- package/dist/src/daemon/audit.js.map +1 -1
- package/dist/src/daemon/daemon.d.ts +174 -2
- package/dist/src/daemon/daemon.js +298 -7
- package/dist/src/daemon/daemon.js.map +1 -1
- package/dist/src/daemon/git-evidence.d.ts +2 -2
- package/dist/src/daemon/git-evidence.js +1 -1
- package/dist/src/daemon/projection.d.ts +13 -2
- package/dist/src/daemon/projection.js +39 -6
- package/dist/src/daemon/projection.js.map +1 -1
- package/dist/src/mcp/server.d.ts +39 -3
- package/dist/src/mcp/server.js +22 -3
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/muse/server.d.ts +16 -0
- package/dist/src/muse/server.js +238 -0
- package/dist/src/muse/server.js.map +1 -0
- package/dist/src/serve/archive.d.ts +158 -0
- package/dist/src/serve/archive.js +354 -0
- package/dist/src/serve/archive.js.map +1 -0
- package/dist/src/serve/arguments.d.ts +93 -0
- package/dist/src/serve/arguments.js +228 -0
- package/dist/src/serve/arguments.js.map +1 -0
- package/dist/src/serve/credentials.d.ts +91 -0
- package/dist/src/serve/credentials.js +143 -0
- package/dist/src/serve/credentials.js.map +1 -0
- package/dist/src/serve/follow.d.ts +86 -0
- package/dist/src/serve/follow.js +101 -0
- package/dist/src/serve/follow.js.map +1 -0
- package/dist/src/serve/hook-thread.d.ts +134 -0
- package/dist/src/serve/hook-thread.js +333 -0
- package/dist/src/serve/hook-thread.js.map +1 -0
- package/dist/src/serve/hook-worker.d.ts +134 -0
- package/dist/src/serve/hook-worker.js +173 -0
- package/dist/src/serve/hook-worker.js.map +1 -0
- package/dist/src/serve/server.d.ts +412 -0
- package/dist/src/serve/server.js +1251 -0
- package/dist/src/serve/server.js.map +1 -0
- package/docs/README-extended.md +766 -0
- package/docs/cli-reference.md +1633 -43
- package/package.json +4 -2
- package/schema/event.schema.json +59 -2
- package/schema/fixtures/event/invalid/daemon-id-malformed.json +15 -0
- package/schema/fixtures/event/invalid/execution-started-truncated-policy-sha256.json +18 -0
- package/schema/fixtures/event/invalid/harness-cap-at-margin.json +16 -0
- package/schema/fixtures/event/invalid/harness-cap-fractional.json +16 -0
- package/schema/fixtures/event/invalid/harness-cap-negative.json +16 -0
- package/schema/fixtures/event/invalid/harness-cap-string.json +16 -0
- package/schema/fixtures/event/invalid/harness-cap-without-harness-execution.json +16 -0
- package/schema/fixtures/event/invalid/harness-cap-zero.json +16 -0
- package/schema/fixtures/event/valid/approval-requested-harness-cap.json +18 -0
- package/schema/fixtures/event/valid/daemon-identity-declared.json +17 -0
- package/schema/fixtures/event/valid/daemon-identity.json +15 -0
- package/schema/fixtures/event/valid/execution-started-policy-sha256.json +18 -0
- package/schema/fixtures/event/valid/harness-kind-hermes.json +23 -0
- package/schema/fixtures/policy/invalid/daemons-malformed-id.json +10 -0
- package/schema/fixtures/policy/valid/daemons-allowlist.json +19 -0
- package/schema/fixtures/policy-md/invalid/schema-invalid-agent-may-request.md +21 -0
- package/schema/fixtures/policy-md/valid/agent-may-request.md +24 -0
- package/schema/policy.schema.json +50 -6
|
@@ -34,6 +34,24 @@
|
|
|
34
34
|
* notify, long-poll, callbacks, failure modes — against a local mock Bot API
|
|
35
35
|
* server and never touches the real network.
|
|
36
36
|
*
|
|
37
|
+
* ## Two transports, one update path (APRV-424)
|
|
38
|
+
*
|
|
39
|
+
* An update reaches this channel either because it long-polled for it
|
|
40
|
+
* ({@link TelegramChannel.pollOnce}) or because Telegram posted it to a URL the
|
|
41
|
+
* runtime registered ({@link TelegramChannel.deliverUpdate}, fed by
|
|
42
|
+
* `channels/telegram-webhook.ts`). That is the WHOLE of the difference. Both
|
|
43
|
+
* entry points hand the update to the same {@link TelegramChannel.handleUpdate}
|
|
44
|
+
* and therefore to the same chat check, the same `senderOf`, the same
|
|
45
|
+
* resolution ladder, the same `onDecision` handler and the same
|
|
46
|
+
* annotate-after-decision edit; a decision does not know which door it came
|
|
47
|
+
* through, and there is no second copy of any of it to drift.
|
|
48
|
+
*
|
|
49
|
+
* The two are mutually exclusive per bot, and the Bot API says so first:
|
|
50
|
+
* `getUpdates` is refused outright while a webhook is set.
|
|
51
|
+
* {@link TelegramChannel.claimTransport} refuses the in-process form of the
|
|
52
|
+
* mistake, and the verbs above ask `getWebhookInfo` and the ownership registry
|
|
53
|
+
* about the cross-process one.
|
|
54
|
+
*
|
|
37
55
|
* ## Config-declared identity — SPEC.md §11
|
|
38
56
|
*
|
|
39
57
|
* > Human identity in v0.1 is config-declared (an environment variable or
|
|
@@ -361,6 +379,13 @@ export declare function decidedLine(actor: string, ts: string, seq: number): str
|
|
|
361
379
|
export declare const TELEGRAM_DEFAULT_RETENTION_MS: number;
|
|
362
380
|
/** Least time between two sweeps. A sweep is O(map); once a minute is plenty. */
|
|
363
381
|
export declare const TELEGRAM_SWEEP_INTERVAL_MS = 60000;
|
|
382
|
+
/**
|
|
383
|
+
* How many refused cards' nonces a channel remembers as dead (APRV-442).
|
|
384
|
+
*
|
|
385
|
+
* A bound on memory and nothing else: a nonce that falls off the end reaches
|
|
386
|
+
* the action-reference fallback, and the gate judges that tap in full.
|
|
387
|
+
*/
|
|
388
|
+
export declare const TELEGRAM_REFUSED_NONCE_CAP = 1024;
|
|
364
389
|
/**
|
|
365
390
|
* The slice of `fetch` this module uses, structurally.
|
|
366
391
|
*
|
|
@@ -831,6 +856,14 @@ export interface DigestState {
|
|
|
831
856
|
* the request's own `ts` remains the only instant a TTL is measured from.
|
|
832
857
|
*/
|
|
833
858
|
deliveredAtMs: number;
|
|
859
|
+
/**
|
|
860
|
+
* How long after {@link deliveredAtMs} the LAST of this digest's members can
|
|
861
|
+
* still be decided, or `null` when some member is bounded by nothing
|
|
862
|
+
* (APRV-423, second review pass). The widest of the members' own windows
|
|
863
|
+
* ({@link Delivery.windowMs}), because a digest is droppable only once every
|
|
864
|
+
* member is past deciding.
|
|
865
|
+
*/
|
|
866
|
+
windowMs: number | null;
|
|
834
867
|
}
|
|
835
868
|
/**
|
|
836
869
|
* The computed facts a digest's members share, as the digest states them.
|
|
@@ -1270,6 +1303,50 @@ export interface TelegramPollResult {
|
|
|
1270
1303
|
ok: boolean;
|
|
1271
1304
|
}[];
|
|
1272
1305
|
}
|
|
1306
|
+
/**
|
|
1307
|
+
* How updates reach this channel (APRV-424).
|
|
1308
|
+
*
|
|
1309
|
+
* `poll` is `getUpdates`, the transport every build before APRV-424 had.
|
|
1310
|
+
* `webhook` is Telegram posting each update to a URL the runtime registered.
|
|
1311
|
+
* They are alternatives and never a pair: the Bot API refuses `getUpdates`
|
|
1312
|
+
* outright while a webhook is set, so a process that did both would spend its
|
|
1313
|
+
* life in a 409 loop and the approver's tap would land on whichever half was
|
|
1314
|
+
* lucky.
|
|
1315
|
+
*/
|
|
1316
|
+
export type TelegramTransport = "poll" | "webhook";
|
|
1317
|
+
/**
|
|
1318
|
+
* Why a transport claim was refused. Frozen, per SPEC §11.1 invariant 6.
|
|
1319
|
+
*
|
|
1320
|
+
* One code, because there is one fact: this channel is already receiving
|
|
1321
|
+
* updates by the other transport.
|
|
1322
|
+
*/
|
|
1323
|
+
export declare const TELEGRAM_TRANSPORT_REFUSAL_CODES: readonly ["transport-conflict"];
|
|
1324
|
+
export type TelegramTransportRefusalCode = (typeof TELEGRAM_TRANSPORT_REFUSAL_CODES)[number];
|
|
1325
|
+
export type TelegramTransportClaim = {
|
|
1326
|
+
ok: true;
|
|
1327
|
+
transport: TelegramTransport;
|
|
1328
|
+
} | {
|
|
1329
|
+
ok: false;
|
|
1330
|
+
code: TelegramTransportRefusalCode;
|
|
1331
|
+
message: string;
|
|
1332
|
+
};
|
|
1333
|
+
/**
|
|
1334
|
+
* The in-process half of "long-poll and webhook are mutually exclusive"
|
|
1335
|
+
* (APRV-424).
|
|
1336
|
+
*
|
|
1337
|
+
* It is a belt on the braces and says so. The exclusion that matters is per
|
|
1338
|
+
* BOT and lives above this class, where a process can ask the Bot API
|
|
1339
|
+
* (`getWebhookInfo`) and the per-machine ownership registry who else is
|
|
1340
|
+
* receiving this bot's updates; a channel object knows only about itself.
|
|
1341
|
+
* What this rules out is the one failure a caller could cause here and
|
|
1342
|
+
* nowhere else: feeding one channel instance from both a poll loop and an
|
|
1343
|
+
* HTTP handler, where `handleUpdate`'s single ack slot and the delivery maps
|
|
1344
|
+
* would be written by two arrivals nobody ordered.
|
|
1345
|
+
*/
|
|
1346
|
+
export declare class TelegramTransportError extends Error {
|
|
1347
|
+
readonly code: TelegramTransportRefusalCode;
|
|
1348
|
+
constructor(message: string);
|
|
1349
|
+
}
|
|
1273
1350
|
export interface TelegramListenOptions {
|
|
1274
1351
|
/** Process exactly one successful `getUpdates` batch, then return. */
|
|
1275
1352
|
once?: boolean;
|
|
@@ -1393,11 +1470,60 @@ export declare class TelegramChannel implements TestableChannel {
|
|
|
1393
1470
|
private readonly digests;
|
|
1394
1471
|
/** "All" nonce -> the digest message it was issued for. */
|
|
1395
1472
|
private readonly allNonces;
|
|
1473
|
+
/**
|
|
1474
|
+
* Action keys whose card this process disarmed on a tap the gate did NOT
|
|
1475
|
+
* settle (APRV-442): a refusal (`sender-unmapped`, a budget, an unattested
|
|
1476
|
+
* policy, anything `ok: false`) or a handler that threw. Drained by
|
|
1477
|
+
* {@link takeReleased}.
|
|
1478
|
+
*
|
|
1479
|
+
* The disarm is right and stays, and {@link refusedNonces} keeps it final:
|
|
1480
|
+
* the refused card's bytes resolve to nothing, not even through the
|
|
1481
|
+
* action-reference fallback to the card that replaces it. What the disarm
|
|
1482
|
+
* must not do is leave the listener believing the REQUEST is on the
|
|
1483
|
+
* approver's phone, which is what `DispatchState.delivered` goes on saying
|
|
1484
|
+
* until something tells it otherwise. This set is that something: it names
|
|
1485
|
+
* a card, never an outcome, and the listener re-derives from the verified
|
|
1486
|
+
* log whether the request is still pending before it offers a new card.
|
|
1487
|
+
* Nothing here decides, and losing it to a restart costs nothing, because a
|
|
1488
|
+
* restarted listener re-sends everything pending anyway.
|
|
1489
|
+
*/
|
|
1490
|
+
private readonly released;
|
|
1491
|
+
/**
|
|
1492
|
+
* Nonces of cards a refused or failed tap disarmed (APRV-442), oldest first,
|
|
1493
|
+
* capped at {@link TELEGRAM_REFUSED_NONCE_CAP}.
|
|
1494
|
+
*
|
|
1495
|
+
* Without this, a released request's fresh card would give the refused
|
|
1496
|
+
* card's bytes somewhere to go: the nonce misses, the action reference
|
|
1497
|
+
* resolves to the new live card, and a Telegram redelivery of the refused
|
|
1498
|
+
* tap (a webhook retry) or a client replaying the removed buttons would be
|
|
1499
|
+
* refused again, append again, disarm the new card and cause another
|
|
1500
|
+
* re-send, once per replay. A nonce in this set never takes the fallback, so
|
|
1501
|
+
* a refused card stays exactly as dead as it was before APRV-442 and only
|
|
1502
|
+
* the REQUEST is offered again. Forgetting an entry past the cap degrades to
|
|
1503
|
+
* the fallback, whose tap the gate still judges in full: volume, never a
|
|
1504
|
+
* decision.
|
|
1505
|
+
*/
|
|
1506
|
+
private readonly refusedNonces;
|
|
1396
1507
|
private rendered;
|
|
1397
1508
|
private offset;
|
|
1398
1509
|
private counter;
|
|
1399
1510
|
private stopped;
|
|
1400
1511
|
private inFlight;
|
|
1512
|
+
/**
|
|
1513
|
+
* The transport this channel has started receiving updates by, or `null`
|
|
1514
|
+
* before the first one (APRV-424). Sticky for the life of the object: a
|
|
1515
|
+
* process that stopped polling has not stopped being a poller, and the
|
|
1516
|
+
* question this answers is which arrival path owns the maps below.
|
|
1517
|
+
*/
|
|
1518
|
+
private transport;
|
|
1519
|
+
/**
|
|
1520
|
+
* Everything {@link redact} scrubs out of anything that leaves this class.
|
|
1521
|
+
*
|
|
1522
|
+
* The bot token from construction, plus any secret a later call was handed:
|
|
1523
|
+
* {@link registerWebhook} adds the `secret_token` before it sends it, so a
|
|
1524
|
+
* Bot API error quoting the request cannot put it on an operator's terminal.
|
|
1525
|
+
*/
|
|
1526
|
+
private readonly secrets;
|
|
1401
1527
|
private readonly counters;
|
|
1402
1528
|
constructor(config: TelegramConfig);
|
|
1403
1529
|
onDecision(handler: (decision: ChannelDecision) => DecisionOutcome): void;
|
|
@@ -1553,6 +1679,28 @@ export declare class TelegramChannel implements TestableChannel {
|
|
|
1553
1679
|
* a decided one is not that.
|
|
1554
1680
|
*/
|
|
1555
1681
|
private disarm;
|
|
1682
|
+
/**
|
|
1683
|
+
* How long after delivery the request behind a prompt can still be decided,
|
|
1684
|
+
* on this process's clock, or `null` when nothing bounds it (APRV-423, second
|
|
1685
|
+
* review pass).
|
|
1686
|
+
*
|
|
1687
|
+
* The SHORTER of two bounds, each of which is at or past the gate's own
|
|
1688
|
+
* lapse, so the sweep never forgets a button a decision could still reach:
|
|
1689
|
+
*
|
|
1690
|
+
* - the request's `ttl_remaining_ms`, computed by the listener from the
|
|
1691
|
+
* verified log against the window the gate judges by (the policy's TTL
|
|
1692
|
+
* narrowed by the harness cap the requesting hook declared). It was
|
|
1693
|
+
* measured at tagging time, and delivery is at or after tagging, so
|
|
1694
|
+
* counting it from delivery ends at or after the real lapse;
|
|
1695
|
+
* - the policy's own TTL ({@link TelegramConfig.approvalTtlMs}), counted from
|
|
1696
|
+
* delivery, which is at or after the `approval.requested` it really runs
|
|
1697
|
+
* from. This was the only bound before APRV-423 and it stays as one.
|
|
1698
|
+
*
|
|
1699
|
+
* A request neither bounds is decidable forever, and its entry is dropped
|
|
1700
|
+
* only on an observed settlement. This channel still reads no policy and no
|
|
1701
|
+
* log: both numbers arrive computed, by the verb and by the tagger.
|
|
1702
|
+
*/
|
|
1703
|
+
private retentionWindowMs;
|
|
1556
1704
|
/**
|
|
1557
1705
|
* Drop the delivery bookkeeping no callback can still be honoured against
|
|
1558
1706
|
* (APRV-135).
|
|
@@ -1646,6 +1794,28 @@ export declare class TelegramChannel implements TestableChannel {
|
|
|
1646
1794
|
* {@link Channel} interface names. Its wording is unchanged.
|
|
1647
1795
|
*/
|
|
1648
1796
|
retract(deliveryId: DeliveryId, reason: string, actionKey?: string): Promise<void>;
|
|
1797
|
+
/**
|
|
1798
|
+
* The action keys whose card a refused or failed tap disarmed since the last
|
|
1799
|
+
* call, and forget them (APRV-442).
|
|
1800
|
+
*
|
|
1801
|
+
* The listener's dispatch cycle calls this once per cycle and offers a fresh
|
|
1802
|
+
* card for every key the verified log still calls pending. It is a statement
|
|
1803
|
+
* about this process's cards and nothing else: it carries no decision, no
|
|
1804
|
+
* sender and no outcome, and a key in it that the log has since settled is
|
|
1805
|
+
* simply not offered.
|
|
1806
|
+
*/
|
|
1807
|
+
takeReleased(): string[];
|
|
1808
|
+
/**
|
|
1809
|
+
* Mark `delivery`'s card dead and its request released, BEFORE the
|
|
1810
|
+
* annotation that disarms it (APRV-442).
|
|
1811
|
+
*
|
|
1812
|
+
* Every nonce still armed for this request on this message is recorded in
|
|
1813
|
+
* {@link refusedNonces}, together with the nonce the tap carried (which
|
|
1814
|
+
* differs when the tap came from an earlier copy through the fallback), so
|
|
1815
|
+
* none of those bytes can later resolve to the fresh card. On a digest only
|
|
1816
|
+
* this member's nonce is taken: its siblings stay armed on the digest.
|
|
1817
|
+
*/
|
|
1818
|
+
private release;
|
|
1649
1819
|
/**
|
|
1650
1820
|
* Send one plain message that carries no question (APRV-196).
|
|
1651
1821
|
*
|
|
@@ -1700,6 +1870,99 @@ export declare class TelegramChannel implements TestableChannel {
|
|
|
1700
1870
|
* what {@link listen} catches and retries.
|
|
1701
1871
|
*/
|
|
1702
1872
|
pollOnce(): Promise<TelegramPollResult>;
|
|
1873
|
+
/**
|
|
1874
|
+
* Which update types this channel asks for, on either transport (APRV-424).
|
|
1875
|
+
*
|
|
1876
|
+
* APRV-216. `message` is asked for only while a command handler is
|
|
1877
|
+
* registered: see {@link onCommand} for why a listener that reads messages
|
|
1878
|
+
* nobody asked for would break `approval setup channel telegram`'s chat
|
|
1879
|
+
* discovery. APRV-299 adds the second reason to read messages: a `loved` or
|
|
1880
|
+
* `disliked` on a review card collects the human's words as a REPLY, because
|
|
1881
|
+
* an inline keyboard has no text input.
|
|
1882
|
+
*
|
|
1883
|
+
* One function since APRV-424, because `setWebhook` takes the same list as
|
|
1884
|
+
* `getUpdates` and two spellings of it would be two answers to "what does
|
|
1885
|
+
* this listener read" — with the webhook's answer frozen at registration
|
|
1886
|
+
* time, where nobody would look for it.
|
|
1887
|
+
*/
|
|
1888
|
+
allowedUpdates(): string[];
|
|
1889
|
+
/**
|
|
1890
|
+
* One update, from whichever transport carried it (APRV-424).
|
|
1891
|
+
*
|
|
1892
|
+
* The whole of what the webhook adds is the ARRIVAL. Everything a tap then
|
|
1893
|
+
* passes through — the chat check, `senderOf`, the checkpoint and review
|
|
1894
|
+
* parsers, the resolution ladder, the early ack, `this.handler` and the
|
|
1895
|
+
* annotation written from the record the gate appended — is
|
|
1896
|
+
* {@link handleUpdate}, called from here and from {@link pollOnce}, and
|
|
1897
|
+
* there is no second copy of any of it. `tests/telegram-webhook.test.ts`
|
|
1898
|
+
* drives one callback through both entry points and compares the records the
|
|
1899
|
+
* log ends up holding.
|
|
1900
|
+
*
|
|
1901
|
+
* The sweep is `pollOnce`'s, for `pollOnce`'s reason: this is the moment the
|
|
1902
|
+
* process is about to be idle, and a channel that only ever wakes for taps
|
|
1903
|
+
* would otherwise never run one.
|
|
1904
|
+
*/
|
|
1905
|
+
deliverUpdate(update: unknown): Promise<TelegramPollResult>;
|
|
1906
|
+
/** The per-update bookkeeping both transports do, before `handleUpdate`. */
|
|
1907
|
+
private intake;
|
|
1908
|
+
/**
|
|
1909
|
+
* Bind this channel to one transport, or say which one already holds it
|
|
1910
|
+
* (APRV-424).
|
|
1911
|
+
*
|
|
1912
|
+
* Idempotent for the transport already claimed, so a webhook server that
|
|
1913
|
+
* claims at start-up and then delivers, or a driver calling `pollOnce` in a
|
|
1914
|
+
* loop, pays nothing. Not released by {@link stop}: a process that stopped
|
|
1915
|
+
* polling has not stopped being a poller, and re-pointing a live channel's
|
|
1916
|
+
* delivery maps at a second arrival path is the state this exists to refuse.
|
|
1917
|
+
*/
|
|
1918
|
+
claimTransport(transport: TelegramTransport): TelegramTransportClaim;
|
|
1919
|
+
/** {@link claimTransport}, for the paths where a refusal is a caller's bug. */
|
|
1920
|
+
private claimOrThrow;
|
|
1921
|
+
/**
|
|
1922
|
+
* Point this bot's updates at `url`, and require `secret` on every post.
|
|
1923
|
+
*
|
|
1924
|
+
* Three properties, and each is a refusal to be clever:
|
|
1925
|
+
*
|
|
1926
|
+
* - **The secret is Telegram's own mechanism**, `secret_token`, echoed back
|
|
1927
|
+
* on every delivery in the `X-Telegram-Bot-Api-Secret-Token` header. The
|
|
1928
|
+
* receiver compares it and refuses anything else, so a URL that leaks (a
|
|
1929
|
+
* proxy log, a referrer, a screenshot) is a URL that still decides
|
|
1930
|
+
* nothing.
|
|
1931
|
+
* - **It is redacted from this moment on.** The value is added to the
|
|
1932
|
+
* channel's secret list BEFORE the call, so a Bot API error that quotes
|
|
1933
|
+
* the request cannot print it.
|
|
1934
|
+
* - **Pending updates are kept.** `drop_pending_updates` is left false:
|
|
1935
|
+
* taps that arrived while the process was down are the approver's answers,
|
|
1936
|
+
* and the gate is what decides whether they are still honourable.
|
|
1937
|
+
*/
|
|
1938
|
+
registerWebhook(url: string, secret: string): Promise<void>;
|
|
1939
|
+
/**
|
|
1940
|
+
* Take this bot's webhook away, so `getUpdates` works again.
|
|
1941
|
+
*
|
|
1942
|
+
* Called on a clean stop of the webhook runner. Pending updates are kept for
|
|
1943
|
+
* {@link registerWebhook}'s reason: the next process to start — a poller or
|
|
1944
|
+
* another webhook — is entitled to the taps that arrived in between.
|
|
1945
|
+
*
|
|
1946
|
+
* `timeoutMs` is what the stop path passes, and it is shorter than this
|
|
1947
|
+
* channel's ordinary request timeout on purpose (APRV-424, second review,
|
|
1948
|
+
* note 6). A stop already waits for the receiver to drain, and an operator
|
|
1949
|
+
* pressing Ctrl-C a second time is asking for the process to end: half a
|
|
1950
|
+
* minute of an unreachable Bot API on top of that reads as a hang, and the
|
|
1951
|
+
* webhook it failed to remove is reported rather than silently retried.
|
|
1952
|
+
*/
|
|
1953
|
+
deleteWebhook(timeoutMs?: number): Promise<void>;
|
|
1954
|
+
/**
|
|
1955
|
+
* What the Bot API says is receiving this bot's updates right now.
|
|
1956
|
+
*
|
|
1957
|
+
* The one authority on the question, and the reason it is asked at start-up
|
|
1958
|
+
* by both transports: the ownership registry knows about processes on THIS
|
|
1959
|
+
* machine, and a webhook registered from a laptop in another timezone is
|
|
1960
|
+
* still a webhook swallowing every tap this poller is waiting for.
|
|
1961
|
+
*/
|
|
1962
|
+
webhookInfo(): Promise<{
|
|
1963
|
+
url: string;
|
|
1964
|
+
pendingUpdateCount: number;
|
|
1965
|
+
}>;
|
|
1703
1966
|
/**
|
|
1704
1967
|
* Exactly one `answerCallbackQuery` per callback query, on every path
|
|
1705
1968
|
* (APRV-196).
|
|
@@ -1919,7 +2182,14 @@ export declare class TelegramChannel implements TestableChannel {
|
|
|
1919
2182
|
* settled, so a member still in the map is one still armed on a live message.
|
|
1920
2183
|
*/
|
|
1921
2184
|
private liveDeliveryFor;
|
|
1922
|
-
/**
|
|
2185
|
+
/**
|
|
2186
|
+
* Replace every secret this channel holds with a placeholder in `text`.
|
|
2187
|
+
*
|
|
2188
|
+
* The bot token always, and since APRV-424 the webhook `secret_token` too,
|
|
2189
|
+
* from the moment {@link registerWebhook} is handed it. Both are values that
|
|
2190
|
+
* only ever travel TO the Bot API, so anything coming back that quotes one
|
|
2191
|
+
* is a diagnostic about to print a credential.
|
|
2192
|
+
*/
|
|
1923
2193
|
private redact;
|
|
1924
2194
|
private describe;
|
|
1925
2195
|
/**
|