Restructure solution layout by module
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -1,86 +1,86 @@ | ||||
| #!/usr/bin/env python3 | ||||
| """Ensure Authority policy client configs use the fine-grained scope set.""" | ||||
|  | ||||
| from __future__ import annotations | ||||
|  | ||||
| import sys | ||||
| from pathlib import Path | ||||
|  | ||||
| EXPECTED_SCOPES = ( | ||||
|     "policy:read", | ||||
|     "policy:author", | ||||
|     "policy:review", | ||||
|     "policy:simulate", | ||||
|     "findings:read", | ||||
| ) | ||||
|  | ||||
|  | ||||
| def extract_scopes(lines: list[str], start_index: int) -> tuple[str, ...] | None: | ||||
|     for offset in range(1, 12): | ||||
|         if start_index + offset >= len(lines): | ||||
|             break | ||||
|         line = lines[start_index + offset].strip() | ||||
|         if not line: | ||||
|             continue | ||||
|         if line.startswith("scopes:"): | ||||
|             try: | ||||
|                 raw = line.split("[", 1)[1].rsplit("]", 1)[0] | ||||
|             except IndexError: | ||||
|                 return None | ||||
|             scopes = tuple(scope.strip().strip('"') for scope in raw.split(",")) | ||||
|             scopes = tuple(scope for scope in scopes if scope) | ||||
|             return scopes | ||||
|     return None | ||||
|  | ||||
|  | ||||
| def validate(path: Path) -> list[str]: | ||||
|     errors: list[str] = [] | ||||
|     try: | ||||
|         text = path.read_text(encoding="utf-8") | ||||
|     except FileNotFoundError: | ||||
|         return [f"{path}: missing file"] | ||||
|  | ||||
|     if "policy:write" in text or "policy:submit" in text: | ||||
|         errors.append(f"{path}: contains legacy policy scope names (policy:write/policy:submit)") | ||||
|  | ||||
|     lines = text.splitlines() | ||||
|     client_indices = [idx for idx, line in enumerate(lines) if 'clientId: "policy-cli"' in line] | ||||
|     if not client_indices: | ||||
|         errors.append(f"{path}: policy-cli client registration not found") | ||||
|         return errors | ||||
|  | ||||
|     for idx in client_indices: | ||||
|         scopes = extract_scopes(lines, idx) | ||||
|         if scopes is None: | ||||
|             errors.append(f"{path}: unable to parse scopes for policy-cli client") | ||||
|             continue | ||||
|         if tuple(sorted(scopes)) != tuple(sorted(EXPECTED_SCOPES)): | ||||
|             errors.append( | ||||
|                 f"{path}: unexpected policy-cli scopes {scopes}; expected {EXPECTED_SCOPES}" | ||||
|             ) | ||||
|  | ||||
|     return errors | ||||
|  | ||||
|  | ||||
| def main(argv: list[str]) -> int: | ||||
|     repo_root = Path(__file__).resolve().parents[1] | ||||
|     targets = [ | ||||
|         repo_root / "etc" / "authority.yaml", | ||||
|         repo_root / "etc" / "authority.yaml.sample", | ||||
|     ] | ||||
|  | ||||
|     failures: list[str] = [] | ||||
|     for target in targets: | ||||
|         failures.extend(validate(target)) | ||||
|  | ||||
|     if failures: | ||||
|         for message in failures: | ||||
|             print(f"error: {message}", file=sys.stderr) | ||||
|         return 1 | ||||
|  | ||||
|     print("policy scope verification passed") | ||||
|     return 0 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     raise SystemExit(main(sys.argv)) | ||||
| #!/usr/bin/env python3 | ||||
| """Ensure Authority policy client configs use the fine-grained scope set.""" | ||||
|  | ||||
| from __future__ import annotations | ||||
|  | ||||
| import sys | ||||
| from pathlib import Path | ||||
|  | ||||
| EXPECTED_SCOPES = ( | ||||
|     "policy:read", | ||||
|     "policy:author", | ||||
|     "policy:review", | ||||
|     "policy:simulate", | ||||
|     "findings:read", | ||||
| ) | ||||
|  | ||||
|  | ||||
| def extract_scopes(lines: list[str], start_index: int) -> tuple[str, ...] | None: | ||||
|     for offset in range(1, 12): | ||||
|         if start_index + offset >= len(lines): | ||||
|             break | ||||
|         line = lines[start_index + offset].strip() | ||||
|         if not line: | ||||
|             continue | ||||
|         if line.startswith("scopes:"): | ||||
|             try: | ||||
|                 raw = line.split("[", 1)[1].rsplit("]", 1)[0] | ||||
|             except IndexError: | ||||
|                 return None | ||||
|             scopes = tuple(scope.strip().strip('"') for scope in raw.split(",")) | ||||
|             scopes = tuple(scope for scope in scopes if scope) | ||||
|             return scopes | ||||
|     return None | ||||
|  | ||||
|  | ||||
| def validate(path: Path) -> list[str]: | ||||
|     errors: list[str] = [] | ||||
|     try: | ||||
|         text = path.read_text(encoding="utf-8") | ||||
|     except FileNotFoundError: | ||||
|         return [f"{path}: missing file"] | ||||
|  | ||||
|     if "policy:write" in text or "policy:submit" in text: | ||||
|         errors.append(f"{path}: contains legacy policy scope names (policy:write/policy:submit)") | ||||
|  | ||||
|     lines = text.splitlines() | ||||
|     client_indices = [idx for idx, line in enumerate(lines) if 'clientId: "policy-cli"' in line] | ||||
|     if not client_indices: | ||||
|         errors.append(f"{path}: policy-cli client registration not found") | ||||
|         return errors | ||||
|  | ||||
|     for idx in client_indices: | ||||
|         scopes = extract_scopes(lines, idx) | ||||
|         if scopes is None: | ||||
|             errors.append(f"{path}: unable to parse scopes for policy-cli client") | ||||
|             continue | ||||
|         if tuple(sorted(scopes)) != tuple(sorted(EXPECTED_SCOPES)): | ||||
|             errors.append( | ||||
|                 f"{path}: unexpected policy-cli scopes {scopes}; expected {EXPECTED_SCOPES}" | ||||
|             ) | ||||
|  | ||||
|     return errors | ||||
|  | ||||
|  | ||||
| def main(argv: list[str]) -> int: | ||||
|     repo_root = Path(__file__).resolve().parents[1] | ||||
|     targets = [ | ||||
|         repo_root / "etc" / "authority.yaml", | ||||
|         repo_root / "etc" / "authority.yaml.sample", | ||||
|     ] | ||||
|  | ||||
|     failures: list[str] = [] | ||||
|     for target in targets: | ||||
|         failures.extend(validate(target)) | ||||
|  | ||||
|     if failures: | ||||
|         for message in failures: | ||||
|             print(f"error: {message}", file=sys.stderr) | ||||
|         return 1 | ||||
|  | ||||
|     print("policy scope verification passed") | ||||
|     return 0 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     raise SystemExit(main(sys.argv)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user