From 2eaff5b79fed364d5eba5eb38e4b7bf76326884d Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 3 Dec 2025 11:19:40 +0000 Subject: remove docs archive --- .../2025-11-04-authorization-flow-diagram.txt | 299 --------------------- 1 file changed, 299 deletions(-) delete mode 100644 docs/archive/2025-11-04-evening/2025-11-04-authorization-flow-diagram.txt (limited to 'docs/archive/2025-11-04-evening/2025-11-04-authorization-flow-diagram.txt') diff --git a/docs/archive/2025-11-04-evening/2025-11-04-authorization-flow-diagram.txt b/docs/archive/2025-11-04-evening/2025-11-04-authorization-flow-diagram.txt deleted file mode 100644 index 10fb529..0000000 --- a/docs/archive/2025-11-04-evening/2025-11-04-authorization-flow-diagram.txt +++ /dev/null @@ -1,299 +0,0 @@ -╔═══════════════════════════════════════════════════════════════════════════════╗ -║ GIT PUSH AUTHORIZATION FLOW (INLINE) ║ -╚═══════════════════════════════════════════════════════════════════════════════╝ - -┌─────────────────────────────────────────────────────────────────────────────┐ -│ CLIENT: git push │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - │ HTTP POST - │ /npub/repo.git/git-receive-pack - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ ACTIX-WEB ROUTER (git-http-backend) │ -│ │ -│ Route: /{namespace}/{repo}/git-receive-pack │ -│ Handler: git_receive_pack() │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 1: RESOLVE REPOSITORY PATH │ -│ │ -│ GitConfig::rewrite("/npub/repo") → /data/git/npub/repo.git │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 2: VALIDATE REPOSITORY EXISTS │ -│ │ -│ ✓ Check HEAD exists │ -│ ✓ Check config exists │ -│ ✓ Check bare = true │ -│ │ -│ ❌ If not: Return 400 "Repository not found" │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 3: READ REQUEST BODY (MODIFIED) │ -│ │ -│ • Read full request body into memory │ -│ • Decode gzip if Content-Encoding: gzip │ -│ • Store in body_data: Vec │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 4: PARSE REF UPDATES (NEW!) │ -│ │ -│ parse_receive_pack_request(&body_data) → Vec │ -│ │ -│ Git Pack Protocol: │ -│ ┌──────────────────────────────────────────────────────────────┐ │ -│ │ 0000000000000000000000000000000000000000 a1b2c3d4e5f6... │ │ -│ │ refs/heads/main\0 report-status\n │ │ -│ │ │ │ -│ │ old_oid: 0000... (new branch) │ │ -│ │ new_oid: a1b2c3d4e5f6... │ │ -│ │ ref_name: refs/heads/main │ │ -│ └──────────────────────────────────────────────────────────────┘ │ -│ │ -│ Result: RefUpdate { │ -│ old_oid: "0000...", │ -│ new_oid: "a1b2c3d4e5f6...", │ -│ ref_name: "refs/heads/main" │ -│ } │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 5: VALIDATE AUTHORIZATION (NEW!) │ -│ │ -│ validator.validate_push(npub, identifier, &ref_updates).await │ -│ │ -│ ┌────────────────────────────────────────────────────────────┐ │ -│ │ PushValidator::validate_push() │ │ -│ │ │ │ -│ │ 1. Get latest state event from Nostr relay │ │ -│ │ • Query: kind=30618, d=identifier, author=npub │ │ -│ │ • Extract refs from state event │ │ -│ │ │ │ -│ │ 2. For each ref update: │ │ -│ │ • If refs/heads/* or refs/tags/*: │ │ -│ │ - Check state event has matching ref │ │ -│ │ - Check new_oid matches state event oid │ │ -│ │ - ❌ Reject if mismatch │ │ -│ │ • If refs/nostr/*: │ │ -│ │ - ✅ Always allow (PRs) │ │ -│ │ │ │ -│ │ 3. Get maintainers (recursive) │ │ -│ │ • Extract maintainers from announcement │ │ -│ │ • Recursively resolve maintainer sets │ │ -│ │ • Check if pusher is in maintainer list │ │ -│ │ • ❌ Reject if not maintainer │ │ -│ │ │ │ -│ │ 4. Return Ok(()) or Err(message) │ │ -│ └────────────────────────────────────────────────────────────┘ │ -│ │ -│ ❌ If validation fails: │ -│ Return 403 Forbidden │ -│ { │ -│ "error": "unauthorized", │ -│ "message": "Push rejected: refs/heads/main points to ..., state has..."│ -│ } │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - │ ✅ AUTHORIZED - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ STEP 6: SPAWN GIT RECEIVE-PACK (EXISTING) │ -│ │ -│ Command::new("git") │ -│ .arg("receive-pack") │ -│ .arg("--stateless-rpc") │ -│ .arg(".") │ -│ .current_dir(&repo_path) │ -│ .spawn() │ -│ │ -│ • Write body_data to git stdin │ -│ • Stream git stdout back to client │ -└────────────────────────────────┬────────────────────────────────────────────┘ - │ - │ Stream response - ▼ -┌─────────────────────────────────────────────────────────────────────────────┐ -│ CLIENT: git push success │ -└─────────────────────────────────────────────────────────────────────────────┘ - - -╔═══════════════════════════════════════════════════════════════════════════════╗ -║ COMPARISON: BEFORE vs AFTER ║ -╚═══════════════════════════════════════════════════════════════════════════════╝ - -┌─────────────────────────────────┬─────────────────────────────────────────┐ -│ BEFORE (git-http-backend) │ AFTER (our fork) │ -├─────────────────────────────────┼─────────────────────────────────────────┤ -│ 1. Resolve path │ 1. Resolve path │ -│ 2. Check bare repo │ 2. Check bare repo │ -│ 3. Read request body │ 3. Read request body │ -│ 4. Spawn git immediately ❌ │ 4. Parse ref updates ← NEW │ -│ 5. Stream response │ 5. Validate authorization ← NEW │ -│ │ 6. Spawn git (if authorized) │ -│ │ 7. Stream response │ -└─────────────────────────────────┴─────────────────────────────────────────┘ - -┌─────────────────────────────────┬─────────────────────────────────────────┐ -│ AUTHORIZATION │ METHOD │ -├─────────────────────────────────┼─────────────────────────────────────────┤ -│ ❌ None │ No validation │ -│ ⚠️ Git hooks (pre-receive) │ After git accepts push │ -│ ✅ Inline (our approach) │ Before git touches repository │ -└─────────────────────────────────┴─────────────────────────────────────────┘ - - -╔═══════════════════════════════════════════════════════════════════════════════╗ -║ KEY MODIFICATIONS NEEDED ║ -╚═══════════════════════════════════════════════════════════════════════════════╝ - -┌─────────────────────────────────────────────────────────────────────────────┐ -│ FILE: src/actix/git_receive_pack.rs │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ CHANGE 1: Add validator parameter │ -│ ──────────────────────────────────────────────────────────────────────── │ -│ pub async fn git_receive_pack( │ -│ request: HttpRequest, │ -│ mut payload: Payload, │ -│ service: web::Data, │ -│ + validator: web::Data, // ← ADD THIS │ -│ ) -> impl Responder { │ -│ │ -│ CHANGE 2: Parse ref updates after reading body │ -│ ──────────────────────────────────────────────────────────────────────── │ -│ // Read and decode body (existing) │ -│ let body_data = read_and_decode_body(&mut payload, &request).await?; │ -│ │ -│ + // Parse ref updates (NEW) │ -│ + let ref_updates = parse_receive_pack_request(&body_data)?; │ -│ │ -│ CHANGE 3: Validate before spawning git │ -│ ──────────────────────────────────────────────────────────────────────── │ -│ + // Extract repo info from path │ -│ + let (npub, identifier) = extract_repo_info(&request.uri().path())?; │ -│ + │ -│ + // Validate authorization │ -│ + if let Err(e) = validator.validate_push(&npub, &identifier, │ -│ + &ref_updates).await { │ -│ + return HttpResponse::Forbidden() │ -│ + .json(json!({ │ -│ + "error": "unauthorized", │ -│ + "message": e.to_string(), │ -│ + })); │ -│ + } │ -│ │ -│ // Spawn git (existing, unchanged) │ -│ let mut cmd = Command::new("git"); │ -│ // ... rest of existing code ... │ -└─────────────────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────────────────┐ -│ NEW FILE: src/git/protocol.rs │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ pub struct RefUpdate { │ -│ pub old_oid: String, │ -│ pub new_oid: String, │ -│ pub ref_name: String, │ -│ } │ -│ │ -│ pub fn parse_receive_pack_request(body: &[u8]) -> Result> { │ -│ // Parse git pack protocol │ -│ // Extract ref updates from pkt-line format │ -│ } │ -└─────────────────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────────────────┐ -│ NEW FILE: src/git/authorization.rs │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ pub struct PushValidator { │ -│ storage: Storage, │ -│ } │ -│ │ -│ impl PushValidator { │ -│ pub async fn validate_push( │ -│ &self, │ -│ npub: &str, │ -│ identifier: &str, │ -│ updates: &[RefUpdate], │ -│ ) -> Result<()> { │ -│ // Query Nostr relay for state event │ -│ // Validate each ref update │ -│ // Check maintainer permissions │ -│ } │ -│ } │ -└─────────────────────────────────────────────────────────────────────────────┘ - - -╔═══════════════════════════════════════════════════════════════════════════════╗ -║ BENEFITS OF INLINE AUTH ║ -╚═══════════════════════════════════════════════════════════════════════════════╝ - -✅ BETTER ERROR MESSAGES - • Return 403 with JSON error details - • Show exactly which ref failed validation - • Show expected vs. actual commit - • Better developer experience - -✅ SIMPLER DEPLOYMENT - • No git hooks to manage - • No symlinks or hook installation - • Single binary handles everything - • Easier to test - -✅ TIGHTER INTEGRATION - • Direct access to Nostr relay state - • Shared storage layer - • No IPC between components - • Atomic validation - -✅ EASIER TESTING - • Pure Rust unit tests - • Mock validator for testing - • No subprocess coordination - • Deterministic behavior - -✅ SECURITY - • Validation before git touches repo - • Can't bypass by manipulating hooks - • Centralized authorization logic - • Audit trail in application logs - - -╔═══════════════════════════════════════════════════════════════════════════════╗ -║ TIMELINE ║ -╚═══════════════════════════════════════════════════════════════════════════════╝ - -Week 1: Foundation -├─ Day 1-2: Fork git-http-backend, set up integration -├─ Day 3-4: Add git2, implement GitRepository -└─ Day 5: Add protocol parsing module - -Week 2: Authorization -├─ Day 1-2: Implement PushValidator -├─ Day 3-4: Modify git_receive_pack handler -└─ Day 5: Integration tests - -Week 3: Polish -├─ Day 1-2: Add CORS support -├─ Day 3-4: Error handling improvements -└─ Day 5: E2E tests with real git - -Week 4: Compliance -├─ Day 1-3: GRASP-01 compliance testing -├─ Day 4: Performance testing -└─ Day 5: Documentation - - -Status: ✅ Analysis complete, ready to implement -- cgit v1.2.3