@uuaid/pillar 0.2.0-alpha.10 → 0.2.0-alpha.12

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 CHANGED
@@ -77,13 +77,66 @@ to build a private mesh.
77
77
  |---|---|---|
78
78
  | `pillar-responder` | Always-on auto-attendant: acks requests instantly, replies from fixed text or a command hook. Run it as a service; agents anywhere get ack+reply without you being live. | one process, outbound HTTPS |
79
79
  | `pillar-seed` | A carrier seed — makes you part of the p2p mesh. Any agent that lists your URL replicates every envelope to you and polls you in parallel with other seeds. | one process, one SQLite file, TLS-terminating proxy in front |
80
- | `pillar` | The full CLI (`init`, `id`, `send`, `send-group`, `recv`, `inbox`, `peers`) — optional libp2p DHT, or carrier-only. | only when used interactively |
80
+ | `pillar` | The full CLI (`init`, `id`, `send`, `send-group`, `recv`, `inbox`, `trust`, `tier`, `peers`) — optional libp2p DHT, or carrier-only. | only when used interactively |
81
81
 
82
82
  ```sh
83
83
  pillar-responder --home ~/.pillar-responder --reply-text "ack" &
84
84
  pillar-seed --port 8799 --db /var/lib/pillar/seed.db & # loopback by default
85
85
  ```
86
86
 
87
+ ## Abuse resistance — consent at the edge, budgets at the carrier
88
+
89
+ Identity is unforgeable (the sender derives from the signing key), the
90
+ carrier is rate-limited and payload-blind, and **consent lives with the
91
+ recipient**:
92
+
93
+ ```sh
94
+ pillar trust set directory # only address-book senders reach handlers
95
+ pillar trust allow uuaid:... # enroll a specific sender (any policy)
96
+ pillar trust block uuaid:... # never deliver (stored as quarantined evidence)
97
+ pillar trust quarantine # inspect gated mail; --release ID to accept one
98
+ ```
99
+
100
+ Policies: `open` (default — today's behavior), `directory` (address-book
101
+ senders only), `allowlist` (explicit allow list only). Gated mail is
102
+ **quarantined, never dropped** — it stays in the chain-hashed mailbox with a
103
+ reason, invisible to handlers. Genuine `ack`/`reply` receipts for your own
104
+ outbox always pass. `pillar-responder` defaults its command hook to the
105
+ `directory` policy: strangers still get ack + a fixed reply (first contact
106
+ keeps working), but their payload never reaches your hook process; per-sender
107
+ reply rate is capped.
108
+
109
+ ## Tier grants — qualified volume for foundations, orgs, enterprises
110
+
111
+ Default (community) carrier budgets: 120 envelopes/min per sender, 512 KiB
112
+ per envelope. Organizations that qualify through the UUAID Foundation's
113
+ review receive a **signed tier grant** — a portable JSON credential
114
+ (Ed25519, expiry-bound, offline-verifiable) that raises their budgets at any
115
+ carrier that trusts the issuer:
116
+
117
+ | Tier | Envelopes/min | Max body |
118
+ |---|---|---|
119
+ | community (default, no grant) | 120 | 512 KiB |
120
+ | supporter | 300 | 1 MiB |
121
+ | org | 600 | 2 MiB |
122
+ | enterprise | 1200 | 2 MiB |
123
+ | foundation | 3000 | 2 MiB |
124
+
125
+ ```sh
126
+ # Issuer (e.g. the foundation identity) signs a grant:
127
+ pillar tier issue uuaid:foundation:agent:... org --expires 2027-01-01T00:00:00Z
128
+ # Grantee installs it (auto-attached to every carrier deliver):
129
+ pillar tier install tier-grant-<fp>.json
130
+ # Carrier operator opts in:
131
+ pillar-carrier --tier-issuers <issuer-pubkey-hex>
132
+ ```
133
+
134
+ Grants are verified locally (signature + expiry + ceiling clamp) — no
135
+ registry lookup, no account, consistent with the self-authenticating design.
136
+ An invalid or foreign grant silently falls back to community budgets; it can
137
+ never break plain delivery. Wire format unchanged: the grant rides an HTTP
138
+ header (`x-pillar-tier-grant`), not the envelope.
139
+
87
140
  ## Seed topology — how messages survive
88
141
 
89
142
  On send, `deliver()` replicates the envelope to **every** carrier in your set
package/bin/carrier.mjs CHANGED
@@ -29,12 +29,17 @@ const port = Number(args.port ?? process.env.CARRIER_PORT ?? 8799);
29
29
  const host = args.host ?? process.env.CARRIER_HOST ?? "127.0.0.1";
30
30
  const dbPath = args.db ?? process.env.CARRIER_DB ?? "carrier.db";
31
31
  const ttlDays = Number(args.ttl ?? process.env.CARRIER_TTL_DAYS ?? 14);
32
+ // Tier grants: comma-separated issuer pubkeys (hex) whose signed grants this
33
+ // carrier honors for raised budgets. Unset = all senders get community tier.
34
+ const tierIssuers = String(args["tier-issuers"] ?? process.env.CARRIER_TIER_ISSUERS ?? "")
35
+ .split(",").map(s => s.trim()).filter(s => /^[0-9a-f]{64}$/i.test(s));
32
36
 
33
- const server = new CarrierServer({ dbPath, ttlDays });
37
+ const server = new CarrierServer({ dbPath, ttlDays, trustedTierIssuers: tierIssuers });
34
38
  const addr = await server.listen(port, host);
35
39
  console.log(`carrier listening on ${addr.address}:${addr.port}`);
36
40
  console.log(` db: ${dbPath}`);
37
41
  console.log(` ttl: ${ttlDays} days`);
42
+ console.log(` tiers: ${tierIssuers.length ? `${tierIssuers.length} trusted issuer(s)` : "disabled (community budgets for all)"}`);
38
43
 
39
44
  // Vacuum expired envelopes hourly.
40
45
  const vacuumTimer = setInterval(() => {