ci: make source secret scan locale independent
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 6m23s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Successful in 10m18s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 42m22s

This commit is contained in:
2026-07-20 21:14:31 +08:00
parent 0003bfa05c
commit 5ad6beac98
4 changed files with 133 additions and 18 deletions
+78 -12
View File
@@ -171,7 +171,7 @@
{ {
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_platform_data.py", "filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_platform_data.py",
"hashed_secret": "944e39e8ed4859e0901b7ca0830067a935c1587d", "hashed_secret": "f8843a16172173b7829ae8e358969e604e792eab",
"line_number": 165, "line_number": 165,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic OCR secret reference used by a unit test." "audit_reason": "Synthetic OCR secret reference used by a unit test."
@@ -190,7 +190,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_provider_flow.py", "filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_provider_flow.py",
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f", "hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
"line_number": 55, "line_number": 67,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic provider key used by a mocked unit test." "audit_reason": "Synthetic provider key used by a mocked unit test."
}, },
@@ -198,7 +198,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_provider_flow.py", "filename": "yuqei-ai-platform/services/ai-platform-api/tests/test_provider_flow.py",
"hashed_secret": "dfd7a37d1dc759fc860644d608aa5d8ad9b53c96", "hashed_secret": "dfd7a37d1dc759fc860644d608aa5d8ad9b53c96",
"line_number": 201, "line_number": 213,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic environment secret reference used by a unit test." "audit_reason": "Synthetic environment secret reference used by a unit test."
} }
@@ -228,7 +228,7 @@
"type": "Basic Auth Credentials", "type": "Basic Auth Credentials",
"filename": "yuqei-contract-platform/services/contract-api/.env.example", "filename": "yuqei-contract-platform/services/contract-api/.env.example",
"hashed_secret": "7205a0abf00d1daec13c63ece029057c974795a9", "hashed_secret": "7205a0abf00d1daec13c63ece029057c974795a9",
"line_number": 17, "line_number": 30,
"is_secret": false, "is_secret": false,
"audit_reason": "Production example uses the explicit CHANGE_ME placeholder." "audit_reason": "Production example uses the explicit CHANGE_ME placeholder."
} }
@@ -251,6 +251,14 @@
"line_number": 808, "line_number": 808,
"is_secret": false, "is_secret": false,
"audit_reason": "Contract template identifier in a test request path." "audit_reason": "Contract template identifier in a test request path."
},
{
"type": "Secret Keyword",
"filename": "yuqei-contract-platform/services/contract-api/tests/test_contract_workflow.py",
"hashed_secret": "3e3a880564d6961104d8ca9e82190ef682b3d11a",
"line_number": 2397,
"is_secret": false,
"audit_reason": "Synthetic AI service key asserted by a mocked review worker test."
} }
], ],
"yuqei-contract-platform/services/contract-api/tests/test_health.py": [ "yuqei-contract-platform/services/contract-api/tests/test_health.py": [
@@ -284,7 +292,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py", "filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py",
"hashed_secret": "2585823c3e56d65632eff0c1eb7f8fffa0736cb3", "hashed_secret": "2585823c3e56d65632eff0c1eb7f8fffa0736cb3",
"line_number": 188, "line_number": 189,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic invite password used by an identity test." "audit_reason": "Synthetic invite password used by an identity test."
}, },
@@ -292,7 +300,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py", "filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py",
"hashed_secret": "d26b0b74aaf44561a94d607e9d73e4dc6b95fe3d", "hashed_secret": "d26b0b74aaf44561a94d607e9d73e4dc6b95fe3d",
"line_number": 241, "line_number": 242,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic tenant-owner password used by an identity test." "audit_reason": "Synthetic tenant-owner password used by an identity test."
}, },
@@ -300,7 +308,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py", "filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py",
"hashed_secret": "42f6c37f356183f42a67d9e0ae515bb51d7590cf", "hashed_secret": "42f6c37f356183f42a67d9e0ae515bb51d7590cf",
"line_number": 280, "line_number": 281,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic old-password fixture used by a reset test." "audit_reason": "Synthetic old-password fixture used by a reset test."
}, },
@@ -308,7 +316,7 @@
"type": "Secret Keyword", "type": "Secret Keyword",
"filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py", "filename": "yuqei-contract-platform/services/contract-api/tests/test_identity_management.py",
"hashed_secret": "a55a3986a699ba4d2b29b2057811322bf076abd0", "hashed_secret": "a55a3986a699ba4d2b29b2057811322bf076abd0",
"line_number": 299, "line_number": 300,
"is_secret": false, "is_secret": false,
"audit_reason": "Synthetic new-password fixture used by a reset test." "audit_reason": "Synthetic new-password fixture used by a reset test."
} }
@@ -318,7 +326,7 @@
"type": "Basic Auth Credentials", "type": "Basic Auth Credentials",
"filename": "yuqei-infra/compose/.env.example", "filename": "yuqei-infra/compose/.env.example",
"hashed_secret": "964a0c3a014c640b82d5ab59c4665a323d20a880", "hashed_secret": "964a0c3a014c640b82d5ab59c4665a323d20a880",
"line_number": 22, "line_number": 24,
"is_secret": false, "is_secret": false,
"audit_reason": "Documented local compose credentials." "audit_reason": "Documented local compose credentials."
} }
@@ -328,7 +336,7 @@
"type": "Basic Auth Credentials", "type": "Basic Auth Credentials",
"filename": "yuqei-infra/compose/.env.production.example", "filename": "yuqei-infra/compose/.env.production.example",
"hashed_secret": "7205a0abf00d1daec13c63ece029057c974795a9", "hashed_secret": "7205a0abf00d1daec13c63ece029057c974795a9",
"line_number": 24, "line_number": 63,
"is_secret": false, "is_secret": false,
"audit_reason": "Production example uses explicit CHANGE_ME placeholders." "audit_reason": "Production example uses explicit CHANGE_ME placeholders."
} }
@@ -338,7 +346,7 @@
"type": "Basic Auth Credentials", "type": "Basic Auth Credentials",
"filename": "yuqei-infra/compose/docker-compose.yml", "filename": "yuqei-infra/compose/docker-compose.yml",
"hashed_secret": "964a0c3a014c640b82d5ab59c4665a323d20a880", "hashed_secret": "964a0c3a014c640b82d5ab59c4665a323d20a880",
"line_number": 78, "line_number": 83,
"is_secret": false, "is_secret": false,
"audit_reason": "Documented local compose fallback credentials." "audit_reason": "Documented local compose fallback credentials."
} }
@@ -348,10 +356,68 @@
"type": "Basic Auth Credentials", "type": "Basic Auth Credentials",
"filename": "yuqei-infra/scripts/deploy-v2-smoke-docker.ps1", "filename": "yuqei-infra/scripts/deploy-v2-smoke-docker.ps1",
"hashed_secret": "f3ae48aa9b0d4eaec403d0f4b9cf89527def9aec", "hashed_secret": "f3ae48aa9b0d4eaec403d0f4b9cf89527def9aec",
"line_number": 340, "line_number": 354,
"is_secret": false, "is_secret": false,
"audit_reason": "Isolated smoke-only database credentials generated by the deploy script." "audit_reason": "Isolated smoke-only database credentials generated by the deploy script."
} }
],
"yuqei-infra/tests/test_production_release_tools.py": [
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "53dc84fccc33570defe1f39cf9612ce69ac7424a",
"line_number": 48,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "05d90b39f109a93348186597904cd4f49152d061",
"line_number": 50,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "a5e7de418383e7e8471cc9a21992ce0daafab40f",
"line_number": 51,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "b5631d35d843013925a520542e7955d954e6b153",
"line_number": 52,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "25c5fef49509171e38e408bc6dacd86b50a890e5",
"line_number": 53,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Secret Keyword",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "5653faf32e2d189e6b2ee91e022735727a89ba7b",
"line_number": 54,
"is_secret": false,
"audit_reason": "Synthetic production-preflight secret placeholder used by an infrastructure test."
},
{
"type": "Basic Auth Credentials",
"filename": "yuqei-infra/tests/test_production_release_tools.py",
"hashed_secret": "2aeae636ff10256fe811ae406cc7aba633b55626",
"line_number": 55,
"is_secret": false,
"audit_reason": "Synthetic PostgreSQL URL with a placeholder password used by an infrastructure test."
}
] ]
} }
} }
+7 -6
View File
@@ -2,7 +2,7 @@
## Decision ## Decision
The current candidate is frozen for release review under tag `v2-rc-20260720.1`. The current candidate is frozen for release review under tag `v2-rc-20260720.2`.
After the tag is created, only blocking bug fixes, tests, deployment configuration, After the tag is created, only blocking bug fixes, tests, deployment configuration,
and release documentation may be added. New product features and schema changes are and release documentation may be added. New product features and schema changes are
outside this RC. outside this RC.
@@ -25,10 +25,11 @@ deployment/backup/health-check tooling, AI Provider acceptance tooling, authenti
review-worker integration, ambient-proxy isolation for internal AI Platform calls, review-worker integration, ambient-proxy isolation for internal AI Platform calls,
and per-key single-flight protection for Contract API read-cache misses. and per-key single-flight protection for Contract API read-cache misses.
Tag `v2-rc-20260720.1` supersedes `v2-rc-20260720`. The original tag remains Tag `v2-rc-20260720.2` supersedes `v2-rc-20260720.1` and `v2-rc-20260720`.
immutable; the only follow-up change pins the CI pip index to the same mirror already The earlier tags remain immutable. This follow-up fixes a cross-platform source-scan
validated by the smoke deployment, preventing official-PyPI throughput from blocking gap by forcing the detect-secrets subprocess to read UTF-8 on Windows, and refreshes
the Python and security jobs before tests begin. the reviewed baseline from the complete Linux-equivalent scan. It also adds a focused
regression test so files containing non-GBK text cannot be silently skipped.
## Verification evidence ## Verification evidence
@@ -39,7 +40,7 @@ the Python and security jobs before tests begin.
| AI Platform schema-check | Pass; only the intentional smoke `provider_runtime` warning | `project-docs/qa-artifacts/v2-release-quality-gate/2026-07-20T18-20-08/ai_platform_api-schema-check.json` | | AI Platform schema-check | Pass; only the intentional smoke `provider_runtime` warning | `project-docs/qa-artifacts/v2-release-quality-gate/2026-07-20T18-20-08/ai_platform_api-schema-check.json` |
| Release quality gate | Pass | `project-docs/qa-artifacts/v2-release-quality-gate/2026-07-20T18-20-08` | | Release quality gate | Pass | `project-docs/qa-artifacts/v2-release-quality-gate/2026-07-20T18-20-08` |
| Remote core user flow | Pass; browser console errors 0 | `project-docs/qa-artifacts/v2-core-regression/2026-07-20-smoke-pass2/core-user-flow-summary.json` | | Remote core user flow | Pass; browser console errors 0 | `project-docs/qa-artifacts/v2-core-regression/2026-07-20-smoke-pass2/core-user-flow-summary.json` |
| Source secret scan | Pass; 15 reviewed candidates, 0 new findings | `project-docs/qa-artifacts/v2-source-secret-scan/2026-07-20T18-40-00/source-secret-scan-summary.json` | | Source secret scan | Pass; 46 reviewed candidates, 0 new findings, 0 stale baseline entries | `project-docs/qa-artifacts/v2-source-secret-scan/2026-07-20T21-07-30/source-secret-scan-summary.json` |
| Security scan | Pass; npm 0, Bandit 0, pip-audit 0 | `project-docs/qa-artifacts/v2-security-scan/2026-07-20T18-45-00` | | Security scan | Pass; npm 0, Bandit 0, pip-audit 0 | `project-docs/qa-artifacts/v2-security-scan/2026-07-20T18-45-00` |
Local verification also passed the complete Contract API suite, AI Platform API, Local verification also passed the complete Contract API suite, AI Platform API,
@@ -2,6 +2,7 @@ from __future__ import annotations
import argparse import argparse
import json import json
import os
import subprocess import subprocess
import sys import sys
from datetime import datetime from datetime import datetime
@@ -112,6 +113,9 @@ def _run_detect_secrets(include_untracked: bool) -> dict[str, Any]:
capture_output=True, capture_output=True,
text=True, text=True,
encoding="utf-8", encoding="utf-8",
# detect-secrets opens source files with the process locale; keep Windows scans
# equivalent to the UTF-8 Linux CI scan instead of silently skipping files.
env={**os.environ, "PYTHONUTF8": "1"},
) )
if completed.returncode != 0: if completed.returncode != 0:
raise RuntimeError(completed.stderr.strip() or "detect-secrets failed without diagnostic output") raise RuntimeError(completed.stderr.strip() or "detect-secrets failed without diagnostic output")
@@ -0,0 +1,44 @@
from __future__ import annotations
import importlib.util
import json
import sys
from pathlib import Path
from types import ModuleType, SimpleNamespace
REPO_ROOT = Path(__file__).resolve().parents[2]
def load_script(name: str, relative_path: str) -> ModuleType:
path = REPO_ROOT / relative_path
spec = importlib.util.spec_from_file_location(name, path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
source_scan = load_script(
"yuqei_source_secret_scan",
"yuqei-infra/scripts/run-source-secret-scan.py",
)
def test_source_secret_scan_forces_utf8_for_detect_secrets(monkeypatch) -> None:
captured: dict[str, object] = {}
def fake_run(command, **kwargs):
captured["command"] = command
captured.update(kwargs)
return SimpleNamespace(
returncode=0,
stdout=json.dumps({"results": {}}),
stderr="",
)
monkeypatch.setattr(source_scan.subprocess, "run", fake_run)
assert source_scan._run_detect_secrets(False) == {"results": {}}
assert captured["env"]["PYTHONUTF8"] == "1"