|
|
4 weeks ago | |
|---|---|---|
| src | 4 weeks ago | |
| static | 4 weeks ago | |
| .gitignore | 4 weeks ago | |
| IMPLEMENTATION.md | 4 weeks ago | |
| NIP-34.md | 4 weeks ago | |
| README.md | 4 weeks ago | |
| package-lock.json | 4 weeks ago | |
| package.json | 4 weeks ago | |
| svelte.config.js | 4 weeks ago | |
| tsconfig.json | 4 weeks ago | |
| vite.config.ts | 4 weeks ago | |
README.md
gitrepublic-web
A decentralized, Nostr-based git server that enables git repository hosting and collaboration using Nostr events. Repositories are announced via NIP-34, and all operations (clone, push, pull) are authenticated using NIP-98 HTTP authentication.ne
Features
Core Functionality
- NIP-34 Repo Announcements: Create and manage repository announcements on Nostr
- NIP-07 Authentication: Web UI authentication via browser extensions (e.g., Alby, nos2x)
- NIP-98 HTTP Authentication: Git operations (clone, push, pull) authenticated using ephemeral Nostr events
- Auto-provisioning: Automatically creates git repositories from NIP-34 announcements
- Multi-remote Sync: Automatically syncs repositories to multiple remotes listed in announcements
- Repository Size Limits: Enforces 2 GB maximum repository size
- Relay Write Proof: Verifies users can write to at least one default Nostr relay before allowing operations
Repository Management
- Repository Ownership Transfer: Transfer ownership using kind 1641 events with a chain of ownership
- Private Repositories: Mark repositories as private, limiting access to owners and maintainers
- Maintainer Management: Add/remove maintainers who can push to repositories
- Forking: Fork repositories with automatic announcement creation and ownership setup
- Repository Settings: Manage privacy, maintainers, and description via web UI
Collaboration Features
- Issues: Create and manage issues (kind 1621) with status tracking
- Pull Requests: Create pull requests (kind 1618) with status management
- Highlights & Comments:
- NIP-84 highlights (kind 9802) for code selections
- NIP-22 comments (kind 1111) for threaded discussions
- Comment on PRs, issues, and code highlights
- Status Events: Track issue/PR status (open, applied/merged, closed, draft)
Web Interface
- Repository Browser: Browse files, directories, and commit history
- Code Editor: Edit files directly in the browser with syntax highlighting
- Branch Management: Create, switch, and manage branches
- Tag Management: Create and view git tags
- README Rendering: Automatic markdown rendering for README files
- Search: Search repositories by name, description, or author
- User Profiles: View user repositories and activity
- Raw File View: Direct access to raw file content
- Download Repository: Download repositories as ZIP archives
- OpenGraph Metadata: Rich social media previews with repository images and banners
Security & Validation
- Path Traversal Protection: Validates and sanitizes file paths
- Input Validation: Validates commit messages, author names, emails, and file paths
- File Size Limits: 500 MB maximum per file (allows for images and demo videos)
- Ownership Verification: Verifies repository ownership via self-transfer events or verification files
- Commit Signing: Sign commits using Nostr private keys (nsec or hex format)
- Supports both bech32 (nsec) and hex format keys
- Signatures embedded in commit messages as trailers
- Server-side signing via
NOSTRGIT_SECRET_KEYenvironment variable - Client-side signing via optional
nsecKeyparameter in API requests
Nostr Event Kinds Used
This project uses the following Nostr event kinds:
Repository Management
- 30617 (
REPO_ANNOUNCEMENT): Repository announcements (NIP-34)- Tags:
d(repo name),name,description,clone,web,relays,maintainers,image,banner,private
- Tags:
- 30618 (
REPO_STATE): Repository state announcements (optional) - 1641 (
OWNERSHIP_TRANSFER): Repository ownership transfer events (non-replaceable)- Transfers ownership from one pubkey to another
- Self-transfers (owner → owner) used for initial ownership proof
- Non-replaceable to maintain immutable chain of ownership
Collaboration
- 1617 (
PATCH): Git patches - 1618 (
PULL_REQUEST): Pull request events - 1619 (
PULL_REQUEST_UPDATE): Pull request updates - 1621 (
ISSUE): Issue events - 1630 (
STATUS_OPEN): Open status - 1631 (
STATUS_APPLIED): Applied/merged status - 1632 (
STATUS_CLOSED): Closed status - 1633 (
STATUS_DRAFT): Draft status - 1640 (
COMMIT_SIGNATURE): Git commit signature events- Tags:
author(name, email),message(commit message),commit(commit hash),e(NIP-98 auth event reference, optional)
- Tags:
Highlights & Comments
- 9802 (
HIGHLIGHT): NIP-84 highlight events for code selections- Tags:
a(anchor),r(range),p(position),context,file,start_line,end_line,start_pos,end_pos
- Tags:
- 1111 (
COMMENT): NIP-22 comment events for threaded discussions- Tags:
A(root event),K(root kind),P(parent event),a,k,p(for replies)
- Tags:
Authentication
- 27235 (
NIP98_AUTH): NIP-98 HTTP authentication events- Tags:
u(URL),method(HTTP method),payload(SHA256 hash of request body)
- Tags:
Relay Discovery
- 3: Contact list (for relay discovery)
- 10002: Relay list metadata (for relay discovery)
- 1: Text note (for relay write proof, fallback)
How It Works
Repository Creation Flow
-
User Creates Announcement:
- User visits
/signupand connects NIP-07 extension - Enters repository name, description, and optional clone URLs
- System automatically creates a self-transfer event (kind 1641) for initial ownership proof
- Both announcement and self-transfer are published to Nostr relays
- User visits
-
Auto-Provisioning:
- Server polls Nostr relays for new repository announcements (kind 30617)
- When found, server:
- Creates a bare git repository at
/repos/{npub}/{repo-name}.git - Fetches the self-transfer event for ownership verification
- Creates initial commit with
.nostr-ownership-transferfile containing the self-transfer event - Creates
.nostr-verificationfile with the announcement event (for backward compatibility) - If repository has
clonetags pointing to other remotes, syncs from those remotes
- Creates a bare git repository at
-
Repository Access:
- Public repositories: Anyone can clone and view
- Private repositories: Only owners and maintainers can access
- Access is checked via NIP-98 authentication for git operations
Git Operations Flow
-
Clone/Fetch:
- User runs
git clone https://{domain}/{npub}/{repo}.git - Server handles GET requests to
info/refs?service=git-upload-pack - For private repos, verifies NIP-98 authentication
- Proxies request to
git-http-backendwhich serves the repository
- User runs
-
Push:
- User configures git with NIP-98 authentication
- Before push, client creates a NIP-98 event (kind 27235) with:
utag: Request URLmethodtag: HTTP method (POST)payloadtag: SHA256 hash of request body
- Client signs event and includes in
Authorization: Nostr {event}header - Server verifies:
- Event signature
- Event timestamp (within 60 seconds)
- URL and method match
- Payload hash matches request body
- Pubkey is current owner or maintainer
- Server checks repository size limit (2 GB)
- Server proxies to
git-http-backend - After successful push, server:
- Extracts other
cloneURLs from announcement - Syncs to all other remotes using
git push --all
- Extracts other
Ownership Transfer Flow
-
Current Owner Initiates Transfer:
- Owner creates a kind 1641 event with:
fromtag: Current owner pubkeytotag: New owner pubkeyatag: Repository identifier (30617:{owner}:{repo})
- Signs and publishes event
- Owner creates a kind 1641 event with:
-
Server Processes Transfer:
- Server fetches all ownership transfer events for repository
- Validates chain of ownership chronologically
- Updates current owner for all permission checks
- Maintainers remain valid (checked against current owner)
Pull Requests & Issues Flow
-
Creating a PR/Issue:
- User creates a kind 1618 (PR) or 1621 (Issue) event
- Includes repository identifier in tags
- Publishes to Nostr relays
-
Status Management:
- Owner/maintainer creates status events (kind 1630-1633)
- Links to PR/Issue via event references
- Status changes: open → applied/closed/draft
-
Highlights & Comments:
- User selects code in PR diff view
- Creates kind 9802 highlight event with code selection metadata
- Users can comment on highlights using kind 1111 events
- Comments are threaded using
A,K,Ptags (root) anda,k,ptags (parent)
Forking Flow
-
User Forks Repository:
- User clicks "Fork" button on repository page
- Server:
- Clones original repository
- Creates new repository at
/repos/{user-npub}/{fork-name}.git - Creates new NIP-34 announcement for fork
- Creates self-transfer event for fork ownership
- Publishes both to Nostr relays
-
Fork Identification:
- Fork announcement includes reference to original repository
- UI displays "Forked from" badge
Private Repository Access
-
Privacy Setting:
- Repository announcement includes
privatetag (orttag with valueprivate) - Server marks repository as private
- Repository announcement includes
-
Access Control:
- All API endpoints check privacy status
- For private repos, requires NIP-98 authentication
- Verifies user is current owner or listed maintainer
- Returns 403 if unauthorized
Relay Write Proof
Instead of traditional rate limiting, users must prove they can write to at least one default Nostr relay:
-
Proof Mechanism:
- User publishes a NIP-98 event (kind 27235) to a default relay
- Event must be within 60 seconds (per NIP-98 spec)
- Server verifies event exists on relay
- Alternative: User publishes kind 1 text note (5-minute window)
-
Verification:
- Server queries relay for the proof event
- Validates timestamp and signature
- Grants access if proof is valid
Architecture
Frontend
- Framework: SvelteKit + TypeScript
- Authentication: NIP-07 browser extension integration
- Components: Code editor, PR detail view, repository browser
Backend
- Git Server:
git-http-backendwrapper for git operations - Authentication: NIP-98 HTTP authentication for git operations
- Repository Management: Automatic provisioning and syncing
- Nostr Integration: WebSocket client for relay communication
Services
- NostrClient: WebSocket client for fetching and publishing Nostr events
- RepoManager: Server-side repository provisioning, syncing, and size management
- FileManager: File operations within git repositories with validation
- CommitSigner: Git commit signing using Nostr keys (supports nsec and hex formats)
- OwnershipTransferService: Manages repository ownership transfers
- MaintainerService: Checks maintainer permissions and privacy settings
- HighlightsService: Manages NIP-84 highlights and NIP-22 comments
- RelayWriteProof: Verifies user can write to Nostr relays
Project Structure
src/
├── lib/
│ ├── services/
│ │ ├── nostr/
│ │ │ ├── nostr-client.ts # WebSocket client for Nostr relays
│ │ │ ├── nip07-signer.ts # NIP-07 browser extension integration
│ │ │ ├── nip98-auth.ts # NIP-98 HTTP authentication
│ │ │ ├── repo-polling.ts # Auto-provision repos from announcements
│ │ │ ├── user-relays.ts # Fetch user's preferred relays
│ │ │ ├── ownership-transfer-service.ts # Repository ownership transfers
│ │ │ ├── maintainer-service.ts # Maintainer permission checks
│ │ │ ├── highlights-service.ts # NIP-84 highlights & NIP-22 comments
│ │ │ ├── relay-write-proof.ts # Relay write proof verification
│ │ │ ├── prs-service.ts # Pull request management
│ │ │ └── issues-service.ts # Issue management
│ │ └── git/
│ │ ├── repo-manager.ts # Repository provisioning & syncing
│ │ └── file-manager.ts # File operations with validation
│ ├── components/
│ │ ├── CodeEditor.svelte # Code editor with syntax highlighting
│ │ └── PRDetail.svelte # Pull request detail view
│ └── types/
│ └── nostr.ts # TypeScript types for Nostr events
├── routes/
│ ├── +page.svelte # Main page: list repositories
│ ├── signup/
│ │ └── +page.svelte # Create/update repo announcements
│ ├── repos/[npub]/[repo]/
│ │ ├── +page.svelte # Repository detail page
│ │ ├── +page.ts # OpenGraph metadata loader
│ │ └── settings/
│ │ └── +page.svelte # Repository settings UI
│ ├── users/[npub]/
│ │ └── +page.svelte # User profile page
│ ├── search/
│ │ └── +page.svelte # Search interface
│ └── api/
│ ├── git/[...path]/
│ │ └── +server.ts # Git HTTP backend API
│ └── repos/[npub]/[repo]/
│ ├── file/+server.ts # File read/write API
│ ├── tree/+server.ts # Directory listing API
│ ├── branches/+server.ts # Branch management API
│ ├── commits/+server.ts # Commit history API
│ ├── tags/+server.ts # Tag management API
│ ├── issues/+server.ts # Issues API
│ ├── prs/+server.ts # Pull requests API
│ ├── highlights/+server.ts # Highlights & comments API
│ ├── fork/+server.ts # Fork repository API
│ ├── readme/+server.ts # README fetching API
│ ├── raw/+server.ts # Raw file view API
│ ├── download/+server.ts # Download repository as ZIP
│ ├── settings/+server.ts # Repository settings API
│ ├── transfer/+server.ts # Ownership transfer API
│ └── verify/+server.ts # Ownership verification API
└── hooks.server.ts # Server initialization (starts polling)
Development
Prerequisites
- Node.js 18+
- Git with
git-http-backendinstalled - NIP-07 browser extension (for web UI)
Setup
npm install
npm run dev
Environment Variables
NOSTRGIT_SECRET_KEY: Server's nsec (bech32 or hex) for signing repo announcements and initial commits (optional)GIT_REPO_ROOT: Path to store git repositories (default:/repos)GIT_DOMAIN: Domain for git repositories (default:localhost:6543)NOSTR_RELAYS: Comma-separated list of Nostr relays (default:wss://theforest.nostr1.com,wss://nostr.land,wss://relay.damus.io)
Git HTTP Backend Setup
The server uses git-http-backend for git operations. Ensure it's installed:
# On Debian/Ubuntu
sudo apt-get install git
# Verify installation
which git-http-backend
The server will automatically locate git-http-backend in common locations.
Usage
Creating a Repository
- Go to
/signup - Connect your NIP-07 extension
- Enter repository name and description
- Optionally add clone URLs (your domain will be added automatically)
- Optionally add images/banners for OpenGraph previews
- Publish the announcement
The server will automatically provision the repository.
Cloning a Repository
git clone https://{domain}/{npub}/{repo-name}.git
For private repositories, configure git with NIP-98 authentication.
Pushing to a Repository
git remote add origin https://{domain}/{npub}/{repo-name}.git
git push origin main
Requires NIP-98 authentication. Your git client needs to support NIP-98 or you can use a custom credential helper.
Viewing Repositories
- Go to
/to see all public repositories - Go to
/repos/{npub}/{repo}to view a specific repository - Go to
/users/{npub}to view a user's repositories - Go to
/searchto search for repositories
Managing Repositories
- Settings: Visit
/repos/{npub}/{repo}/settingsto manage privacy, maintainers, and description - Forking: Click "Fork" button on repository page
- Transfer Ownership: Use the transfer API endpoint or create a kind 1641 event manually
Security Considerations
- Path Traversal: All file paths are validated and sanitized
- Input Validation: Commit messages, author info, and file paths are validated
- Size Limits: 2 GB per repository, 100 MB per file
- Authentication: All write operations require NIP-98 authentication
- Authorization: Ownership and maintainer checks for all operations
- Private Repositories: Access restricted to owners and maintainers
License
[Add your license here]
Contributing
[Add contribution guidelines here]