Merge remote-tracking branch 'gitea-ssh/main' into codex/ai-agent-controlled-loop-20260629
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 20s
CD Pipeline / build-and-deploy (push) Successful in 6m28s
AI 技術雷達監控 / ai-technology-watch (push) Successful in 42s
CD Pipeline / post-deploy-checks (push) Has been cancelled

# Conflicts:
#	apps/api/src/api/v1/agents.py
This commit is contained in:
Your Name
2026-06-29 19:59:21 +08:00
10 changed files with 805 additions and 9 deletions

View File

@@ -260,6 +260,8 @@ jobs:
;;
apps/api/src/services/gitea_authenticated_inventory_payload_validation.py)
;;
apps/api/src/services/gitea_owner_coverage_attestation_validation.py)
;;
apps/api/src/services/gitea_private_inventory_p0_scorecard.py)
;;
apps/api/src/services/reboot_auto_recovery_slo_scorecard.py)
@@ -495,6 +497,7 @@ jobs:
src/services/heartbeat_report_service.py \
src/services/credential_escrow_evidence_intake_readiness.py \
src/services/gitea_authenticated_inventory_payload_validation.py \
src/services/gitea_owner_coverage_attestation_validation.py \
src/services/gitea_private_inventory_p0_scorecard.py \
src/services/reboot_auto_recovery_slo_scorecard.py \
src/services/iwooos_security_operating_system.py \

View File

@@ -341,6 +341,9 @@ from src.services.docker_build_surface_inventory import (
from src.services.gitea_authenticated_inventory_payload_validation import (
validate_gitea_authenticated_inventory_payload,
)
from src.services.gitea_owner_coverage_attestation_validation import (
validate_gitea_owner_coverage_attestation,
)
from src.services.gitea_private_inventory_p0_scorecard import (
load_latest_gitea_private_inventory_p0_scorecard,
)
@@ -1147,6 +1150,42 @@ async def validate_gitea_authenticated_inventory_payload_packet(
) from exc
@router.post(
"/gitea-private-inventory-p0-scorecard/validate-owner-coverage-attestation",
response_model=dict[str, Any],
summary="驗證 P0-003 Gitea owner coverage attestation 脫敏回覆",
description=(
"針對單次 owner-provided redacted Gitea coverage attestation response "
"packet 進行 no-persist validation此端點只回傳 owner attestation "
"reviewer readiness / needs supplement / quarantined / rejected execution "
"分流,不保存 payload、不呼叫 Gitea/GitHub、不收 token value、"
"不建立 repo、不改 visibility、不同步 refs、不觸發 workflow、"
"不讀 secret、不讀 raw session/SQLite。"
),
)
async def validate_gitea_owner_coverage_attestation_packet(
owner_response: dict[str, Any],
) -> dict[str, Any]:
"""Return no-persist validation for one P0-003 owner attestation packet."""
try:
payload = await asyncio.to_thread(
validate_gitea_owner_coverage_attestation,
owner_response,
)
return redact_public_lan_topology(payload)
except FileNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=str(exc),
) from exc
except (json.JSONDecodeError, ValueError) as exc:
logger.error("gitea_owner_coverage_attestation_invalid", error=str(exc))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="P0-003 Gitea owner coverage attestation 驗證器無效",
) from exc
@router.get(
"/github-target-private-backup-evidence-gate",
response_model=dict[str, Any],

View File

@@ -0,0 +1,388 @@
"""P0-003 Gitea owner coverage attestation no-persist validation.
This service validates one owner-provided redacted coverage attestation packet.
It loads the committed response templates, accepts only redacted metadata, and
never writes repos, refs, secrets, workflow state, or runtime state.
"""
from __future__ import annotations
import json
import re
from pathlib import Path
from typing import Any
from urllib.parse import parse_qsl, urlsplit
from src.services.gitea_private_inventory_p0_scorecard import (
load_latest_gitea_private_inventory_p0_scorecard,
)
from src.services.snapshot_paths import default_security_dir
_SCHEMA_VERSION = "gitea_owner_coverage_attestation_validation_v1"
_OWNER_RESPONSE_SCHEMA_VERSION = "gitea_inventory_owner_attestation_response_v1"
_OWNER_RESPONSE_PACKET = "gitea-inventory-owner-attestation-response.snapshot.json"
_LANE_ID = "s4_9_gitea_inventory_owner_attestation_response"
_BLOCKERS_CLEARED_BY_ACCEPTED_ATTESTATION = {
"gitea_owner_coverage_attestation_not_received",
}
_BLOCKERS_CLEARED_AFTER_INVENTORY_RECEIPT_WRITEBACK = {
"gitea_repo_inventory_status_not_ok",
"gitea_visibility_scope_public_only_or_unknown",
"gitea_authenticated_inventory_payload_not_accepted",
"gitea_owner_coverage_attestation_not_received",
}
_FORBIDDEN_TRUE_FIELDS = {
"action_buttons_allowed",
"change_repo_visibility",
"create_gitea_repo",
"create_github_repo",
"delete_or_archive_gitea_repo",
"execution_authorized",
"force_push",
"gitea_repo_write_authorized",
"github_primary_switch_authorized",
"refs_sync_allowed",
"refs_sync_authorized",
"repo_write_allowed",
"runtime_action_requested",
"runtime_execution_authorized",
"secret_value_collection_allowed",
"sync_git_refs",
"token_value_collection_allowed",
"workflow_dispatch_requested",
"write_to_gitea",
}
_SECRET_PATTERNS = {
"authorization_header": re.compile(r"Authorization\s*:", re.IGNORECASE),
"bearer_token": re.compile(r"Bearer\s+[A-Za-z0-9._~+/=-]{12,}", re.IGNORECASE),
"cookie_header": re.compile(r"\bCookie\s*:", re.IGNORECASE),
"password_assignment": re.compile(r"\bpassword\s*[:=]\s*[^,\s]+", re.IGNORECASE),
"private_key": re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----"),
"token_assignment": re.compile(r"\btoken\s*[:=]\s*[^,\s]+", re.IGNORECASE),
}
_SECRET_QUERY_KEYS = {"access_token", "auth", "key", "password", "secret", "token"}
def validate_gitea_owner_coverage_attestation(
owner_response: dict[str, Any],
scorecard: dict[str, Any] | None = None,
security_dir: Path | None = None,
) -> dict[str, Any]:
"""Validate one redacted P0-003 owner attestation packet without persisting it."""
current = scorecard or load_latest_gitea_private_inventory_p0_scorecard()
templates = _load_response_templates(security_dir)
template_by_item = {
str(template.get("attestation_item_id")): template for template in templates
}
required_item_ids = set(template_by_item)
blockers: list[str] = []
sensitive_hits = _find_sensitive_strings(owner_response)
forbidden_true_fields = _find_forbidden_true_fields(owner_response)
if owner_response.get("schema_version") != _OWNER_RESPONSE_SCHEMA_VERSION:
blockers.append(f"schema_version_not_{_OWNER_RESPONSE_SCHEMA_VERSION}")
if str(owner_response.get("lane_id") or "") != _LANE_ID:
blockers.append("lane_id_not_s4_9_owner_attestation_response")
responses = _response_items(owner_response)
response_by_item: dict[str, dict[str, Any]] = {}
duplicate_item_ids: list[str] = []
for index, response in enumerate(responses):
item_id = str(response.get("attestation_item_id") or "")
if not item_id:
blockers.append(f"responses[{index}].attestation_item_id_missing")
continue
if item_id in response_by_item:
duplicate_item_ids.append(item_id)
response_by_item[item_id] = response
unknown_item_ids = sorted(set(response_by_item) - required_item_ids)
missing_item_ids = sorted(required_item_ids - set(response_by_item))
blockers.extend(f"unknown_attestation_item_id:{item_id}" for item_id in unknown_item_ids)
blockers.extend(f"missing_attestation_item_id:{item_id}" for item_id in missing_item_ids)
blockers.extend(f"duplicate_attestation_item_id:{item_id}" for item_id in duplicate_item_ids)
for item_id in sorted(required_item_ids & set(response_by_item)):
blockers.extend(
_validate_response_item(
item_id=item_id,
response=response_by_item[item_id],
template=template_by_item[item_id],
)
)
if forbidden_true_fields:
status = "rejected_execution_request"
elif sensitive_hits:
status = "quarantined_sensitive_payload"
elif blockers:
status = "needs_supplement"
else:
status = "accepted_for_owner_coverage_attestation_review_only"
accepted = status == "accepted_for_owner_coverage_attestation_review_only"
current_rollups = _as_dict(current.get("rollups"))
current_blockers = _strings(current.get("active_blockers"))
projected_blockers = (
[
blocker
for blocker in current_blockers
if blocker not in _BLOCKERS_CLEARED_BY_ACCEPTED_ATTESTATION
]
if accepted
else current_blockers
)
projected_after_inventory_receipt = (
[
blocker
for blocker in current_blockers
if blocker not in _BLOCKERS_CLEARED_AFTER_INVENTORY_RECEIPT_WRITEBACK
]
if accepted
else current_blockers
)
current_accepted_attestation_count = _as_int(
current_rollups.get("owner_coverage_attestation_accepted_count")
)
projected_accepted_attestation_count = (
max(current_accepted_attestation_count, 1)
if accepted
else current_accepted_attestation_count
)
return {
"schema_version": _SCHEMA_VERSION,
"status": status,
"priority": "P0-003",
"scope": "gitea_owner_coverage_attestation_validation",
"source_contract": _OWNER_RESPONSE_SCHEMA_VERSION,
"source_scorecard_status": current.get("status"),
"result": {
"accepted_attestation_packet_count": 1 if accepted else 0,
"required_response_item_count": len(required_item_ids),
"provided_response_item_count": len(response_by_item),
"accepted_response_count": len(required_item_ids) if accepted else 0,
"blocker_count": len(blockers),
"sensitive_payload_hit_count": len(sensitive_hits),
"forbidden_true_field_count": len(forbidden_true_fields),
"current_active_blocker_count": len(current_blockers),
"projected_active_blocker_count": len(projected_blockers),
"projected_active_blocker_count_after_redacted_inventory_receipt_writeback": (
len(projected_after_inventory_receipt)
),
"current_owner_coverage_attestation_accepted_count": (
current_accepted_attestation_count
),
"projected_owner_coverage_attestation_accepted_count": (
projected_accepted_attestation_count
),
"token_value_collection_allowed": False,
"secret_value_collection_allowed": False,
"repo_write_allowed": False,
"refs_sync_allowed": False,
"github_primary_switch_authorized": False,
"runtime_gate_count": 0,
},
"blockers": blockers,
"missing_attestation_item_ids": missing_item_ids,
"unknown_attestation_item_ids": unknown_item_ids,
"duplicate_attestation_item_ids": sorted(duplicate_item_ids),
"sensitive_payload_hits": sensitive_hits,
"forbidden_true_fields": forbidden_true_fields,
"operation_boundaries": {
"payload_persisted": False,
"gitea_api_called": False,
"gitea_write_performed": False,
"repo_write_performed": False,
"refs_sync_performed": False,
"github_api_used": False,
"github_cli_used": False,
"secret_plaintext_read": False,
"token_value_collection_allowed": False,
"secret_value_collection_allowed": False,
"runtime_action_performed": False,
"raw_session_or_sqlite_read_performed": False,
},
"reviewer_readiness": {
"schema_version": "gitea_owner_coverage_attestation_reviewer_readiness_v1",
"status": (
"ready_for_private_inventory_closeout_after_inventory_receipt_writeback"
if accepted
else "not_ready_for_private_inventory_closeout"
),
"redacted_owner_attestation_receipt_writeback_ready_count": (
1 if accepted else 0
),
"accepted_response_count": len(required_item_ids) if accepted else 0,
"projected_active_blocker_count": len(projected_blockers),
"projected_remaining_blockers": projected_blockers,
"projected_active_blocker_count_after_redacted_inventory_receipt_writeback": (
len(projected_after_inventory_receipt)
),
"projected_remaining_blockers_after_redacted_inventory_receipt_writeback": (
projected_after_inventory_receipt
),
"repo_write_authorized_count": 0,
"refs_sync_authorized_count": 0,
"github_primary_switch_authorized_count": 0,
"runtime_gate_count": 0,
"token_value_collection_allowed": False,
"secret_value_collection_allowed": False,
"payload_persisted": False,
"safe_next_step": (
"write_redacted_inventory_receipt_and_owner_attestation_receipt_then_close_p0_003"
if accepted
else "supplement_owner_coverage_attestation_redacted_metadata"
),
"blocked_operations": [
"store_token_value",
"store_raw_secret",
"gitea_api_write",
"repo_write",
"refs_sync",
"github_api",
"github_primary_switch",
"workflow_dispatch",
"runtime_action",
"raw_session_or_sqlite_read",
],
},
"safe_next_step": (
"review_redacted_owner_attestation_then_pair_with_inventory_receipt_writeback"
if accepted
else "supplement_owner_coverage_attestation_redacted_metadata"
),
}
def _load_response_templates(security_dir: Path | None) -> list[dict[str, Any]]:
directory = security_dir or default_security_dir(Path(__file__))
path = directory / _OWNER_RESPONSE_PACKET
with path.open(encoding="utf-8") as handle:
packet = json.load(handle)
if packet.get("schema_version") != _OWNER_RESPONSE_SCHEMA_VERSION:
raise ValueError(f"{path}: owner response packet schema mismatch")
templates = packet.get("response_templates")
if not isinstance(templates, list) or len(templates) != 5:
raise ValueError(f"{path}: expected five response templates")
return [template for template in templates if isinstance(template, dict)]
def _response_items(owner_response: dict[str, Any]) -> list[dict[str, Any]]:
for key in ("responses", "owner_responses", "attestation_responses"):
value = owner_response.get(key)
if isinstance(value, list):
return [item for item in value if isinstance(item, dict)]
return []
def _validate_response_item(
*,
item_id: str,
response: dict[str, Any],
template: dict[str, Any],
) -> list[str]:
blockers: list[str] = []
decision = str(response.get("decision") or "")
acceptable_decisions = set(_strings(template.get("acceptable_decisions")))
if decision not in acceptable_decisions:
blockers.append(f"{item_id}.decision_not_allowed")
for field in _strings(template.get("required_owner_fields")):
value = response.get(field)
if field == "evidence_refs":
if not _has_redacted_evidence_refs(value):
blockers.append(f"{item_id}.evidence_refs_missing_or_not_redacted_list")
continue
if _is_placeholder(value):
blockers.append(f"{item_id}.{field}_missing")
if _is_placeholder(response.get("decision_reason")):
blockers.append(f"{item_id}.decision_reason_missing")
return blockers
def _has_redacted_evidence_refs(value: Any) -> bool:
if not isinstance(value, list) or not value:
return False
for item in value:
if not isinstance(item, str) or _is_placeholder(item):
return False
if _url_has_secret(item):
return False
return True
def _find_sensitive_strings(value: Any) -> list[str]:
hits: list[str] = []
def walk(node: Any, path: str) -> None:
if isinstance(node, dict):
for key, item in node.items():
walk(item, f"{path}.{key}" if path else str(key))
elif isinstance(node, list):
for index, item in enumerate(node):
walk(item, f"{path}[{index}]")
elif isinstance(node, str):
for name, pattern in _SECRET_PATTERNS.items():
if pattern.search(node):
hits.append(f"{path}:{name}")
if _url_has_secret(node):
hits.append(f"{path}:url_contains_secret_material")
walk(value, "")
return sorted(set(hits))
def _find_forbidden_true_fields(value: Any) -> list[str]:
hits: list[str] = []
def walk(node: Any, path: str) -> None:
if isinstance(node, dict):
for key, item in node.items():
next_path = f"{path}.{key}" if path else str(key)
if key in _FORBIDDEN_TRUE_FIELDS and item is True:
hits.append(next_path)
walk(item, next_path)
elif isinstance(node, list):
for index, item in enumerate(node):
walk(item, f"{path}[{index}]")
walk(value, "")
return sorted(hits)
def _url_has_secret(value: str) -> bool:
if "://" not in value:
return False
parsed = urlsplit(value)
if parsed.username or parsed.password:
return True
return any(key.lower() in _SECRET_QUERY_KEYS for key, _ in parse_qsl(parsed.query))
def _is_placeholder(value: Any) -> bool:
if value is None:
return True
if isinstance(value, str):
return value.strip().lower() in {"", "pending", "todo", "tbd", "n/a", "na"}
if isinstance(value, list):
return not value
return False
def _strings(value: Any) -> list[str]:
if not isinstance(value, list):
return []
return [str(item) for item in value if item is not None]
def _as_dict(value: Any) -> dict[str, Any]:
return value if isinstance(value, dict) else {}
def _as_int(value: Any) -> int:
try:
return int(value)
except (TypeError, ValueError):
return 0

View File

@@ -10,6 +10,9 @@ from src.api.v1.agents import router
from src.services.gitea_authenticated_inventory_payload_validation import (
validate_gitea_authenticated_inventory_payload,
)
from src.services.gitea_owner_coverage_attestation_validation import (
validate_gitea_owner_coverage_attestation,
)
from src.services.gitea_private_inventory_p0_scorecard import (
load_latest_gitea_private_inventory_p0_scorecard,
)
@@ -201,6 +204,105 @@ def test_gitea_authenticated_inventory_payload_endpoint_validates_without_persis
assert data["operation_boundaries"]["raw_session_or_sqlite_read_performed"] is False
def test_gitea_owner_coverage_attestation_validator_accepts_redacted_response():
payload = validate_gitea_owner_coverage_attestation(
_valid_owner_coverage_attestation_payload(),
scorecard=_scorecard_readback(),
)
assert payload["schema_version"] == "gitea_owner_coverage_attestation_validation_v1"
assert payload["status"] == "accepted_for_owner_coverage_attestation_review_only"
assert payload["result"]["accepted_attestation_packet_count"] == 1
assert payload["result"]["required_response_item_count"] == 5
assert payload["result"]["provided_response_item_count"] == 5
assert payload["result"]["accepted_response_count"] == 5
assert payload["result"]["current_active_blocker_count"] == 4
assert payload["result"]["projected_active_blocker_count"] == 3
assert (
payload["result"][
"projected_active_blocker_count_after_redacted_inventory_receipt_writeback"
]
== 0
)
assert payload["result"]["projected_owner_coverage_attestation_accepted_count"] == 1
assert payload["result"]["runtime_gate_count"] == 0
assert payload["operation_boundaries"]["payload_persisted"] is False
assert payload["operation_boundaries"]["gitea_api_called"] is False
assert payload["operation_boundaries"]["repo_write_performed"] is False
assert payload["operation_boundaries"]["refs_sync_performed"] is False
assert payload["operation_boundaries"]["github_api_used"] is False
assert payload["operation_boundaries"]["secret_plaintext_read"] is False
assert (
payload["reviewer_readiness"]["status"]
== "ready_for_private_inventory_closeout_after_inventory_receipt_writeback"
)
assert (
payload["reviewer_readiness"][
"redacted_owner_attestation_receipt_writeback_ready_count"
]
== 1
)
assert payload["reviewer_readiness"]["repo_write_authorized_count"] == 0
def test_gitea_owner_coverage_attestation_endpoint_validates_without_persisting():
app = FastAPI()
app.include_router(router, prefix="/api/v1")
client = TestClient(app)
response = client.post(
"/api/v1/agents/gitea-private-inventory-p0-scorecard/validate-owner-coverage-attestation",
json=_valid_owner_coverage_attestation_payload(),
)
assert response.status_code == 200
data = response.json()
assert data["status"] == "accepted_for_owner_coverage_attestation_review_only"
assert data["result"]["accepted_attestation_packet_count"] == 1
assert data["result"]["projected_active_blocker_count"] == 3
assert (
data["reviewer_readiness"][
"redacted_owner_attestation_receipt_writeback_ready_count"
]
== 1
)
assert data["operation_boundaries"]["payload_persisted"] is False
assert data["operation_boundaries"]["gitea_write_performed"] is False
assert data["operation_boundaries"]["raw_session_or_sqlite_read_performed"] is False
def test_gitea_owner_coverage_attestation_validator_quarantines_secret_material():
payload = _valid_owner_coverage_attestation_payload()
payload["responses"][0]["evidence_refs"] = [
"https://gitea.example/wooo/awoooi?token=secret-value"
]
validation = validate_gitea_owner_coverage_attestation(
payload,
scorecard=_scorecard_readback(),
)
assert validation["status"] == "quarantined_sensitive_payload"
assert validation["result"]["accepted_attestation_packet_count"] == 0
assert validation["result"]["sensitive_payload_hit_count"] >= 1
assert validation["operation_boundaries"]["payload_persisted"] is False
def test_gitea_owner_coverage_attestation_validator_rejects_execution_request():
payload = _valid_owner_coverage_attestation_payload()
payload["write_to_gitea"] = True
validation = validate_gitea_owner_coverage_attestation(
payload,
scorecard=_scorecard_readback(),
)
assert validation["status"] == "rejected_execution_request"
assert validation["result"]["accepted_attestation_packet_count"] == 0
assert validation["result"]["forbidden_true_field_count"] == 1
assert validation["operation_boundaries"]["repo_write_performed"] is False
def test_gitea_authenticated_inventory_payload_validator_quarantines_secret_material():
payload = _valid_authenticated_inventory_payload()
payload["repos"][0]["clone_url_redacted"] = "https://user:password@example.test/repo.git"
@@ -417,6 +519,81 @@ def _valid_authenticated_inventory_payload() -> dict:
}
def _valid_owner_coverage_attestation_payload() -> dict:
return {
"schema_version": "gitea_inventory_owner_attestation_response_v1",
"lane_id": "s4_9_gitea_inventory_owner_attestation_response",
"runtime_execution_authorized": False,
"token_value_collection_allowed": False,
"secret_value_collection_allowed": False,
"gitea_repo_write_authorized": False,
"refs_sync_authorized": False,
"github_primary_switch_authorized": False,
"action_buttons_allowed": False,
"responses": [
{
"attestation_item_id": "public_only_vs_local_gitea_gap",
"owner_role_or_team": "platform-security-owner",
"decision": "in_scope",
"decision_reason": "admin export must cover the public-only gap",
"affected_repos": ["wooo/awoooi", "wooo/ewoooc"],
"evidence_refs": [
"docs/security/gitea-repo-inventory.snapshot.json",
"docs/security/gitea-org-repo-inventory-blocked.snapshot.json",
],
"followup_owner": "platform-security-owner",
},
{
"attestation_item_id": "org_user_endpoint_identity",
"owner_role_or_team": "platform-security-owner",
"decision": "in_scope",
"decision_reason": "wooo namespace is the canonical Gitea scope",
"canonical_namespace": "wooo",
"evidence_refs": [
"docs/security/gitea-org-repo-inventory-blocked.snapshot.json"
],
"followup_owner": "platform-security-owner",
},
{
"attestation_item_id": "internal_110_adjacent_scope",
"owner_role_or_team": "platform-security-owner",
"decision": "in_scope",
"decision_reason": "internal adjacent source is covered by redacted metadata",
"affected_sources": ["gitea-ssh-main-redacted", "public-route-redacted"],
"evidence_refs": [
"docs/security/git-remote-refs-bitan-exposure.snapshot.json"
],
"followup_owner": "platform-security-owner",
},
{
"attestation_item_id": "repo_owner_canonical_scope",
"owner_role_or_team": "platform-security-owner",
"decision": "in_scope",
"decision_reason": "repo owner and canonical source remain Gitea-only",
"repo_owner": "wooo",
"canonical_source": "gitea",
"github_target_candidate": "stopped_retired_do_not_use",
"visibility_review_owner": "platform-security-owner",
"evidence_refs": [
"docs/operations/awoooi-gitea-private-inventory-p0-scorecard.snapshot.json"
],
},
{
"attestation_item_id": "legacy_or_inaccessible_repo_disposition",
"owner_role_or_team": "platform-security-owner",
"decision": "legacy_archived",
"decision_reason": "legacy or inaccessible sources stay outside active P0 apply",
"affected_repos_or_sources": ["legacy-github-mirror-retired"],
"disposition": "stopped_retired_do_not_use",
"evidence_refs": [
"docs/security/gitea-inventory-owner-attestation-response.snapshot.json"
],
"followup_owner": "platform-security-owner",
},
],
}
def _repo(full_name: str) -> dict:
_, name = full_name.split("/", 1)
return {

View File

@@ -12815,11 +12815,36 @@
"iwooos": {
"eyebrow": "資訊安全網",
"title": "IwoooS",
"subtitle": "AWOOOI 的 AI 自動化資安閉環:把 Kali、原始碼、主機、告警、候選、執行閘門、驗證器與 AwoooP 證據串成可視化資安態勢。",
"subtitle": "AI SOC 資安控制台:集中讀取主機、原始碼、告警、候選處置與驗證器狀態。",
"boundary": {
"label": "目前邊界",
"state": "只讀鏡像 / 先觀測",
"detail": "只顯示態勢與缺口;掃描、修復、更新、阻擋仍未開閘。"
"state": "AI 受控推進 / critical break-glass",
"detail": "低 / 中 / 高風險走 selector、dry-run、rollback 與 verifiersecret、破壞性 DB、重啟、付費 provider 與 refs 破壞維持 break-glass。"
},
"commandRail": {
"eyebrow": "控制面",
"title": "AI SOC 工作台",
"navLabel": "IwoooS 第一屏控制入口",
"metrics": {
"controlledApply": {
"label": "受控執行"
},
"automationClosure": {
"label": "自動化"
},
"securityPosture": {
"label": "資安態勢"
},
"breakGlass": {
"label": "硬邊界"
}
},
"links": {
"evidence": "證據",
"decisions": "決策",
"scope": "範圍",
"owners": "Owner"
}
},
"progressIntegrityRibbon": {
"eyebrow": "進度誠實儀表",

View File

@@ -12815,11 +12815,36 @@
"iwooos": {
"eyebrow": "資訊安全網",
"title": "IwoooS",
"subtitle": "AWOOOI 的 AI 自動化資安閉環:把 Kali、原始碼、主機、告警、候選、執行閘門、驗證器與 AwoooP 證據串成可視化資安態勢。",
"subtitle": "AI SOC 資安控制台:集中讀取主機、原始碼、告警、候選處置與驗證器狀態。",
"boundary": {
"label": "目前邊界",
"state": "只讀鏡像 / 先觀測",
"detail": "只顯示態勢與缺口;掃描、修復、更新、阻擋仍未開閘。"
"state": "AI 受控推進 / critical break-glass",
"detail": "低 / 中 / 高風險走 selector、dry-run、rollback 與 verifiersecret、破壞性 DB、重啟、付費 provider 與 refs 破壞維持 break-glass。"
},
"commandRail": {
"eyebrow": "控制面",
"title": "AI SOC 工作台",
"navLabel": "IwoooS 第一屏控制入口",
"metrics": {
"controlledApply": {
"label": "受控執行"
},
"automationClosure": {
"label": "自動化"
},
"securityPosture": {
"label": "資安態勢"
},
"breakGlass": {
"label": "硬邊界"
}
},
"links": {
"evidence": "證據",
"decisions": "決策",
"scope": "範圍",
"owners": "Owner"
}
},
"progressIntegrityRibbon": {
"eyebrow": "進度誠實儀表",

View File

@@ -6295,6 +6295,20 @@ const evidenceItems = [
'kali-integration-status.snapshot.json',
]
const commandRailMetrics = [
{ key: 'controlledApply', value: 'L/M/H', icon: Activity, tone: 'steady' },
{ key: 'automationClosure', value: '21/21', icon: Workflow, tone: 'steady' },
{ key: 'securityPosture', value: '64%', icon: ShieldCheck, tone: 'warn' },
{ key: 'breakGlass', value: 'critical', icon: Lock, tone: 'locked' },
] as const
const commandRailLinks = [
{ key: 'evidence', href: '#iwooos-first-layer-evidence', icon: SearchCheck, tone: 'steady' },
{ key: 'decisions', href: '#iwooos-decision-gate-visuals', icon: Radar, tone: 'warn' },
{ key: 'scope', href: '#iwooos-scope-evidence-visuals', icon: Network, tone: 'steady' },
{ key: 'owners', href: '#iwooos-source-control-readiness-board', icon: ClipboardCheck, tone: 'warn' },
] as const
const toneColors = {
steady: '#1f7a4d',
warn: '#b66a2d',
@@ -15504,6 +15518,128 @@ function IwoooSFirstProgressUnlockPathBoard() {
)
}
function IwoooSCommandRail() {
const t = useTranslations('iwooos.commandRail')
return (
<section
data-testid="iwooos-command-rail"
style={{ marginBottom: 14, maxWidth: '100%', overflow: 'hidden' }}
>
<div
style={{
...band,
padding: 12,
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 260px), 1fr))',
gap: 10,
alignItems: 'stretch',
background: '#fcfdfa',
borderColor: '#dce3d4',
}}
>
<div style={{ minWidth: 0, display: 'grid', alignContent: 'center', gap: 4 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: '#46624a', fontSize: 11, fontWeight: 800 }}>
<ShieldCheck size={15} />
<span>{t('eyebrow')}</span>
</div>
<h2 style={{ margin: 0, fontSize: 18, lineHeight: 1.15, color: '#141413' }}>{t('title')}</h2>
</div>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(106px, 1fr))',
gap: 8,
minWidth: 0,
}}
>
{commandRailMetrics.map(item => {
const Icon = item.icon
return (
<div
key={item.key}
style={{
border: '0.5px solid #dbe5d6',
borderRadius: 8,
background: '#fff',
minHeight: 58,
padding: 9,
display: 'grid',
gap: 5,
minWidth: 0,
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>
<Icon size={14} color={toneColors[item.tone]} />
<span
style={{
color: '#626b5c',
fontSize: 10,
fontWeight: 800,
minWidth: 0,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{t(`metrics.${item.key}.label` as never)}
</span>
</div>
<strong style={{ color: toneColors[item.tone], fontSize: 16, lineHeight: 1.05 }}>{item.value}</strong>
</div>
)
})}
</div>
<nav
aria-label={t('navLabel')}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(92px, 1fr))',
gap: 8,
alignContent: 'center',
minWidth: 0,
}}
>
{commandRailLinks.map(item => {
const Icon = item.icon
return (
<a
key={item.key}
href={item.href}
style={{
border: '0.5px solid #d6dfd2',
borderRadius: 8,
background: '#f7faf3',
color: '#213823',
minHeight: 42,
padding: '8px 9px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 6,
fontSize: 11,
fontWeight: 900,
textDecoration: 'none',
minWidth: 0,
}}
>
<Icon size={14} color={toneColors[item.tone]} />
<span style={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{t(`links.${item.key}` as never)}
</span>
</a>
)
})}
</nav>
</div>
</section>
)
}
function IwoooSProgressIntegrityRibbon() {
const t = useTranslations('iwooos.progressIntegrityRibbon')
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
@@ -23548,6 +23684,7 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) {
</div>
</section>
<IwoooSCommandRail />
<IwoooSProgressIntegrityRibbon />
<IwoooSExecutiveSnapshotBoard />
<IwoooSAgentBountySecurityOnboardingBoard />

View File

@@ -79,7 +79,7 @@ spec:
- name: AWOOOI_BUILD_COMMIT_SHA
# 2026-06-29 Codex: CD rewrites this to the deployed image tag so
# production deploy readback does not rely on a stale static snapshot.
value: "d14a25f93ca95e4fe96fc339c4bf35ceec5bbe56"
value: "b9293b76b56cd327f34b4f2fb723674665f69a1c"
- name: USE_AI_ROUTER
value: "true"
- name: ENABLE_NEMOTRON_COLLABORATION

View File

@@ -41,7 +41,7 @@ resources:
images:
- name: 192.168.0.110:5000/library/api:IMAGE_TAG_PLACEHOLDER
newName: 192.168.0.110:5000/awoooi/api
newTag: d14a25f93ca95e4fe96fc339c4bf35ceec5bbe56
newTag: b9293b76b56cd327f34b4f2fb723674665f69a1c
- name: 192.168.0.110:5000/library/web:IMAGE_TAG_PLACEHOLDER
newName: 192.168.0.110:5000/awoooi/web
newTag: d14a25f93ca95e4fe96fc339c4bf35ceec5bbe56
newTag: b9293b76b56cd327f34b4f2fb723674665f69a1c

View File

@@ -121,6 +121,7 @@ def test_gitea_private_inventory_scorecard_stays_on_controlled_runtime_profile()
expected_sources = [
"docs/operations/awoooi-gitea-private-inventory-p0-scorecard.snapshot.json)",
"apps/api/src/services/gitea_authenticated_inventory_payload_validation.py)",
"apps/api/src/services/gitea_owner_coverage_attestation_validation.py)",
"apps/api/src/services/gitea_private_inventory_p0_scorecard.py)",
"apps/api/tests/test_gitea_private_inventory_p0_scorecard_api.py)",
"docs/operations/awoooi-gitea-authenticated-inventory-payload-validation.snapshot.json)",
@@ -131,6 +132,7 @@ def test_gitea_private_inventory_scorecard_stays_on_controlled_runtime_profile()
"scripts/security/gitea-authenticated-inventory-payload-validator.py)",
"scripts/security/tests/test_gitea_private_inventory_p0_scorecard.py)",
"src/services/gitea_authenticated_inventory_payload_validation.py",
"src/services/gitea_owner_coverage_attestation_validation.py",
"src/services/gitea_private_inventory_p0_scorecard.py",
"tests/test_gitea_private_inventory_p0_scorecard_api.py",
"scripts/security/tests/test_gitea_authenticated_inventory_payload_validator.py)",