docs(FN-011): complete Step 8 — update architecture and development docs

Fusion-Task-Id: FN-011
Fusion-Task-Lineage: 4a9aca6f-9d91-43aa-8d2a-d59657c1541a
This commit is contained in:
Fusion
2026-05-14 08:29:42 +02:00
parent 31b363edb0
commit 2c52b1634f
2 changed files with 46 additions and 3 deletions
+26 -3
View File
@@ -30,17 +30,40 @@ The backend must define provider contracts before implementing any concrete adap
### 3.1 GitProvider
> **Architecture divergence note (FN-011):** The original spec defined a single
> `GitProvider(Protocol)` with `clone/fetch/push` methods. The implementation
> intentionally splits this responsibility into two abstractions:
>
> - `GitProvider` (`app/git/provider.py`) — provider API adapter for remote
> operations (`validate_connection`, `list_repositories`, `create_deploy_key`,
> etc.).
> - `GitOperations` (`app/git/operations.py`) — local Git subprocess interface
> (`clone`, `fetch`, `push`, `get_status`).
>
> This separation keeps provider-specific API logic distinct from local Git CLI
> orchestration.
```python
class GitProvider(Protocol):
def clone(self, repo_url: str, dest: Path, credentials: GitCredentials) -> None: ...
def fetch(self, repo_path: Path, credentials: GitCredentials) -> None: ...
def push(self, repo_path: Path, credentials: GitCredentials) -> None: ...
def validate_connection(self, repo_url: str, credential_id: str) -> ConnectionStatus: ...
def list_repositories(self, credential_id: str) -> list[dict[str, Any]]: ...
def create_deploy_key(self, repo_url: str, public_key: str) -> str: ...
def delete_deploy_key(self, repo_url: str, deploy_key_id: str) -> None: ...
def get_default_branch(self, repo_url: str, credential_id: str) -> str: ...
```
- Adapters: GitHub, GitLab, Gitea, Forgejo, etc.
- Credentials: generated SSH keys (per-repository) or access tokens.
- SSH keys must be scoped per repository connection for clean revocation.
```python
class GitOperations(Protocol):
def clone(self, repo_url: str, dest: Path, credential_id: str) -> None: ...
def fetch(self, repo_path: Path, credential_id: str) -> None: ...
def push(self, repo_path: Path, credential_id: str) -> None: ...
def get_status(self, repo_path: Path) -> dict[str, Any]: ...
```
### 3.2 RuntimeProvider
```python