Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

## Table of Contents

- [What's new (2026-06-19) — Compliance Control Report (SOC2 / ISO 27001)](#whats-new-2026-06-19--compliance-control-report-soc2--iso-27001)
- [What's new (2026-06-19) — Agent Trajectory Evaluation](#whats-new-2026-06-19--agent-trajectory-evaluation)
- [What's new (2026-06-19) — Approval Testing (Golden-Master Baselines)](#whats-new-2026-06-19--approval-testing-golden-master-baselines)
- [What's new (2026-06-19) — Network Egress Allowlist Guard](#whats-new-2026-06-19--network-egress-allowlist-guard)
Expand Down Expand Up @@ -89,6 +90,12 @@

---

## What's new (2026-06-19) — Compliance Control Report (SOC2 / ISO 27001)

Map governance evidence to named controls. Full reference: [`docs/source/Eng/doc/new_features/v37_features_doc.rst`](docs/source/Eng/doc/new_features/v37_features_doc.rst).

- **`build_compliance_report`** (`AC_compliance_report`, `ac_compliance_report`): the framework already ships the controls an auditor cares about — egress allowlist, JIT credential leases, maker-checker approval, secrets scanner, audit logging, CycloneDX SBOM. This maps a flat `evidence` mapping to SOC2 (CC6.1/CC6.3/CC6.8/CC7.3/CC8.1) and ISO 27001 (A.5.23/A.8.16/A.8.30) controls, each marked `satisfied`/`gap`/`not_assessed`, and renders JSON or a standalone HTML table. The capstone of the governance set — a reporting aid, not a certification.

## What's new (2026-06-19) — Agent Trajectory Evaluation

Score an agent run against a rubric. Full reference: [`docs/source/Eng/doc/new_features/v36_features_doc.rst`](docs/source/Eng/doc/new_features/v36_features_doc.rst).
Expand Down
7 changes: 7 additions & 0 deletions README/README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目录

- [本次更新 (2026-06-19) — 合规控制报告(SOC2 / ISO 27001)](#本次更新-2026-06-19--合规控制报告soc2--iso-27001)
- [本次更新 (2026-06-19) — Agent 轨迹评估](#本次更新-2026-06-19--agent-轨迹评估)
- [本次更新 (2026-06-19) — 核准式测试(Golden-Master 基准)](#本次更新-2026-06-19--核准式测试golden-master-基准)
- [本次更新 (2026-06-19) — 网络出口允许清单守卫](#本次更新-2026-06-19--网络出口允许清单守卫)
Expand Down Expand Up @@ -88,6 +89,12 @@

---

## 本次更新 (2026-06-19) — 合规控制报告(SOC2 / ISO 27001)

将治理证据映射到具名控制项。完整参考:[`docs/source/Zh/doc/new_features/v37_features_doc.rst`](../docs/source/Zh/doc/new_features/v37_features_doc.rst)。

- **`build_compliance_report`**(`AC_compliance_report`、`ac_compliance_report`):框架已内建审计员关注的控制项 —— 出口允许清单、JIT 凭证租约、maker-checker 审批、密钥扫描器、审计记录、CycloneDX SBOM。本功能将扁平的 `evidence` 映射表映射到 SOC2(CC6.1/CC6.3/CC6.8/CC7.3/CC8.1)与 ISO 27001(A.5.23/A.8.16/A.8.30)控制项,每项标记为 `satisfied`/`gap`/`not_assessed`,并输出 JSON 或独立 HTML 表格。治理套件的收尾 —— 为报告辅助,非认证。

## 本次更新 (2026-06-19) — Agent 轨迹评估

依评分标准为 agent 运行评分。完整参考:[`docs/source/Zh/doc/new_features/v36_features_doc.rst`](../docs/source/Zh/doc/new_features/v36_features_doc.rst)。
Expand Down
7 changes: 7 additions & 0 deletions README/README_zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目錄

- [本次更新 (2026-06-19) — 合規控制報告(SOC2 / ISO 27001)](#本次更新-2026-06-19--合規控制報告soc2--iso-27001)
- [本次更新 (2026-06-19) — Agent 軌跡評估](#本次更新-2026-06-19--agent-軌跡評估)
- [本次更新 (2026-06-19) — 核准式測試(Golden-Master 基準)](#本次更新-2026-06-19--核准式測試golden-master-基準)
- [本次更新 (2026-06-19) — 網路出口允許清單守衛](#本次更新-2026-06-19--網路出口允許清單守衛)
Expand Down Expand Up @@ -88,6 +89,12 @@

---

## 本次更新 (2026-06-19) — 合規控制報告(SOC2 / ISO 27001)

將治理證據對應到具名控制項。完整參考:[`docs/source/Zh/doc/new_features/v37_features_doc.rst`](../docs/source/Zh/doc/new_features/v37_features_doc.rst)。

- **`build_compliance_report`**(`AC_compliance_report`、`ac_compliance_report`):框架已內建稽核員關注的控制項 —— 出口允許清單、JIT 憑證租約、maker-checker 審批、密鑰掃描器、稽核記錄、CycloneDX SBOM。本功能將扁平的 `evidence` 對應表映射到 SOC2(CC6.1/CC6.3/CC6.8/CC7.3/CC8.1)與 ISO 27001(A.5.23/A.8.16/A.8.30)控制項,每項標記為 `satisfied`/`gap`/`not_assessed`,並輸出 JSON 或獨立 HTML 表格。治理套件的收尾 —— 為報告輔助,非認證。

## 本次更新 (2026-06-19) — Agent 軌跡評估

依評分標準為 agent 執行評分。完整參考:[`docs/source/Zh/doc/new_features/v36_features_doc.rst`](../docs/source/Zh/doc/new_features/v36_features_doc.rst)。
Expand Down
62 changes: 62 additions & 0 deletions docs/source/Eng/doc/new_features/v37_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Compliance Control Report (SOC2 / ISO 27001)
============================================

AutoControl already ships the *controls* an auditor cares about — a network
egress allowlist, just-in-time credential leases, maker-checker approval, a
secrets scanner, audit logging, a CycloneDX SBOM. :func:`build_compliance_report`
turns "are those controls in place?" into an auditor-readable **control evidence
report**: you supply a flat ``evidence`` mapping of observed facts, and each
catalogued control is marked ``satisfied`` / ``gap`` / ``not_assessed``.

It is a reporting *aid*, not a certification — it records the evidence you
assert, it does not itself verify the controls. Pure standard library; imports
no ``PySide6``.

Mapped controls
---------------

================ ============= =================================================== ==============================
Framework Control Title Evidence key
================ ============= =================================================== ==============================
SOC2 CC6.1 Logical access restricted to authorized hosts ``egress_allowlist_enforced``
SOC2 CC6.3 Least-privilege, time-boxed credentials ``jit_credentials_used``
SOC2 CC6.8 Secrets not hardcoded and scanned ``secrets_scanned``
SOC2 CC7.3 Security events logged for review ``audit_logging_enabled``
SOC2 CC8.1 Changes require segregated (maker-checker) approval ``change_approval_required``
ISO 27001 A.5.23 Information security for cloud/network egress ``egress_allowlist_enforced``
ISO 27001 A.8.16 Monitoring activities / audit trail ``audit_logging_enabled``
ISO 27001 A.8.30 Software bill of materials maintained ``sbom_generated``
================ ============= =================================================== ==============================

Headless API
------------

.. code-block:: python

from je_auto_control import build_compliance_report, write_compliance_report

report = build_compliance_report({
"egress_allowlist_enforced": True,
"jit_credentials_used": True,
"secrets_scanned": True,
"audit_logging_enabled": True,
"change_approval_required": True,
"sbom_generated": True,
}, frameworks=["SOC2"]) # frameworks is optional

print(report["summary"]) # {satisfied, gap, not_assessed, total}
write_compliance_report(report, "build/compliance.html", fmt="html")

A control is ``satisfied`` when its evidence key is truthy, ``gap`` when
explicitly falsy, and ``not_assessed`` when the key is absent — so a partial
evidence dict produces an honest gap analysis. ``render_compliance_html`` returns
a standalone HTML table; ``write_compliance_report`` writes ``json`` or ``html``.

Executor command
----------------

``AC_compliance_report`` takes ``evidence`` (a JSON object, or JSON string from
the visual builder), an optional ``frameworks`` list/comma-string, and optional
``path`` + ``fmt`` to write a file; it returns ``{summary, controls, path?}``.
The same operation is exposed as the MCP tool ``ac_compliance_report`` and as a
Script Builder command under **Report**.
1 change: 1 addition & 0 deletions docs/source/Eng/eng_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Comprehensive guides for all AutoControl features.
doc/new_features/v34_features_doc
doc/new_features/v35_features_doc
doc/new_features/v36_features_doc
doc/new_features/v37_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
58 changes: 58 additions & 0 deletions docs/source/Zh/doc/new_features/v37_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
合規控制報告(SOC2 / ISO 27001)
================================

AutoControl 已內建稽核員關注的*控制項* —— 網路出口允許清單、即時憑證租約、
maker-checker 審批、密鑰掃描器、稽核記錄、CycloneDX SBOM。
:func:`build_compliance_report` 把「這些控制項是否到位?」轉化為稽核員可讀的**控制證
據報告**:你提供一個扁平的 ``evidence`` 觀察事實對應表,每個編目控制項即被標記為
``satisfied`` / ``gap`` / ``not_assessed``。

它是報告*輔助工具*,非認證 —— 它記錄你所聲明的證據,並不自行驗證控制項。純標準函式
庫,不匯入 ``PySide6``。

對應的控制項
------------

================ ============= =================================================== ==============================
框架 控制項 標題 證據鍵
================ ============= =================================================== ==============================
SOC2 CC6.1 邏輯存取限制於授權主機 ``egress_allowlist_enforced``
SOC2 CC6.3 最小權限、限時憑證 ``jit_credentials_used``
SOC2 CC6.8 密鑰不硬編碼且經掃描 ``secrets_scanned``
SOC2 CC7.3 安全事件留存供審查 ``audit_logging_enabled``
SOC2 CC8.1 變更需職責分離(maker-checker)審批 ``change_approval_required``
ISO 27001 A.5.23 雲端/網路出口的資訊安全 ``egress_allowlist_enforced``
ISO 27001 A.8.16 監控活動 / 稽核軌跡 ``audit_logging_enabled``
ISO 27001 A.8.30 維護軟體物料清單 ``sbom_generated``
================ ============= =================================================== ==============================

無頭 API
--------

.. code-block:: python

from je_auto_control import build_compliance_report, write_compliance_report

report = build_compliance_report({
"egress_allowlist_enforced": True,
"jit_credentials_used": True,
"secrets_scanned": True,
"audit_logging_enabled": True,
"change_approval_required": True,
"sbom_generated": True,
}, frameworks=["SOC2"]) # frameworks 為選用

print(report["summary"]) # {satisfied, gap, not_assessed, total}
write_compliance_report(report, "build/compliance.html", fmt="html")

當控制項的證據鍵為真時為 ``satisfied``,明確為假時為 ``gap``,鍵不存在時為
``not_assessed`` —— 因此部分證據字典會產生誠實的缺口分析。``render_compliance_html``
回傳獨立的 HTML 表格;``write_compliance_report`` 寫出 ``json`` 或 ``html``。

執行器指令
----------

``AC_compliance_report`` 接受 ``evidence``(JSON 物件,或視覺化建構器傳入的 JSON 字
串)、選用的 ``frameworks`` 清單/逗號字串,以及選用的 ``path`` + ``fmt`` 以寫出檔案;
回傳 ``{summary, controls, path?}``。相同操作亦提供為 MCP 工具
``ac_compliance_report``,以及 Script Builder 中 **Report** 分類下的指令。
1 change: 1 addition & 0 deletions docs/source/Zh/zh_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ AutoControl 所有功能的完整使用指南。
doc/new_features/v34_features_doc
doc/new_features/v35_features_doc
doc/new_features/v36_features_doc
doc/new_features/v37_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
6 changes: 6 additions & 0 deletions je_auto_control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@
)
# Agent trajectory evaluation: score a recorded run against a rubric
from je_auto_control.utils.trajectory_eval import evaluate_trajectory
# Compliance: map governance evidence to SOC2 / ISO 27001 controls
from je_auto_control.utils.compliance import (
build_compliance_report, render_compliance_html, write_compliance_report,
)
# Background popup/interrupt watchdog (unattended automation)
from je_auto_control.utils.watchdog import (
PopupWatchdog, WatchdogRule, default_popup_watchdog,
Expand Down Expand Up @@ -659,6 +663,8 @@ def start_autocontrol_gui(*args, **kwargs):
"ApprovalResult", "approve_artifact", "pending_artifacts",
"verify_artifact",
"evaluate_trajectory",
"build_compliance_report", "render_compliance_html",
"write_compliance_report",
# MCP server
"AuditLogger", "HttpMCPServer", "MCPContent", "MCPPrompt",
"MCPPromptArgument", "MCPResource", "MCPServer", "MCPTool",
Expand Down
13 changes: 13 additions & 0 deletions je_auto_control/gui/script_builder/command_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,19 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
),
description="Score an agent trajectory against a rubric (JSON).",
))
specs.append(CommandSpec(
"AC_compliance_report", "Report", "Compliance Control Report",
fields=(
FieldSpec("evidence", FieldType.STRING,
placeholder='{"egress_allowlist_enforced": true}'),
FieldSpec("frameworks", FieldType.STRING, optional=True,
placeholder="SOC2, ISO27001"),
FieldSpec("path", FieldType.STRING, optional=True),
FieldSpec("fmt", FieldType.ENUM, optional=True, default="json",
choices=("json", "html")),
),
description="Map governance evidence to SOC2/ISO 27001 controls.",
))
specs.append(CommandSpec(
"AC_generate_sop", "Report", "Generate SOP Document",
fields=(
Expand Down
10 changes: 10 additions & 0 deletions je_auto_control/utils/compliance/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Compliance: map automation governance evidence to SOC2 / ISO 27001 controls."""
from je_auto_control.utils.compliance.compliance_report import (
CONTROL_CATALOGUE, build_compliance_report, render_compliance_html,
write_compliance_report,
)

__all__ = [
"CONTROL_CATALOGUE", "build_compliance_report", "render_compliance_html",
"write_compliance_report",
]
126 changes: 126 additions & 0 deletions je_auto_control/utils/compliance/compliance_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
"""Map AutoControl governance evidence to SOC2 / ISO 27001 controls.

The framework already ships the *controls* an auditor cares about — an egress
allowlist, just-in-time credential leases, maker-checker approval, a secrets
scanner, audit logging, a CycloneDX SBOM. This module turns "are those controls
in place?" into an auditor-readable **control evidence report**: the caller
supplies a flat ``evidence`` mapping of observed facts, and each catalogued
control is marked ``satisfied`` / ``gap`` / ``not_assessed`` accordingly.

It is a reporting aid, not a certification: it does not itself verify the
controls, it records the evidence you assert. Pure standard library; imports no
``PySide6``.
"""
import html
import json
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Mapping, Optional, Sequence

STATUS_SATISFIED = "satisfied"
STATUS_GAP = "gap"
STATUS_NOT_ASSESSED = "not_assessed"


@dataclass(frozen=True)
class Control:
"""A single mapped control and the evidence key that satisfies it."""

control_id: str
framework: str
title: str
evidence_key: str


CONTROL_CATALOGUE: Sequence[Control] = (
Control("CC6.1", "SOC2", "Logical access restricted to authorized hosts",
"egress_allowlist_enforced"),
Control("CC6.3", "SOC2", "Least-privilege, time-boxed credentials",
"jit_credentials_used"),
Control("CC6.8", "SOC2", "Secrets are not hardcoded and are scanned",
"secrets_scanned"),
Control("CC7.3", "SOC2", "Security-relevant events are logged for review",
"audit_logging_enabled"),
Control("CC8.1", "SOC2", "Changes require segregated (maker-checker) approval",
"change_approval_required"),
Control("A.5.23", "ISO27001", "Information security for cloud/network egress",
"egress_allowlist_enforced"),
Control("A.8.16", "ISO27001", "Monitoring activities / audit trail",
"audit_logging_enabled"),
Control("A.8.30", "ISO27001", "Software bill of materials maintained",
"sbom_generated"),
)


def _status_for(evidence: Mapping[str, Any], key: str) -> str:
if key not in evidence:
return STATUS_NOT_ASSESSED
return STATUS_SATISFIED if evidence[key] else STATUS_GAP


def build_compliance_report(evidence: Mapping[str, Any],
frameworks: Optional[Sequence[str]] = None
) -> Dict[str, Any]:
"""Map ``evidence`` to the control catalogue, optionally filtered.

``frameworks`` restricts the report (e.g. ``["SOC2"]``); ``None`` includes
all. Each control is ``satisfied`` (truthy evidence), ``gap`` (explicitly
falsy), or ``not_assessed`` (key absent).
"""
wanted = {f.upper() for f in frameworks} if frameworks else None
controls: List[Dict[str, Any]] = []
summary = {STATUS_SATISFIED: 0, STATUS_GAP: 0, STATUS_NOT_ASSESSED: 0}
for control in CONTROL_CATALOGUE:
if wanted is not None and control.framework.upper() not in wanted:
continue
status = _status_for(evidence, control.evidence_key)
summary[status] += 1
controls.append({
"control_id": control.control_id, "framework": control.framework,
"title": control.title, "evidence_key": control.evidence_key,
"status": status,
})
summary["total"] = len(controls)
return {
"generated_utc": datetime.now(timezone.utc).isoformat(),
"summary": summary, "controls": controls,
}


def render_compliance_html(report: Mapping[str, Any]) -> str:
"""Render a compliance ``report`` as a standalone HTML table."""
summary = report.get("summary", {})
rows = "".join(
f"<tr class='{html.escape(str(c['status']))}'>"
f"<td>{html.escape(str(c['framework']))}</td>"
f"<td>{html.escape(str(c['control_id']))}</td>"
f"<td>{html.escape(str(c['title']))}</td>"
f"<td>{html.escape(str(c['status']))}</td></tr>"
for c in report.get("controls", []))
return (
"<!DOCTYPE html><html><head><meta charset='utf-8'>"
"<title>Compliance Control Evidence</title></head><body>"
"<h1>Compliance Control Evidence</h1>"
f"<p>Generated {html.escape(str(report.get('generated_utc', '')))} — "
f"satisfied {summary.get(STATUS_SATISFIED, 0)}, "
f"gap {summary.get(STATUS_GAP, 0)}, "
f"not assessed {summary.get(STATUS_NOT_ASSESSED, 0)}.</p>"
"<table border='1'><tr><th>Framework</th><th>Control</th>"
"<th>Title</th><th>Status</th></tr>"
f"{rows}</table></body></html>")


def write_compliance_report(report: Mapping[str, Any], path: str,
fmt: str = "json") -> str:
"""Write ``report`` to ``path`` as ``json`` or ``html``; return the path."""
output = Path(path)
output.parent.mkdir(parents=True, exist_ok=True)
if fmt == "html":
output.write_text(render_compliance_html(report), encoding="utf-8")
elif fmt == "json":
output.write_text(json.dumps(report, ensure_ascii=False, indent=2),
encoding="utf-8")
else:
raise ValueError(f"unknown compliance report format: {fmt!r}")
return str(output)
Loading
Loading