Files
headquarter/apps/api/app/git/credentials.py
T
Fusion 31b363edb0 test(FN-011): complete Step 7 — tests for provider, credentials, and operations
Fusion-Task-Id: FN-011
Fusion-Task-Lineage: 4a9aca6f-9d91-43aa-8d2a-d59657c1541a
2026-05-14 08:37:11 +02:00

53 lines
1.5 KiB
Python

"""Credential models and storage interface.
Security rules:
- No plaintext ``private_key`` or ``token`` fields exist on any model class.
- The ``encrypted_payload`` field is opaque bytes encoded as a string.
"""
import abc
import uuid
from datetime import UTC, datetime
from pydantic import BaseModel, ConfigDict, Field
from app.git.types import CredentialKind
class GitCredential(BaseModel):
"""Base credential model.
Never stores plaintext secrets. The ``encrypted_payload`` field holds
opaque encrypted data.
"""
model_config = ConfigDict(extra="forbid")
id: uuid.UUID = Field(default_factory=uuid.uuid4)
kind: CredentialKind
encrypted_payload: str = Field(repr=False)
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
class AccessTokenCredential(GitCredential):
"""Access-token credential discriminated by ``kind``."""
kind: CredentialKind = CredentialKind.access_token
class CredentialStorage(abc.ABC):
"""Abstract storage backend for :class:`GitCredential` records."""
@abc.abstractmethod
def create(self, credential: GitCredential) -> uuid.UUID:
"""Persist *credential* and return its ID."""
@abc.abstractmethod
def get(self, credential_id: uuid.UUID) -> GitCredential | None:
"""Retrieve a credential by ID, or ``None`` if not found."""
@abc.abstractmethod
def delete(self, credential_id: uuid.UUID) -> None:
"""Remove a credential by ID."""