122 lines
4.5 KiB
Python
Executable File
122 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Phase 5 audit for cross-request/static state risks in site code files."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from dataclasses import asdict, dataclass
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SITE = ROOT / "site"
|
|
|
|
PATTERNS = [
|
|
("static local/global", "static "),
|
|
("once hook", "ONCE("),
|
|
("init hook", "INIT("),
|
|
("background task", "task_"),
|
|
]
|
|
|
|
SKIP_PARTS = {".git", "tmp", "work", "bin", "pkg", "__pycache__"}
|
|
CODE_SUFFIXES = {".uce", ".h"}
|
|
DOC_SUFFIXES = {".txt"}
|
|
|
|
|
|
@dataclass
|
|
class Finding:
|
|
path: str
|
|
line: int
|
|
kind: str
|
|
severity: str
|
|
text: str
|
|
note: str
|
|
|
|
|
|
def iter_files(include_doc_text: bool) -> list[Path]:
|
|
suffixes = CODE_SUFFIXES | (DOC_SUFFIXES if include_doc_text else set())
|
|
result: list[Path] = []
|
|
for path in SITE.rglob("*"):
|
|
if not path.is_file():
|
|
continue
|
|
if any(part in SKIP_PARTS for part in path.parts):
|
|
continue
|
|
if path.suffix not in suffixes:
|
|
continue
|
|
result.append(path)
|
|
return sorted(result)
|
|
|
|
|
|
def note_for(kind: str, severity: str) -> str:
|
|
if severity == "documentation":
|
|
return "Documentation prose mention; useful for terminology review, not a direct static-state migration finding."
|
|
if kind in {"once hook", "init hook"}:
|
|
return "Audit behavior under per-request wasm workspaces; ONCE/INIT may need host-side cache semantics if used for cross-request state."
|
|
if kind == "background task":
|
|
return "Task APIs cross request lifetimes; verify they are host handles, not guest statics."
|
|
return "Check whether state is request-local, immutable, or intentionally persistent; unit statics reset per wasm workspace."
|
|
|
|
|
|
def severity_for(path: Path) -> str:
|
|
return "documentation" if path.suffix in DOC_SUFFIXES else "code"
|
|
|
|
|
|
def scan(include_doc_text: bool) -> list[Finding]:
|
|
findings: list[Finding] = []
|
|
for path in iter_files(include_doc_text):
|
|
try:
|
|
lines = path.read_text(encoding="utf-8").splitlines()
|
|
except UnicodeDecodeError:
|
|
continue
|
|
severity = severity_for(path)
|
|
for lineno, line in enumerate(lines, 1):
|
|
stripped = line.strip()
|
|
if severity == "code" and (stripped.startswith("//") or stripped.startswith("# ")):
|
|
continue
|
|
for kind, needle in PATTERNS:
|
|
if needle in line:
|
|
findings.append(Finding(
|
|
path=str(path.relative_to(ROOT)),
|
|
line=lineno,
|
|
kind=kind,
|
|
severity=severity,
|
|
text=stripped[:180],
|
|
note=note_for(kind, severity),
|
|
))
|
|
return findings
|
|
|
|
|
|
def write_reports(findings: list[Finding], out_dir: Path) -> None:
|
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
(out_dir / "site-static-audit.json").write_text(json.dumps([asdict(f) for f in findings], indent=2) + "\n")
|
|
lines = ["# Phase 5 site static-state audit", ""]
|
|
if not findings:
|
|
lines.append("No candidate cross-request/static-state patterns found.")
|
|
else:
|
|
code_count = sum(1 for f in findings if f.severity == "code")
|
|
doc_count = sum(1 for f in findings if f.severity == "documentation")
|
|
lines.append(f"Findings: {code_count} code, {doc_count} documentation prose.")
|
|
lines.append("")
|
|
lines.extend(["| file | line | severity | kind | code | note |", "|---|---:|---|---|---|---|"])
|
|
for f in findings:
|
|
code = f.text.replace("|", "\\|")
|
|
note = f.note.replace("|", "\\|")
|
|
lines.append(f"| {f.path} | {f.line} | {f.severity} | {f.kind} | `{code}` | {note} |")
|
|
(out_dir / "site-static-audit.md").write_text("\n".join(lines) + "\n")
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Phase 5 site static/cross-request-state audit")
|
|
parser.add_argument("--include-doc-text", action="store_true", help="include site/doc .txt prose as documentation-severity findings")
|
|
parser.add_argument("--out-dir", default="/tmp/uce/wasm-phase5")
|
|
args = parser.parse_args()
|
|
out_dir = Path(args.out_dir)
|
|
findings = scan(args.include_doc_text)
|
|
write_reports(findings, out_dir)
|
|
print(f"Found {len(findings)} candidate static/cross-request patterns")
|
|
print(f"wrote {out_dir / 'site-static-audit.json'} and {out_dir / 'site-static-audit.md'}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|