Files
headquarter/openspec/changes/git-connection-model/design.md
T
alex 024278a3d2 docs(openspec): add FN-007 Git Connection Model change
- Add proposal, design, specs, and tasks for git connection model
- Include provider adapter, credential storage, SSH key lifecycle specs
- Add repository connection API and git operations specifications
2026-05-16 13:43:49 +02:00

3.0 KiB

Context

The platform has a Git abstraction layer in apps/api/app/git/ with:

  • provider.py: GitProvider ABC (validate_connection, list_repos, create_deploy_key, delete_deploy_key, get_default_branch)
  • connection.py: ConnectionManager (connect/disconnect/get_connection)
  • credentials.py: GitCredential, AccessTokenCredential, CredentialStorage ABC
  • ssh_key.py: SshKeyPair, SshKeyLifecycle with Ed25519 generation
  • operations.py: GitOperations ABC, LocalGitOperations (clone/fetch/push are NotImplementedError)
  • types.py: ProviderKind, CredentialKind, ConnectionStatus, SshKeyStatus enums

Current gaps:

  • No concrete provider adapters (GitHub, GitLab)
  • CredentialStorage has no database implementation
  • LocalGitOperations is incomplete
  • No RepositoryConnection router or API endpoints
  • SSH key generation uses base64 placeholder

Goals / Non-Goals

Goals:

  • Implement concrete GitHub and GitLab provider adapters
  • Create database-backed credential storage with encryption
  • Complete LocalGitOperations with credential-aware subprocess
  • Add RepositoryConnection router with CRUD endpoints
  • Generate Ed25519 SSH keys and register deploy keys
  • Frontend UI for repository connections and SSH key management

Non-Goals:

  • Support for Gitea/Forgejo (deferred post-MVP)
  • GitHub/GitLab OAuth app integration (use personal access tokens)
  • Webhook management
  • Repository mirroring
  • Branch protection management

Decisions

1. Use httpx for provider API calls

  • Rationale: Already in dependencies, async support, consistent with FastAPI
  • Alternative: requests - blocking, would need thread pool

2. Store credentials encrypted with Fernet (same as secrets)

  • Rationale: Consistent with existing secret storage in FN-009
  • Implementation: Reuse encryption service from app/encryption.py

3. SSH keys generated per-repository (not per-user)

  • Rationale: Fine-grained access control, easy revocation per repo
  • Alternative: Per-user keys - broader blast radius on compromise

4. Provider adapters implement GitProvider ABC

  • Rationale: Clean abstraction, easy to add new providers
  • Implementation: GitHubAdapter, GitLabAdapter with unified interface

5. Git operations use subprocess with SSH key in temp file

  • Rationale: Standard git CLI is most reliable
  • Implementation: Write key to temp file, set GIT_SSH_COMMAND env var

Risks / Trade-offs

[Risk] Personal access tokens have broad permissions → Mitigation: Document minimal required scopes (repo read/write, deploy key management)

[Risk] SSH keys in temp files are briefly exposed on disk → Mitigation: Use 0600 permissions, clean up immediately after operation

[Risk] Provider API rate limits → Mitigation: Cache repository lists, implement exponential backoff

[Risk] Token storage compromise → Mitigation: Fernet encryption with rotation support

Migration Plan

No migration. New feature.

Open Questions

  1. Should we support SSH key passphrases?
  2. Do we need to validate repository URLs before connection?
  3. Should we auto-detect provider from URL?