mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
"""Backend-owned graph provenance and live resource boundary (pre-push Req 4.3, 7.3).
|
|
|
|
Structural validity is necessary but insufficient for reuse. Task 6.1 will validate
|
|
actual source bytes, graph digest/census and engine compatibility before issuing leases.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Literal, Protocol
|
|
|
|
from openultrasast.contracts import Contract
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GraphIdentity(Contract):
|
|
source_digest: str
|
|
declarations_digest: str
|
|
exclusions_digest: str
|
|
unit: str
|
|
language: str
|
|
engine_version: str
|
|
frontend: str
|
|
frontend_version: str
|
|
overlay_semantics: tuple[str, ...]
|
|
overlay_options: tuple[tuple[str, str], ...]
|
|
frontend_options: tuple[tuple[str, str], ...] = ()
|
|
|
|
def __post_init__(self) -> None:
|
|
super().__post_init__()
|
|
for options in (self.overlay_options, self.frontend_options):
|
|
if len({key for key, _ in options}) != len(options):
|
|
raise ValueError("graph option names must be unique")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GraphCensus(Contract):
|
|
files: int
|
|
methods: int
|
|
calls: int
|
|
|
|
def __post_init__(self) -> None:
|
|
super().__post_init__()
|
|
if min(self.files, self.methods, self.calls) < 0:
|
|
raise ValueError("graph census counts must be nonnegative")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GraphArtifact(Contract):
|
|
identity: GraphIdentity
|
|
graph_digest: str
|
|
source_bytes: int
|
|
census: GraphCensus
|
|
completeness: Literal["complete", "partial"]
|
|
diagnostics: tuple[str, ...]
|
|
|
|
def __post_init__(self) -> None:
|
|
super().__post_init__()
|
|
if self.source_bytes < 0:
|
|
raise ValueError("source byte count must be nonnegative")
|
|
if self.completeness == "complete" and (not self.source_bytes or not self.census.files or self.diagnostics):
|
|
raise ValueError("complete graph requires readable source, a file census and no incomplete diagnostics")
|
|
if self.completeness == "partial" and not self.diagnostics:
|
|
raise ValueError("partial graph requires a recorded reason")
|
|
|
|
|
|
class GraphLease(Protocol):
|
|
"""A backend-issued live lease; never reconstructed from a JSON manifest.
|
|
|
|
The backend validates the artifact before issuing the lease and isolates loading
|
|
when it may mutate graph bytes. The consumer owns releasing it exactly once; the
|
|
backend's release is idempotent and bounded by the supplied monotonic deadline.
|
|
A cached artifact survives release. Implementations belong to task 6.1.
|
|
"""
|
|
|
|
@property
|
|
def artifact(self) -> GraphArtifact: ...
|
|
|
|
@property
|
|
def path(self) -> Path: ...
|
|
|
|
def close(self, *, deadline_monotonic: float) -> None: ...
|