feat: implement institutional governance and recovery architecture
Dependency Audit / dependency-audit (push) Failing after 10s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 9s

This commit is contained in:
2026-08-01 17:46:53 +02:00
parent 3c658fa32d
commit d78b13f9d3
45 changed files with 4388 additions and 262 deletions
+92
View File
@@ -16,6 +16,7 @@ META_ROOT = Path(__file__).resolve().parents[2]
MODULE_NAME_PATTERN = re.compile(
r"[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*"
)
REQUIRED_DOCUMENTATION_TYPES = frozenset({"admin", "user"})
def main() -> int:
@@ -26,6 +27,14 @@ def main() -> int:
default=None,
help="Directory containing the GovOPlaN repositories. Defaults to repositories.json default_parent.",
)
parser.add_argument(
"--require-architecture",
action="store_true",
help=(
"Reject every module that has not adopted the versioned architecture "
"declaration. GovOPlaN release and focused checks enable this gate."
),
)
args = parser.parse_args()
catalog = json.loads((META_ROOT / "repositories.json").read_text(encoding="utf-8"))
@@ -90,6 +99,36 @@ def main() -> int:
)
continue
documented_types = {
documentation_type
for topic in manifest.documentation
for documentation_type in topic.documentation_types
}
missing_documentation_types = sorted(REQUIRED_DOCUMENTATION_TYPES - documented_types)
if missing_documentation_types:
errors.append(
f"{repository_name}: module {manifest.id!r} is missing static documentation for "
f"{', '.join(missing_documentation_types)}; add manifest DocumentationTopic entries "
"even when runtime documentation providers are registered"
)
continue
repository_root = manifest_path.parents[3]
if manifest.architecture is None:
if args.require_architecture:
errors.append(
f"{repository_name}: module {manifest.id!r} has no architecture declaration"
)
continue
else:
errors.extend(
_architecture_evidence_errors(
repository_name=repository_name,
repository_root=repository_root,
manifest=manifest,
)
)
manifests.append(manifest)
if errors:
@@ -109,6 +148,11 @@ def main() -> int:
f"Manifest registry check passed: {len(snapshot.manifests)} manifests "
f"from {len(manifest_sources)} source files."
)
declared = sum(manifest.architecture is not None for manifest in manifests)
print(
f"Architecture declaration coverage: {declared}/{len(manifests)} modules "
f"({(declared / len(manifests) * 100):.1f}%)."
)
return 0
@@ -120,5 +164,53 @@ def _module_entry_points(pyproject_path: Path) -> dict[str, str]:
return {str(name): str(target) for name, target in values.items()}
def _architecture_evidence_errors(
*,
repository_name: str,
repository_root: Path,
manifest: object,
) -> list[str]:
architecture = getattr(manifest, "architecture", None)
if architecture is None:
return []
errors: list[str] = []
references = [
(f"{item.kind} evidence", item.reference)
for item in architecture.evidence
]
for category in ("migration", "upgrade", "recovery", "security", "operations"):
references.extend(
(f"{category} documentation", reference)
for reference in getattr(architecture.documentation, category)
)
for label, reference in references:
if not _looks_like_repository_reference(reference):
continue
candidate = (repository_root / reference).resolve()
try:
candidate.relative_to(repository_root.resolve())
except ValueError:
errors.append(
f"{repository_name}: {label} escapes the repository: {reference!r}"
)
continue
if not candidate.exists():
errors.append(
f"{repository_name}: {label} does not exist: {reference!r}"
)
return errors
def _looks_like_repository_reference(reference: str) -> bool:
normalized = reference.strip()
if not normalized or "://" in normalized:
return False
return (
"/" in normalized
or normalized.startswith("README")
or normalized.endswith((".md", ".py", ".json", ".yaml", ".yml"))
)
if __name__ == "__main__":
raise SystemExit(main())