Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/issue-detection-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Issue Detection Coverage

on:
push:
branches: [develop, main]
paths:
- "appguardrail_core/issue_detection.py"
- "appguardrail_core/issue_detection_registry.json"
- "appguardrail_core/__init__.py"
- "tests/test_issue_detection.py"
- "tests/test_issue_detection_release_contract.py"
- "tests/fixtures/appguardrail_issue_numbers_2026-08-09.json"
- "docs/issue-detection-contract.md"
- "CHANGELOG.d/issue-detection-contract.md"
- "pyproject.toml"
- "MANIFEST.in"
- ".github/workflows/issue-detection-coverage.yml"
- ".github/workflows/issue-detection-registry-audit.yml"
pull_request:
branches: [develop, main]
paths:
- "appguardrail_core/issue_detection.py"
- "appguardrail_core/issue_detection_registry.json"
- "appguardrail_core/__init__.py"
- "tests/test_issue_detection.py"
- "tests/test_issue_detection_release_contract.py"
- "tests/fixtures/appguardrail_issue_numbers_2026-08-09.json"
- "docs/issue-detection-contract.md"
- "CHANGELOG.d/issue-detection-contract.md"
- "pyproject.toml"
- "MANIFEST.in"
- ".github/workflows/issue-detection-coverage.yml"
- ".github/workflows/issue-detection-registry-audit.yml"

permissions:
contents: read

concurrency:
group: issue-detection-coverage-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
exact-issue-detection-coverage:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.13"
- name: Install hash-locked test dependencies
run: python -m pip install --disable-pip-version-check --no-cache-dir --require-hashes -r requirements-test.txt
- name: Run issue-detection contracts
run: |
python -m pytest -q \
tests/test_issue_detection.py \
tests/test_issue_detection_release_contract.py
- name: Verify exact unrounded statement coverage
run: |
python -m scripts.ci.verify_module_coverage \
--module appguardrail_core/issue_detection.py \
--test tests/test_issue_detection.py \
--test tests/test_issue_detection_release_contract.py
47 changes: 47 additions & 0 deletions .github/workflows/issue-detection-registry-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Issue Detection Registry Audit

on:
issues:
types: [opened, edited, reopened, closed]
pull_request:
branches: [develop, main]
paths:
- "appguardrail_core/issue_detection.py"
- "appguardrail_core/issue_detection_registry.json"
- "tests/fixtures/appguardrail_issue_numbers_2026-08-09.json"
- ".github/workflows/issue-detection-registry-audit.yml"
schedule:
- cron: "17 */6 * * *"
workflow_dispatch:

permissions:
contents: read
issues: read

concurrency:
group: issue-detection-registry-audit-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
audit-live-issues:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.13"
- name: Fetch every open and closed issue page
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api --paginate --slurp "/repos/${GITHUB_REPOSITORY}/issues?state=all&per_page=100" \
> "${RUNNER_TEMP}/appguardrail-issues.json"
- name: Require exact issue-to-detector coverage
run: |
python -m appguardrail_core.issue_detection audit-registry \
--issues-file "${RUNNER_TEMP}/appguardrail-issues.json"
11 changes: 11 additions & 0 deletions CHANGELOG.d/issue-detection-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### Added

- Added an executable no-exclusions contract for all 414 retained AppGuardrail
issues and 417 independent claims, with 17 callable detector families,
closed evidence-field and required-evidence-field contracts, and
machine-readable `obligations[]` proven by positive, negative, and unknown
executions of each full condition. Unsupported, extra, or missing evidence
is unknown and fail-closed. The contract also includes provenance-bound
workflow-result classification authenticated by an externally provisioned
HMAC capability, recomputed payload and issue-requirement digests, an
installed audit CLI, and read-only exact-coverage and live-inventory workflows.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include README.md
include LICENSE
include CHANGELOG.md
recursive-include appguardrail_core *.json
recursive-include scanner/rules *.yml
recursive-include scanner/dashboard *.html
recursive-include scanner/dashboard *.json
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Agent. See [Release Automation](docs/release-automation.md).
For the productization roadmap, see the
[2B KRW sale readiness plan](docs/product/2026-07-02-2b-krw-sale-readiness-plan.md).

Maintainers can review the exhaustive issue-to-detector policy and live audit
procedure in the [issue-derived detection contract](docs/issue-detection-contract.md).
It binds all 17 detector families to closed evidence fields and machine-readable
obligations with positive, negative, and unknown executions; unsupported, extra,
or missing evidence remains fail-closed and unknown.

### Initialize security rules in your project

```bash
Expand Down
36 changes: 36 additions & 0 deletions appguardrail_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@
safe_report_snippet,
severity_counts,
)
from appguardrail_core.issue_detection import (
DetectionResult,
FamilyAssessment,
IssueCoverageAudit,
IssueDetectionClaim,
IssueDetectionRegistry,
IssueDetectionTarget,
WorkflowEvidence,
WorkflowResultVerifier,
audit_issue_coverage,
audit_issue_requirements,
compute_issue_requirement_sha256,
detect_workflow_causes,
evaluate_detector_family,
evaluate_issue_claim,
load_issue_detection_registry,
materialize_issue_claim_fixture,
registered_detector_families,
)
from appguardrail_core.language import (
StackProfile,
detect_language_axes,
Expand Down Expand Up @@ -157,11 +176,17 @@ def render_buyer_diligence_report(
"DEFAULT_RETENTION_DAYS",
"DEPLOY_BLOCKING_SEVERITIES",
"DestinationValidationError",
"DetectionResult",
"DriftAssessment",
"ExternalEngineDecision",
"ExternalScanPlan",
"FamilyAssessment",
"GENESIS_EVENT_HASH",
"HTTPSDestination",
"IssueCoverageAudit",
"IssueDetectionClaim",
"IssueDetectionRegistry",
"IssueDetectionTarget",
"MAX_RETENTION_DAYS",
"MIN_RETENTION_DAYS",
"MetricResult",
Expand Down Expand Up @@ -189,6 +214,10 @@ def render_buyer_diligence_report(
"SchemaMigrationResult",
"StackProfile",
"StalePurgePreview",
"WorkflowEvidence",
"WorkflowResultVerifier",
"audit_issue_coverage",
"audit_issue_requirements",
"build_buyer_evidence_pack",
"build_code_scanning_snapshot",
"build_external_scan_plan",
Expand All @@ -199,23 +228,30 @@ def render_buyer_diligence_report(
"classify_pr_gate",
"collect_openssf_evidence",
"compare_code_scanning_snapshots",
"compute_issue_requirement_sha256",
"create_audit_event",
"create_purge_receipt",
"detect_language_axes",
"detect_stack_profile",
"detect_workflow_causes",
"evaluate_detector_family",
"evaluate_issue_claim",
"evidence_to_finding",
"extract_public_references",
"finding_sort_key",
"gate_action_bucket",
"inspect_controlplane_schema",
"is_deploy_blocking",
"load_issue_detection_registry",
"materialize_issue_claim_fixture",
"migrate_controlplane_schema",
"normalize_code_scanning_analysis",
"normalize_finding",
"normalize_findings",
"parse_openssf_project_matches",
"post_json_pinned_https",
"recompute_event_hash",
"registered_detector_families",
"render_buyer_diligence_report",
"render_org_readiness_report",
"resolve_public_https_destination",
Expand Down
Loading
Loading