mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
313 lines
12 KiB
Markdown
313 lines
12 KiB
Markdown
# ngit-grasp
|
|
|
|
A [GRASP](https://gitworkshop.dev/danconwaydev.com/grasp) (Git Relays Authorized via Signed-Nostr Proofs) implementation in Rust.
|
|
|
|
## Overview
|
|
|
|
`ngit-grasp` is a Rust-based implementation of the GRASP protocol, which enables decentralized Git repository hosting with Nostr-based authorization. This implementation combines:
|
|
|
|
- **Git Smart HTTP Backend**: Serves Git repositories over HTTP
|
|
- **Nostr Relay**: Stores and validates repository announcements and state events
|
|
- **Integrated Authorization**: Validates Git pushes against Nostr state events without requiring external hooks
|
|
|
|
Unlike the reference implementation ([ngit-relay](https://gitworkshop.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-relay)) which uses nginx + git-http-backend + pre-receive hooks + Khatru (Go), `ngit-grasp` provides a unified Rust service that handles both Git and Nostr protocols natively.
|
|
|
|
## Status
|
|
|
|
**ALPHA** - Under active development. API and architecture subject to change.
|
|
|
|
## Key Features
|
|
|
|
- **Pure Rust Implementation**: Single binary, no external dependencies beyond Git itself
|
|
- **Integrated Authorization**: Push validation happens inline during the Git receive-pack operation
|
|
- **GRASP-01 Compliant**: Core service requirements for Git hosting with Nostr authorization
|
|
- **Extensible Architecture**: Designed to support GRASP-02 (Proactive Sync) and GRASP-05 (Archive) extensions
|
|
- **Developer-Friendly**: Built with modern Rust async patterns using tokio and actix-web
|
|
|
|
## Architecture Highlights
|
|
|
|
The key architectural decision is **inline authorization** rather than Git hooks:
|
|
|
|
- Vendored and customised `git-http-backend` crate provides low-level access to the Git protocol
|
|
- We intercept the `git-receive-pack` operation before spawning the Git process
|
|
- Push validation happens by checking the Nostr relay for the latest state event
|
|
- Only matching pushes are forwarded to the actual Git repository
|
|
|
|
This approach provides:
|
|
|
|
- **Better error messages**: Direct HTTP responses vs. hook stderr
|
|
- **Simpler deployment**: No hook management or symlinks
|
|
- **Tighter integration**: Shared state between Git and Nostr components
|
|
- **Easier testing**: Pure Rust unit and integration tests
|
|
|
|
## GRASP Compliance
|
|
|
|
### GRASP-01 (Core Service Requirements)
|
|
|
|
- ✅ NIP-01 compliant Nostr relay at `/`
|
|
- ✅ Accepts NIP-34 repository announcements and state events
|
|
- ✅ Git Smart HTTP service at `/<npub>/<identifier>.git`
|
|
- ✅ Push validation against Nostr state events
|
|
- ✅ Multi-maintainer support via recursive maintainer sets
|
|
- ✅ Support for `refs/nostr/<event-id>` for PRs
|
|
- ✅ CORS support for web-based Git clients
|
|
- ✅ NIP-11 relay information document
|
|
|
|
### GRASP-02 (Proactive Sync) - Planned
|
|
|
|
- 🔄 Proactive event sync from listed relays
|
|
- 🔄 Proactive Git data sync from listed clone URLs
|
|
- 🔄 PR data fetching and serving
|
|
|
|
### GRASP-05 (Archive) - Planned
|
|
|
|
- 🔄 Accept repositories not listing this instance
|
|
- 🔄 Backup/mirror mode operation
|
|
|
|
## Technology Stack
|
|
|
|
- **Rust**: Core language
|
|
- **actix-web**: HTTP server framework
|
|
- **git-http-backend**: Git protocol handling but vendored and customised for authorisation logic
|
|
- **nostr-relay-builder**: Nostr relay infrastructure from rust-nostr
|
|
- **nostr-sdk**: Nostr event handling and validation
|
|
- **tokio**: Async runtime
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# install ngit
|
|
curl -Ls https://ngit.dev/install.sh | bash
|
|
# Clone the repository
|
|
git clone nostr://danconwaydev.com/relay.ngit.dev/ngit-grasp
|
|
cd ngit-grasp
|
|
|
|
# Build (using Nix for reproducible environment)
|
|
nix develop -c cargo build --release
|
|
|
|
# Configure
|
|
cp .env.example .env
|
|
# Edit .env with your settings
|
|
|
|
# Run
|
|
nix develop -c cargo run --release
|
|
|
|
# Run tests
|
|
nix develop -c cargo test --lib
|
|
```
|
|
|
|
**Don't have Nix?** See [Getting Started Tutorial](docs/tutorials/getting-started.md) for alternative setup methods.
|
|
|
|
## Configuration
|
|
|
|
Configuration is loaded with the following priority (highest to lowest):
|
|
|
|
1. **CLI flags** (e.g., `--domain example.com`)
|
|
2. **Environment variables** (e.g., `NGIT_DOMAIN=example.com`)
|
|
3. **.env file** (loaded automatically if present)
|
|
4. **Built-in defaults**
|
|
|
|
This means CLI flags always take precedence over environment variables, which take precedence over `.env` file values.
|
|
|
|
### CLI Usage
|
|
|
|
```bash
|
|
# View all options with defaults
|
|
ngit-grasp --help
|
|
|
|
# Run with CLI flags (override everything else)
|
|
ngit-grasp --domain relay.example.com --owner-npub npub1... --bind-address 0.0.0.0:8080
|
|
|
|
# Mix CLI flags with environment variables
|
|
NGIT_OWNER_NPUB=npub1... ngit-grasp --domain relay.example.com
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
| Option | CLI Flag | Environment Variable | Default |
|
|
| ----------------- | --------------------- | ------------------------ | -------------------------------------------- |
|
|
| Domain | `--domain` | `NGIT_DOMAIN` | (required) |
|
|
| Owner npub | `--owner-npub` | `NGIT_OWNER_NPUB` | (optional) |
|
|
| Relay name | `--relay-name` | `NGIT_RELAY_NAME` | `${domain} grasp relay` |
|
|
| Relay description | `--relay-description` | `NGIT_RELAY_DESCRIPTION` | `Git Nostr Relay - a grasp implementation` |
|
|
| Git data path | `--git-data-path` | `NGIT_GIT_DATA_PATH` | `./data/git` (temp dir for memory backend) |
|
|
| Relay data path | `--relay-data-path` | `NGIT_RELAY_DATA_PATH` | `./data/relay` (temp dir for memory backend) |
|
|
| Bind address | `--bind-address` | `NGIT_BIND_ADDRESS` | `127.0.0.1:8080` |
|
|
| Database backend | `--database-backend` | `NGIT_DATABASE_BACKEND` | `lmdb` |
|
|
|
|
### Database Backends
|
|
|
|
- `lmdb`: LMDB backend (default, persistent, general purpose)
|
|
- `memory`: In-memory database (fastest, no persistence - uses temp directories)
|
|
- `nostrdb`: NostrDB backend (persistent, optimized for Nostr) [Not yet implemented]
|
|
|
|
> **Note:** When using the `memory` backend, git data are automatically stored in temporary directories for ephemeral testing. This is useful for development and CI/CD pipelines.
|
|
|
|
### Example: Production Deployment
|
|
|
|
```bash
|
|
# Using environment variables (recommended for production)
|
|
export NGIT_DOMAIN=gitnostr.com
|
|
export NGIT_OWNER_NPUB=npub1...
|
|
export NGIT_BIND_ADDRESS=0.0.0.0:8080
|
|
export NGIT_DATABASE_BACKEND=lmdb
|
|
ngit-grasp
|
|
```
|
|
|
|
### Example: Development
|
|
|
|
```bash
|
|
# Using .env file
|
|
cp .env.example .env
|
|
# Edit .env with your settings
|
|
ngit-grasp
|
|
|
|
# Or override specific values with CLI flags
|
|
ngit-grasp --domain localhost:3000 --bind-address 127.0.0.1:3000
|
|
```
|
|
|
|
## Documentation
|
|
|
|
We use the **[Diátaxis](https://diataxis.fr/)** framework for documentation:
|
|
|
|
- **[Tutorials](docs/tutorials/)** - Learn by doing (Getting Started, First Audit)
|
|
- **[How-To Guides](docs/how-to/)** - Solve specific problems (Deploy, Configure)
|
|
- **[Reference](docs/reference/)** - Look up technical details (Config, Protocols)
|
|
- **[Explanation](docs/explanation/)** - Understand concepts (Architecture, Decisions)
|
|
|
|
**Start here:** [Documentation Index](docs/README.md)
|
|
|
|
## Development
|
|
|
|
See [Architecture Overview](docs/explanation/architecture.md) for system design and [Test Strategy](docs/reference/test-strategy.md) for testing approach.
|
|
|
|
### Running Tests
|
|
|
|
We have two test suites:
|
|
|
|
**1. Main Project Tests (ngit-grasp)**
|
|
|
|
```bash
|
|
# Run unit tests (no external dependencies)
|
|
nix develop -c cargo test --lib
|
|
|
|
# Run all integration tests (automatic relay management)
|
|
nix develop -c cargo test --test nip01_compliance --test nip34_announcements
|
|
|
|
# Run NIP-01 compliance tests
|
|
nix develop -c cargo test --test nip01_compliance
|
|
|
|
# Run NIP-34 announcement tests
|
|
nix develop -c cargo test --test nip34_announcements
|
|
|
|
# With detailed output
|
|
nix develop -c cargo test --test nip01_compliance -- --nocapture
|
|
|
|
# Run specific test
|
|
nix develop -c cargo test --test nip01_compliance test_nip01_smoke
|
|
```
|
|
|
|
**Integration tests automatically:**
|
|
|
|
- Start a fresh relay instance
|
|
- Run compliance tests using grasp-audit library
|
|
- Clean up when done
|
|
- No manual relay management needed!
|
|
|
|
**2. GRASP Audit Tool (grasp-audit)**
|
|
|
|
The audit tool tests GRASP compliance of any relay (including ours or external ones).
|
|
|
|
```bash
|
|
# Enter grasp-audit directory
|
|
cd grasp-audit
|
|
|
|
# Run unit tests
|
|
nix develop -c cargo test
|
|
|
|
# Test against any relay (including external ones)
|
|
nix develop -c cargo run -- --url wss://relay.example.com
|
|
|
|
# Or test against any external relay:
|
|
nix develop -c cargo run -- --url wss://relay.example.com
|
|
```
|
|
|
|
### Development Commands
|
|
|
|
```bash
|
|
# Run with logging
|
|
RUST_LOG=debug nix develop -c cargo run
|
|
|
|
# Check code
|
|
nix develop -c cargo clippy
|
|
nix develop -c cargo fmt --check
|
|
|
|
# Generate test coverage (requires tarpaulin)
|
|
nix develop -c cargo tarpaulin --out Html
|
|
```
|
|
|
|
**Note:** Always use `nix develop` to ensure the correct build environment. See [docs/how-to/nix-flakes.md](docs/how-to/nix-flakes.md) for details.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
ngit-grasp/
|
|
├── src/
|
|
│ ├── main.rs # Entry point, server setup
|
|
│ ├── git/
|
|
│ │ ├── mod.rs # Git module
|
|
│ │ ├── handler.rs # Git HTTP handlers
|
|
│ │ └── authorization.rs # Push validation logic
|
|
│ ├── nostr/
|
|
│ │ ├── mod.rs # Nostr module
|
|
│ │ ├── relay.rs # Relay setup and policies
|
|
│ │ └── events.rs # Event handlers
|
|
│ ├── storage/
|
|
│ │ ├── mod.rs # Storage abstraction
|
|
│ │ └── repository.rs # Repository management
|
|
│ └── config.rs # Configuration
|
|
├── docs/
|
|
│ └── ARCHITECTURE.md # Detailed architecture
|
|
├── tests/
|
|
│ ├── integration/ # Integration tests
|
|
│ └── fixtures/ # Test data
|
|
└── README.md
|
|
```
|
|
|
|
## Comparison with ngit-relay
|
|
|
|
| Feature | ngit-relay (Go) | ngit-grasp (Rust) |
|
|
| ------------- | ----------------------------------------- | ----------------------------- |
|
|
| Language | Go | Rust |
|
|
| Components | nginx + git-http-backend + hooks + Khatru | Single integrated binary |
|
|
| Authorization | Pre-receive Git hook | Inline during receive-pack |
|
|
| Deployment | Docker + supervisord | Single binary |
|
|
| Testing | Go tests + shell scripts | Rust unit + integration tests |
|
|
| Performance | Good | Excellent (zero-copy, async) |
|
|
|
|
## Contributing
|
|
|
|
Contributions welcome! Please:
|
|
|
|
1. Read [docs/explanation/architecture.md](docs/ARCHITECTURE.md)
|
|
2. Open an issue to discuss major changes
|
|
3. Follow Rust conventions and run `cargo fmt` + `cargo clippy`
|
|
4. Add tests for new functionality
|
|
|
|
## License
|
|
|
|
MIT License - see [LICENSE](LICENSE) for details
|
|
|
|
## Related Projects
|
|
|
|
- [GRASP Protocol](https://gitworkshop.dev/danconwaydev.com/grasp) - Protocol specification
|
|
- [ngit-relay](https://gitworkshop.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-relay) - Reference implementation in Go
|
|
- [ngit](https://gitworkshop.dev/ngit) - Nostr Git plugin for git CLI
|
|
- [NIP-34](https://nips.nostr.com/34) - Git Stuff (Nostr protocol)
|
|
|
|
## Acknowledgments
|
|
|
|
- Reference implementation by [@DanConwayDev](https://gitworkshop.dev/danconwaydev.com)
|
|
- [rust-nostr](https://github.com/rust-nostr/nostr) team for excellent Nostr libraries
|
|
- Git community for the Smart HTTP protocol
|