proofctl 0.1.2__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {proofctl-0.1.2 → proofctl-0.1.3}/PKG-INFO +1 -43
  2. {proofctl-0.1.2 → proofctl-0.1.3}/README.md +0 -42
  3. proofctl-0.1.3/proofctl/reporters/terminal.py +88 -0
  4. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/PKG-INFO +1 -43
  5. {proofctl-0.1.2 → proofctl-0.1.3}/pyproject.toml +1 -1
  6. proofctl-0.1.2/proofctl/reporters/terminal.py +0 -110
  7. {proofctl-0.1.2 → proofctl-0.1.3}/LICENSE +0 -0
  8. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/__init__.py +0 -0
  9. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/baseline.py +0 -0
  10. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/__init__.py +0 -0
  11. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/base.py +0 -0
  12. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/dockerfile.py +0 -0
  13. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/hcl_utils.py +0 -0
  14. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/imports.py +0 -0
  15. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/leakage.py +0 -0
  16. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/llm_integration.py +0 -0
  17. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/placeholders.py +0 -0
  18. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/quality.py +0 -0
  19. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/security.py +0 -0
  20. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/terraform.py +0 -0
  21. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/terragrunt.py +0 -0
  22. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/variants.py +0 -0
  23. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/checkers/yaml_checker.py +0 -0
  24. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/cli.py +0 -0
  25. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/config.py +0 -0
  26. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/engine.py +0 -0
  27. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/fixer.py +0 -0
  28. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/models.py +0 -0
  29. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/reporters/__init__.py +0 -0
  30. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/reporters/html_reporter.py +0 -0
  31. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl/reporters/json_reporter.py +0 -0
  32. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/SOURCES.txt +0 -0
  33. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/dependency_links.txt +0 -0
  34. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/entry_points.txt +0 -0
  35. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/requires.txt +0 -0
  36. {proofctl-0.1.2 → proofctl-0.1.3}/proofctl.egg-info/top_level.txt +0 -0
  37. {proofctl-0.1.2 → proofctl-0.1.3}/setup.cfg +0 -0
  38. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_baseline.py +0 -0
  39. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_config_proofctl.py +0 -0
  40. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_dockerfile.py +0 -0
  41. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_engine.py +0 -0
  42. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_fixer.py +0 -0
  43. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_imports.py +0 -0
  44. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_leakage.py +0 -0
  45. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_llm.py +0 -0
  46. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_placeholders.py +0 -0
  47. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_quality.py +0 -0
  48. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_quality_ext.py +0 -0
  49. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_security.py +0 -0
  50. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_security_ext.py +0 -0
  51. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_suppression.py +0 -0
  52. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_terraform.py +0 -0
  53. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_terraform_ext.py +0 -0
  54. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_terragrunt.py +0 -0
  55. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_variants.py +0 -0
  56. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_yaml.py +0 -0
  57. {proofctl-0.1.2 → proofctl-0.1.3}/tests/test_yaml_k8s_gha.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proofctl
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
5
5
  Author-email: Kolawolu Odunola <kolawolu.o@gmail.com>
6
6
  License: MIT
@@ -491,48 +491,6 @@ Print all rule IDs, names, and severities.
491
491
 
492
492
  ---
493
493
 
494
- ## Architecture
495
-
496
- proofctl is a pure Python AST linter with zero subprocess dependencies. It walks the repository with Python's `pathlib`, runs AST visitors for Python files, and custom regex/text parsers for Terraform HCL, Dockerfiles, and YAML. This makes it:
497
-
498
- - **Fast** — typically < 1s for a 10k-line Python repo
499
- - **Offline** — no network calls needed with `--no-pypi`
500
- - **Dependency-free** — only `typer`, `rich`, `pyyaml` are required at runtime
501
-
502
- ```
503
- proofctl/
504
- ├── cli.py # typer commands: check, baseline, rules
505
- ├── engine.py # orchestrator: walks files, dispatches checkers
506
- ├── config.py # .proofctl.yaml loader
507
- ├── models.py # Finding dataclass + Severity enum
508
- ├── baseline.py # snapshot save/load/filter
509
- ├── fixer.py # auto-fix for Q-001
510
- ├── checkers/
511
- │ ├── placeholders.py # P family
512
- │ ├── quality.py # Q family
513
- │ ├── security.py # S family (S-001 to S-013)
514
- │ ├── leakage.py # L family
515
- │ ├── imports.py # I family
516
- │ ├── methods.py # M family
517
- │ ├── variants.py # V family
518
- │ ├── llm.py # LLM family
519
- │ ├── terraform.py # TF/TG families (T, G, A, AZ, M, V, TG)
520
- │ ├── dockerfile.py # DF family
521
- │ └── yaml_checker.py # YAML/K8s/GHA families
522
- └── reporters/
523
- ├── terminal.py
524
- ├── json_reporter.py
525
- └── html_reporter.py
526
- ```
527
-
528
- ---
529
-
530
- ## Companion tool
531
-
532
- [**shieldctl**](https://pypi.org/project/shieldctl) — CI-stage scanner that wraps best-of-breed external tools (checkov, tfsec, gitleaks, shellcheck, hadolint, actionlint, pip-audit) for deeper infrastructure security scanning. Run proofctl pre-commit; run shieldctl in CI.
533
-
534
- ---
535
-
536
494
  ## License
537
495
 
538
496
  MIT
@@ -460,48 +460,6 @@ Print all rule IDs, names, and severities.
460
460
 
461
461
  ---
462
462
 
463
- ## Architecture
464
-
465
- proofctl is a pure Python AST linter with zero subprocess dependencies. It walks the repository with Python's `pathlib`, runs AST visitors for Python files, and custom regex/text parsers for Terraform HCL, Dockerfiles, and YAML. This makes it:
466
-
467
- - **Fast** — typically < 1s for a 10k-line Python repo
468
- - **Offline** — no network calls needed with `--no-pypi`
469
- - **Dependency-free** — only `typer`, `rich`, `pyyaml` are required at runtime
470
-
471
- ```
472
- proofctl/
473
- ├── cli.py # typer commands: check, baseline, rules
474
- ├── engine.py # orchestrator: walks files, dispatches checkers
475
- ├── config.py # .proofctl.yaml loader
476
- ├── models.py # Finding dataclass + Severity enum
477
- ├── baseline.py # snapshot save/load/filter
478
- ├── fixer.py # auto-fix for Q-001
479
- ├── checkers/
480
- │ ├── placeholders.py # P family
481
- │ ├── quality.py # Q family
482
- │ ├── security.py # S family (S-001 to S-013)
483
- │ ├── leakage.py # L family
484
- │ ├── imports.py # I family
485
- │ ├── methods.py # M family
486
- │ ├── variants.py # V family
487
- │ ├── llm.py # LLM family
488
- │ ├── terraform.py # TF/TG families (T, G, A, AZ, M, V, TG)
489
- │ ├── dockerfile.py # DF family
490
- │ └── yaml_checker.py # YAML/K8s/GHA families
491
- └── reporters/
492
- ├── terminal.py
493
- ├── json_reporter.py
494
- └── html_reporter.py
495
- ```
496
-
497
- ---
498
-
499
- ## Companion tool
500
-
501
- [**shieldctl**](https://pypi.org/project/shieldctl) — CI-stage scanner that wraps best-of-breed external tools (checkov, tfsec, gitleaks, shellcheck, hadolint, actionlint, pip-audit) for deeper infrastructure security scanning. Run proofctl pre-commit; run shieldctl in CI.
502
-
503
- ---
504
-
505
463
  ## License
506
464
 
507
465
  MIT
@@ -0,0 +1,88 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import Counter
4
+
5
+ from rich import box
6
+ from rich.console import Console
7
+ from rich.padding import Padding
8
+ from rich.table import Table
9
+ from rich.text import Text
10
+
11
+ from ..models import Finding, Severity
12
+
13
+ _BADGE: dict[Severity, tuple[str, str]] = {
14
+ Severity.ERROR: ("bold white on red", "ERROR"),
15
+ Severity.WARNING: ("bold black on yellow", "WARNING"),
16
+ Severity.INFO: ("bold white on grey50", "INFO"),
17
+ }
18
+
19
+ _SEV_STYLE: dict[Severity, str] = {
20
+ Severity.ERROR: "bold red",
21
+ Severity.WARNING: "bold yellow",
22
+ Severity.INFO: "dim",
23
+ }
24
+
25
+ console = Console(highlight=False, width=160)
26
+
27
+
28
+ def _location(f: Finding) -> str:
29
+ if f.line:
30
+ return f"{f.file}:{f.line}"
31
+ return f.file
32
+
33
+
34
+ class TerminalReporter:
35
+ def render(self, findings: list[Finding]) -> str:
36
+ if not findings:
37
+ console.print(Padding("[bold green]✓ No findings.[/bold green]", (1, 2)))
38
+ return ""
39
+
40
+ console.print()
41
+
42
+ sorted_findings = sorted(
43
+ findings, key=lambda x: (-x.severity, x.file, x.line or 0)
44
+ )
45
+
46
+ table = Table(
47
+ box=box.HORIZONTALS,
48
+ show_header=True,
49
+ show_edge=True,
50
+ show_lines=True,
51
+ header_style="bold",
52
+ padding=(0, 1),
53
+ )
54
+ table.add_column("Severity", no_wrap=True, min_width=10, max_width=10)
55
+ table.add_column("Rule", no_wrap=True, min_width=20, max_width=28)
56
+ table.add_column("Family", no_wrap=True, min_width=10, max_width=30)
57
+ table.add_column("Location", no_wrap=True, min_width=24, max_width=44)
58
+ table.add_column("Message", no_wrap=True, min_width=20, max_width=60)
59
+
60
+ for f in sorted_findings:
61
+ badge_style, badge_label = _BADGE[f.severity]
62
+ sev_cell = Text(f" {badge_label} ", style=badge_style)
63
+ msg = f.message if len(f.message) <= 60 else f.message[:57] + "..."
64
+ table.add_row(
65
+ sev_cell,
66
+ Text(f.rule_id, style="bold"),
67
+ Text(f.rule_name, style="dim"),
68
+ Text(_location(f), style=_SEV_STYLE[f.severity]),
69
+ Text(msg),
70
+ )
71
+
72
+ console.print(Padding(table, (0, 2)))
73
+ console.print()
74
+
75
+ # Summary bar
76
+ counts = Counter(f.severity for f in findings)
77
+ total = len(findings)
78
+ bar = Text(f" {total} finding{'s' if total != 1 else ''} ")
79
+ for sev in reversed(Severity):
80
+ if not counts[sev]:
81
+ continue
82
+ badge_style, badge_label = _BADGE[sev]
83
+ bar.append(f" {badge_label} ", style=badge_style)
84
+ bar.append(f" {counts[sev]} ", style="bold")
85
+ console.print(bar)
86
+ console.print()
87
+
88
+ return ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proofctl
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
5
5
  Author-email: Kolawolu Odunola <kolawolu.o@gmail.com>
6
6
  License: MIT
@@ -491,48 +491,6 @@ Print all rule IDs, names, and severities.
491
491
 
492
492
  ---
493
493
 
494
- ## Architecture
495
-
496
- proofctl is a pure Python AST linter with zero subprocess dependencies. It walks the repository with Python's `pathlib`, runs AST visitors for Python files, and custom regex/text parsers for Terraform HCL, Dockerfiles, and YAML. This makes it:
497
-
498
- - **Fast** — typically < 1s for a 10k-line Python repo
499
- - **Offline** — no network calls needed with `--no-pypi`
500
- - **Dependency-free** — only `typer`, `rich`, `pyyaml` are required at runtime
501
-
502
- ```
503
- proofctl/
504
- ├── cli.py # typer commands: check, baseline, rules
505
- ├── engine.py # orchestrator: walks files, dispatches checkers
506
- ├── config.py # .proofctl.yaml loader
507
- ├── models.py # Finding dataclass + Severity enum
508
- ├── baseline.py # snapshot save/load/filter
509
- ├── fixer.py # auto-fix for Q-001
510
- ├── checkers/
511
- │ ├── placeholders.py # P family
512
- │ ├── quality.py # Q family
513
- │ ├── security.py # S family (S-001 to S-013)
514
- │ ├── leakage.py # L family
515
- │ ├── imports.py # I family
516
- │ ├── methods.py # M family
517
- │ ├── variants.py # V family
518
- │ ├── llm.py # LLM family
519
- │ ├── terraform.py # TF/TG families (T, G, A, AZ, M, V, TG)
520
- │ ├── dockerfile.py # DF family
521
- │ └── yaml_checker.py # YAML/K8s/GHA families
522
- └── reporters/
523
- ├── terminal.py
524
- ├── json_reporter.py
525
- └── html_reporter.py
526
- ```
527
-
528
- ---
529
-
530
- ## Companion tool
531
-
532
- [**shieldctl**](https://pypi.org/project/shieldctl) — CI-stage scanner that wraps best-of-breed external tools (checkov, tfsec, gitleaks, shellcheck, hadolint, actionlint, pip-audit) for deeper infrastructure security scanning. Run proofctl pre-commit; run shieldctl in CI.
533
-
534
- ---
535
-
536
494
  ## License
537
495
 
538
496
  MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "proofctl"
7
- version = "0.1.2"
7
+ version = "0.1.3"
8
8
  description = "Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,110 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from collections import Counter
4
-
5
- from rich import box
6
- from rich.console import Console
7
- from rich.padding import Padding
8
- from rich.table import Table
9
- from rich.text import Text
10
-
11
- from ..models import Finding, Severity
12
-
13
- _BADGE: dict[Severity, tuple[str, str]] = {
14
- Severity.ERROR: ("bold white on red", "ERROR"),
15
- Severity.WARNING: ("bold black on yellow", "WARNING"),
16
- Severity.INFO: ("bold white on grey50", "INFO"),
17
- }
18
-
19
- _LOC_COLOUR: dict[Severity, str] = {
20
- Severity.ERROR: "red",
21
- Severity.WARNING: "yellow",
22
- Severity.INFO: "dim",
23
- }
24
-
25
- _FAMILY_LABEL: dict[str, str] = {
26
- "P": "Placeholder",
27
- "L": "Leakage",
28
- "Q": "Quality",
29
- "I": "Import",
30
- "M": "Method",
31
- "V": "Variant",
32
- }
33
-
34
- console = Console(highlight=False)
35
-
36
-
37
- def _location(f: Finding) -> str:
38
- if f.line:
39
- return f"{f.file}:{f.line}"
40
- return f.file
41
-
42
-
43
- class TerminalReporter:
44
- def render(self, findings: list[Finding]) -> str:
45
- if not findings:
46
- console.print(Padding("[bold green]✓ No findings.[/bold green]", (1, 2)))
47
- return ""
48
-
49
- console.print()
50
-
51
- by_severity: dict[Severity, list[Finding]] = {}
52
- for f in findings:
53
- by_severity.setdefault(f.severity, []).append(f)
54
-
55
- for sev in reversed(Severity):
56
- group = by_severity.get(sev)
57
- if not group:
58
- continue
59
-
60
- badge_style, badge_label = _BADGE[sev]
61
- loc_colour = _LOC_COLOUR[sev]
62
- count = len(group)
63
-
64
- header = Text(" ")
65
- header.append(f" {badge_label} ", style=badge_style)
66
- header.append(f" {count} finding{'s' if count != 1 else ''}",
67
- style="bold")
68
- console.print(header)
69
- console.print()
70
-
71
- table = Table(
72
- box=box.SIMPLE_HEAD,
73
- show_header=True,
74
- show_edge=False,
75
- header_style="dim",
76
- padding=(0, 1),
77
- )
78
- table.add_column("Rule", no_wrap=True, min_width=20, max_width=24)
79
- table.add_column("Found at", overflow="fold", ratio=1)
80
-
81
- for f in group:
82
- rule_cell = Text()
83
- rule_cell.append(f.rule_id, style="bold")
84
- rule_cell.append(f"\n{f.rule_name}", style="dim")
85
-
86
- found_cell = Text()
87
- found_cell.append(_location(f), style=loc_colour)
88
- found_cell.append(f"\n {f.message}", style="default")
89
- if f.hint:
90
- found_cell.append(f"\n → {f.hint}", style="dim italic")
91
-
92
- table.add_row(rule_cell, found_cell)
93
-
94
- console.print(Padding(table, (0, 2)))
95
- console.print()
96
-
97
- # Summary bar
98
- counts = Counter(f.severity for f in findings)
99
- total = len(findings)
100
- bar = Text(f" {total} finding{'s' if total != 1 else ''} ")
101
- for sev in reversed(Severity):
102
- if not counts[sev]:
103
- continue
104
- badge_style, badge_label = _BADGE[sev]
105
- bar.append(f" {badge_label} ", style=badge_style)
106
- bar.append(f" {counts[sev]} ", style="bold")
107
- console.print(bar)
108
- console.print()
109
-
110
- return ""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes