#!/usr/bin/env python3 # file: scripts/audit_khadhroony_workspace_rules.py # version: 23 """Audit mechanically verifiable rules specific to khadhroony-bot3.""" from __future__ import annotations import argparse import dataclasses import json import pathlib import re import sys import tomllib @dataclasses.dataclass(frozen=True) class Violation: """One project-specific workspace rule violation.""" code: str path: str line: int message: str def package_name(crate_dir: pathlib.Path) -> str | None: """Return a crate package name.""" cargo = crate_dir / "Cargo.toml" if not cargo.exists(): return None value = tomllib.loads(cargo.read_text(encoding="utf-8")).get("package", {}).get("name") return value if isinstance(value, str) else None def relevant_tracing_crate(crate_dir: pathlib.Path) -> bool: """Return whether the crate owns a tracing target contract.""" cargo = crate_dir / "Cargo.toml" data = tomllib.loads(cargo.read_text(encoding="utf-8")) if "tracing" in data.get("dependencies", {}): return True return any("TRACING_TARGET" in path.read_text(encoding="utf-8") for path in crate_dir.glob("src/**/*.rs")) def audit_tracing(root: pathlib.Path) -> list[Violation]: """Audit the project tracing target contract.""" violations: list[Violation] = [] for cargo in sorted(root.glob("*/Cargo.toml")): crate = cargo.parent if crate.name == "ks-lib": continue if not relevant_tracing_crate(crate): continue name = package_name(crate) if name is None: continue constants = crate / "src/constants.rs" expected = f'pub(crate) const TRACING_TARGET: &str = "{name}";' relative_constants = constants.relative_to(root).as_posix() if not constants.exists() or expected not in constants.read_text(encoding="utf-8"): violations.append(Violation("KH_TRACE001", relative_constants, 1, f"expected `{expected}`")) crate_root = crate / "src/lib.rs" if not crate_root.exists(): crate_root = crate / "src/main.rs" relative_root = crate_root.relative_to(root).as_posix() if not crate_root.exists() or "pub(crate) use self::constants::TRACING_TARGET;" not in crate_root.read_text(encoding="utf-8"): violations.append(Violation("KH_TRACE002", relative_root, 1, "missing crate-root TRACING_TARGET re-export")) for path in crate.glob("src/**/*.rs"): relative = path.relative_to(root).as_posix() for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): if "khbot." in line: violations.append(Violation("KH_TRACE003", relative, index, "legacy khbot tracing target is forbidden")) if "crate::constants::TRACING_TARGET" in line: violations.append(Violation("KH_TRACE004", relative, index, "use crate::TRACING_TARGET outside crate root")) if re.search(r"(?:crate::[A-Za-z0-9_]+::|(? list[Violation]: """Audit hierarchical tracing targets owned by operational ks-lib components.""" violations: list[Violation] = [] crate = root / "ks-lib" crate_root = crate / "src/lib.rs" if not crate_root.exists(): return violations root_text = crate_root.read_text(encoding="utf-8") re_exports = set() re_export_pattern = re.compile( r"^pub\(crate\) use self::[A-Za-z0-9_:]+::" r"([A-Z][A-Z0-9_]+);$", re.MULTILINE, ) for match in re_export_pattern.finditer(root_text): if match.group(1).startswith("TRACING_TARGET_"): re_exports.add(match.group(1)) target_pattern = re.compile( r'pub\(crate\) const (TRACING_TARGET_[A-Z0-9_]+): &str\s*=\s*"([^"]+)";', re.MULTILINE, ) declared_targets: dict[str, tuple[str, int]] = {} for constants in sorted((crate / "src").rglob("constants.rs")): text = constants.read_text(encoding="utf-8") component = constants.parent.relative_to(crate / "src") component_parts = component.parts if component_parts and component_parts[0] in {"decoder", "executor", "materializer"}: suffix = ".".join(component_parts[1:]) expected = f"ks-lib-{component_parts[0]}" if suffix: expected = f"{expected}.{suffix}" else: expected = "ks-lib." + ".".join(component_parts) relative = constants.relative_to(root).as_posix() for match in target_pattern.finditer(text): line = text[: match.start()].count("\n") + 1 declared_targets[match.group(1)] = (relative, line) if match.group(2) != expected: violations.append( Violation( "KH_TRACE101", relative, line, f"`{match.group(1)}` must use hierarchical target `{expected}`", ) ) macro_pattern = re.compile( r"tracing::(?:debug|error|info|trace|warn)!\(\s*target:\s*crate::(TRACING_TARGET_[A-Z0-9_]+)" ) used_targets: set[str] = set() for path in sorted((crate / "src").rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for index, line in enumerate(text.splitlines(), 1): if "let _target" in line: violations.append( Violation( "KH_TRACE102", relative, index, "fake tracing target consumption is forbidden", ) ) for match in macro_pattern.finditer(text): used_targets.add(match.group(1)) if match.group(1) not in re_exports: violations.append( Violation( "KH_TRACE103", relative, text[: match.start()].count("\n") + 1, f"missing crate-root re-export for `{match.group(1)}`", ) ) for target, (relative, line) in sorted(declared_targets.items()): if target not in used_targets: violations.append( Violation( "KH_TRACE104", relative, line, f"declared operational tracing target `{target}` is not used by a real tracing event", ) ) return violations def audit_solana_types(root: pathlib.Path) -> list[Violation]: """Reject non-canonical Solana address types in workspace Rust code.""" violations: list[Violation] = [] for path in sorted(root.rglob("*.rs")): if "target" in path.parts or ".git" in path.parts: continue relative = path.relative_to(root).as_posix() for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): if "solana_address::Address" in line: violations.append(Violation("KH_SOL001", relative, index, "use solana_pubkey::Pubkey instead of solana_address::Address")) return violations def audit_ks_lib_symbol_prefixes(root: pathlib.Path) -> list[Violation]: """Require stable family prefixes on non-method ks-lib declarations.""" violations: list[Violation] = [] families = { "decoder": ("DC_", "Dc", "decoder_"), "executor": ("EX_", "Ex", "executor_"), "materializer": ("MT_", "Mt", "materializer_"), "model": ("MD_", "Md", "model_"), } declaration = re.compile( r"^pub(?:\(crate\))?\s+" r"(?:(?:async|const|unsafe)\s+)*" r"(const|static|type|struct|enum|trait|union|fn)\s+" r"([A-Za-z_][A-Za-z0-9_]*)" ) for family, prefixes in families.items(): family_root = root / "ks-lib/src" / family paths = [family_root.with_suffix(".rs")] if family_root.is_dir(): paths.extend(sorted(family_root.rglob("*.rs"))) for path in paths: if not path.is_file(): continue relative = path.relative_to(root).as_posix() for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): match = declaration.match(line) if match is None: continue kind = match.group(1) name = match.group(2) expected = prefixes[0] if kind in {"const", "static"} else prefixes[2] if kind == "fn" else prefixes[1] if kind in {"const", "static"} and name.startswith("TRACING_TARGET_"): continue if not name.startswith(expected): violations.append( Violation( "KH_NAME001", relative, index, f"`{name}` must start with `{expected}` for the {family} family", ) ) return violations def audit_reserved_decoder_scaffolds(root: pathlib.Path) -> list[Violation]: """Reject incomplete reserved decoder contracts.""" violations: list[Violation] = [] decoder_root = root / "ks-lib/src/decoder" forbidden = ( "MIGRATION_BOUNDARIES", "LEGACY_CRATE", "MIGRATION_STATUS", "source-preserved-pending-port", ) struct_pattern = re.compile(r"^pub struct (Dc[A-Za-z0-9]+Decoder);$", re.MULTILINE) for path in sorted(decoder_root.rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for marker in forbidden: offset = text.find(marker) if offset >= 0: violations.append( Violation( "KH_DC001", relative, text[:offset].count("\n") + 1, f"temporary decoder migration marker `{marker}` is forbidden", ) ) if "Reserved protocol decoder for `" not in text: continue struct_match = struct_pattern.search(text) if struct_match is None: violations.append( Violation( "KH_DC002", relative, 1, "reserved decoder must expose one `Dc*Decoder` unit struct", ) ) continue type_name = struct_match.group(1) implementation = f"impl crate::DcApiProtocolDecoder for crate::{type_name} {{" if implementation not in text: violations.append( Violation( "KH_DC003", relative, text[: struct_match.start()].count("\n") + 1, f"`{type_name}` must implement `DcApiProtocolDecoder`", ) ) if "fn program_ids(&self) -> &'static [&'static str]" not in text: violations.append( Violation( "KH_DC004", relative, 1, "reserved decoder must declare its exact Program ID boundary", ) ) if "crate::DcApiDecoderSupport::Maybe" not in text: violations.append( Violation( "KH_DC005", relative, 1, "reserved decoder must remain explicitly `Maybe` until implemented", ) ) return violations def audit_reserved_materializer_scaffolds(root: pathlib.Path) -> list[Violation]: """Reject incomplete reserved materializer contracts.""" violations: list[Violation] = [] materializer_root = root / "ks-lib/src/materializer" forbidden = ( "MIGRATION_BOUNDARIES", "LEGACY_CRATE", "MIGRATION_STATUS", "source-preserved-pending-port", ) struct_pattern = re.compile(r"^pub struct (Mt[A-Za-z0-9]+Materializer);$", re.MULTILINE) for path in sorted(materializer_root.rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for marker in forbidden: offset = text.find(marker) if offset >= 0: violations.append( Violation( "KH_MT001", relative, text[:offset].count("\n") + 1, f"temporary materializer migration marker `{marker}` is forbidden", ) ) if not text.startswith("// file:") or "\n//! Reserved " not in text: continue struct_match = struct_pattern.search(text) if struct_match is None: violations.append( Violation( "KH_MT002", relative, 1, "reserved materializer must expose one `Mt*Materializer` unit struct", ) ) continue type_name = struct_match.group(1) legacy_implementation = f"impl crate::MtMaterializer for crate::{type_name} {{" if legacy_implementation not in text: violations.append( Violation( "KH_MT003", relative, text[: struct_match.start()].count("\n") + 1, f"`{type_name}` must implement `MtMaterializer`", ) ) api_implementation = f"impl crate::MtApiEventMaterializer for crate::{type_name} {{" if api_implementation not in text: violations.append( Violation( "KH_MT004", relative, text[: struct_match.start()].count("\n") + 1, f"`{type_name}` must implement `MtApiEventMaterializer`", ) ) if "fn accepted_families(&self) -> &'static [crate::MdEventFamily]" not in text: violations.append( Violation( "KH_MT005", relative, 1, "reserved materializer must declare its inactive family boundary", ) ) if "crate::MtApiMaterializerExecutionResult::ignored()" not in text: violations.append( Violation( "KH_MT006", relative, 1, "reserved materializer must return an ignored API result", ) ) if "std::result::Result::Ok(std::vec::Vec::new())" not in text: violations.append( Violation( "KH_MT007", relative, 1, "reserved materializer legacy contract must return an empty event list", ) ) if not re.search(r"return crate::MT_[A-Z0-9_]+_ACCEPTED_FAMILIES;", text): violations.append( Violation( "KH_MT008", relative, 1, "reserved materializer must use its exported accepted-family constant", ) ) return violations def iter_rust_json_object_macros(text: str) -> list[tuple[int, str]]: """Return balanced `serde_json::json!({ ... })` object macro bodies.""" blocks: list[tuple[int, str]] = [] needle = "serde_json::json!({" offset = 0 while True: start = text.find(needle, offset) if start < 0: break brace = text.find("{", start) depth = 0 in_string = False escaped = False end = brace while end < len(text): character = text[end] if in_string: if escaped: escaped = False elif character == "\\": escaped = True elif character == '"': in_string = False elif character == '"': in_string = True elif character == "{": depth += 1 elif character == "}": depth -= 1 if depth == 0: blocks.append((start, text[start: end + 1])) offset = end + 1 break end += 1 else: offset = start + len(needle) return blocks def audit_materializer_conventions(root: pathlib.Path) -> list[Violation]: """Audit materializer names, constants and component facade structure.""" violations: list[Violation] = [] materializer_root = root / "ks-lib/src/materializer" component_pattern = re.compile( r'pub\(crate\) const (MT_[A-Z0-9_]+)_COMPONENT_NAME: &str\s*=\s*"([^"]+)";' ) processor_pattern = re.compile( r'pub\(crate\) const (MT_[A-Z0-9_]+)_PROCESSOR_NAME: &str\s*=\s*"([^"]+)";' ) component_names: dict[str, tuple[str, str, int]] = {} processor_names: dict[str, tuple[str, str, int]] = {} for path in sorted(materializer_root.rglob("constants.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for match in component_pattern.finditer(text): prefix = match.group(1) line = text[: match.start()].count("\n") + 1 component_names[prefix] = (match.group(2), relative, line) for match in processor_pattern.finditer(text): prefix = match.group(1) line = text[: match.start()].count("\n") + 1 processor_names[prefix] = (match.group(2), relative, line) for prefix, (component_name, relative, line) in sorted(component_names.items()): processor = processor_names.get(prefix) if processor is None: violations.append( Violation( "KH_MT009", relative, line, f"`{prefix}` component name requires one matching processor name", ) ) continue processor_name = processor[0] if not component_name.startswith("ks-lib-materializer."): violations.append( Violation( "KH_MT010", relative, line, f"materializer component name `{component_name}` must start with `ks-lib-materializer.`", ) ) expected_processor = "materializer." + component_name.removeprefix("ks-lib-materializer.") if processor_name != expected_processor: violations.append( Violation( "KH_MT011", processor[1], processor[2], f"processor name `{processor_name}` must equal `{expected_processor}`", ) ) for prefix, (_, relative, line) in sorted(processor_names.items()): if prefix not in component_names: violations.append( Violation( "KH_MT012", relative, line, f"`{prefix}` processor name requires one matching component name", ) ) for path in sorted(materializer_root.rglob("constants.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for match in component_pattern.finditer(text): symbol = f"{match.group(1)}_COMPONENT_NAME" used_by_implementation = any( symbol in candidate.read_text(encoding="utf-8") for candidate in path.parent.rglob("*.rs") if candidate.name != "constants.rs" ) if not used_by_implementation: violations.append( Violation( "KH_MT025", relative, text[: match.start()].count("\n") + 1, f"materializer component constant `{symbol}` is not consumed by its implementation", ) ) component_values = {value[0] for value in component_names.values()} processor_values = {value[0] for value in processor_names.values()} if len(component_values) != len(component_names): violations.append( Violation( "KH_MT017", "ks-lib/src/materializer", 1, "materializer component names must be unique", ) ) if len(processor_values) != len(processor_names): violations.append( Violation( "KH_MT018", "ks-lib/src/materializer", 1, "materializer processor names must be unique", ) ) tracing_pattern = re.compile( r'pub\(crate\) const TRACING_TARGET_MATERIALIZER_[A-Z0-9_]+: &str\s*=\s*"([^"]+)";' ) for path in sorted(materializer_root.rglob("constants.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for match in tracing_pattern.finditer(text): if match.group(1) not in component_values: line = text[: match.start()].count("\n") + 1 violations.append( Violation( "KH_MT019", relative, line, f"materializer tracing target `{match.group(1)}` must equal one component name", ) ) config_path = root / "config/logging.config.json" if config_path.exists(): try: config = json.loads(config_path.read_text(encoding="utf-8")) except json.JSONDecodeError: config = None pending: list[object] = [config] if config is not None else [] while pending: value = pending.pop() if isinstance(value, dict): targets = value.get("targets") if isinstance(targets, list): for target in targets: if ( isinstance(target, str) and target.startswith("ks-lib-materializer.") and target not in component_values ): violations.append( Violation( "KH_MT020", "config/logging.config.json", 1, f"logging target `{target}` is not a declared materializer component", ) ) pending.extend(value.values()) elif isinstance(value, list): pending.extend(value) for path in sorted(materializer_root.rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") if path.name != "constants.rs" and re.search(r'"processorName"\s*:\s*"', text): violations.append( Violation( "KH_MT021", relative, 1, "persisted processor names must come from exported component constants", ) ) for offset, block in iter_rust_json_object_macros(text): if '"projectionVersion"' not in block: continue line = text[:offset].count("\n") + 1 if '"processorName"' not in block: violations.append( Violation( "KH_MT022", relative, line, "versioned materializer output must persist its processor provenance", ) ) if re.search( r'"projectionVersion"\s*:\s*crate::MT_[A-Z0-9_]+_PROJECTION_VERSION', block, ) is None: violations.append( Violation( "KH_MT023", relative, line, "materializer projection version must come from an exported component constant", ) ) if re.search( r'"processorName"\s*:\s*crate::MT_[A-Z0-9_]+_PROCESSOR_NAME', block, ) is None: violations.append( Violation( "KH_MT024", relative, line, "materializer processor provenance must come from an exported component constant", ) ) if path.name != "constants.rs" and re.search( r"^\s*(?:pub(?:\(crate\))?\s+)?const\s+[A-Z][A-Z0-9_]*\b", text, re.MULTILINE, ): violations.append( Violation( "KH_MT013", relative, 1, "materializer constants must be declared in the component `constants.rs`", ) ) if path.name == "materializer.rs" and re.search( r"^pub struct Mt[A-Za-z0-9]+Materializer;", text, re.MULTILINE ): constants_path = path.parent / "constants.rs" if not constants_path.exists(): violations.append( Violation( "KH_MT014", relative, 1, "materializer implementation requires a sibling `constants.rs`", ) ) if re.search(r'"(?:ks-lib-)?materializer\.[^"]+"', text): violations.append( Violation( "KH_MT015", relative, 1, "materializer identities must come from exported component constants", ) ) module_lines = [ line for line in text.splitlines() if re.fullmatch(r"mod [A-Za-z_][A-Za-z0-9_]*;", line.strip()) is not None ] if not module_lines: continue for index, line in enumerate(text.splitlines(), 1): stripped = line.strip() if not stripped or stripped.startswith("//") or stripped == "#[cfg(test)]": continue if re.fullmatch(r"mod [A-Za-z_][A-Za-z0-9_]*;", stripped) is not None: continue if stripped.startswith("pub use ") or stripped.startswith("pub(crate) use "): continue violations.append( Violation( "KH_MT016", relative, index, "materializer facade may contain only submodule declarations and re-exports", ) ) break return violations def audit_reserved_executor_scaffolds(root: pathlib.Path) -> list[Violation]: """Reject incomplete reserved executor contracts.""" violations: list[Violation] = [] executor_root = root / "ks-lib/src/executor" forbidden = ( "MIGRATION_BOUNDARIES", "LEGACY_CRATE", "MIGRATION_STATUS", "source-preserved-pending-port", ) struct_pattern = re.compile(r"^pub struct (Ex[A-Za-z0-9]+Executor);$", re.MULTILINE) reserved_count = 0 for path in sorted(executor_root.rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for marker in forbidden: offset = text.find(marker) if offset >= 0: violations.append( Violation( "KH_EX001", relative, text[:offset].count("\n") + 1, f"temporary executor migration marker `{marker}` is forbidden", ) ) if "\n//! Reserved executor for `" not in text: continue reserved_count += 1 struct_match = struct_pattern.search(text) if struct_match is None: violations.append( Violation( "KH_EX002", relative, 1, "reserved executor must expose one `Ex*Executor` unit struct", ) ) continue type_name = struct_match.group(1) implementation = f"impl crate::ExApiInstructionExecutor for crate::{type_name} {{" if implementation not in text: violations.append( Violation( "KH_EX003", relative, text[: struct_match.start()].count("\n") + 1, f"`{type_name}` must implement `ExApiInstructionExecutor`", ) ) if "fn program_ids(&self) -> &'static [&'static str]" not in text: violations.append( Violation( "KH_EX004", relative, 1, "reserved executor must declare its exact Program ID boundary", ) ) if "crate::ExApiExecutionSupport::Maybe" not in text: violations.append( Violation( "KH_EX005", relative, 1, "reserved executor must remain explicitly `Maybe` until implemented", ) ) if '"status":"reserved_executor"' not in text or "instruction_count: 0" not in text: violations.append( Violation( "KH_EX006", relative, 1, "reserved executor must build only an explicit zero-instruction plan", ) ) if reserved_count != 103: violations.append( Violation( "KH_EX007", "ks-lib/src/executor", 1, f"expected 103 reserved executor boundaries, found {reserved_count}", ) ) return violations def audit_token_2022_naming(root: pathlib.Path) -> list[Violation]: """Reject obsolete internal Token2022 spellings while preserving legacy evidence.""" violations: list[Violation] = [] obsolete = ( "kb-lib.decoder.spl.token_2022", "`core_spl_token_2022", ) candidates = [ root / "README.md", root / "ROADMAP.md", root / "RULES.md", root / "docs/rules/RULES_GENERAL.md", root / "docs/rules/RULES_RUST.md", root / "docs/rules/RULES_SPECIFIC_KHADHROONY.md", root / "ks-lib/README.md", ] candidates.extend(sorted((root / "docs").glob("*.md"))) for path in candidates: if not path.is_file() or path.name == "RUST_WORKSPACE_RULE_AUDIT.md": continue relative = path.relative_to(root).as_posix() for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): for spelling in obsolete: if spelling in line: violations.append( Violation( "KH_NAME002", relative, index, f"obsolete internal Token2022 spelling `{spelling}`", ) ) return violations def audit_private_ks_lib_paths_in_active_docs(root: pathlib.Path) -> list[Violation]: """Reject documentation that presents private ks-lib modules as public APIs.""" violations: list[Violation] = [] candidates = [ root / "README.md", root / "ROADMAP.md", root / "RULES.md", root / "docs/rules/RULES_GENERAL.md", root / "docs/rules/RULES_RUST.md", root / "docs/rules/RULES_SPECIFIC_KHADHROONY.md", root / "ks-lib/README.md", root / "ks-program-ids/README.md", ] candidates.extend(sorted((root / "docs").glob("*.md"))) candidates.extend(sorted((root / "docs").glob("*.json"))) pattern = re.compile(r"ks_lib::(?:decoder|executor|materializer|model)::") for path in candidates: if not path.is_file(): continue relative = path.relative_to(root).as_posix() for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): match = pattern.search(line) if match is not None: violations.append( Violation( "KH_API001", relative, index, f"private ks-lib module path `{match.group(0)}` is forbidden in active documentation", ) ) return violations def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]: """Require workspace-owned environment variables to use KS_* or KB_* namespaces.""" violations: list[Violation] = [] rust_pattern = re.compile( r'std::env::(?:var|var_os|set_var|remove_var)\(\s*"([A-Z][A-Z0-9_]*)"' ) rust_roots = [path.parent for path in sorted(root.glob("ks-*/Cargo.toml"))] desktop = root / "kb-app-demo-desktop" if desktop.is_dir(): rust_roots.append(desktop) for rust_root in rust_roots: for path in sorted((rust_root / "src").rglob("*.rs")): relative = path.relative_to(root).as_posix() text = path.read_text(encoding="utf-8") for match in rust_pattern.finditer(text): name = match.group(1) if name.startswith(("KS_", "KB_")): continue violations.append( Violation( "KH_ENV001", relative, text[: match.start()].count("\n") + 1, f"workspace-owned environment variable `{name}` must use a `KS_*` or `KB_*` namespace", ) ) env_example = root / ".env.example" if env_example.is_file(): assignment = re.compile(r"^\s*#?\s*([A-Z][A-Z0-9_]*)=") for index, line in enumerate(env_example.read_text(encoding="utf-8").splitlines(), 1): match = assignment.match(line) if match is None or match.group(1).startswith(("KS_", "KB_")): continue violations.append( Violation( "KH_ENV002", ".env.example", index, f"workspace environment example `{match.group(1)}` must use a `KS_*` or `KB_*` namespace", ) ) placeholder = re.compile(r"\$\{([A-Z][A-Z0-9_]*)") for relative in [ "config/kb-app-demo-desktop.default.config.json", "config/logging.config.json", "config/transport.config.json", "config/listeners.config.json", "config/store.config.json", "config/wallet.config.json", "config/execution.config.json", "config/example.kb-app-demo-desktop.default.config.json", "config/example.logging.config.json", "config/example.transport.config.json", "config/example.listeners.config.json", "config/example.store.config.json", "config/example.wallet.config.json", "config/example.execution.config.json", ]: config = root / relative if not config.is_file(): continue text = config.read_text(encoding="utf-8") for match in placeholder.finditer(text): name = match.group(1) if name.startswith(("KS_", "KB_")): continue violations.append( Violation( "KH_ENV003", relative, text[: match.start()].count("\n") + 1, f"configuration placeholder `{name}` must use a `KS_*` or `KB_*` namespace", ) ) guide = root / "docs/DEVNET_EXECUTION_GUIDE.md" if guide.is_file(): text = guide.read_text(encoding="utf-8") exported = re.compile(r"\bexport\s+([A-Z][A-Z0-9_]*)=") for match in exported.finditer(text): name = match.group(1) if name.startswith(("KS_", "KB_")): continue violations.append( Violation( "KH_ENV004", "docs/DEVNET_EXECUTION_GUIDE.md", text[: match.start()].count("\n") + 1, f"operator environment variable `{name}` must use a `KS_*` or `KB_*` namespace", ) ) return violations def audit_configuration_split(root: pathlib.Path) -> list[Violation]: """Require one binary composition plus independent shared configuration documents.""" violations: list[Violation] = [] required_files = [ "config/kb-app-demo-desktop.default.config.json", "config/logging.config.json", "config/transport.config.json", "config/listeners.config.json", "config/store.config.json", "config/wallet.config.json", "config/execution.config.json", "config/example.kb-app-demo-desktop.default.config.json", "config/example.logging.config.json", "config/example.transport.config.json", "config/example.listeners.config.json", "config/example.store.config.json", "config/example.wallet.config.json", "config/example.execution.config.json", "config/schemas/composition.config.schema.json", "config/schemas/logging.config.schema.json", "config/schemas/transport.config.schema.json", "config/schemas/listeners.config.schema.json", "config/schemas/store.config.schema.json", "config/schemas/wallet.config.schema.json", "config/schemas/execution.config.schema.json", "config/schemas/resolved.app.config.schema.json", ] for relative in required_files: if (root / relative).is_file(): continue violations.append(Violation("KH_CFG001", relative, 1, "required split configuration file is missing")) composition_path = root / "config/kb-app-demo-desktop.default.config.json" if composition_path.is_file(): try: composition = json.loads(composition_path.read_text(encoding="utf-8")) except json.JSONDecodeError: composition = None if isinstance(composition, dict): sources = composition.get("sources") expected_sources = {"logging", "transport", "listeners", "store", "wallet", "execution"} if not isinstance(sources, dict) or set(sources) != expected_sources: violations.append(Violation("KH_CFG002", composition_path.relative_to(root).as_posix(), 1, "binary composition must reference all six shared configuration sources")) for index, profile in enumerate(composition.get("profiles", []), 1): if not isinstance(profile, dict): continue forbidden = {"solana", "logging", "database", "data", "wallet", "execution"} if forbidden.intersection(profile): violations.append(Violation("KH_CFG003", composition_path.relative_to(root).as_posix(), index, "composition profiles must reference shared profiles instead of embedding shared configuration")) for key in ["logging_profile", "transport_profile", "listeners_profile", "store_profile", "wallet_profile", "execution_profile"]: if key in profile and (not isinstance(profile.get(key), str) or not profile.get(key, "").strip()): violations.append(Violation("KH_CFG004", composition_path.relative_to(root).as_posix(), index, f"optional composition override `{key}` must be non-empty when present")) shared = [ "config/logging.config.json", "config/transport.config.json", "config/listeners.config.json", "config/store.config.json", "config/wallet.config.json", "config/execution.config.json", ] for relative in shared: path = root / relative if not path.is_file(): continue try: document = json.loads(path.read_text(encoding="utf-8")) except json.JSONDecodeError: document = None if not isinstance(document, dict): continue if not isinstance(document.get("default_profile"), str) or not document.get("default_profile", "").strip(): violations.append(Violation("KH_CFG005", relative, 1, "shared configuration document must define a non-empty default_profile")) if not isinstance(document.get("profiles"), list) or not document.get("profiles"): violations.append(Violation("KH_CFG006", relative, 1, "shared configuration document must define named profiles")) logging = root / "config/logging.config.json" if logging.is_file(): document = json.loads(logging.read_text(encoding="utf-8")) if not isinstance(document.get("logs_directory"), str) or not document.get("logs_directory", "").strip(): violations.append(Violation("KH_CFG008", "config/logging.config.json", 1, "logging root directory must be global and non-empty")) wallet = root / "config/wallet.config.json" if wallet.is_file(): document = json.loads(wallet.read_text(encoding="utf-8")) if not isinstance(document.get("wallets_directory"), str) or not document.get("wallets_directory", "").strip(): violations.append(Violation("KH_CFG009", "config/wallet.config.json", 1, "wallet root directory must be global and non-empty")) for index, profile in enumerate(document.get("profiles", []), 1): if isinstance(profile, dict) and any(key.endswith("_send_enabled") for key in profile): violations.append(Violation("KH_CFG010", "config/wallet.config.json", index, "send authorization belongs to execution configuration, not wallet profiles")) transport = root / "config/transport.config.json" if transport.is_file(): document = json.loads(transport.read_text(encoding="utf-8")) defaults = document.get("ws_endpoint_defaults") if not isinstance(defaults, list) or not defaults: violations.append(Violation("KH_CFG011", "config/transport.config.json", 1, "transport configuration must define named WebSocket endpoint defaults")) for pindex, profile in enumerate(document.get("profiles", []), 1): if not isinstance(profile, dict): continue for endpoint in profile.get("ws_endpoints", []): if isinstance(endpoint, dict) and (not isinstance(endpoint.get("defaults"), str) or not endpoint.get("defaults", "").strip()): violations.append(Violation("KH_CFG012", "config/transport.config.json", pindex, "each WebSocket endpoint must select one named defaults class")) legacy = [ "config/app.config.json", "config/example.app.config.json", "config/schemas/app.config.schema.json", "config/example.config.json", "config/schema.config.json", "config/ks-pipeline-demo-scenarios.default.config.json", ] for relative in legacy: if not (root / relative).exists(): continue violations.append(Violation("KH_CFG007", relative, 1, "legacy or unnecessary configuration composition file must be removed")) return violations def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]: """Require the currently compatible Solana wincode dependency family.""" violations: list[Violation] = [] cargo_path = root / "Cargo.toml" lock_path = root / "Cargo.lock" if not cargo_path.exists(): return violations cargo = tomllib.loads(cargo_path.read_text(encoding="utf-8")) workspace_wincode = cargo.get("workspace", {}).get("dependencies", {}).get("wincode") version = workspace_wincode.get("version") if isinstance(workspace_wincode, dict) else None if version != "^0.5": violations.append( Violation( "KH_DEP001", "Cargo.toml", 1, "workspace wincode must remain constrained to `^0.5`", ) ) if not lock_path.exists(): violations.append( Violation( "KH_DEP002", "Cargo.lock", 1, "local workspace Cargo.lock is required to verify the pinned wincode resolution", ) ) return violations lock = tomllib.loads(lock_path.read_text(encoding="utf-8")) packages = lock.get("package", []) resolved_wincode = [ package.get("version") for package in packages if package.get("name") == "wincode" ] resolved_varint = [ package.get("version") for package in packages if package.get("name") == "solana-wincode-varint" ] if resolved_wincode != ["0.5.5"]: violations.append( Violation( "KH_DEP003", "Cargo.lock", 1, f"expected only wincode 0.5.5, resolved {resolved_wincode}", ) ) if resolved_varint != ["1.0.0"]: violations.append( Violation( "KH_DEP004", "Cargo.lock", 1, f"expected only solana-wincode-varint 1.0.0, resolved {resolved_varint}", ) ) return violations def main() -> int: """Run the khadhroony-specific audit.""" parser = argparse.ArgumentParser() parser.add_argument("--root", default=".") parser.add_argument("--report-only", action="store_true") arguments = parser.parse_args() root = pathlib.Path(arguments.root).resolve() violations = ( audit_tracing(root) +audit_ks_lib_tracing(root) +audit_ks_lib_symbol_prefixes(root) +audit_reserved_decoder_scaffolds(root) +audit_reserved_materializer_scaffolds(root) +audit_materializer_conventions(root) +audit_reserved_executor_scaffolds(root) +audit_token_2022_naming(root) +audit_private_ks_lib_paths_in_active_docs(root) +audit_solana_types(root) +audit_environment_namespaces(root) +audit_configuration_split(root) +audit_wincode_resolution(root) ) violations.sort(key=lambda item: (item.code, item.path, item.line, item.message)) if not violations: sys.stdout.write("Khadhroony workspace rule audit: clean\n") return 0 sys.stdout.write(f"Khadhroony workspace rule audit: {len(violations)} violation(s)\n") for item in violations: sys.stdout.write(f"{item.code} {item.path}:{item.line}: {item.message}\n") return 0 if arguments.report_only else 1 if __name__ == "__main__": raise SystemExit(main())