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
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval channel telegram webhook` — the same channel, the other arrival
|
|
3
|
+
* (SPEC.md §10.3, APRV-424).
|
|
4
|
+
*
|
|
5
|
+
* `approval channel telegram listen` holds a socket open against `getUpdates`
|
|
6
|
+
* for as long as the gate exists. That works, and it costs one always-running
|
|
7
|
+
* process per bot and forbids a second poller on the same token. This verb
|
|
8
|
+
* registers a URL with `setWebhook` instead and serves the callback, which is
|
|
9
|
+
* what makes a sleep-when-idle host able to run a gate, and what lets an
|
|
10
|
+
* operator put the receiver behind a proxy they already own.
|
|
11
|
+
*
|
|
12
|
+
* **Everything below the arrival is unchanged, and deliberately not restated
|
|
13
|
+
* here.** The pending queue is still `dispatchPending`'s, re-derived from the
|
|
14
|
+
* verified log every cycle. The handlers are still {@link wireListener}'s, the
|
|
15
|
+
* same four function objects `listen` registers. A tap still becomes a
|
|
16
|
+
* decision through `channels/telegram.ts`'s `handleUpdate` and
|
|
17
|
+
* `channels/contract.ts`'s `recordChannelDecision`. This file resolves
|
|
18
|
+
* configuration, refuses what it must refuse, binds a port and keeps a cycle
|
|
19
|
+
* running; it decides nothing and it renders nothing.
|
|
20
|
+
*
|
|
21
|
+
* ## The three refusals that are the point of the task
|
|
22
|
+
*
|
|
23
|
+
* 1. **The secret comes from the launch environment, never from the tree.**
|
|
24
|
+
* `APPROVAL_TG_WEBHOOK_SECRET` (`core/telegram-config.ts` says why the name
|
|
25
|
+
* is conventional rather than policy-declared), refused when it is unset,
|
|
26
|
+
* when it is shorter than a value a host would generate, and when it holds
|
|
27
|
+
* a character Telegram will not accept. SPEC.md §11.1 invariant 7.
|
|
28
|
+
* 2. **A post without the matching header decides nothing.** That check is
|
|
29
|
+
* `channels/telegram-webhook.ts`'s, before the path, the method or the
|
|
30
|
+
* body, and its refusal is counted and complained about rather than
|
|
31
|
+
* appended: an endpoint the internet can reach must not be able to grow the
|
|
32
|
+
* tenant's log.
|
|
33
|
+
* 3. **One transport per bot.** The preflight asks the Bot API which webhook
|
|
34
|
+
* holds this bot and refuses a foreign one; `listen` and `approval up` ask
|
|
35
|
+
* the same question and refuse when any webhook holds it. Within one
|
|
36
|
+
* process the channel refuses the second claim outright.
|
|
37
|
+
*
|
|
38
|
+
* ## Where TLS is, and why the bind is loopback
|
|
39
|
+
*
|
|
40
|
+
* Telegram will only deliver to an HTTPS URL, and this process terminates no
|
|
41
|
+
* TLS and holds no certificate — exactly as `approval serve` does not
|
|
42
|
+
* (APRV-421, `cli/serve.ts`). The supported deployment is a loopback bind
|
|
43
|
+
* behind a proxy or a tunnel the operator owns, which is what `--url` names
|
|
44
|
+
* and what `docs/cli-reference.md#channel-telegram-webhook` states. A
|
|
45
|
+
* non-loopback bind takes two flags and prints a banner, because the secret
|
|
46
|
+
* arrives in a header and a cleartext hop hands it to whoever is on it.
|
|
47
|
+
*/
|
|
48
|
+
import type { DaemonIdSource } from "../core/daemon-identity.js";
|
|
49
|
+
import { type ListenRefusalCode, type ListenSetup } from "./channel-telegram.js";
|
|
50
|
+
import type { GlossRunner } from "./gloss.js";
|
|
51
|
+
import type { Streams } from "./main.js";
|
|
52
|
+
/**
|
|
53
|
+
* The shortest `secret_token` this verb will start with.
|
|
54
|
+
*
|
|
55
|
+
* `serve/credentials.ts`'s floor, for its reason: not a password policy, a
|
|
56
|
+
* floor under the one mistake that makes the check meaningless, which is a
|
|
57
|
+
* memorable value somebody typed. The host generates this; the floor costs it
|
|
58
|
+
* nothing.
|
|
59
|
+
*/
|
|
60
|
+
export declare const WEBHOOK_MIN_SECRET_LENGTH = 24;
|
|
61
|
+
/** How often the dispatch cycle runs when the operator names no period. */
|
|
62
|
+
export declare const WEBHOOK_DEFAULT_CYCLE_MS = 30000;
|
|
63
|
+
/**
|
|
64
|
+
* How long the stop path waits for `deleteWebhook` (APRV-424, second review,
|
|
65
|
+
* note 6).
|
|
66
|
+
*
|
|
67
|
+
* The channel's ordinary request timeout is thirty seconds, which is right for
|
|
68
|
+
* a delivery and wrong for a stop: on top of the receiver's drain it made a
|
|
69
|
+
* second Ctrl-C look swallowed for the better part of a minute. A removal that
|
|
70
|
+
* does not land in five seconds is reported, and the operator is told the
|
|
71
|
+
* webhook is still registered, which is a sentence they can act on.
|
|
72
|
+
*/
|
|
73
|
+
export declare const WEBHOOK_STOP_DELETE_TIMEOUT_MS = 5000;
|
|
74
|
+
/**
|
|
75
|
+
* Why a webhook runner could not be built. A closed union, distinct per
|
|
76
|
+
* repair, per SPEC.md §11.1 invariant 6.
|
|
77
|
+
*
|
|
78
|
+
* It sits BESIDE `LISTEN_REFUSAL_CODES` rather than inside it: every reason a
|
|
79
|
+
* listener cannot start is a reason this cannot either (it needs the same
|
|
80
|
+
* token, chat, identity, log and policy), and these are the reasons peculiar
|
|
81
|
+
* to a transport that binds a port and registers a URL.
|
|
82
|
+
*/
|
|
83
|
+
export declare const WEBHOOK_REFUSAL_CODES: readonly [
|
|
84
|
+
/** `APPROVAL_TG_WEBHOOK_SECRET` is unset or empty. */
|
|
85
|
+
"webhook-secret-missing",
|
|
86
|
+
/** It is shorter than {@link WEBHOOK_MIN_SECRET_LENGTH}. */
|
|
87
|
+
"webhook-secret-weak",
|
|
88
|
+
/** It holds a character Telegram will not accept in a `secret_token`. */
|
|
89
|
+
"webhook-secret-charset",
|
|
90
|
+
/** No `--url`: nothing to register, so nothing would ever be delivered. */
|
|
91
|
+
"webhook-url-missing",
|
|
92
|
+
/** `--url` is not a URL, or its scheme is not `https`. */
|
|
93
|
+
"webhook-url-insecure",
|
|
94
|
+
/** `--url` names a port Telegram does not deliver to. */
|
|
95
|
+
"webhook-url-port",
|
|
96
|
+
/**
|
|
97
|
+
* `--url` carries userinfo (`https://user:pw@host/hook`) (review finding 10).
|
|
98
|
+
*
|
|
99
|
+
* Refused rather than stripped. A credential in a url is a credential the
|
|
100
|
+
* operator put on a command line, and a runtime that quietly dropped it
|
|
101
|
+
* would register an endpoint that answers differently from the one they
|
|
102
|
+
* typed; a runtime that kept it would carry it into `setWebhook`, into the
|
|
103
|
+
* start-up banner and into every refusal that names the url.
|
|
104
|
+
*/
|
|
105
|
+
"webhook-url-userinfo",
|
|
106
|
+
/**
|
|
107
|
+
* `--path` is not a servable path: it does not start with `/`, or it holds a
|
|
108
|
+
* `..` segment (review finding 3).
|
|
109
|
+
*/
|
|
110
|
+
"webhook-path-invalid",
|
|
111
|
+
/**
|
|
112
|
+
* `--path` is a servable path, and not the one `--url` names (review finding
|
|
113
|
+
* 3).
|
|
114
|
+
*
|
|
115
|
+
* The pair used to be free to disagree, described as an override for a proxy
|
|
116
|
+
* that rewrites on the way. What it actually bought was a receiver that
|
|
117
|
+
* registered cleanly, verified the secret on every real delivery, and then
|
|
118
|
+
* answered all of them 404: `telegram/webhook` against a url path of
|
|
119
|
+
* `/telegram/webhook`, or `/hook/` against a url ending `/hook`, both start
|
|
120
|
+
* without a word. A path mismatch is now a startup refusal.
|
|
121
|
+
*/
|
|
122
|
+
"webhook-path-mismatch",
|
|
123
|
+
/** `--cycle` was not a duration. */
|
|
124
|
+
"webhook-cycle",
|
|
125
|
+
/**
|
|
126
|
+
* `setWebhook` was refused by the Bot API.
|
|
127
|
+
*
|
|
128
|
+
* Emitted by {@link runWebhook} since the review of this task; before it the
|
|
129
|
+
* code was declared here and the failure was reported as a bare `io`, which
|
|
130
|
+
* made "Telegram will not take this registration" indistinguishable from
|
|
131
|
+
* "the log could not be read". The status and the Bot API's own description
|
|
132
|
+
* are carried, redacted of the token and the secret by the channel.
|
|
133
|
+
*/
|
|
134
|
+
"webhook-registration-failed"];
|
|
135
|
+
export type WebhookRefusalCode = (typeof WEBHOOK_REFUSAL_CODES)[number];
|
|
136
|
+
export interface WebhookSetup {
|
|
137
|
+
/** Everything a listener has: the channel, the log, the identity, the policy. */
|
|
138
|
+
listen: ListenSetup;
|
|
139
|
+
/** The `secret_token`, as a value. Never printed, never logged, never recorded. */
|
|
140
|
+
secret: string;
|
|
141
|
+
/** The public URL registered with `setWebhook`. */
|
|
142
|
+
url: string;
|
|
143
|
+
/** The path this process answers. Derived from `--url` unless `--path` says otherwise. */
|
|
144
|
+
path: string;
|
|
145
|
+
/** The interface to bind. Loopback unless the operator widened it. */
|
|
146
|
+
host: string;
|
|
147
|
+
/** The port to bind. Distinct from the URL's port, which is the proxy's. */
|
|
148
|
+
port: number;
|
|
149
|
+
/** How often the dispatch cycle runs. */
|
|
150
|
+
cycleMs: number;
|
|
151
|
+
/**
|
|
152
|
+
* `--reclaim`: register over a webhook that already holds this bot (review
|
|
153
|
+
* finding 6).
|
|
154
|
+
*
|
|
155
|
+
* Carried on the setup rather than consulted from the flags again, because
|
|
156
|
+
* the check it overrides is made by {@link claimListenerBot}, which this
|
|
157
|
+
* verb shares with the poller.
|
|
158
|
+
*/
|
|
159
|
+
reclaim: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* The daemon id every record this process appends carries (APRV-448),
|
|
162
|
+
* resolved by {@link prepareWebhook} from the launch environment and the log
|
|
163
|
+
* path with the function the daemon loop uses, and declared by
|
|
164
|
+
* {@link runWebhook} before anything can append. An unusable declared id never
|
|
165
|
+
* reaches a setup: it is refused `daemon-id-invalid` at preparation.
|
|
166
|
+
*/
|
|
167
|
+
daemon: {
|
|
168
|
+
ok: true;
|
|
169
|
+
id: string;
|
|
170
|
+
source: DaemonIdSource;
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export type WebhookPreparation = {
|
|
174
|
+
ok: true;
|
|
175
|
+
setup: WebhookSetup;
|
|
176
|
+
} | {
|
|
177
|
+
ok: false;
|
|
178
|
+
/**
|
|
179
|
+
* This verb's own codes, the listener's, and `daemon-id-invalid`
|
|
180
|
+
* (APRV-448), which is the write boundary's own code for the same fault,
|
|
181
|
+
* reported here before anything binds rather than on the first append.
|
|
182
|
+
*/
|
|
183
|
+
code: WebhookRefusalCode | ListenRefusalCode | "daemon-id-invalid";
|
|
184
|
+
message: string;
|
|
185
|
+
};
|
|
186
|
+
/** Everything {@link prepareWebhook} needs, already resolved. */
|
|
187
|
+
export interface WebhookRequest {
|
|
188
|
+
logPath: string;
|
|
189
|
+
policy: {
|
|
190
|
+
dir?: string;
|
|
191
|
+
file?: string;
|
|
192
|
+
};
|
|
193
|
+
as: string | null;
|
|
194
|
+
payloads: string | null;
|
|
195
|
+
apiBase: string | null;
|
|
196
|
+
json: boolean;
|
|
197
|
+
allowCrossInstance?: boolean;
|
|
198
|
+
/** `--url` as typed, or `null`. */
|
|
199
|
+
url: string | null;
|
|
200
|
+
/** `--path`, or `null` to take the URL's own path. */
|
|
201
|
+
path: string | null;
|
|
202
|
+
/** The bind, already parsed by the verb. */
|
|
203
|
+
host: string;
|
|
204
|
+
port: number;
|
|
205
|
+
/** `--cycle` as typed, or `null` for {@link WEBHOOK_DEFAULT_CYCLE_MS}. */
|
|
206
|
+
cycle: string | null;
|
|
207
|
+
/** `--reclaim` as passed. Defaults to false, which is the refusing side. */
|
|
208
|
+
reclaim?: boolean;
|
|
209
|
+
/** The environment the secret is read from. Injectable for tests. */
|
|
210
|
+
env?: NodeJS.ProcessEnv;
|
|
211
|
+
log(message: string): void;
|
|
212
|
+
/** The gloss runner, if the caller wants one. See {@link ListenSetup.gloss}. */
|
|
213
|
+
gloss?: GlossRunner;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Everything that can fail without touching the network, in order.
|
|
217
|
+
*
|
|
218
|
+
* {@link prepareListen} first, because a webhook runner that has no bot token,
|
|
219
|
+
* no chat and no human identity is not a webhook problem: the two verbs refuse
|
|
220
|
+
* those the same way, in the same sentences, for the reason `prepareListen`
|
|
221
|
+
* exists at all. Then the three this transport adds.
|
|
222
|
+
*
|
|
223
|
+
* It PRINTS NOTHING and CHOOSES NO EXIT CODE, exactly as `prepareListen` does.
|
|
224
|
+
*/
|
|
225
|
+
export declare function prepareWebhook(request: WebhookRequest): WebhookPreparation;
|
|
226
|
+
/**
|
|
227
|
+
* `--listen` / `--port` -> the interface and port this process binds (review
|
|
228
|
+
* finding 9).
|
|
229
|
+
*
|
|
230
|
+
* Its own function, and exported, because three refusals live in it and each
|
|
231
|
+
* one is a thing an operator can type:
|
|
232
|
+
*
|
|
233
|
+
* - **Port 0 is refused.** The kernel hands out an ephemeral port for it, and
|
|
234
|
+
* an ephemeral port is the one thing this transport cannot use: the whole
|
|
235
|
+
* deployment is a proxy forwarding a fixed public url to a fixed local
|
|
236
|
+
* address, so a receiver that bound 51423 registered a url nothing would
|
|
237
|
+
* ever reach and said nothing about it. Tests bind 0 by calling the receiver
|
|
238
|
+
* directly, which is the level where an ephemeral port is the point.
|
|
239
|
+
* - **A port outside 1..65535 is refused**, on either flag. `parseListen`
|
|
240
|
+
* accepts 0 for `approval serve`'s own reasons, so the floor is applied
|
|
241
|
+
* here rather than assumed there.
|
|
242
|
+
* - **A routable interface needs `--allow-non-loopback`**, because this
|
|
243
|
+
* process speaks plain HTTP and the secret arrives in a header.
|
|
244
|
+
*/
|
|
245
|
+
export type WebhookBind = {
|
|
246
|
+
ok: true;
|
|
247
|
+
host: string;
|
|
248
|
+
port: number;
|
|
249
|
+
} | {
|
|
250
|
+
ok: false;
|
|
251
|
+
message: string;
|
|
252
|
+
};
|
|
253
|
+
export declare function resolveWebhookBind(listenFlag: string | null, portFlag: string | null, allowNonLoopback: boolean): WebhookBind;
|
|
254
|
+
/**
|
|
255
|
+
* The banner a non-loopback bind prints, every time, on stderr.
|
|
256
|
+
*
|
|
257
|
+
* `cli/serve.ts`'s, with the one credential this surface has in place of that
|
|
258
|
+
* one's two. Reached only when the operator passed both `--listen` naming a
|
|
259
|
+
* routable interface and `--allow-non-loopback`, so it is not a warning about
|
|
260
|
+
* something that happened by accident.
|
|
261
|
+
*/
|
|
262
|
+
export declare function webhookNonLoopbackBanner(host: string, port: number): string;
|
|
263
|
+
/**
|
|
264
|
+
* Run the receiver until a signal stops it.
|
|
265
|
+
*
|
|
266
|
+
* The order is the one `cli/serve.ts` argues for, with one change that is this
|
|
267
|
+
* transport's own: everything that can refuse refuses first, and the LOCAL
|
|
268
|
+
* bind happens before `setWebhook`, so there is no window in which Telegram is
|
|
269
|
+
* posting to a port nothing is listening on.
|
|
270
|
+
*/
|
|
271
|
+
export declare function runWebhook(setup: WebhookSetup, streams: Streams): Promise<number>;
|
|
272
|
+
/** `approval channel telegram webhook [flags]`. */
|
|
273
|
+
export declare function commandTelegramWebhook(argv: string[], streams: Streams, cwd: string): Promise<number>;
|