Metadata database tracks all uploads with project, package, tag, and timestamp queryable via API
This commit is contained in:
@@ -12,6 +12,7 @@ class PaginationMeta(BaseModel):
|
||||
limit: int
|
||||
total: int
|
||||
total_pages: int
|
||||
has_more: bool = False # True if there are more pages after current page
|
||||
|
||||
|
||||
class PaginatedResponse(BaseModel, Generic[T]):
|
||||
@@ -39,6 +40,13 @@ class ProjectResponse(BaseModel):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ProjectUpdate(BaseModel):
|
||||
"""Schema for updating a project"""
|
||||
|
||||
description: Optional[str] = None
|
||||
is_public: Optional[bool] = None
|
||||
|
||||
|
||||
# Package format and platform enums
|
||||
PACKAGE_FORMATS = [
|
||||
"generic",
|
||||
@@ -86,6 +94,14 @@ class PackageResponse(BaseModel):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class PackageUpdate(BaseModel):
|
||||
"""Schema for updating a package"""
|
||||
|
||||
description: Optional[str] = None
|
||||
format: Optional[str] = None
|
||||
platform: Optional[str] = None
|
||||
|
||||
|
||||
class TagSummary(BaseModel):
|
||||
"""Lightweight tag info for embedding in package responses"""
|
||||
|
||||
@@ -189,6 +205,93 @@ class TagHistoryResponse(BaseModel):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TagHistoryDetailResponse(BaseModel):
|
||||
"""Tag history with artifact metadata for each version"""
|
||||
|
||||
id: UUID
|
||||
tag_id: UUID
|
||||
tag_name: str
|
||||
old_artifact_id: Optional[str]
|
||||
new_artifact_id: str
|
||||
changed_at: datetime
|
||||
changed_by: str
|
||||
# Artifact metadata for new artifact
|
||||
artifact_size: int
|
||||
artifact_original_name: Optional[str]
|
||||
artifact_content_type: Optional[str]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Audit log schemas
|
||||
class AuditLogResponse(BaseModel):
|
||||
"""Audit log entry response"""
|
||||
|
||||
id: UUID
|
||||
action: str
|
||||
resource: str
|
||||
user_id: str
|
||||
details: Optional[Dict[str, Any]]
|
||||
timestamp: datetime
|
||||
source_ip: Optional[str]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Upload history schemas
|
||||
class UploadHistoryResponse(BaseModel):
|
||||
"""Upload event with artifact details"""
|
||||
|
||||
id: UUID
|
||||
artifact_id: str
|
||||
package_id: UUID
|
||||
package_name: str
|
||||
project_name: str
|
||||
original_name: Optional[str]
|
||||
tag_name: Optional[str]
|
||||
uploaded_at: datetime
|
||||
uploaded_by: str
|
||||
source_ip: Optional[str]
|
||||
deduplicated: bool
|
||||
# Artifact metadata
|
||||
artifact_size: int
|
||||
artifact_content_type: Optional[str]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Artifact provenance schemas
|
||||
class ArtifactProvenanceResponse(BaseModel):
|
||||
"""Full provenance/history of an artifact"""
|
||||
|
||||
artifact_id: str
|
||||
sha256: str
|
||||
size: int
|
||||
content_type: Optional[str]
|
||||
original_name: Optional[str]
|
||||
created_at: datetime
|
||||
created_by: str
|
||||
ref_count: int
|
||||
# First upload info
|
||||
first_uploaded_at: datetime
|
||||
first_uploaded_by: str
|
||||
# Usage statistics
|
||||
upload_count: int
|
||||
# References
|
||||
packages: List[Dict[str, Any]] # List of {project_name, package_name, tag_names}
|
||||
tags: List[
|
||||
Dict[str, Any]
|
||||
] # List of {project_name, package_name, tag_name, created_at}
|
||||
# Upload history
|
||||
uploads: List[Dict[str, Any]] # List of upload events
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ArtifactTagInfo(BaseModel):
|
||||
"""Tag info for embedding in artifact responses"""
|
||||
|
||||
@@ -240,6 +343,44 @@ class PackageArtifactResponse(BaseModel):
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class GlobalArtifactResponse(BaseModel):
|
||||
"""Artifact with project/package context for global listing"""
|
||||
|
||||
id: str
|
||||
sha256: str
|
||||
size: int
|
||||
content_type: Optional[str]
|
||||
original_name: Optional[str]
|
||||
created_at: datetime
|
||||
created_by: str
|
||||
format_metadata: Optional[Dict[str, Any]] = None
|
||||
ref_count: int = 0
|
||||
# Context from tags/packages
|
||||
projects: List[str] = [] # List of project names containing this artifact
|
||||
packages: List[str] = [] # List of "project/package" paths
|
||||
tags: List[str] = [] # List of "project/package:tag" references
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class GlobalTagResponse(BaseModel):
|
||||
"""Tag with project/package context for global listing"""
|
||||
|
||||
id: UUID
|
||||
name: str
|
||||
artifact_id: str
|
||||
created_at: datetime
|
||||
created_by: str
|
||||
project_name: str
|
||||
package_name: str
|
||||
artifact_size: Optional[int] = None
|
||||
artifact_content_type: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Upload response
|
||||
class UploadResponse(BaseModel):
|
||||
artifact_id: str
|
||||
@@ -254,6 +395,11 @@ class UploadResponse(BaseModel):
|
||||
format_metadata: Optional[Dict[str, Any]] = None
|
||||
deduplicated: bool = False
|
||||
ref_count: int = 1 # Current reference count after this upload
|
||||
# Enhanced metadata (Issue #19)
|
||||
upload_id: Optional[UUID] = None # UUID of the upload record
|
||||
content_type: Optional[str] = None
|
||||
original_name: Optional[str] = None
|
||||
created_at: Optional[datetime] = None
|
||||
|
||||
|
||||
# Resumable upload schemas
|
||||
@@ -440,6 +586,19 @@ class StorageStatsResponse(BaseModel):
|
||||
storage_saved_bytes: int # Bytes saved through deduplication
|
||||
|
||||
|
||||
class ConsistencyCheckResponse(BaseModel):
|
||||
"""Result of S3/Database consistency check"""
|
||||
|
||||
total_artifacts_checked: int
|
||||
orphaned_s3_objects: int # Objects in S3 but not in DB
|
||||
missing_s3_objects: int # Records in DB but not in S3
|
||||
size_mismatches: int # Records where DB size != S3 size
|
||||
healthy: bool
|
||||
orphaned_s3_keys: List[str] = [] # Limited list of orphaned S3 keys
|
||||
missing_s3_keys: List[str] = [] # Limited list of missing S3 keys
|
||||
size_mismatch_artifacts: List[Dict[str, Any]] = [] # Limited list of mismatches
|
||||
|
||||
|
||||
class DeduplicationStatsResponse(BaseModel):
|
||||
"""Deduplication effectiveness statistics"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user