Files
ngit-grasp/docs/explanation
DanConwayDev 7334e04b88 feat(identity): publish relay owner events
The relay-owner key is intended to double as the service identity used by
ngit-ci, but clients could only discover it through HTTP and owner-authored
coordinator events without repository roots failed admission.

Sign a minimal kind-0 NIP-05 bot profile at startup — per NIP-24 `name` is
always set, here to the scheme-less public URL — alongside a single
unmarked kind-10002 relay entry. An operator-customized profile is kept
and never overwritten, and no identity event — locally stored or freshly
generated — is published before the local database and at least one
user-index relay have been successfully checked for that kind, so a
database wiped and reseeded during an index outage can never displace a
customized profile surviving on the indexes. Every send is preceded by a
per-relay re-check: an identity found on an index relay is adopted
locally, where replaceable-event semantics keep the newest copy, and is
never overwritten, so publication only fills gaps on index relays that
individually confirm they hold none; propagating a profile update onto an
index that already has one is left to the operator's own client. A kind
with no local copy is not even seeded until a reachable user-index relay
confirms it holds no identity of that kind. Publication never blocks
startup, retries transient failures with a capped backoff, and stops on
terminal protocol rejections. With no user-index relays configured,
missing kinds are seeded locally right away. In private mode (GRASP-08)
identity events are seeded and served locally but never published, so a
private relay does not advertise its existence.

Trust valid owner-signed events only for kinds without a dedicated
admission policy, such as ngit-ci coordinator advertisements that carry
no repository root tag. Owner-signed NIP-34 announcements, state events,
and PRs run the normal announcement validation, ref alignment, and
purgatory git-data handling like any other author, and the relay's own
kind 0/10002 identity is always accepted. The NIP-09/NIP-62 deletion gate
still runs before any owner acceptance, so replaying a retracted owner
event cannot undo its tombstone, and owner deletion/vanish requests keep
their lifecycle handling. Because the event blacklist cannot block the
owner key, rotating the key is the only remediation if it is compromised;
this is documented.

NGIT_DOMAIN is assumed to be the documented bare public authority:
loopback authorities use ws and other hosts advertise wss, with bare IPv6
authorities bracketed. The test fixture reuses relay-owner keys across
TestRelay::restart, and gains caller-provided keys, a private-mode member
setup, and explicit user-index relay lists; MockRelay can start
pre-seeded so a "recovering" index deterministically holds prior state.
Identity retry intervals honor the existing NGIT_TEST fast-timer
convention. No new configuration switches or ngit-ci changes are
included. Includes rustfmt fixes for src/nostr/policy/announcement.rs and
tests/private_mode.rs, which arrived on master unformatted and would
otherwise fail the workspace format gate.

Validated with rustfmt, strict workspace Clippy, the relay_identity and
private_mode integration binaries, and the full workspace test suite.
Individual sync/grasp06 integration tests fail intermittently under
parallel full-suite load, each passing in isolation and on rerun; the
same intermittent failures reproduce on origin/master without these
changes.
2026-08-15 11:17:57 +00:00
..

Explanation

Understanding-oriented documentation - Concepts, design decisions, and the "why" behind ngit-grasp.


What Is Explanation?

Explanation documentation helps you understand concepts and design decisions, providing context and discussing alternatives.

Characteristics:

  • ✅ Understanding-oriented (clarify concepts)
  • ✅ Theoretical (ideas and design)
  • ✅ Discuss alternatives
  • ✅ Provide context and background
  • ✅ Answer "why" questions

Not explanation:

  • ❌ Step-by-step lessons (those are Tutorials)
  • ❌ Problem-solving recipes (those are How-To)
  • ❌ Technical specifications (those are Reference)

Available Explanation Documentation

Architecture Overview

Understand the system design and component interaction

Topics:

  • Overall architecture
  • Component responsibilities
  • Data flows
  • Technology choices
  • Design patterns

Read when: You want to understand how ngit-grasp works as a system


Inline Authorization

Why we validate pushes inline instead of using Git hooks

Topics:

  • The authorization problem
  • Git hooks approach
  • Inline approach
  • Comparison and trade-offs
  • Implementation details

Read when: You want to understand the core architectural decision


Design Decisions

Key architectural choices and their rationale

Topics:

  • Inline authorization vs hooks
  • Technology stack choices
  • Storage design
  • API design
  • Performance considerations

Read when: You want to know why things are the way they are


Comparison with ngit-relay

How ngit-grasp differs from the reference implementation

Topics:

  • Architecture comparison
  • Component differences
  • Trade-offs
  • Migration path
  • Compatibility

Read when: You're familiar with ngit-relay and want to understand differences


Purgatory Design

In-memory holding area for events awaiting git data

Topics:

  • The "which arrives first?" problem
  • Separate storage for state vs PR events
  • Late binding for state events
  • Bidirectional waiting for PR events
  • Authorization during push

Read when: You want to understand how ngit-grasp handles out-of-order event/git data arrival


GRASP-02 Proactive Sync

Relay-to-relay synchronization for repository discovery

Topics:

  • Negentropy-based event sync
  • Repository announcement discovery
  • Relay management and reconnection
  • Layer 2 filtering
  • Bootstrap and dynamic relay discovery

Read when: You want to understand how ngit-grasp discovers and syncs repositories across relays


GRASP-03 Proactive Sync Plus

NIP-65 inbox/outbox discovery for accepted repository conversations

Read when: You want to understand how accepted conversations are recovered from participant mailboxes


Sync Scaling Constraints and Budgets

Relay-imposed limits and how sync spends them at scale

Topics:

  • Verified relay limits (strfry, live NIP-11, our embedded relay)
  • Per-connection budget ledger (live vs historic vs fallback)
  • Byte-budgeted filter chunking and REQ packing
  • Bounded negentropy concurrency
  • Multi-connection escalation and serving-side obligations

Read when: You're changing filter construction, subscription management, or sync concurrency, and need the constraint justification


GRASP-02 Purgatory Git Data Fetching

Proactive git data fetching from remote servers

Topics:

  • Identifier-based batching
  • Exponential backoff with fresh start
  • Domain throttling (5 concurrent, 30/min)
  • Debounced delays (3min user, 500ms sync)
  • 30-minute expiry
  • Mock-based testability

Read when: You want to understand how purgatory automatically fetches missing git data


Unified Git Data Sync

Shared processing for git push and purgatory sync paths

Topics:

  • Why unify push and sync processing
  • OID syncing to owner repos
  • Ref alignment logic
  • Event release from purgatory
  • WebSocket notification

Read when: You want to understand how git data is processed consistently regardless of arrival method


Monitoring Overview

Prometheus metrics and observability

Topics:

  • Metrics philosophy
  • Connection tracking
  • Git operation metrics
  • Nostr event metrics
  • Privacy considerations

Read when: You want to understand how to monitor ngit-grasp in production


Defensive Measures & Rate Limiting

Protection against abuse, spam, and denial-of-service attacks

Topics:

  • Connection and subscription management
  • Event publishing rate limits
  • Content filtering (blacklists/whitelists)
  • Event validation plugin system (WritePolicy/QueryPolicy)
  • Relay health management (naughty list, exponential backoff)
  • Privacy-preserving IP tracking
  • Future enhancements (per-IP rate limiting)

Read when: You want to understand how ngit-grasp protects against abuse and what defensive features are available


GRASP-05 Archive Mode

Read-only mirroring of repositories

Topics:

  • Archive whitelist configuration
  • Archive-all mode
  • Read-only mode defaults
  • Use cases for backup/mirror relays

Read when: You want to understand how to run an archive/backup relay


GRASP-08 Private Service Authentication

Service-wide NIP-42/NIP-98 authentication for private repositories

Topics:

  • Fail-closed private mode and indistinguishable 401 responses
  • The GRASP-08 repository-scoped NIP-98 profile vs generic NIP-98
  • NIP-42 authentication outside the embedded relay
  • Service-wide membership and dynamic accepted-relay-owner admission
  • Trust model and follow-up scope

Read when: You want to understand how a private GRASP instance authenticates clients and peers


Repository Lifecycle

Handling repository removal, holding, archive, recovery, and purgatory

Topics:

  • Repository lifecycle architecture
  • Delete disrespector concept
  • Preventing left-pad scenarios
  • Archival policies
  • Holding, recovery, purgatory, and operator curation flows

Read when: You want to understand how ngit-grasp keeps nostr state and git data aligned across deletion, vanish, moderation, recovery, and purgatory flows


Planned Explanation Documentation

GRASP Protocol Design

Status: 🔜 Planned

Topics:

  • Why Nostr for Git?
  • Authorization model
  • Trust and verification
  • Decentralization benefits

Storage Architecture

Status: 🔜 Planned

Topics:

  • Why separate Git and Nostr storage?
  • Indexing strategy
  • Performance considerations
  • Scaling approach

Testing Philosophy

Status: 🔜 Planned

Topics:

  • Why test isolation?
  • Integration vs unit tests
  • Compliance testing approach
  • Test-driven development

Performance Considerations

Status: 🔜 Planned

Topics:

  • Async architecture
  • Caching strategy
  • Database choices
  • Bottlenecks and solutions

How to Use Explanation Documentation

  1. Read to understand - Not to accomplish a task
  2. Follow your curiosity - Read what interests you
  3. Connect concepts - Link ideas together
  4. Question and explore - Think critically

Not sure if this is what you need?


Contributing Explanation Documentation

When writing explanation:

DO:

  • ✅ Discuss concepts and ideas
  • ✅ Provide context and background
  • ✅ Explain alternatives
  • ✅ Use analogies and examples
  • ✅ Connect to broader context
  • ✅ Answer "why" questions

DON'T:

  • ❌ Provide step-by-step instructions (link to Tutorials/How-To)
  • ❌ List technical details (link to Reference)
  • ❌ Assume you must be comprehensive
  • ❌ Avoid opinions (explanation can be opinionated)

Template:

# Explanation: [Topic]

**Purpose:** [What concept/decision this explains]  
**Audience:** [Who wants to understand this]

---

## The Problem/Question

[What are we trying to understand?]

---

## Background

[Context and history]

---

## Our Approach

[How we address it]

### Why This Works

[Explanation of benefits]

### Trade-offs

[What we gain and lose]

---

## Alternatives Considered

### [Alternative 1]

**Pros:**
- [Benefits]

**Cons:**
- [Drawbacks]

**Why we didn't choose it:**
[Reasoning]

---

## Conclusion

[Summary of understanding]

---

## Related Documentation
- [Links to relevant docs]

See Diátaxis: Explanation for detailed guidance.


Part of the ngit-grasp documentation using the Diátaxis framework.