mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-06 07:28:23 +00:00
Some accepted root authors do not publish a discoverable NIP-65 kind 10002, leaving their conversations outside Sync+ even after a successful user-index lookup. Use a bounded operator-configured fallback relay set only after such a successful empty lookup. Feed fallback roots into the existing GRASP-02 target overlay, so historic, live, rotating, subscription-budget, and recovery behavior remain unified. A later accepted relay list removes the author from desired fallback coverage while shared live subscriptions drain naturally. Keep eligibility restricted to accepted root authors and preserve single-flight identity discovery. This does not expand to response authors, add another scheduler, or infer fallback need from failed queries. Validated with the end-to-end missing-list fallback and later-list replacement scenario, discovery/config unit tests, Nix module parsing, rustfmt, clippy with warnings denied, and diff checks.
86 lines
5.2 KiB
Markdown
86 lines
5.2 KiB
Markdown
# GRASP-03 proactive sync plus
|
|
|
|
GRASP-03 extends repository-declared GRASP-02 coverage to the Nostr outbox
|
|
model. An accepted issue, patch or pull request may have replies in the root
|
|
author's inbox even when those events are absent from repository relays.
|
|
|
|
The overlay is enabled by default and can be disabled with
|
|
`NGIT_SYNC_PLUS_ENABLED=false`. Because it extends the proactive GRASP-02
|
|
manager, it is effective only while that manager is running. NIP-11 advertises
|
|
`GRASP-03` only when the overlay is enabled.
|
|
|
|
## Minimal approach
|
|
|
|
The implementation adds a narrow discovery control-plane, not a second sync
|
|
engine: derive accepted root IDs and authors locally; ask a small existing
|
|
index set for each author's latest profile kind `0` and NIP-65 kind `10002`;
|
|
retain those replaceable events locally; treat `read` and unmarked relays as
|
|
inboxes; and merge inbox-to-root mappings into ordinary per-relay sync targets.
|
|
|
|
GRASP-02 then owns all transport. Its current root tiers, historic and
|
|
live/rotating coverage, grouping, subscription ledger, rate-limit recovery,
|
|
pagination and per-relay connection lifecycle apply unchanged.
|
|
|
|
Authors without an accepted stored relay list are queried through the configured
|
|
user-index set plus the bootstrap relay. Once a list is retained, discovery
|
|
follows its `write` and unmarked outboxes instead, allowing newer replacements
|
|
to converge without making arbitrary repository relays identity sources.
|
|
Discovery remains best effort and bounded to this operator-visible source graph.
|
|
|
|
If a successful user-index query returns no accepted kind `10002`, accepted
|
|
roots by that author temporarily use the operator-configured Sync+ fallback
|
|
relay set as inboxes. This is the same root-only overlay consumed by ordinary
|
|
GRASP-02 historic, live and rotating coverage; it creates no separate
|
|
subscription scheduler. An accepted relay list removes the author from desired
|
|
fallback coverage and installs its declared inboxes. Existing shared live
|
|
subscriptions still drain naturally, as with any other relay-list replacement.
|
|
|
|
The self-subscriber builds a compact root-candidate inventory during its
|
|
existing startup load and maintains it incrementally as roots arrive. StateOnly
|
|
candidates remain inert; promotion of their repository to Full makes them
|
|
eligible without rescanning retained events. Eligible identity authors are the
|
|
owners and declared maintainers of accepted Full announcements plus accepted
|
|
root authors—not every author retained by the relay. A once-per-minute
|
|
reconciliation derives sources from this index. Remote queries contain at most 100 authors and
|
|
only one discovery batch may be in flight globally. Admission samples immediate
|
|
transient capacity; if historic work wins the small race before the permit is
|
|
acquired, that single batch may wait but discovery can never build a waiter
|
|
queue. Its SDK-owned REQ draws from the same pacer and subscription ledger as
|
|
historic work. Discovery sources use the managed connection safety and
|
|
reconnection machinery, but are a distinct control-plane role: connecting to a
|
|
user index or outbox does not start ordinary announcement, repository, or
|
|
descendant sync against it. At most one new discovery source is dialled per
|
|
maintenance pass, and an exclusively discovery connection retires after its
|
|
currently due author batches drain. A relay that independently becomes a
|
|
repository source is promoted to the ordinary lifecycle without opening a
|
|
duplicate connection. Authors returned by a successful query refresh after 24 hours;
|
|
missing authors and failed queries retry after five minutes. Configured user
|
|
index relays discover authors with no accepted local relay list, requesting the
|
|
profile alongside it. Accepted NIP-65
|
|
write/unmarked outboxes are then followed additively for newer replacements;
|
|
new outboxes discovered by a replacement join the same bounded round until no
|
|
unvisited source remains. Identity events
|
|
pass through the ordinary write policy, persistence and broadcast path. Only a
|
|
stored, accepted kind `10002` can change inbox ownership. On startup, retained
|
|
relay lists for eligible authors rebuild inbox ownership from the local
|
|
database before any network refresh, so serving established coverage does not
|
|
depend on an external index remaining available. Remote discovery then refreshes
|
|
that retained state on the normal cadence.
|
|
|
|
Inbox replacement/removal changes desired ownership immediately. Additions are
|
|
derived promptly. Removals prevent future rotating and historic work, but do
|
|
not eagerly CLOSE live descendants or abort shared in-flight batches: existing
|
|
coverage drains on its natural EOSE/CLOSED/disconnect or an ordinary later
|
|
consolidation rebuild. This avoids interrupting unrelated roots and subscription
|
|
churn merely because one author replaced a relay list. Root deletion follows
|
|
the existing GRASP-02 root-index lifecycle and is reconstructed from retained
|
|
accepted events on restart; this change does not add a second deletion graph.
|
|
|
|
## Deliberately excluded
|
|
|
|
- the old recursive `SyncScope` graph and response-author fan-out;
|
|
- maintainer mailbox expansion unrelated to an accepted root;
|
|
- identity storage for authors other than accepted roots;
|
|
- per-user fallback configuration knobs; and
|
|
- a separate GRASP-03 subscription scheduler.
|