@estiva-app/protocol 0.4.0 → 0.5.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/CHANGELOG.md +45 -0
- package/dist/bridge.d.ts +12 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +44 -0
- package/dist/bridge.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/bridge.ts +44 -0
- package/src/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,51 @@ Every entry answers the wire question explicitly, including when the answer is
|
|
|
4
4
|
nothing (ADR 0002 §4b). A change to the bytes an app publishes is a MAJOR — in
|
|
5
5
|
`0.x`, a MINOR — even when no TypeScript signature moved.
|
|
6
6
|
|
|
7
|
+
## 0.5.0 — 2026-09-01
|
|
8
|
+
|
|
9
|
+
**Wire behaviour: unchanged.** No builder, tag layout, id computation or
|
|
10
|
+
signature input moved. `queryAll` returns the same events; it asks for them in
|
|
11
|
+
half as many requests.
|
|
12
|
+
|
|
13
|
+
- **A short page no longer always costs a confirming round trip.** `queryAll`
|
|
14
|
+
spent two requests on every filter, including one holding three events, and
|
|
15
|
+
on Ship's `loadAll` that doubling was **33 filters → 66 requests** against a
|
|
16
|
+
relay that meters `POST /query` at 300 a minute.
|
|
17
|
+
|
|
18
|
+
The confirmation existed for a real reason: a page shorter than the requested
|
|
19
|
+
`limit` is ambiguous, because the relay clamps to `min(requested, ceiling)`
|
|
20
|
+
and may have clamped at exactly that many. The ambiguity dissolves
|
|
21
|
+
arithmetically rather than by trusting anyone — a clamp at `n` requires the
|
|
22
|
+
ceiling to *equal* `n`, the ceiling is one constant for the relay, and the
|
|
23
|
+
largest page it has already handed back is a lower bound on it. So
|
|
24
|
+
`n < observedPageCeiling` rules the clamp out on evidence the relay itself
|
|
25
|
+
produced.
|
|
26
|
+
|
|
27
|
+
**Deliberately not NIP-11's `limitation.max_limit`.** That number is a claim,
|
|
28
|
+
and a relay advertising more than it clamps to would make every page look
|
|
29
|
+
short and the first one get mistaken for the whole set — the SHA-8 bug, back.
|
|
30
|
+
Buzz currently advertises 1000 and clamps at 1000, so trusting it would work
|
|
31
|
+
today; the source default in `nip11.rs` is 10000 against a `buzz-db` clamp of
|
|
32
|
+
1000, so it has not always been true, and being right by luck is not a
|
|
33
|
+
design. Substituting a trusted 1000 for the observed bound fails the SHA-8
|
|
34
|
+
regression test outright, which is the control that settles it.
|
|
35
|
+
|
|
36
|
+
Conservative before it has evidence: the first filter through a fresh `Relay`
|
|
37
|
+
still confirms, and so does the **widest** filter on every read, since it
|
|
38
|
+
ties its own bound. The floor is therefore one request per filter *plus one*.
|
|
39
|
+
|
|
40
|
+
Measured on Ship's `loadAll` against production, published client versus this
|
|
41
|
+
one: **66 requests → 35 cold, 34 warm — 48% fewer — 8.8 s → 0.9 s, and the
|
|
42
|
+
fold compares equal event for event** (every project and issue address with
|
|
43
|
+
its status, every change id, every conversation id).
|
|
44
|
+
|
|
45
|
+
- **This still does not fit a five-second poll.** 34 requests × 12 reads a
|
|
46
|
+
minute is 408 against a 300 budget; at a ten-second poll it is 204 and fits.
|
|
47
|
+
The remaining half is the caller's cadence, not this package's.
|
|
48
|
+
|
|
49
|
+
Additive with no signature change, but the request pattern a caller produces
|
|
50
|
+
changes, so a MINOR: ADR 0002 §4b puts the break on MINOR within `0.x`.
|
|
51
|
+
|
|
7
52
|
## 0.4.0 — 2026-09-01
|
|
8
53
|
|
|
9
54
|
**Wire behaviour: unchanged.** No builder, tag layout, id computation or
|
package/dist/bridge.d.ts
CHANGED
|
@@ -137,6 +137,18 @@ export declare class Relay {
|
|
|
137
137
|
private readonly signer;
|
|
138
138
|
private readonly headers;
|
|
139
139
|
private readonly transport;
|
|
140
|
+
/**
|
|
141
|
+
* The largest page this relay has ever handed back, across every call.
|
|
142
|
+
*
|
|
143
|
+
* A *lower bound* on the relay's real clamp, and the only one obtainable
|
|
144
|
+
* without trusting anybody: the relay returned this many events in one
|
|
145
|
+
* response, so its ceiling is at least this large. {@link Relay.pageFilter}
|
|
146
|
+
* uses it to tell a short page apart from a clamped one — see there.
|
|
147
|
+
*
|
|
148
|
+
* Per instance and never reset, so the second read through a long-lived
|
|
149
|
+
* `Relay` is cheaper than the first.
|
|
150
|
+
*/
|
|
151
|
+
private observedPageCeiling;
|
|
140
152
|
constructor(url: string, signer: Signer, options?: RelayOptions | RelayHeaders);
|
|
141
153
|
private post;
|
|
142
154
|
publish(event: SignedEvent): Promise<PublishResult>;
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAehF;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAgB5E;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KACpE,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAAA;AAKzD,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAEzF,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge.js
CHANGED
|
@@ -136,6 +136,18 @@ export class Relay {
|
|
|
136
136
|
signer;
|
|
137
137
|
headers;
|
|
138
138
|
transport;
|
|
139
|
+
/**
|
|
140
|
+
* The largest page this relay has ever handed back, across every call.
|
|
141
|
+
*
|
|
142
|
+
* A *lower bound* on the relay's real clamp, and the only one obtainable
|
|
143
|
+
* without trusting anybody: the relay returned this many events in one
|
|
144
|
+
* response, so its ceiling is at least this large. {@link Relay.pageFilter}
|
|
145
|
+
* uses it to tell a short page apart from a clamped one — see there.
|
|
146
|
+
*
|
|
147
|
+
* Per instance and never reset, so the second read through a long-lived
|
|
148
|
+
* `Relay` is cheaper than the first.
|
|
149
|
+
*/
|
|
150
|
+
observedPageCeiling = 0;
|
|
139
151
|
constructor(url, signer, options = {}) {
|
|
140
152
|
this.url = url.replace(/\/+$/, '');
|
|
141
153
|
this.signer = signer;
|
|
@@ -306,6 +318,38 @@ export class Relay {
|
|
|
306
318
|
if (events.length === 0)
|
|
307
319
|
break;
|
|
308
320
|
out.push(...events);
|
|
321
|
+
/*
|
|
322
|
+
A page smaller than one this relay has already delivered is the end of
|
|
323
|
+
the filter, and no confirming round trip is needed to know it.
|
|
324
|
+
|
|
325
|
+
The reason the confirmation existed is real: a page shorter than the
|
|
326
|
+
`limit` we asked for is ambiguous, because the relay clamps to
|
|
327
|
+
`min(requested, ceiling)` and might have clamped at exactly this many.
|
|
328
|
+
But that requires the ceiling to *equal* this page's size — and the
|
|
329
|
+
ceiling is one constant for the relay, already known to be at least
|
|
330
|
+
`observedPageCeiling`. So `n < observedPageCeiling` rules the clamp out
|
|
331
|
+
arithmetically rather than by trusting anything.
|
|
332
|
+
|
|
333
|
+
Deliberately not NIP-11's `limitation.max_limit`. That number is a
|
|
334
|
+
claim: a relay advertising more than it clamps to would make every page
|
|
335
|
+
look short and the first one get mistaken for the whole set, which is
|
|
336
|
+
exactly the SHA-8 bug this loop exists to prevent. An observed page is
|
|
337
|
+
evidence — the relay demonstrably produced it.
|
|
338
|
+
|
|
339
|
+
Conservative before it has evidence: the first filter through a fresh
|
|
340
|
+
`Relay` still pays the confirmation, and so does any page that ties the
|
|
341
|
+
largest seen so far — which means **the widest filter always confirms**,
|
|
342
|
+
since it ties its own bound on every read. So the floor is one request
|
|
343
|
+
per filter plus one, not one per filter.
|
|
344
|
+
|
|
345
|
+
Measured on Ship's `loadAll` against production: **66 requests to 35
|
|
346
|
+
cold and 34 warm**, the same fold event for event, and 8.8 s to 0.9 s
|
|
347
|
+
alongside the concurrency of 0.4.0.
|
|
348
|
+
*/
|
|
349
|
+
if (events.length > this.observedPageCeiling)
|
|
350
|
+
this.observedPageCeiling = events.length;
|
|
351
|
+
if (events.length < pageSize && events.length < this.observedPageCeiling)
|
|
352
|
+
break;
|
|
309
353
|
const oldest = Math.min(...events.map((e) => e.created_at));
|
|
310
354
|
if (until !== undefined && oldest >= until) {
|
|
311
355
|
if (events.length >= pageSize) {
|
package/dist/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
/** Bumped by hand with the version in package.json — `test/version.test.ts`
|
|
47
47
|
* pins the two together. It exists so "the upgrade reached the app" can be
|
|
48
48
|
* checked by grepping a built bundle rather than by trusting a lockfile. */
|
|
49
|
-
export declare const PROTOCOL_VERSION = "0.
|
|
49
|
+
export declare const PROTOCOL_VERSION = "0.5.0";
|
|
50
50
|
export { type NostrTag, type UnsignedEvent, type SignedEvent, type Profile, type ThreadRef, type ChannelVisibility, type ChannelKind, type MemberRole, type Label, type ResolutionAction, KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE, computeEventId, toNostrSeconds, canonicalChannelName, threadTags, addr, relayAuthUrl, buildProfile, parseProfile, buildCreateChannel, buildDeleteChannel, buildEditChannelMetadata, buildAddMember, buildReaction, buildDeletion, buildMessage, buildResolution, buildFile, buildComponent, buildHighlight, buildUnsignedRelayAuthEvent, } from './events.js';
|
|
51
51
|
export { type AddressPointer, type EventPointer, encodeNevent, decodeNevent, convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
|
|
52
52
|
export { type AuthEventArgs, TIMESTAMP_TOLERANCE_SECS, normalizeUrl, buildUnsignedAuthEvent, base64, authorizationHeaderFor, authorizationHeader, } from './nip98.js';
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
/** Bumped by hand with the version in package.json — `test/version.test.ts`
|
|
47
47
|
* pins the two together. It exists so "the upgrade reached the app" can be
|
|
48
48
|
* checked by grepping a built bundle rather than by trusting a lockfile. */
|
|
49
|
-
export const PROTOCOL_VERSION = '0.
|
|
49
|
+
export const PROTOCOL_VERSION = '0.5.0';
|
|
50
50
|
export {
|
|
51
51
|
// constants
|
|
52
52
|
KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@estiva-app/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The Estiva wire format: Buzz-shaped Nostr event builders, NIP-01 ids, NIP-19 naddr, NIP-98 HTTP auth, and the relay clients. Speaks the protocol; interprets nothing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/bridge.ts
CHANGED
|
@@ -205,6 +205,18 @@ export class Relay {
|
|
|
205
205
|
private readonly signer: Signer
|
|
206
206
|
private readonly headers: RelayHeaders
|
|
207
207
|
private readonly transport: FetchLike | undefined
|
|
208
|
+
/**
|
|
209
|
+
* The largest page this relay has ever handed back, across every call.
|
|
210
|
+
*
|
|
211
|
+
* A *lower bound* on the relay's real clamp, and the only one obtainable
|
|
212
|
+
* without trusting anybody: the relay returned this many events in one
|
|
213
|
+
* response, so its ceiling is at least this large. {@link Relay.pageFilter}
|
|
214
|
+
* uses it to tell a short page apart from a clamped one — see there.
|
|
215
|
+
*
|
|
216
|
+
* Per instance and never reset, so the second read through a long-lived
|
|
217
|
+
* `Relay` is cheaper than the first.
|
|
218
|
+
*/
|
|
219
|
+
private observedPageCeiling = 0
|
|
208
220
|
|
|
209
221
|
constructor(url: string, signer: Signer, options: RelayOptions | RelayHeaders = {}) {
|
|
210
222
|
this.url = url.replace(/\/+$/, '')
|
|
@@ -391,6 +403,38 @@ export class Relay {
|
|
|
391
403
|
])
|
|
392
404
|
if (events.length === 0) break
|
|
393
405
|
out.push(...events)
|
|
406
|
+
|
|
407
|
+
/*
|
|
408
|
+
A page smaller than one this relay has already delivered is the end of
|
|
409
|
+
the filter, and no confirming round trip is needed to know it.
|
|
410
|
+
|
|
411
|
+
The reason the confirmation existed is real: a page shorter than the
|
|
412
|
+
`limit` we asked for is ambiguous, because the relay clamps to
|
|
413
|
+
`min(requested, ceiling)` and might have clamped at exactly this many.
|
|
414
|
+
But that requires the ceiling to *equal* this page's size — and the
|
|
415
|
+
ceiling is one constant for the relay, already known to be at least
|
|
416
|
+
`observedPageCeiling`. So `n < observedPageCeiling` rules the clamp out
|
|
417
|
+
arithmetically rather than by trusting anything.
|
|
418
|
+
|
|
419
|
+
Deliberately not NIP-11's `limitation.max_limit`. That number is a
|
|
420
|
+
claim: a relay advertising more than it clamps to would make every page
|
|
421
|
+
look short and the first one get mistaken for the whole set, which is
|
|
422
|
+
exactly the SHA-8 bug this loop exists to prevent. An observed page is
|
|
423
|
+
evidence — the relay demonstrably produced it.
|
|
424
|
+
|
|
425
|
+
Conservative before it has evidence: the first filter through a fresh
|
|
426
|
+
`Relay` still pays the confirmation, and so does any page that ties the
|
|
427
|
+
largest seen so far — which means **the widest filter always confirms**,
|
|
428
|
+
since it ties its own bound on every read. So the floor is one request
|
|
429
|
+
per filter plus one, not one per filter.
|
|
430
|
+
|
|
431
|
+
Measured on Ship's `loadAll` against production: **66 requests to 35
|
|
432
|
+
cold and 34 warm**, the same fold event for event, and 8.8 s to 0.9 s
|
|
433
|
+
alongside the concurrency of 0.4.0.
|
|
434
|
+
*/
|
|
435
|
+
if (events.length > this.observedPageCeiling) this.observedPageCeiling = events.length
|
|
436
|
+
if (events.length < pageSize && events.length < this.observedPageCeiling) break
|
|
437
|
+
|
|
394
438
|
const oldest = Math.min(...events.map((e) => e.created_at))
|
|
395
439
|
if (until !== undefined && oldest >= until) {
|
|
396
440
|
if (events.length >= pageSize) {
|
package/src/index.ts
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
/** Bumped by hand with the version in package.json — `test/version.test.ts`
|
|
48
48
|
* pins the two together. It exists so "the upgrade reached the app" can be
|
|
49
49
|
* checked by grepping a built bundle rather than by trusting a lockfile. */
|
|
50
|
-
export const PROTOCOL_VERSION = '0.
|
|
50
|
+
export const PROTOCOL_VERSION = '0.5.0'
|
|
51
51
|
|
|
52
52
|
export {
|
|
53
53
|
// types
|