Files
ngit-grasp/.env.example
T
DanConwayDev c29191b1e1 feat(grasp-05): implement archive mode for backup/mirror operation
Implements GRASP-05 specification for accepting repository announcements
that don't list this relay, enabling archive, mirror, and backup use cases.

Core Features:
- Three whitelist formats: <npub>, <npub>/<identifier>, <identifier>
- Archive-all mode for complete ecosystem mirrors
- Fail-fast npub validation at startup
- Read-only enforcement (archived repos reject pushes)
- Full GRASP-02 sync (git data + Nostr events)
- Dynamic archive status (no flags/metadata)

Implementation:
- Add ArchiveWhitelistEntry enum with Pubkey/Repository/Identifier variants
- Add ArchiveConfig with validation and matching logic
- Update AnnouncementResult to include AcceptArchive variant
- Refactor validate_announcement() to return AnnouncementResult with archive check
- Update AnnouncementPolicy with catch-all pattern for cleaner code
- Wire archive config through builder and policy layers

Configuration:
- NGIT_ARCHIVE_ALL: Accept all announcements (⚠️ storage risk)
- NGIT_ARCHIVE_WHITELIST: Comma-separated whitelist entries
- Updated docs, .env.example, and nix/module.nix

Testing:
- 28 unit tests for config parsing and whitelist matching
- 7 integration tests for archive mode validation
- All 296 tests passing

Validation Priority:
1. Lists our service → Accept (GRASP-01, read/write)
2. Is maintainer → AcceptMaintainer (multi-maintainer, read/write)
3. Matches archive config → AcceptArchive (GRASP-05, read-only)
4. None of above → Reject

Security Considerations:
- Archive-all mode has storage/bandwidth DoS risk
- Identifier-only format matches any pubkey (use npub/identifier for high-value)
- Invalid npubs cause startup failure (fail-fast)

Documentation:
- Concise explanation focused on rationale
- Reference docs updated with all config options
- README updated to reflect completed feature
- Removed from roadmap, added to compliance section

See docs/explanation/grasp-05-archive.md for details.
2026-01-12 17:40:25 +00:00

192 lines
7.3 KiB
Bash

# ngit-grasp Configuration
#
# Configuration Priority (highest to lowest):
# 1. CLI flags (e.g., --domain example.com)
# 2. Environment variables (e.g., NGIT_DOMAIN=example.com)
# 3. This .env file
# 4. Built-in defaults
#
# Run `ngit-grasp --help` for all CLI options
# ============================================================================
# REQUIRED
# ============================================================================
# Domain where this instance is hosted (required, used in GRASP validation)
# CLI: --domain <domain>
# No default - must be set
# NGIT_DOMAIN=
# ============================================================================
# SERVER CONFIGURATION
# ============================================================================
# Server bind address (IP:PORT)
# CLI: --bind-address <address>
# Default: 127.0.0.1:8080
# NGIT_BIND_ADDRESS=127.0.0.1:8080
# ============================================================================
# RELAY INFORMATION (NIP-11)
# ============================================================================
# Relay operator's nsec (private key) for signing and authentication
# Used for:
# - NIP-11 relay information document (pubkey field derived from this nsec)
# - NIP-42 authentication when syncing from other relays
# - Future: signing events, WoT-based rate limiting of syncing relays
#
# CLI: --relay-owner-nsec <nsec>
# Default: Loaded from/saved to .relay-owner.nsec file in current directory
# If file doesn't exist, a new key is generated and saved automatically
# NGIT_RELAY_OWNER_NSEC=nsec1...
# Relay name shown in NIP-11 information document
# CLI: --relay-name <name>
# Default: ${domain} grasp relay (e.g., "gitnostr.com grasp relay")
# NGIT_RELAY_NAME=My GRASP Relay
# Relay description shown in NIP-11 information document
# CLI: --relay-description <description>
# Default: Git Nostr Relay - a grasp implementation
# NGIT_RELAY_DESCRIPTION="A GRASP-compliant Git relay with Nostr authorization"
# ============================================================================
# STORAGE
# ============================================================================
# Path to store Git repositories
# CLI: --git-data-path <path>
# Default: ./data/git
# NGIT_GIT_DATA_PATH=./data/git
# Path to store Nostr relay data
# CLI: --relay-data-path <path>
# Default: ./data/relay
# NGIT_RELAY_DATA_PATH=./data/relay
# Database backend for Nostr events
# CLI: --database-backend <backend>
# Options: lmdb, memory, nostrdb
# Default: lmdb
# - lmdb: LMDB backend (persistent, general purpose) - RECOMMENDED
# - memory: In-memory database (fastest, no persistence, uses temp dirs)
# - nostrdb: NostrDB backend (persistent, Nostr-optimized) [Not yet implemented]
#
# Note: When using 'memory' backend, git_data_path and relay_data_path
# are automatically set to temporary directories for ephemeral testing.
# NGIT_DATABASE_BACKEND=lmdb
# ============================================================================
# METRICS
# ============================================================================
# Enable Prometheus metrics endpoint at /metrics
# CLI: --metrics-enabled
# Default: true
# NGIT_METRICS_ENABLED=true
# Connections per IP before flagging as potential abuse in metrics
# (display only, no rate limiting - purely for monitoring visibility)
# CLI: --metrics-connection-per-ip-abuse-threshold <count>
# Default: 10
# NGIT_METRICS_CONNECTION_PER_IP_ABUSE_THRESHOLD=10
# Number of top bandwidth repositories to track in metrics
# CLI: --metrics-top-n-repos <count>
# Default: 10
# NGIT_METRICS_TOP_N_REPOS=10
# ============================================================================
# LOGGING
# ============================================================================
# Rust log level (not a ngit-grasp config, but useful for debugging)
# Options: error, warn, info, debug, trace
# RUST_LOG=info
# ============================================================================
# PROACTIVE SYNC (GRASP-02)
# ============================================================================
# Bootstrap relay URL for initial sync (optional)
# Additional relays are automatically discovered from repository announcements
# that list our service domain.
# CLI: --sync-bootstrap-relay-url <url>
# Default: (none - relay discovery from stored announcements only)
# NGIT_SYNC_BOOTSTRAP_RELAY_URL=wss://relay.example.com
# Maximum backoff time in seconds for sync relay reconnection
# CLI: --sync-max-backoff-secs <seconds>
# Default: 3600 (1 hour)
# NGIT_SYNC_MAX_BACKOFF_SECS=3600
# Interval in seconds for checking disconnected relays and attempting reconnection
# Set to lower value for faster reconnection testing
# CLI: --sync-disconnect-check-interval-secs <seconds>
# Default: 60
# NGIT_SYNC_DISCONNECT_CHECK_INTERVAL_SECS=60
# Base backoff time in seconds for relay reconnection
# Used for exponential backoff: base * 2^(failures-1)
# Set to 1 for faster test cycles
# Note: The connection timeout is capped at this value
# CLI: --sync-base-backoff-secs <seconds>
# Default: 5
# NGIT_SYNC_BASE_BACKOFF_SECS=5
# Disable NIP-77 negentropy sync (use REQ+EOSE instead)
# When enabled, sync will use REQ+EOSE instead of negentropy for history sync
# Primarily useful for testing that sync works without negentropy support
# CLI: --sync-disable-negentropy
# Default: false
# NGIT_SYNC_DISABLE_NEGENTROPY=false
# ============================================================================
# REJECTED EVENTS INDEX
# ============================================================================
# Hot cache duration in seconds for rejected announcements
# Stores full event objects for immediate re-processing when dependencies resolve
# Too short (<30s): Miss events from slow relays
# Too long (>5min): Waste memory
# CLI: --rejected-hot-cache-duration-secs <seconds>
# Default: 120 (2 minutes)
# NGIT_REJECTED_HOT_CACHE_DURATION_SECS=120
# Cold index expiry in seconds for rejected announcements
# Stores metadata only to prevent repeated downloads of rejected events
# CLI: --rejected-cold-index-expiry-secs <seconds>
# Default: 604800 (7 days)
# NGIT_REJECTED_COLD_INDEX_EXPIRY_SECS=604800
# Hours before removing relay from naughty list
# Relays with persistent infrastructure issues (DNS, TLS, protocol errors) are
# tracked separately and retried after this expiration period
# CLI: --naughty-list-expiration-hours <hours>
# Default: 12
# NGIT_NAUGHTY_LIST_EXPIRATION_HOURS=12
# ============================================================================
# GRASP-05 ARCHIVE MODE
# ============================================================================
# Accept all repository announcements (⚠️ WARNING: Storage/bandwidth risk)
# When enabled, any repository can be mirrored to this relay
# CLI: --archive-all
# Default: false
# NGIT_ARCHIVE_ALL=false
# Whitelist specific repos/pubkeys/identifiers for archiving
# Comma-separated list supporting three formats:
# <npub> - Archive all repos from this pubkey
# <npub>/<identifier> - Archive specific repo
# <identifier> - Archive repos with this identifier (any pubkey)
#
# CLI: --archive-whitelist <list>
# Default: (empty)
# Examples:
# NGIT_ARCHIVE_WHITELIST=npub1alice...
# NGIT_ARCHIVE_WHITELIST=npub1alice...,npub1bob.../linux
# NGIT_ARCHIVE_WHITELIST=bitcoin-core,linux,rust
# NGIT_ARCHIVE_WHITELIST=