fixes global

This commit is contained in:
user committed 2025-08-08 09:14:18 +03:00
1 parent 13dc4f39c8
commit cad0f6aebe
64 files changed
+10379 -254

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
from __future__ import annotations
from typing import Dict, Any, Optional, List, Literal
from pydantic import BaseModel, Field
class NodeHealthResponse(BaseModel):
status: Literal["ok", "degraded", "down"] = "ok"
node_id: str
public_key: str
uptime_seconds: Optional[int] = None
cpu_usage: Optional[float] = None
memory_usage_mb: Optional[float] = None
disk_free_mb: Optional[float] = None
last_sync_ts: Optional[int] = None
details: Dict[str, Any] = Field(default_factory=dict)
class ContentStatsItem(BaseModel):
content_id: str
total_chunks: int
stored_chunks: int
missing_chunks: int
size_bytes: Optional[int] = None
verified: Optional[bool] = None
class NodeContentStatsResponse(BaseModel):
total_contents: int
total_chunks: int
stored_chunks: int
missing_chunks: int
contents: List[ContentStatsItem] = Field(default_factory=list)
class NodeStatsReport(BaseModel):
action: Literal["stats_report"] = "stats_report"
reporter_node_id: str
reporter_public_key: str
timestamp: int
metrics: Dict[str, Any] = Field(default_factory=dict)
signature: Optional[str] = None # подпись может быть и в заголовке
+74
View File
@@ -0,0 +1,74 @@
from __future__ import annotations
from typing import List, Optional, Dict, Any, Literal
from pydantic import BaseModel, Field, validator
class SignedRequestHeaders(BaseModel):
"""Заголовки межузлового запроса с подписью Ed25519"""
x_node_communication: Literal["true"] = Field(alias="X-Node-Communication")
x_node_id: str = Field(alias="X-Node-ID")
x_node_public_key: str = Field(alias="X-Node-Public-Key")
x_node_signature: str = Field(alias="X-Node-Signature")
class Config:
populate_by_name = True
class ChunkRef(BaseModel):
chunk_id: str
content_id: str
chunk_index: int
chunk_hash: str
encrypted_data: str
signature: Optional[str] = None
created_at: Optional[str] = None
class ContentRequest(BaseModel):
action: Literal["content_sync"]
sync_type: Literal["content_request", "new_content", "content_list"]
content_info: Dict[str, Any] = Field(default_factory=dict)
timestamp: Optional[int] = None
@validator("content_info")
def validate_content_info(cls, v, values):
st = values.get("sync_type")
if st == "content_request":
# ожидаем content_id и indexes
if "content_id" not in v or "indexes" not in v:
raise ValueError("content_request requires content_info.content_id and content_info.indexes")
if not isinstance(v.get("indexes"), list):
raise ValueError("content_info.indexes must be a list")
elif st == "new_content":
if "content_id" not in v or "total_chunks" not in v:
raise ValueError("new_content requires content_info.content_id and content_info.total_chunks")
return v
class ContentProvideResponse(BaseModel):
success: bool = True
chunks: List[ChunkRef] = Field(default_factory=list)
errors: List[Dict[str, Any]] = Field(default_factory=list)
class ContentStatusResponse(BaseModel):
content_id: str
total_chunks: int
have_indexes: List[int] = Field(default_factory=list)
missing_indexes: List[int] = Field(default_factory=list)
verified: Optional[bool] = None
message: Optional[str] = None
class ContentVerifyRequest(BaseModel):
content_id: str
chunks: List[ChunkRef] = Field(default_factory=list)
verify_signatures: bool = True
class GenericSignedResponse(BaseModel):
success: bool
data: Dict[str, Any] = Field(default_factory=dict)
node_id: Optional[str] = None
timestamp: Optional[str] = None