OverviewFilesCommitsIssuesDocsReleasesPeers

favela-peer commits / a71fb5e

0.0.58: ask a bridge what it saw while this node was unreachable
`buildCollect`, beside the claim, release and front builders it matches. ⛔ WHY A PULL AND NOT A PUSH. A handset is not addressable, and that is measured rather than assumed: `/ap/users/fleeky/outbox` on ap.7rnx.net hangs for the full timeout because the device holding that feed does not answer. A bridge with a like to hand over has nowhere to send it, so the direction has to be ours — we connect, we ask, we decide what to keep. ⛔ IT IS ALSO THE ONLY DIRECTION THE MODEL ALLOWS. A bridge is not a writer on this feed and must never author into it (#61 §4). What comes back is a list of things OTHER people did; it is ours to record as an observation, never to author as an edge. ⚠ THIS BUILDS THE REQUEST AND NOTHING ELSE. Where the rows are stored is not decided here and deliberately not decided yet — #73 §6.3. Nothing in this daemon learns what network any of it came from; boundary.test.js is what keeps that true and still passes. ⚠ A PAGE PER CHALLENGE, deliberately. The nonce is single-use and the signed bytes name the cursor that page asked for, so collecting N pages is N challenges. Tests prove the request verifies as the bytes a bridge rebuilds, and that the cursor cannot be rewound in flight. 395/395. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
a71fb5e4011805fde936692113041d9bcdc67ac2
by plankatron <fleeky@gmail.com> · 2026-09-16T01:53:16.000Z

Changed files (4) +168 -98

.pgh-lock.json +95 -95
……@@ -1,9 +1,9 @@
11{
22 "name": "favela-peer",
3 "version": "0.0.56",
3 "version": "0.0.57",
44 "runtime": "bare",
5 "rootTreeHash": "d671f1d149cab9418c05acb06158ebeb24cd1daa984d57e428f31a716732f590",
6 "publishedAt": "2026-09-15T16:44:35.825Z",
5 "rootTreeHash": "d9a4175b27e1b3a814b3f7a6a335fdd0bf83b5688f91502cf1be755b7869339f",
6 "publishedAt": "2026-09-15T18:05:02.187Z",
77 "deps": [
88 {
99 "name": "@hyperswarm/secret-stream",
……@@ -3209,8 +3209,8 @@
32093209 "tree": "da4c6b2654e9d66f10b0faa989311cf182878c24ab51b1c41458cfbf37ad29cd"
32103210 }
32113211 ],
3212 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3213 "acceptedAt": "2026-09-15T16:44:35.844Z"
3212 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3213 "acceptedAt": "2026-09-15T18:05:02.206Z"
32143214 },
32153215 {
32163216 "type": "VERSION_CONFLICT",
……@@ -3224,8 +3224,8 @@
32243224 "tree": "40be8f559a13b54ebf0689e63e6c70f0d218035359e17c497ed7bc8a85c3cc95"
32253225 }
32263226 ],
3227 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3228 "acceptedAt": "2026-09-15T16:44:35.844Z"
3227 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3228 "acceptedAt": "2026-09-15T18:05:02.206Z"
32293229 },
32303230 {
32313231 "type": "VERSION_CONFLICT",
……@@ -3239,8 +3239,8 @@
32393239 "tree": "3eae85efce82299769898c8151b5ed0a94e5a5ebdbcdee2105b815ca733a61cb"
32403240 }
32413241 ],
3242 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3243 "acceptedAt": "2026-09-15T16:44:35.844Z"
3242 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3243 "acceptedAt": "2026-09-15T18:05:02.206Z"
32443244 },
32453245 {
32463246 "type": "VERSION_CONFLICT",
……@@ -3254,8 +3254,8 @@
32543254 "tree": "8d9e01d443a127781773598d2e77c3f372334fad09e20623a819dabe49b22e1a"
32553255 }
32563256 ],
3257 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3258 "acceptedAt": "2026-09-15T16:44:35.844Z"
3257 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3258 "acceptedAt": "2026-09-15T18:05:02.206Z"
32593259 },
32603260 {
32613261 "type": "VERSION_CONFLICT",
……@@ -3269,8 +3269,8 @@
32693269 "tree": "dc1ad6c999fe90d946ba0ef34698ea9af451b639be2ad1c5b61eabb08337a6ca"
32703270 }
32713271 ],
3272 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3273 "acceptedAt": "2026-09-15T16:44:35.844Z"
3272 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3273 "acceptedAt": "2026-09-15T18:05:02.206Z"
32743274 },
32753275 {
32763276 "type": "VERSION_CONFLICT",
……@@ -3284,8 +3284,8 @@
32843284 "tree": "88b4779570e5113aa21b204989ac018d1628b387681f7e53428a7c99114fb701"
32853285 }
32863286 ],
3287 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3288 "acceptedAt": "2026-09-15T16:44:35.844Z"
3287 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3288 "acceptedAt": "2026-09-15T18:05:02.206Z"
32893289 },
32903290 {
32913291 "type": "VERSION_CONFLICT",
……@@ -3299,8 +3299,8 @@
32993299 "tree": "f81b0df4731379088009176f2b02a3af0b32c33df73049d78f00c282e9a48203"
33003300 }
33013301 ],
3302 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3303 "acceptedAt": "2026-09-15T16:44:35.844Z"
3302 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3303 "acceptedAt": "2026-09-15T18:05:02.206Z"
33043304 },
33053305 {
33063306 "type": "VERSION_CONFLICT",
……@@ -3314,8 +3314,8 @@
33143314 "tree": "720b867ec4300a3caa2325eb1449499f9940bfb88341ecceb5992fa0fdf5f37d"
33153315 }
33163316 ],
3317 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3318 "acceptedAt": "2026-09-15T16:44:35.844Z"
3317 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3318 "acceptedAt": "2026-09-15T18:05:02.206Z"
33193319 },
33203320 {
33213321 "type": "VERSION_CONFLICT",
……@@ -3329,8 +3329,8 @@
33293329 "tree": "b697fe174482a708b49d0764cd4786291845f0034a31e0699381ca7e7b269d04"
33303330 }
33313331 ],
3332 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3333 "acceptedAt": "2026-09-15T16:44:35.844Z"
3332 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3333 "acceptedAt": "2026-09-15T18:05:02.206Z"
33343334 },
33353335 {
33363336 "type": "VERSION_CONFLICT",
……@@ -3344,8 +3344,8 @@
33443344 "tree": "767f07242277ae80bd395de5a4969fcdbf956c216158ae517fb2b562558ac1a4"
33453345 }
33463346 ],
3347 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3348 "acceptedAt": "2026-09-15T16:44:35.844Z"
3347 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3348 "acceptedAt": "2026-09-15T18:05:02.206Z"
33493349 },
33503350 {
33513351 "type": "VERSION_CONFLICT",
……@@ -3359,8 +3359,8 @@
33593359 "tree": "de7deed21f587ffc8bde4971abe00fca77bb6c71c4e7effb31ad34ee330815df"
33603360 }
33613361 ],
3362 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3363 "acceptedAt": "2026-09-15T16:44:35.844Z"
3362 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3363 "acceptedAt": "2026-09-15T18:05:02.206Z"
33643364 },
33653365 {
33663366 "type": "VERSION_CONFLICT",
……@@ -3374,8 +3374,8 @@
33743374 "tree": "2df42517ebf73cd9c11f2f652f75e87401fd4ed7b856c0adc15c33baf1d4f1ad"
33753375 }
33763376 ],
3377 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3378 "acceptedAt": "2026-09-15T16:44:35.844Z"
3377 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3378 "acceptedAt": "2026-09-15T18:05:02.206Z"
33793379 },
33803380 {
33813381 "type": "VERSION_CONFLICT",
……@@ -3389,8 +3389,8 @@
33893389 "tree": "325aca171cbff560487177584078c8066133e91176639ca47c98d70e195aa92e"
33903390 }
33913391 ],
3392 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3393 "acceptedAt": "2026-09-15T16:44:35.844Z"
3392 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3393 "acceptedAt": "2026-09-15T18:05:02.206Z"
33943394 },
33953395 {
33963396 "type": "VERSION_CONFLICT",
……@@ -3404,8 +3404,8 @@
34043404 "tree": "1bd0eb382789c62cd4622d47bffb60984fdd766260c79f73a2fc7a136f3edbe9"
34053405 }
34063406 ],
3407 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3408 "acceptedAt": "2026-09-15T16:44:35.844Z"
3407 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3408 "acceptedAt": "2026-09-15T18:05:02.206Z"
34093409 },
34103410 {
34113411 "type": "VERSION_CONFLICT",
……@@ -3419,8 +3419,8 @@
34193419 "tree": "4526fe9dc5468264c7171ec16e9303726674b7b44ca0b3e09cb8b9a6a1be6169"
34203420 }
34213421 ],
3422 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3423 "acceptedAt": "2026-09-15T16:44:35.844Z"
3422 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3423 "acceptedAt": "2026-09-15T18:05:02.206Z"
34243424 },
34253425 {
34263426 "type": "VERSION_CONFLICT",
……@@ -3434,8 +3434,8 @@
34343434 "tree": "32b291cd756e142da18a6ed01c351e024fcedc3e2b1ecfbfb85f3106ada4419b"
34353435 }
34363436 ],
3437 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3438 "acceptedAt": "2026-09-15T16:44:35.844Z"
3437 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3438 "acceptedAt": "2026-09-15T18:05:02.206Z"
34393439 },
34403440 {
34413441 "type": "VERSION_CONFLICT",
……@@ -3449,8 +3449,8 @@
34493449 "tree": "4a8cd3b0093092b33088617dc0415e8179882d7f2f13b7649962ca20b08beeed"
34503450 }
34513451 ],
3452 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3453 "acceptedAt": "2026-09-15T16:44:35.844Z"
3452 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3453 "acceptedAt": "2026-09-15T18:05:02.206Z"
34543454 },
34553455 {
34563456 "type": "VERSION_CONFLICT",
……@@ -3464,8 +3464,8 @@
34643464 "tree": "4f63f165ee6a581f689b40c4a40df4df01ab6fba17d46bd29e40ef5bbdd9884f"
34653465 }
34663466 ],
3467 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3468 "acceptedAt": "2026-09-15T16:44:35.844Z"
3467 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3468 "acceptedAt": "2026-09-15T18:05:02.206Z"
34693469 },
34703470 {
34713471 "type": "VERSION_CONFLICT",
……@@ -3479,8 +3479,8 @@
34793479 "tree": "735109c736c0bd3413ab47414fd8b6ea9a99c401fe8e6d608459c79293806754"
34803480 }
34813481 ],
3482 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3483 "acceptedAt": "2026-09-15T16:44:35.844Z"
3482 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3483 "acceptedAt": "2026-09-15T18:05:02.206Z"
34843484 },
34853485 {
34863486 "type": "VERSION_CONFLICT",
……@@ -3494,8 +3494,8 @@
34943494 "tree": "b32b75bf1b2acdd18ed0cc370d01d477fba42ba09fd1f2f78af3ebad925e72d5"
34953495 }
34963496 ],
3497 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3498 "acceptedAt": "2026-09-15T16:44:35.844Z"
3497 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3498 "acceptedAt": "2026-09-15T18:05:02.206Z"
34993499 },
35003500 {
35013501 "type": "VERSION_CONFLICT",
……@@ -3509,8 +3509,8 @@
35093509 "tree": "3bedca5287a9041fc2fd5ec5ace4df1fa86240e6afec0a105ba67398bafc09a5"
35103510 }
35113511 ],
3512 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3513 "acceptedAt": "2026-09-15T16:44:35.844Z"
3512 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3513 "acceptedAt": "2026-09-15T18:05:02.206Z"
35143514 },
35153515 {
35163516 "type": "VERSION_CONFLICT",
……@@ -3524,8 +3524,8 @@
35243524 "tree": "b9ca9b272008bd67672a1b252390e8b527095c46b46cf6b6725a7a187eb038b6"
35253525 }
35263526 ],
3527 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3528 "acceptedAt": "2026-09-15T16:44:35.844Z"
3527 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3528 "acceptedAt": "2026-09-15T18:05:02.206Z"
35293529 },
35303530 {
35313531 "type": "VERSION_CONFLICT",
……@@ -3539,8 +3539,8 @@
35393539 "tree": "7793645d7d4248d6d6533e3cbcd4bf40bed4f38c678b0ca0606c15640ba5e7b9"
35403540 }
35413541 ],
3542 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3543 "acceptedAt": "2026-09-15T16:44:35.844Z"
3542 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3543 "acceptedAt": "2026-09-15T18:05:02.206Z"
35443544 },
35453545 {
35463546 "type": "VERSION_CONFLICT",
……@@ -3554,8 +3554,8 @@
35543554 "tree": "79447513d4ac0357c8d60bdc7b81b3c5143d761b26700340cba266c4d1cb77b0"
35553555 }
35563556 ],
3557 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3558 "acceptedAt": "2026-09-15T16:44:35.844Z"
3557 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3558 "acceptedAt": "2026-09-15T18:05:02.206Z"
35593559 },
35603560 {
35613561 "type": "VERSION_CONFLICT",
……@@ -3569,8 +3569,8 @@
35693569 "tree": "279d4e0447eb79fd75816864ba7f41f2df03080c9da69ea4603fe2900c8d9e53"
35703570 }
35713571 ],
3572 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3573 "acceptedAt": "2026-09-15T16:44:35.844Z"
3572 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3573 "acceptedAt": "2026-09-15T18:05:02.206Z"
35743574 },
35753575 {
35763576 "type": "VERSION_CONFLICT",
……@@ -3619,8 +3619,8 @@
36193619 "tree": "3bb78d8f06263a549bd1077f37a7df257b1d557e44608631435af625f05a9c11"
36203620 }
36213621 ],
3622 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3623 "acceptedAt": "2026-09-15T16:44:35.844Z"
3622 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3623 "acceptedAt": "2026-09-15T18:05:02.206Z"
36243624 },
36253625 {
36263626 "type": "VERSION_CONFLICT",
……@@ -3639,8 +3639,8 @@
36393639 "tree": "58c0bf8698af19464d0ee8354a77ed1ac96d3a5fa18aa4e794686cfbbf080e5d"
36403640 }
36413641 ],
3642 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3643 "acceptedAt": "2026-09-15T16:44:35.844Z"
3642 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3643 "acceptedAt": "2026-09-15T18:05:02.206Z"
36443644 },
36453645 {
36463646 "type": "VERSION_CONFLICT",
……@@ -3669,8 +3669,8 @@
36693669 "tree": "89a40400106bf4fef95fb5c44a66ee29aada6f76c7740bfba09d8aeeb841f39c"
36703670 }
36713671 ],
3672 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3673 "acceptedAt": "2026-09-15T16:44:35.844Z"
3672 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3673 "acceptedAt": "2026-09-15T18:05:02.206Z"
36743674 },
36753675 {
36763676 "type": "VERSION_CONFLICT",
……@@ -3699,8 +3699,8 @@
36993699 "tree": "b799e6ba8726aa951b45f12cc7ecffe5f4e9ee1e8adf09a34d026d9d5658828a"
37003700 }
37013701 ],
3702 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3703 "acceptedAt": "2026-09-15T16:44:35.844Z"
3702 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3703 "acceptedAt": "2026-09-15T18:05:02.206Z"
37043704 },
37053705 {
37063706 "type": "VERSION_CONFLICT",
……@@ -3714,8 +3714,8 @@
37143714 "tree": "c486fe73805bf013e9c5de91b5780d1aa5d2b2295306f411f7863757aaa05e60"
37153715 }
37163716 ],
3717 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3718 "acceptedAt": "2026-09-15T16:44:35.844Z"
3717 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3718 "acceptedAt": "2026-09-15T18:05:02.206Z"
37193719 },
37203720 {
37213721 "type": "VERSION_CONFLICT",
……@@ -3749,8 +3749,8 @@
37493749 "tree": "ceb96c67cbac0fda8612669b90fc6574c408b25c985f0563cbb31136c1fb44e8"
37503750 }
37513751 ],
3752 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3753 "acceptedAt": "2026-09-15T16:44:35.844Z"
3752 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3753 "acceptedAt": "2026-09-15T18:05:02.206Z"
37543754 },
37553755 {
37563756 "type": "VERSION_CONFLICT",
……@@ -3764,8 +3764,8 @@
37643764 "tree": "a366a73e74f8d80f106465058083b62bb70b833c721047124e99c89880e5c706"
37653765 }
37663766 ],
3767 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3768 "acceptedAt": "2026-09-15T16:44:35.844Z"
3767 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3768 "acceptedAt": "2026-09-15T18:05:02.206Z"
37693769 },
37703770 {
37713771 "type": "VERSION_CONFLICT",
……@@ -3779,8 +3779,8 @@
37793779 "tree": "7b3f314cf92558edbc90295c573885276a6add925318998c829c03d335edc765"
37803780 }
37813781 ],
3782 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3783 "acceptedAt": "2026-09-15T16:44:35.844Z"
3782 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3783 "acceptedAt": "2026-09-15T18:05:02.206Z"
37843784 },
37853785 {
37863786 "type": "VERSION_CONFLICT",
……@@ -3799,8 +3799,8 @@
37993799 "tree": "189397178121e9a18430943345dab820691648a324229071ceb980bbb77a7393"
38003800 }
38013801 ],
3802 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3803 "acceptedAt": "2026-09-15T16:44:35.844Z"
3802 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3803 "acceptedAt": "2026-09-15T18:05:02.206Z"
38043804 },
38053805 {
38063806 "type": "VERSION_CONFLICT",
……@@ -3814,8 +3814,8 @@
38143814 "tree": "fc766e83f3b898a1a78e898755509ca8ae59d9ecacbbad6e160787d541aeb655"
38153815 }
38163816 ],
3817 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3818 "acceptedAt": "2026-09-15T16:44:35.844Z"
3817 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3818 "acceptedAt": "2026-09-15T18:05:02.206Z"
38193819 },
38203820 {
38213821 "type": "VERSION_CONFLICT",
……@@ -3849,8 +3849,8 @@
38493849 "tree": "a9e07d54e526c838dfe5e27df33936682aefb218f61a45b6c15289243999f648"
38503850 }
38513851 ],
3852 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3853 "acceptedAt": "2026-09-15T16:44:35.844Z"
3852 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3853 "acceptedAt": "2026-09-15T18:05:02.206Z"
38543854 },
38553855 {
38563856 "type": "VERSION_CONFLICT",
……@@ -3879,8 +3879,8 @@
38793879 "tree": "9d84c86441fe138b227c4fd01d1e948aa83bf8d13cfb1aa957838feea05fbb57"
38803880 }
38813881 ],
3882 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3883 "acceptedAt": "2026-09-15T16:44:35.844Z"
3882 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3883 "acceptedAt": "2026-09-15T18:05:02.206Z"
38843884 },
38853885 {
38863886 "type": "VERSION_CONFLICT",
……@@ -3894,8 +3894,8 @@
38943894 "tree": "4a3afbe2fc7a882e24454eb2e7e7cfe6816811ee5d73ae0f92e8b9ea9cfb8c78"
38953895 }
38963896 ],
3897 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3898 "acceptedAt": "2026-09-15T16:44:35.844Z"
3897 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3898 "acceptedAt": "2026-09-15T18:05:02.206Z"
38993899 },
39003900 {
39013901 "type": "VERSION_CONFLICT",
……@@ -3909,8 +3909,8 @@
39093909 "tree": "1e5c5810d8971a3c27fde7fb0e4d633dcabbe2cf98d8df86b473f8d67eead8b9"
39103910 }
39113911 ],
3912 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3913 "acceptedAt": "2026-09-15T16:44:35.844Z"
3912 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3913 "acceptedAt": "2026-09-15T18:05:02.206Z"
39143914 },
39153915 {
39163916 "type": "VERSION_CONFLICT",
……@@ -3924,8 +3924,8 @@
39243924 "tree": "e3478f50e85ba0ac288efed83e84c992483904897dc39ccf243d20a4ea25d972"
39253925 }
39263926 ],
3927 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3928 "acceptedAt": "2026-09-15T16:44:35.844Z"
3927 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3928 "acceptedAt": "2026-09-15T18:05:02.206Z"
39293929 },
39303930 {
39313931 "type": "VERSION_CONFLICT",
……@@ -3954,8 +3954,8 @@
39543954 "tree": "c05d8bf7eab5024ea98140f78c84d12fb494b4b7b10c7eedeb50b2be842fa519"
39553955 }
39563956 ],
3957 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3958 "acceptedAt": "2026-09-15T16:44:35.844Z"
3957 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3958 "acceptedAt": "2026-09-15T18:05:02.206Z"
39593959 },
39603960 {
39613961 "type": "VERSION_CONFLICT",
……@@ -3969,8 +3969,8 @@
39693969 "tree": "0697bb338bbcec517353cffcdb2345a8232b9b90cc627a549a306f0323576390"
39703970 }
39713971 ],
3972 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3973 "acceptedAt": "2026-09-15T16:44:35.844Z"
3972 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3973 "acceptedAt": "2026-09-15T18:05:02.206Z"
39743974 },
39753975 {
39763976 "type": "VERSION_CONFLICT",
……@@ -3984,8 +3984,8 @@
39843984 "tree": "10193a86e2c6f80c2d4377379a0aae4a959f8a40fd9e852b85fee081bfe6675a"
39853985 }
39863986 ],
3987 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
3988 "acceptedAt": "2026-09-15T16:44:35.844Z"
3987 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
3988 "acceptedAt": "2026-09-15T18:05:02.206Z"
39893989 },
39903990 {
39913991 "type": "VERSION_CONFLICT",
……@@ -3999,8 +3999,8 @@
39993999 "tree": "20b1ecd2937f3e35102892288234b86a8ec6deb3711016d96ff3509474ac465b"
40004000 }
40014001 ],
4002 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
4003 "acceptedAt": "2026-09-15T16:44:35.844Z"
4002 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
4003 "acceptedAt": "2026-09-15T18:05:02.206Z"
40044004 },
40054005 {
40064006 "type": "VERSION_CONFLICT",
……@@ -4019,8 +4019,8 @@
40194019 "tree": "7912e790c9e87e9829a6daa037c5f5da0cc4355214f51d334f96e57678dfddeb"
40204020 }
40214021 ],
4022 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
4023 "acceptedAt": "2026-09-15T16:44:35.844Z"
4022 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
4023 "acceptedAt": "2026-09-15T18:05:02.206Z"
40244024 },
40254025 {
40264026 "type": "VERSION_CONFLICT",
……@@ -4034,8 +4034,8 @@
40344034 "tree": "003ac841449fcdda1abc3c87fee291a5d9596d245925a7298bd8ef5f8e423eae"
40354035 }
40364036 ],
4037 "reason": "favela-peer 0.0.56: 46 conflicts, all version-splits/docs/packaging, 0 code-differs per pgh's classification",
4038 "acceptedAt": "2026-09-15T16:44:35.844Z"
4037 "reason": "favela-peer 0.0.57: version-splits/docs/packaging only, 0 code-differs",
4038 "acceptedAt": "2026-09-15T18:05:02.206Z"
40394039 }
40404040 ]
40414041}
lib/bridge.js +24 -2
……@@ -19,7 +19,7 @@ import ProtomuxRPC from 'protomux-rpc'
1919import c from 'compact-encoding'
2020import b4a from 'b4a'
2121import { signAttested } from 'favela-identity/lib/attestation.js'
22import { claimBytes, releaseBytes, frontBytes } from 'favela-identity/lib/bridge-claim.js'
22import { claimBytes, releaseBytes, frontBytes, collectBytes } from 'favela-identity/lib/bridge-claim.js'
2323
2424export const PROTOCOL = 'favela/bridge-register/1'
2525const HEX64 = /^[0-9a-f]{64}$/i
……@@ -121,7 +121,29 @@ export function buildFront ({ nonce, id, root, cred }) {
121121 return { id, root, nonce, proof: signAttested(frontBytes({ nonce, id }), cred) }
122122}
123123
124export default { connectBridge, buildClaim, buildRelease, buildFront, PROTOCOL }
124/**
125 * Ask a bridge for what it OBSERVED while this node was not reachable.
126 *
127 * ⛔ WHY A PULL. A handset is not addressable — measured on ap.7rnx.net, a registered peer's outbox
128 * hangs for the full timeout because the device holding that feed does not answer. A bridge with
129 * something to tell us has nowhere to send it, so the direction has to be ours: we connect, we ask,
130 * we decide what to keep. It is also the only direction the model allows — a bridge is not a writer
131 * on this feed and must never author into it (hyper-social #61 §4).
132 *
133 * ⛔ THE CURSOR IS SIGNED, so it cannot be wound back in flight. That is also why a page needs its
134 * own challenge: the nonce is single-use, and the bytes name the cursor this particular page asked
135 * for. Collecting N pages is N challenges, deliberately.
136 *
137 * ⚠ THIS BUILDS THE REQUEST AND NOTHING ELSE. What arrives is a list of things OTHER people did, on
138 * a network this daemon deliberately knows nothing about — boundary.test.js forbids naming one here.
139 * Deciding what those rows mean, and writing them down, is the caller's job.
140 */
141export function buildCollect ({ nonce, username, since = 0, root, cred }) {
142 if (!root) throw new Error('this node cannot sign yet — link this device to its identity first')
143 return { username, root, since, nonce, proof: signAttested(collectBytes({ nonce, username, since }), cred) }
144}
145
146export default { connectBridge, buildClaim, buildRelease, buildFront, buildCollect, PROTOCOL }
125147
126148// ── which bridges carry this node ────────────────────────────────────────────────────────────────
127149//
package.json +1 -1
……@@ -1,6 +1,6 @@
11{
22 "name": "favela-peer",
3 "version": "0.0.57",
3 "version": "0.0.58",
44 "description": "The favela daemon \u2014 feeds and documents of markdown records over Hypercore. No atproto, no ActivityPub.",
55 "type": "module",
66 "scripts": {
test/bridge-collect.test.js +48 -0
……@@ -0,0 +1,48 @@
1// bridge-collect.test.js — the request this node sends to collect what a bridge saw for it.
2//
3// ⛔ WHY A PULL AT ALL. A handset is not addressable. Measured on ap.7rnx.net: a registered peer's
4// outbox hangs for the full timeout because the device holding that feed does not answer, so a bridge
5// with a like to hand over has nowhere to send it. The direction has to be ours.
6//
7// ⚠ This daemon still learns nothing about the network — boundary.test.js is what keeps that true,
8// and nothing here names one.
9
10import test from 'brittle'
11import b4a from 'b4a'
12import IdentityKey from 'keet-identity-key'
13import crypto from 'hypercore-crypto'
14import { readAttested } from 'favela-identity/lib/attestation.js'
15import { collectBytes } from 'favela-identity/lib/bridge-claim.js'
16import { buildCollect } from '../lib/bridge.js'
17
18async function identity () {
19 const idk = await IdentityKey.from({ mnemonic: IdentityKey.generateMnemonic() })
20 const kp = crypto.keyPair()
21 const proof = await IdentityKey.bootstrap({ identity: idk.identityKeyPair }, kp.publicKey)
22 return { rootHex: b4a.toString(idk.identityKeyPair.publicKey, 'hex'), cred: { keyPair: kp, proof: b4a.toString(proof, 'base64') } }
23}
24
25test('★★ what this node sends verifies as the bytes a bridge rebuilds', async (t) => {
26 const me = await identity()
27 const req = buildCollect({ nonce: 'n1', username: 'alice', since: 4, root: me.rootHex, cred: me.cred })
28
29 t.is(req.username, 'alice')
30 t.is(req.since, 4, 'the cursor travels, so the bridge can rebuild the same bytes')
31
32 // This is exactly what ap-bridge's Admission does, minus the challenge it owns.
33 const seen = readAttested(req.proof, collectBytes({ nonce: 'n1', username: 'alice', since: 4 }), me.rootHex)
34 t.ok(seen, 'attested')
35 t.is(seen.root, me.rootHex)
36})
37
38test('⛔ the cursor is inside the proof — a reply cannot be rewound in flight', async (t) => {
39 const me = await identity()
40 const req = buildCollect({ nonce: 'n1', username: 'alice', since: 4, root: me.rootHex, cred: me.cred })
41 // Somebody rewrites `since` to 0 on the way to the bridge to rake in the whole buffer.
42 t.absent(readAttested(req.proof, collectBytes({ nonce: 'n1', username: 'alice', since: 0 }), me.rootHex), 'refused')
43})
44
45test('⛔ an unlinked device is told what to do, not handed a crypto error', async (t) => {
46 const me = await identity()
47 t.exception(() => buildCollect({ nonce: 'n1', username: 'alice', root: null, cred: me.cred }), /link this device/)
48})