@ai-ecoverse/wasi-ntfy 0.0.0 → 2.32.0-2
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/LICENSE +201 -0
- package/LICENSE.GPLv2 +340 -0
- package/README.md +125 -4
- package/THIRD-PARTY-NOTICES.md +849 -0
- package/bin/ntfy.wasm +0 -0
- package/host/ntfy-host.mjs +172 -0
- package/package.json +47 -4
package/README.md
CHANGED
|
@@ -1,9 +1,130 @@
|
|
|
1
1
|
# @ai-ecoverse/wasi-ntfy
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The [ntfy](https://ntfy.sh) 2.32.0 client as a WASI preview1 command for
|
|
4
|
+
SLICC: `ntfy`, with `ntfy publish` (`pub`) and `ntfy subscribe` (`sub`). It is
|
|
5
|
+
seven's replacement for six's webhooks. A webhook, a phone or another agent
|
|
6
|
+
publishes to a topic, and `ntfy sub <topic> '<command>'` runs the command in
|
|
7
|
+
seven for each message. The connection is outbound only, because a tab can't
|
|
8
|
+
listen. It works against [ntfy.sh](https://ntfy.sh), any ntfy server, and the
|
|
9
|
+
ntfy gateway at `https://ntfy.sliccy.ai` (ai-ecoverse/sliccy-ai, "The ntfy
|
|
10
|
+
gateway").
|
|
4
11
|
|
|
5
|
-
|
|
12
|
+
On `@ai-ecoverse/slicc-kernel` ≥ 1.125.4, `host/ntfy-host.mjs` (loaded through
|
|
13
|
+
`slicc.commands.ntfy.imports`) sends ntfy's HTTP requests through the kernel's
|
|
14
|
+
network (`net-request`, `net-read`) and starts the commands `ntfy sub` runs.
|
|
6
15
|
|
|
7
|
-
|
|
16
|
+
`bin/ntfy.wasm` is built by homescoop from ntfy's source (tag v2.32.0, commit
|
|
17
|
+
`9d0b6d9`). It uses Go 1.27.1 with `GOOS=wasip1 GOARCH=wasm CGO_ENABLED=0
|
|
18
|
+
-trimpath -tags noserver`, which is upstream's `make cli-client` build: the
|
|
19
|
+
client only, with no server, no SQLite and no web app. Two patches are
|
|
20
|
+
applied (see [Patches](#patches)), so this isn't an upstream ntfy release.
|
|
21
|
+
The build is reproducible.
|
|
8
22
|
|
|
9
|
-
|
|
23
|
+
## Seven usage
|
|
24
|
+
|
|
25
|
+
The gateway's owner mints a `tk_` token per consumer (`scopes`: `subscribe`,
|
|
26
|
+
`publish`, `hooks`; optional `topics`). Keep the token in the vault and pass
|
|
27
|
+
it as `NTFY_TOKEN` or `--token`. Prefer that over `?auth=`, which puts the
|
|
28
|
+
token in URLs.
|
|
29
|
+
|
|
30
|
+
Subscribe, and turn every message into a `webhook` lick for the cone:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
NTFY_TOKEN=tk_… ntfy sub https://ntfy.sliccy.ai/github \
|
|
34
|
+
'agent send cone --lick=webhook --source github "$NTFY_RAW"'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Publish (needs a token with `publish`):
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
NTFY_TOKEN=tk_… ntfy pub --title 'Build' https://ntfy.sliccy.ai/alerts 'deploy finished'
|
|
41
|
+
echo 'from stdin' | ntfy pub https://ntfy.sliccy.ai/alerts
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Poll once and exit, instead of streaming:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
ntfy sub --poll --since 10m https://ntfy.sliccy.ai/github
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or put the defaults in `~/.config/ntfy/client.yml`
|
|
51
|
+
(`$XDG_CONFIG_HOME/ntfy/client.yml` when that is set):
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
default-host: https://ntfy.sliccy.ai
|
|
55
|
+
default-token: tk_…
|
|
56
|
+
subscribe:
|
|
57
|
+
- topic: github
|
|
58
|
+
command: 'agent send cone --lick=webhook --source github "$NTFY_RAW"'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then use `ntfy pub alerts hi`, `ntfy sub github '<command>'`, or
|
|
62
|
+
`ntfy sub --from-config`. With `--from-config`, an auth error on any one
|
|
63
|
+
subscription ends the command.
|
|
64
|
+
|
|
65
|
+
The command runs as `sh -c '<command>'`, once per message, in order, one at a
|
|
66
|
+
time. Its stdin, stdout and stderr are ntfy's own. It gets ntfy's own
|
|
67
|
+
environment plus `NTFY_ID`, `NTFY_TIME`, `NTFY_TOPIC`, `NTFY_MESSAGE`,
|
|
68
|
+
`NTFY_TITLE`, `NTFY_PRIORITY`, `NTFY_TAGS` and `NTFY_RAW`, with upstream's
|
|
69
|
+
short aliases (`$m`, `$t`, `$raw`, …). `NTFY_RAW` is the message's JSON line
|
|
70
|
+
as the server sent it, so the fields the gateway adds (`headers`, `verified`,
|
|
71
|
+
`hook`, `attachment.url` for bodies it stores as attachments) reach the
|
|
72
|
+
command. `NTFY_TITLE`, `NTFY_MESSAGE`, `NTFY_TAGS`, `NTFY_PRIORITY` and
|
|
73
|
+
`NTFY_TOPIC` are also flags of `ntfy pub`, so a command that publishes again
|
|
74
|
+
should `unset ${!NTFY_*}` first. Otherwise its `ntfy pub` takes the incoming
|
|
75
|
+
message's topic and fields.
|
|
76
|
+
|
|
77
|
+
The command runs as the user who started `ntfy sub`, with that user's
|
|
78
|
+
privileges, files and environment. Treat everything in a message (`NTFY_*`)
|
|
79
|
+
as untrusted input: anyone who can publish to the topic, or post to a hook
|
|
80
|
+
URL of it, chooses those values. They arrive as data in the environment, so a
|
|
81
|
+
message's `$(…)` or backticks are not run unless the command itself `eval`s
|
|
82
|
+
them. Quote them (`"$NTFY_MESSAGE"`), and never paste them into a shell
|
|
83
|
+
command line. `--token` is not passed to the command's environment;
|
|
84
|
+
`NTFY_TOKEN` is, if you set it in ntfy's own.
|
|
85
|
+
|
|
86
|
+
## The gateway's contract
|
|
87
|
+
|
|
88
|
+
| The gateway | What the client does |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `tk_` tokens are scoped. A subscribe-only token's publish gets 403; no token or a forged one gets 401. | `ntfy pub` prints the server's error and exits 1 (upstream). `ntfy sub` exits 1 on 401 or 403 instead of retrying every 10 s (patched). |
|
|
91
|
+
| 429 with `retry-after: 60` past 10 claims a minute per IP, or 300 messages or deliveries a minute per home. | `ntfy sub` waits for the longer of `Retry-After` and its usual 10 s before it reconnects. `ntfy pub` waits `Retry-After` and sends the message (or the `--file` upload) again, at most twice. It fails at once, naming the wait, when the wait is over 5 minutes or the body can't be sent again (`--file -`) (patched). |
|
|
92
|
+
| At most 8 open streams per token. A subscriber more than 1 MiB behind is dropped. | After any drop, `ntfy sub` reconnects after 10 s with `since=<last message id>` and skips a repeat of that message, so nothing is lost or run twice. Before the first message it resumes from the time of the stream's `open` event (patched). A ninth stream is refused by the gateway; use one `ntfy sub` with several topics (`a,b`) or `--from-config`. |
|
|
93
|
+
| A JSON publish (`POST /`) is capped at 1 MiB. | The CLI never sends a JSON publish; it posts the message to `/<topic>`. A message over 1 MiB, from arguments, `--message` or stdin, is refused before any request (`message is over the 1 MiB limit (1048576 bytes); send it as an attachment with --file instead`). Upstream cut stdin at 1 MiB without a word (patched). `--file` uploads aren't capped by the client; the gateway takes bodies up to 25 MiB. |
|
|
94
|
+
| Message lines stay under 60 KiB; larger bodies become `attachment`s. | Lines up to 4 MiB are read (upstream: 64 KiB) (patched). |
|
|
95
|
+
| Revoking a token answers `{ revoked, hooks }` and ends its streams. | That's the owner's API, not the CLI's. A `ntfy sub` on the revoked token reconnects, gets 401 and exits 1. |
|
|
96
|
+
|
|
97
|
+
## Patches
|
|
98
|
+
|
|
99
|
+
- `0001-wasip1-slicc-host.patch`: the wasip1 build files upstream lacks
|
|
100
|
+
(`cmd/*_unix.go` and `client/config_unix.go` exclude wasip1), and
|
|
101
|
+
`slicchost`, which talks to `host/ntfy-host.mjs` through the `ntfy_host`
|
|
102
|
+
imports. `http.DefaultTransport` sends requests there and reads each
|
|
103
|
+
response chunk as it arrives. Before each blocking read it yields to the
|
|
104
|
+
other goroutines, so a message's command runs as soon as its line arrives,
|
|
105
|
+
not when the next one does (wasip1 Go has one thread, and a host call
|
|
106
|
+
blocks all of it). The `ntfy sub` command and `pub --wait-cmd` run through
|
|
107
|
+
the host's spawn. `--wait-pid` fails with a clear error.
|
|
108
|
+
- `0002-gateway-contract.patch`: resuming with `since=`, `Retry-After`, auth
|
|
109
|
+
errors ending `ntfy sub`, the 1 MiB refusal and the longer line limit
|
|
110
|
+
described above. Upstream's own reconnect waits 10 s and resubscribes with
|
|
111
|
+
the original options ("may lose messages").
|
|
112
|
+
|
|
113
|
+
## What does not work
|
|
114
|
+
|
|
115
|
+
- In a runtime without this host module, every request fails with
|
|
116
|
+
`this runtime cannot start commands or open network connections for ntfy (it needs slicc-kernel with @ai-ecoverse/wasi-ntfy's host module)`.
|
|
117
|
+
- `ntfy serve` and the server's admin commands (`user`, `access`, `token`,
|
|
118
|
+
`tier`, `webpush`): this is the client build.
|
|
119
|
+
- Desktop notifications. `ntfy sub` without a command prints each message's
|
|
120
|
+
JSON line, as upstream does on Linux.
|
|
121
|
+
- `ntfy pub --wait-pid`: there's no process table to watch.
|
|
122
|
+
- A password prompt (`--user name` without `:password`) needs a terminal.
|
|
123
|
+
Pass `--user name:password` or a token.
|
|
124
|
+
|
|
125
|
+
## Licence
|
|
126
|
+
|
|
127
|
+
ntfy is dual-licensed, Apache-2.0 or GPL-2.0-only, at your choice. This
|
|
128
|
+
package is distributed under both, like upstream (`LICENSE`, `LICENSE.GPLv2`).
|
|
129
|
+
Homescoop's patches are under the same terms. `THIRD-PARTY-NOTICES.md` lists
|
|
130
|
+
the Go runtime and every module `ntfy.wasm` links, with their licences.
|