Files
ngit-grasp/tests/sync
DanConwayDev 8b69971593 Merge #0a6a0d75: feat(private-repos): authenticate outbound sync betwee…
feat(private-repos): authenticate outbound sync between GRASP-08 services

nostr:nevent1qgsx2lyl2e4zvfadwcvkd9fkrcwczj7mf858hy85mwqclwgut8wpg2spz3mhxue69uhhyetvv9ujumn8d96zuer9wcq3yamnwvaz7tm8d96xummnw3ezucm0d5q3kamnwvaz7tmwva5hgtnyv9hxxmmwwashjer9wchxxmmdqqsq56sdwh0cccm69uqln5ar58hf38xssqwpzs9fz87kfdtlv3x45qqr462cs

PR-Author: DanConwayDev's Agent
nostr:npub1v47f74n2ycn66asev62nv8sas99akj0g0wg0fkup37u3ckwuzs4q7cwtp0

PR description:

Implements the outbound half of GRASP-08 private-service support: how an instance behaves as a sync client toward relays that demand authentication or advertise GRASP-08.

Policy: (1) every sync connection answers NIP-42 AUTH challenges with the relay owner key when available, on public and private instances alike; after successful authentication the refused subscription is retried once, and without an owner key authentication is skipped and auth-demanding subscriptions park immediately. (2) A restricted: rejection after valid authentication is terminal and parks subscription work via the existing policy-refusal machinery, so there are no retry storms. (3) A relay whose NIP-11 supported_grasps advertises GRASP-08 is recognised with a pre-dial NIP-11 fetch that re-runs the outbound target policy, keeping the SSRF gate intact: a public instance parks such a relay without ever opening the WebSocket (no AUTH exchange, nothing to launder), while a private instance treats it as a peer and attaches the GRASP-08 repository-root NIP-98 credential (60-second validity, minted fresh per git subprocess) to purgatory Git fetches from that host, both signed with the relay owner key. (4) Relays with missing or unreadable NIP-11 remain ordinary sync targets. (5) Membership tightening: the NIP-11 owner of a relay referenced by an accepted announcement is only admitted as a derived member when that relay also advertises GRASP-08; configured NGIT_PRIVATE_MEMBERS are unaffected.

NIP-42 here is identification, not confidentiality: our pubkey is already published via NIP-11 and NIP-05, and a private instance authenticating outbound discloses its identity consistently with the public-discovery stance of GRASP-08. Also adds disclosure guidance for private services: security contact via NIP-11 contact and the NIP-05 root identity, reports as NIP-17 encrypted DMs on the public mailbox relays of maintainers, collaboration access by adding the reporter to NGIT_PRIVATE_MEMBERS, and deliberately no non-member submission lane.

Validation: cargo fmt --check, cargo clippy --all-targets -D warnings, cargo test --lib (792 passed), and the private_mode, sync, outbound_policy, purgatory_sync, nip11_document and relay_identity integration suites all pass.
2026-08-15 19:50:34 +01:00
..