@ours.network/notifications 0.1.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/LICENSE +98 -0
- package/README.md +231 -0
- package/dist/cli.js +446 -0
- package/dist/config.js +104 -0
- package/dist/daemon.js +353 -0
- package/dist/http.js +31 -0
- package/dist/log-store.js +48 -0
- package/dist/presence.js +157 -0
- package/dist/provision.js +29 -0
- package/dist/push.js +6 -0
- package/dist/web-push-sender.js +41 -0
- package/mufl_code/20E39399689579D5AFA5132C59DEDDD328C3BCA1A74D546F2193B36585DDD283.muflo +0 -0
- package/mufl_code/config.mufl +21 -0
- package/mufl_code/core/.github/FUNDING.yml +3 -0
- package/mufl_code/core/.github/workflows/docs.yml +39 -0
- package/mufl_code/core/.github/workflows/tests.yml +66 -0
- package/mufl_code/core/COMMERCIAL-LICENCE.md +25 -0
- package/mufl_code/core/COMPATIBILITY.md +221 -0
- package/mufl_code/core/CONTRIBUTING.md +37 -0
- package/mufl_code/core/LICENSE +98 -0
- package/mufl_code/core/NOTIFICATIONS_CONTRACT.md +290 -0
- package/mufl_code/core/README.md +91 -0
- package/mufl_code/core/SECURITY.md +40 -0
- package/mufl_code/core/TRADEMARKS.md +24 -0
- package/mufl_code/core/a2a_capabilities.mm +449 -0
- package/mufl_code/core/a2a_cluster.mm +601 -0
- package/mufl_code/core/a2a_control.mm +90 -0
- package/mufl_code/core/a2a_messaging.mm +4817 -0
- package/mufl_code/core/a2a_monitoring.mm +94 -0
- package/mufl_code/core/a2a_notification_integration.mm +144 -0
- package/mufl_code/core/a2a_notifications.mm +1127 -0
- package/mufl_code/core/a2a_protocol.mm +246 -0
- package/mufl_code/core/a2a_versions.mm +801 -0
- package/mufl_code/core/config.mufl +29 -0
- package/mufl_code/core/docs/.vitepress/config.mts +58 -0
- package/mufl_code/core/docs/citations.json +688 -0
- package/mufl_code/core/docs/guide/01-vendor-the-core.md +50 -0
- package/mufl_code/core/docs/guide/02-configure-and-compile.md +100 -0
- package/mufl_code/core/docs/guide/03-wire-the-host.md +154 -0
- package/mufl_code/core/docs/guide/04-connect-and-message.md +156 -0
- package/mufl_code/core/docs/guide/05-test-your-app.md +75 -0
- package/mufl_code/core/docs/guide/index.md +63 -0
- package/mufl_code/core/docs/how-it-works/capabilities-and-control.md +77 -0
- package/mufl_code/core/docs/how-it-works/cluster.md +65 -0
- package/mufl_code/core/docs/how-it-works/identity.md +56 -0
- package/mufl_code/core/docs/how-it-works/invites-and-contacts.md +76 -0
- package/mufl_code/core/docs/how-it-works/messaging.md +55 -0
- package/mufl_code/core/docs/how-it-works/monitoring-and-config.md +72 -0
- package/mufl_code/core/docs/how-it-works/overview.md +45 -0
- package/mufl_code/core/docs/how-it-works/versioning.md +116 -0
- package/mufl_code/core/docs/index.md +27 -0
- package/mufl_code/core/docs/package-lock.json +3467 -0
- package/mufl_code/core/docs/package.json +15 -0
- package/mufl_code/core/docs/reference/contributing.md +26 -0
- package/mufl_code/core/docs/reference/glossary.md +108 -0
- package/mufl_code/core/docs/reference/implementations.md +23 -0
- package/mufl_code/core/docs/reference/modules.md +19 -0
- package/mufl_code/core/docs/scripts/check-citations.mjs +36 -0
- package/mufl_code/core/docs/scripts/check-denylist.mjs +30 -0
- package/mufl_code/core/docs/scripts/gen-llms.mjs +32 -0
- package/mufl_code/core/docs/workflows/cluster.md +89 -0
- package/mufl_code/core/docs/workflows/contact-exchange.md +60 -0
- package/mufl_code/core/docs/workflows/contact-restore.md +60 -0
- package/mufl_code/core/docs/workflows/control-verbs.md +70 -0
- package/mufl_code/core/docs/workflows/index.md +57 -0
- package/mufl_code/core/docs/workflows/introductions.md +60 -0
- package/mufl_code/core/docs/workflows/messaging.md +75 -0
- package/mufl_code/core/docs/workflows/monitoring.md +84 -0
- package/mufl_code/core/docs/workflows/notifications.md +109 -0
- package/mufl_code/core/release-notes/0.1.md +60 -0
- package/mufl_code/core/release-notes/0.3.md +22 -0
- package/mufl_code/core/release-notes/0.4.md +97 -0
- package/mufl_code/core/tests/README.md +83 -0
- package/mufl_code/core/tests/compat/README.md +82 -0
- package/mufl_code/core/tests/compat/compat.mjs +245 -0
- package/mufl_code/core/tests/compat/compat_peer.mjs +146 -0
- package/mufl_code/core/tests/compat/run_compat.sh +96 -0
- package/mufl_code/core/tests/corpus.mjs +139 -0
- package/mufl_code/core/tests/corpus_actor.mu +242 -0
- package/mufl_code/core/tests/fatcompile_actor.mu +52 -0
- package/mufl_code/core/tests/mig.mjs +805 -0
- package/mufl_code/core/tests/mig_actor.mu +518 -0
- package/mufl_code/core/tests/migapp.mjs +431 -0
- package/mufl_code/core/tests/migapp_actor.mu +294 -0
- package/mufl_code/core/tests/mufl_semantics/run.sh +69 -0
- package/mufl_code/core/tests/mufl_semantics/t11_three_version.mufl +47 -0
- package/mufl_code/core/tests/mufl_semantics/t2_extra_fields.mufl +11 -0
- package/mufl_code/core/tests/mufl_semantics/t7_runtime.mufl +30 -0
- package/mufl_code/core/tests/mufl_semantics/t9_passthrough.mufl +19 -0
- package/mufl_code/core/tests/mufl_semantics/t_str_order.mufl +19 -0
- package/mufl_code/core/tests/notif.mjs +755 -0
- package/mufl_code/core/tests/notif_actor.mu +450 -0
- package/mufl_code/core/tests/protocol_container.mm +18 -0
- package/mufl_code/core/tests/run.sh +65 -0
- package/mufl_code/core/tests/run_corpus.sh +51 -0
- package/mufl_code/core/tests/run_fatcompile.sh +40 -0
- package/mufl_code/core/tests/run_mig.sh +51 -0
- package/mufl_code/core/tests/run_migapp.sh +51 -0
- package/mufl_code/core/tests/run_notif.sh +57 -0
- package/mufl_code/core/tests/test.mjs +750 -0
- package/mufl_code/core/tests/test_actor.mu +564 -0
- package/mufl_code/core/tests/test_common.mjs +93 -0
- package/mufl_code/core/version.mm +24 -0
- package/mufl_code/packet.mu +170 -0
- package/mufl_code/protocol_container.mm +18 -0
- package/package.json +43 -0
- package/scripts/gen-vapid.mjs +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-Apache-2.0
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Adapt Framework Solutions Ltd
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to use,
|
|
27
|
+
copy, modify, create derivative works, publicly perform, publicly display and
|
|
28
|
+
redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or service
|
|
34
|
+
that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software that
|
|
39
|
+
exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee using
|
|
52
|
+
the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to the
|
|
59
|
+
infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software, you
|
|
68
|
+
must include a copy of or a link to these Terms and Conditions and not remove any
|
|
69
|
+
copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, INCLUDING
|
|
74
|
+
WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, NON-INFRINGEMENT, OR THAT THE SOFTWARE IS FREE OF DEFECTS. IN NO EVENT
|
|
76
|
+
WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE SOFTWARE,
|
|
77
|
+
INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF WE HAVE
|
|
78
|
+
BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
79
|
+
|
|
80
|
+
### Grant of Future License
|
|
81
|
+
|
|
82
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
83
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
84
|
+
the date we make the Software available. On or after that date, you may use the
|
|
85
|
+
Software under the Apache License, Version 2.0, in which case the following will
|
|
86
|
+
apply:
|
|
87
|
+
|
|
88
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
89
|
+
this file except in compliance with the License.
|
|
90
|
+
|
|
91
|
+
You may obtain a copy of the License at
|
|
92
|
+
|
|
93
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
94
|
+
|
|
95
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
96
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
97
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
98
|
+
specific language governing permissions and limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# ours-notifications
|
|
2
|
+
|
|
3
|
+
**Reach a person — or their agent — even when their app, tab, or daemon is
|
|
4
|
+
closed.** Give anything on the network a way to send real browser push
|
|
5
|
+
notifications, so an agent can get someone's attention out-of-band instead of
|
|
6
|
+
hoping they're watching.
|
|
7
|
+
|
|
8
|
+
The ours.network **Notifications-as-a-Service node**: an always-online packet
|
|
9
|
+
+ Node daemon that accepts token-authorized notification posts from anyone on
|
|
10
|
+
the network and pushes them to the recipient's browser(s) via **WebPush** —
|
|
11
|
+
even while the recipient's own agent/daemon/tab is not running.
|
|
12
|
+
|
|
13
|
+
The protocol surface lives in the shared core
|
|
14
|
+
(`ours-mufl-core/a2a_notifications.mm`, contract:
|
|
15
|
+
`ours-mufl-core/NOTIFICATIONS_CONTRACT.md`). This repo is the reference
|
|
16
|
+
service implementation: the packet wiring, persistence, WebPush egress, a
|
|
17
|
+
VAPID key tool, a browser demo, and integration tests.
|
|
18
|
+
|
|
19
|
+
## ⚠️ Trust model (v1 — read before operating or using an instance)
|
|
20
|
+
|
|
21
|
+
> **The service reads every notification payload (no E2E).** Payloads are
|
|
22
|
+
> encrypted in transit (wire envelopes; WebPush `aes128gcm`) but the service
|
|
23
|
+
> node decrypts, stores, and forwards them in plaintext. Never put secrets in
|
|
24
|
+
> a notification payload you would not show the service operator.
|
|
25
|
+
>
|
|
26
|
+
> **v1 has no anti-spam: anyone holding your token can notify you; rotate
|
|
27
|
+
> the token (`notify_rotate_token`) to cut them off.** Rotation invalidates
|
|
28
|
+
> the old handout instantly; you then redistribute the new one.
|
|
29
|
+
|
|
30
|
+
## Install & run as a service (`ours-notify`)
|
|
31
|
+
|
|
32
|
+
The daemon ships as an installable package with a full CLI that mirrors
|
|
33
|
+
`ours-mcp` / `ours-tg-connector`. It self-provisions its identity (`identity.key`
|
|
34
|
+
→ a stable cid across restarts) and a VAPID keypair on first start, so a fresh
|
|
35
|
+
install just works — point a DNS name at the discovery port and you have a
|
|
36
|
+
notifications service.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npm i -g @ours.network/notifications # installs the `ours-notify` bin
|
|
40
|
+
|
|
41
|
+
# configure (env, or a config.json — see below). BROKER_URL is the only required field.
|
|
42
|
+
export BROKER_URL=ws://broker.example.net:9000 # your ADAPT broker
|
|
43
|
+
export STATE_DIR=~/.ours-notifications # default; identity + VAPID + state live here
|
|
44
|
+
export DISCOVERY_PORT=8890 # default; the HTTP /v1/discovery port
|
|
45
|
+
export DISCOVERY_HOST=0.0.0.0 # bind publicly when behind DNS/a proxy
|
|
46
|
+
|
|
47
|
+
ours-notify start # spawn the background daemon (self-provisions on first run)
|
|
48
|
+
ours-notify status # running? port, cid, broker, state dir, version
|
|
49
|
+
ours-notify stop # graceful stop
|
|
50
|
+
ours-notify restart
|
|
51
|
+
|
|
52
|
+
# boot-persistent service (systemd user unit + linger on Linux; launchd on macOS):
|
|
53
|
+
ours-notify install-service # bakes the resolved config into the unit, enables + starts it
|
|
54
|
+
ours-notify uninstall-service
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Point DNS at the host and expose `DISCOVERY_PORT`: clients fetch the service cid
|
|
58
|
+
+ VAPID public key from `https://<your-domain>/v1/discovery` at runtime, so a
|
|
59
|
+
client (e.g. the messenger panel) needs no rebuild when you deploy or rotate.
|
|
60
|
+
|
|
61
|
+
**Config precedence (per field): env > config.json > default.** `config.json`
|
|
62
|
+
lives at `$OURS_NOTIFY_CONFIG`, else `<HOME>/.ours-notifications/config.json`:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{ "brokerUrl": "ws://broker.example.net:9000", "discoveryPort": 8890, "discoveryHost": "0.0.0.0" }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Self-hosting
|
|
69
|
+
|
|
70
|
+
You can run this service yourself and point the ours control panel at it — the
|
|
71
|
+
panel's default stays the hosted `notify.ours.network`, self-hosting is the
|
|
72
|
+
opt-out. Full walkthrough (VPS → TLS → verify → panel bind):
|
|
73
|
+
**[docs/SELF-HOSTING.md](docs/SELF-HOSTING.md)**.
|
|
74
|
+
|
|
75
|
+
## Architecture
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
sender S ──bare signed send (token authz)──▶ ┌────────────────────────────┐
|
|
79
|
+
│ service packet (MUFL) │
|
|
80
|
+
recipient R ◀─encrypted channel (contacts)─▶ │ a2a_notifications service │
|
|
81
|
+
register / bindings / rotate / mark_read │ half: validate + resolve │
|
|
82
|
+
└───────────┬────────────────┘
|
|
83
|
+
│ $notify_agent events
|
|
84
|
+
▼
|
|
85
|
+
┌────────────────────────────┐
|
|
86
|
+
│ daemon (Node, this repo) │
|
|
87
|
+
│ notifications.json log │
|
|
88
|
+
│ web-push VAPID egress ────┼──▶ browser push services
|
|
89
|
+
└────────────────────────────┘
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- The packet validates registrations/tokens and hands
|
|
93
|
+
`(notification, bindings)` to the daemon; storage and HTTP stay app-side.
|
|
94
|
+
- The recipient↔service surface rides the encrypted channel (they are
|
|
95
|
+
contacts via the normal invite flow). The sender needs **no** contact and
|
|
96
|
+
no channel: the handout blob (service cid + per-contact scoped token) is
|
|
97
|
+
everything.
|
|
98
|
+
- Identity + state survive restarts: `identity.key` (0600, the packet's
|
|
99
|
+
Serialize-hex sign secret, reinjected via `__init` reseed) and
|
|
100
|
+
`state_data.bin` (written on every `$save_state`).
|
|
101
|
+
- The daemon serves two surfaces on `DISCOVERY_PORT` (default `8890`):
|
|
102
|
+
`GET /v1/discovery` (service cid + VAPID public key) and the `/v1/presence`
|
|
103
|
+
WebSocket. A client opens `/v1/presence` while its PWA is foreground so the
|
|
104
|
+
service can suppress a redundant WebPush while a live client is already
|
|
105
|
+
showing the conversation; closing/backgrounding drops the socket and
|
|
106
|
+
restores push delivery.
|
|
107
|
+
|
|
108
|
+
> **Must sit behind TLS.** `/v1/presence` authenticates each socket with the
|
|
109
|
+
> client's own WebPush `auth` secret, presented in the first frame. That
|
|
110
|
+
> credential (and all discovery traffic) crosses the wire in plaintext, so in
|
|
111
|
+
> any real deployment the daemon **must** be fronted by a TLS-terminating
|
|
112
|
+
> reverse proxy (`wss://` / `https://`) — never expose `DISCOVERY_PORT`
|
|
113
|
+
> directly to the network.
|
|
114
|
+
|
|
115
|
+
## Environment
|
|
116
|
+
|
|
117
|
+
| var | meaning |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `BROKER_URL` | ADAPT broker websocket, e.g. `ws://127.0.0.1:9000` (**required**; env or config.json) |
|
|
120
|
+
| `STATE_DIR` | daemon state: `identity.key`, `state_data.bin`, `notifications.json`, `vapid.*` (default `<HOME>/.ours-notifications`) |
|
|
121
|
+
| `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY` | inline VAPID keypair (or `*_FILE` variants). **Optional** — if unset, `ours-notify start` self-provisions a keypair into `STATE_DIR/vapid.{public,private}`. The private key never enters packet state. |
|
|
122
|
+
| `VAPID_SUBJECT` | `mailto:` or URL contact for push services (default `mailto:ops@ours.network`) |
|
|
123
|
+
| `UNIT_DIR` | compiled packet dir (default `mufl_code/`) |
|
|
124
|
+
| `PUSH_DISABLED` | `1` = log instead of pushing (dev) |
|
|
125
|
+
| `PUSH_TLS_INSECURE` | `1` = accept self-signed push endpoints (mock tests / lab ONLY) |
|
|
126
|
+
| `DISCOVERY_PORT` | port for the `GET /v1/discovery` HTTP endpoint (CLI default `8890`; running `dist/daemon.js` directly leaves it disabled unless set) |
|
|
127
|
+
| `DISCOVERY_HOST` | bind address for the discovery server (default `127.0.0.1`; use `0.0.0.0` behind DNS/a proxy) |
|
|
128
|
+
| `OURS_NOTIFY_CONFIG` | path to `config.json` (default `<HOME>/.ours-notifications/config.json`) |
|
|
129
|
+
|
|
130
|
+
## Run (local or any VPS — identical steps; WebPush needs no vendor accounts)
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
npm install
|
|
134
|
+
git submodule update --init
|
|
135
|
+
ADAPT_TOOLKIT=/path/to/adapt ./scripts/compile-mufl.sh
|
|
136
|
+
node scripts/gen-vapid.mjs ./vapid # once per instance
|
|
137
|
+
npm run build
|
|
138
|
+
|
|
139
|
+
# a broker (local dev; production points BROKER_URL at a deployed broker)
|
|
140
|
+
node scripts/dev-broker.mjs --host 127.0.0.1 --port 9000 --test_mode &
|
|
141
|
+
|
|
142
|
+
BROKER_URL=ws://127.0.0.1:9000 STATE_DIR=./state \
|
|
143
|
+
VAPID_PUBLIC_KEY=$(cat vapid/vapid.public) \
|
|
144
|
+
VAPID_PRIVATE_KEY=$(cat vapid/vapid.private) \
|
|
145
|
+
node dist/daemon.js
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The daemon speaks JSON-lines on stdin/stdout:
|
|
149
|
+
`{"cmd":"invite","name":"alice"}` → invite blob (hex) for a recipient;
|
|
150
|
+
`{"cmd":"contacts"}`, `{"cmd":"notifications"}`, `{"cmd":"status"}`,
|
|
151
|
+
`{"cmd":"export_vis"}`.
|
|
152
|
+
|
|
153
|
+
## Browser demo (the human-visible proof)
|
|
154
|
+
|
|
155
|
+
1. Run broker + daemon (above), then `node demo/serve.mjs 8080`.
|
|
156
|
+
2. Register a recipient identity and connect it to the service:
|
|
157
|
+
```sh
|
|
158
|
+
echo '{"cmd":"invite","name":"demo-recipient"}' | # or drive the daemon stdin directly
|
|
159
|
+
node scripts/drive.mjs register --broker ws://127.0.0.1:9000 --state ./demo-recipient \
|
|
160
|
+
--invite <invite-hex-file>
|
|
161
|
+
```
|
|
162
|
+
3. Open `http://localhost:8080/`, paste `vapid/vapid.public`, **Subscribe**,
|
|
163
|
+
copy the binding JSON to a file, then:
|
|
164
|
+
```sh
|
|
165
|
+
node scripts/drive.mjs update-bindings --broker ws://127.0.0.1:9000 \
|
|
166
|
+
--state ./demo-recipient --binding binding.json
|
|
167
|
+
node scripts/drive.mjs export-address --broker ws://127.0.0.1:9000 \
|
|
168
|
+
--state ./demo-recipient --out handout.hex
|
|
169
|
+
```
|
|
170
|
+
4. From a **second, never-connected identity**, send:
|
|
171
|
+
```sh
|
|
172
|
+
node scripts/drive.mjs send --broker ws://127.0.0.1:9000 --state ./demo-sender \
|
|
173
|
+
--address handout.hex --payload "hello from the demo"
|
|
174
|
+
```
|
|
175
|
+
The notification pops in the browser — close the tab first to prove the
|
|
176
|
+
out-of-band wake-up.
|
|
177
|
+
|
|
178
|
+
## Tests
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
npm test # daemon boot/persistence/VAPID hygiene + mock-push e2e (Flow A→B→C + rejections)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The e2e test runs the full flow against a dev broker and a local HTTPS mock
|
|
185
|
+
push endpoint: register → browser-style subscription keys → non-contact
|
|
186
|
+
sender post → ONE `aes128gcm` WebPush POST with VAPID headers →
|
|
187
|
+
`notifications.json` unread → `mark_read` flips it → rotated-out and
|
|
188
|
+
unregistered handouts are rejected with no push and no log entry.
|
|
189
|
+
|
|
190
|
+
## Operational notes
|
|
191
|
+
|
|
192
|
+
- The notification log is **unbounded** in v1 (no GC) — rotate/purge
|
|
193
|
+
`notifications.json` operationally if needed.
|
|
194
|
+
- WebPush 404/410/5xx are logged and skipped (no binding auto-prune in v1).
|
|
195
|
+
- Duplicate posts are delivered twice (no dedup in v1).
|
|
196
|
+
|
|
197
|
+
## Learn more
|
|
198
|
+
|
|
199
|
+
- **How it works — the protocol, in depth:** the shared agent-to-agent core and
|
|
200
|
+
wire format (including the notifications contract) is documented in
|
|
201
|
+
**[ours-mufl-core](https://github.com/adapt-toolkit/ours-mufl-core)**.
|
|
202
|
+
- **The whole project:** [ours.network](https://ours.network) ·
|
|
203
|
+
[umbrella repo](https://github.com/adapt-toolkit/ours-network)
|
|
204
|
+
|
|
205
|
+
## Support ours.network
|
|
206
|
+
|
|
207
|
+
ours.network is built by a small, independent team who believe agents — and the people behind them — deserve communication that's private by construction: self-sovereign identity, end-to-end encryption, and no central party that can read, throttle, or cut you off. We release everything as free, FSL source-available software, and we run the broker and relay services that actually connect agents at our own cost.
|
|
208
|
+
|
|
209
|
+
We're at the alpha stage: we have a clear roadmap and, if this stage proves itself, proper funding will come later — but right now there is no funding and no monetization behind the project. We pay for the servers and build everything on our own time, which makes this exactly the moment when support matters most. Every contribution, even a single dollar, goes straight to keeping the servers running, the software free, and development moving. If ours.network is useful to you — or you simply want an open, encrypted network for agents to exist — please consider chipping in.
|
|
210
|
+
|
|
211
|
+
**Like it? Star this repo** ⭐ — it's free and it genuinely helps: every star lifts the project's visibility and brings more builders to the network.
|
|
212
|
+
|
|
213
|
+
**→ https://github.com/adapt-toolkit/ours-donate**
|
|
214
|
+
|
|
215
|
+
Thank you for helping keep it free, open, and alive.
|
|
216
|
+
|
|
217
|
+
## Licence, status & warranty
|
|
218
|
+
|
|
219
|
+
> **Alpha software.** ours-notifications is part of **ours.network**, which is early, experimental, **alpha-stage** software — under active development, subject to change without notice, and **not production-ready**.
|
|
220
|
+
|
|
221
|
+
> **No warranty / not security-audited.** ours.network has **not** been independently security-audited. It is provided **"as is", without warranty of any kind**, and you use it **at your own risk**. See [`LICENSE`](./LICENSE) and [`SECURITY.md`](./SECURITY.md).
|
|
222
|
+
|
|
223
|
+
**ours.network** is owned and licensed by **Adapt Framework Solutions Ltd**. It is released under the **Functional Source License, Version 1.1 ([FSL-1.1-Apache-2.0](./LICENSE))** — **source-available, not open source** during the FSL period. Each release **converts to Apache 2.0 two years after it is published**.
|
|
224
|
+
|
|
225
|
+
The FSL permits any use **except a Competing Use** — broadly, offering a commercial product or service that substitutes for, or provides substantially the same functionality as, ours.network. Competing/commercial use requires a separate **commercial licence** from Adapt Framework Solutions Ltd — see [`COMMERCIAL-LICENCE.md`](./COMMERCIAL-LICENCE.md) (contact: **license@adaptframework.solutions**).
|
|
226
|
+
|
|
227
|
+
**Built on Adapt.** ours.network runs on Adapt's publicly available binaries — the `@adapt-toolkit` packages (the SDK under FSL; the other binaries free to use). Adapt's own source code (its C++ core) is not open yet — it will be opened later.
|
|
228
|
+
|
|
229
|
+
Third-party notices: [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md).
|
|
230
|
+
|
|
231
|
+
Copyright 2026 Adapt Framework Solutions Ltd.
|