Skip to content

Commit 9fc619a

Browse files
committed
chore(closeout): harden prooftrail governance and security gates
1 parent 4ba1b8a commit 9fc619a

14 files changed

Lines changed: 433 additions & 73 deletions

.github/dependabot.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ updates:
44
directory: "/"
55
schedule:
66
interval: "weekly"
7-
open-pull-requests-limit: 0
7+
open-pull-requests-limit: 2
88
labels:
99
- "dependencies"
1010
- "github-actions"
@@ -13,7 +13,7 @@ updates:
1313
directory: "/"
1414
schedule:
1515
interval: "weekly"
16-
open-pull-requests-limit: 0
16+
open-pull-requests-limit: 5
1717
labels:
1818
- "dependencies"
1919
- "javascript"
@@ -22,7 +22,7 @@ updates:
2222
directory: "/"
2323
schedule:
2424
interval: "weekly"
25-
open-pull-requests-limit: 0
25+
open-pull-requests-limit: 2
2626
labels:
2727
- "dependencies"
2828
- "python"

.github/workflows/ci.yml

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ jobs:
231231

232232
hooks_equivalence_gate:
233233
needs: [changes]
234-
if: ${{ github.repository_owner != 'xiaojiou176-open' && (github.event_name == 'workflow_dispatch' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.automation == 'true' || needs.changes.outputs.ci_gatechain == 'true') }}
234+
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.automation == 'true' || needs.changes.outputs.ci_gatechain == 'true' }}
235235
runs-on: ubuntu-latest
236236
steps:
237237
- name: Pre-checkout workspace sanitize
@@ -311,9 +311,12 @@ jobs:
311311
with:
312312
mode: post
313313

314-
security:
314+
trivy_fs:
315315
needs: [changes]
316+
if: ${{ github.event_name == 'workflow_dispatch' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.automation == 'true' || needs.changes.outputs.ci_gatechain == 'true' }}
316317
runs-on: ubuntu-latest
318+
permissions:
319+
contents: read
317320
steps:
318321
- name: Pre-checkout workspace sanitize
319322
shell: bash
@@ -346,16 +349,61 @@ jobs:
346349
with:
347350
fetch-depth: 0
348351
- uses: ./.github/actions/workspace-sanitize
349-
- name: Secret scan (history audit, strict when license configured)
350-
if: ${{ vars.GITLEAKS_LICENSE != '' }}
351-
uses: gitleaks/gitleaks-action@dcedce43c6f43de0b836d1fe38946645c9c638dc # v2
352-
env:
353-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
354-
GITLEAKS_LICENSE: ${{ vars.GITLEAKS_LICENSE }}
355-
- name: Skip history secret scan (no GITLEAKS_LICENSE configured)
356-
if: ${{ vars.GITLEAKS_LICENSE == '' }}
352+
- name: Trivy filesystem scan
353+
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
354+
with:
355+
scan-type: fs
356+
scan-ref: .
357+
format: table
358+
exit-code: "1"
359+
ignore-unfixed: true
360+
vuln-type: library
361+
severity: HIGH,CRITICAL
362+
- name: Upload failure bundle artifact
363+
if: ${{ failure() || cancelled() }}
364+
uses: ./.github/actions/failure-bundle
365+
- uses: ./.github/actions/workspace-sanitize
366+
if: ${{ always() }}
367+
with:
368+
mode: post
369+
370+
security:
371+
needs: [changes]
372+
runs-on: ubuntu-latest
373+
steps:
374+
- name: Pre-checkout workspace sanitize
375+
shell: bash
357376
run: |
358-
echo "security history audit skipped: missing GITLEAKS_LICENSE repository variable"
377+
set -euo pipefail
378+
workspace="${GITHUB_WORKSPACE:?GITHUB_WORKSPACE is required}"
379+
home_dir="${HOME:-}"
380+
case "$workspace" in
381+
/|/.|/..|"")
382+
echo "::error::refusing dangerous workspace path: $workspace"
383+
exit 1
384+
;;
385+
esac
386+
if [[ -n "$home_dir" && "$workspace" == "$home_dir" ]]; then
387+
echo "::error::refusing workspace equal to HOME: $workspace"
388+
exit 1
389+
fi
390+
if [[ -d "$workspace" ]]; then
391+
if command -v sudo >/dev/null 2>&1; then
392+
sudo chown -R "$(id -u):$(id -g)" "$workspace" || true
393+
sudo bash -lc 'shopt -s dotglob nullglob; rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ "$workspace" || true
394+
sudo mkdir -p "$workspace" || true
395+
sudo chown "$(id -u):$(id -g)" "$workspace" || true
396+
else
397+
chmod -R u+rwX "$workspace" || true
398+
find "$workspace" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + || true
399+
fi
400+
fi
401+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
402+
with:
403+
fetch-depth: 0
404+
- uses: ./.github/actions/workspace-sanitize
405+
- name: Secret scan (history audit, repo-owned gate)
406+
run: bash scripts/ci/gitleaks-history-gate.sh
359407
- name: Upload failure bundle artifact
360408
if: ${{ failure() || cancelled() }}
361409
uses: ./.github/actions/failure-bundle

.github/workflows/pr.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ jobs:
8787
fi
8888
echo 'is_untrusted_fork=false' >> "$GITHUB_OUTPUT"
8989
90+
dependency-review:
91+
needs: changes
92+
if: ${{ github.event_name == 'pull_request' && needs.changes.outputs.is_untrusted_fork != 'true' }}
93+
runs-on: ubuntu-24.04
94+
permissions:
95+
contents: read
96+
steps:
97+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
98+
with:
99+
fetch-depth: 0
100+
- name: Dependency review
101+
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
102+
90103
build_ci_image:
91104
needs: changes
92105
if: ${{ needs.changes.outputs.is_untrusted_fork != 'true' }}
@@ -163,6 +176,68 @@ jobs:
163176
- name: OpenAI residue hard gate
164177
run: bash scripts/ci/gate-openai-residue.sh
165178

179+
pr-gitleaks-history:
180+
needs: changes
181+
if: ${{ needs.changes.outputs.is_untrusted_fork != 'true' && (github.event_name == 'workflow_dispatch' || needs.changes.outputs.docs == 'true' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.automation == 'true' || needs.changes.outputs.apps == 'true' || needs.changes.outputs.packages == 'true' || needs.changes.outputs.scripts == 'true' || needs.changes.outputs.shared == 'true' || needs.changes.outputs.ci == 'true') }}
182+
runs-on: ubuntu-24.04
183+
permissions:
184+
contents: read
185+
steps:
186+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
187+
with:
188+
fetch-depth: 0
189+
- name: Gitleaks history gate
190+
run: bash scripts/ci/gitleaks-history-gate.sh
191+
- name: Upload gitleaks history artifact
192+
if: ${{ always() }}
193+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
194+
with:
195+
name: uiq-pr-gitleaks-history
196+
path: .runtime-cache/artifacts/ci/gitleaks-history.json
197+
retention-days: 7
198+
if-no-files-found: warn
199+
200+
pr-trivy-fs:
201+
needs: changes
202+
if: ${{ needs.changes.outputs.is_untrusted_fork != 'true' && (github.event_name == 'workflow_dispatch' || needs.changes.outputs.frontend == 'true' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.automation == 'true' || needs.changes.outputs.apps == 'true' || needs.changes.outputs.packages == 'true' || needs.changes.outputs.shared == 'true' || needs.changes.outputs.ci == 'true') }}
203+
runs-on: ubuntu-24.04
204+
permissions:
205+
contents: read
206+
steps:
207+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
208+
with:
209+
fetch-depth: 0
210+
- name: Trivy filesystem scan
211+
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
212+
with:
213+
scan-type: fs
214+
scan-ref: .
215+
format: table
216+
exit-code: "1"
217+
ignore-unfixed: true
218+
vuln-type: library
219+
severity: HIGH,CRITICAL
220+
221+
public-readiness-deep:
222+
needs: changes
223+
if: ${{ github.event_name == 'workflow_dispatch' && needs.changes.outputs.is_untrusted_fork != 'true' }}
224+
runs-on: ubuntu-24.04
225+
permissions:
226+
contents: read
227+
steps:
228+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
229+
with:
230+
fetch-depth: 0
231+
- uses: ./.github/actions/setup-deps
232+
with:
233+
pnpm-cache: "false"
234+
node-version: "20"
235+
python-version: "3.11"
236+
enable-playwright: "false"
237+
uv-sync-command: uv sync --frozen --extra dev
238+
- name: Public readiness deep check
239+
run: pnpm public:readiness:deep-check
240+
166241
upstream-mode-check:
167242
needs: changes
168243
runs-on: ubuntu-24.04

.github/workflows/pre-commit.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,26 @@ jobs:
7676
with:
7777
mode: post
7878

79+
zizmor:
80+
needs: [workflow-hygiene]
81+
runs-on: ubuntu-latest
82+
permissions:
83+
contents: read
84+
actions: read
85+
steps:
86+
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4
87+
with:
88+
fetch-depth: 2
89+
persist-credentials: false
90+
- name: Run zizmor
91+
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
92+
with:
93+
advanced-security: false
94+
- uses: ./.github/actions/workspace-sanitize
95+
if: ${{ always() }}
96+
with:
97+
mode: post
98+
7999
precommit-config-contract:
80100
needs: [workflow-hygiene]
81101
runs-on: ubuntu-latest
@@ -105,7 +125,6 @@ jobs:
105125

106126
hooks-equivalence-gate:
107127
needs: [workflow-hygiene]
108-
if: ${{ github.repository_owner != 'xiaojiou176-open' }}
109128
runs-on: ubuntu-latest
110129
steps:
111130
- uses: actions/checkout@64ffef1ea610c4052efefeb955034987fb104bc4 # v4

configs/tooling/pre-commit-config.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ repos:
4646
- id: uiq-commitizen-branch-pre-push
4747
name: UIQ branch naming gate (pre-push)
4848
entry: >-
49-
bash -lc 'branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo detached)"; if [[ "$branch" == "HEAD" || "$branch" == "detached" ]]; then echo "[branch-gate] detached HEAD; skip"; exit 0; fi; if [[ "$branch" =~ ^(main|master|develop|dev|release/.+|hotfix/.+|feat/.+|fix/.+|chore/.+|docs/.+|refactor/.+|test/.+) ]]; then echo "[branch-gate] ok: $branch"; exit 0; fi; echo "[branch-gate] invalid branch name: $branch"; echo "[branch-gate] expected prefixes: feat/, fix/, chore/, docs/, refactor/, test/, release/, hotfix/"; exit 1'
49+
bash -lc 'branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo detached)"; if [[ "$branch" == "HEAD" || "$branch" == "detached" ]]; then echo "[branch-gate] detached HEAD; skip"; exit 0; fi; if [[ "$branch" =~ ^(main|master|develop|dev|codex/.+|release/.+|hotfix/.+|feat/.+|fix/.+|chore/.+|docs/.+|refactor/.+|test/.+) ]]; then echo "[branch-gate] ok: $branch"; exit 0; fi; echo "[branch-gate] invalid branch name: $branch"; echo "[branch-gate] expected prefixes: codex/, feat/, fix/, chore/, docs/, refactor/, test/, release/, hotfix/"; exit 1'
5050
language: system
5151
pass_filenames: false
5252
stages: [pre-push]
@@ -241,8 +241,9 @@ repos:
241241
hooks:
242242
- id: biome-check
243243
entry: biome check
244-
pass_filenames: false
245-
args: [biome.json]
244+
pass_filenames: true
245+
args: [--config-path=configs/ci/biome.json]
246+
files: '^(apps|packages|scripts|\.github)/.*\.(js|jsx|ts|tsx|mjs|cjs)$|^package\.json$'
246247

247248
- repo: https://github.com/thibaudcolas/pre-commit-stylelint
248249
rev: v16.26.0
@@ -281,6 +282,7 @@ repos:
281282
rev: v0.11.0.1
282283
hooks:
283284
- id: shellcheck
285+
args: [-x]
284286
files: '\.sh$'
285287

286288
- repo: https://github.com/hadolint/hadolint

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@
201201
"form-data": "4.0.5",
202202
"hono": "4.12.7",
203203
"js-yaml": "4.1.1",
204+
"lodash": "4.18.0",
205+
"lodash-es": "4.18.0",
204206
"minimatch": "10.2.3",
205207
"picomatch": "4.0.4",
206208
"path-to-regexp@0.1.12": "0.1.13",

pnpm-lock.yaml

Lines changed: 16 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/ci/check-cold-cache-recovery.sh

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ GOVERNANCE_STATIC_RECOVERY_COMMAND="node scripts/ci/check-root-governance.mjs &&
7070

7171
COMMANDS=(
7272
"$GOVERNANCE_STATIC_RECOVERY_COMMAND"
73-
"export PROJECT_PYTHON_ENV=.runtime-cache/toolchains/python/.venv UV_PROJECT_ENVIRONMENT=.runtime-cache/toolchains/python/.venv DATABASE_URL=sqlite+pysqlite:///${COLD_CACHE_DB_PATH} && uv sync --frozen --extra dev >/dev/null 2>&1 && rm -f ${COLD_CACHE_DB_PATH} && bash scripts/dev-up.sh && bash scripts/dev-down.sh && rm -f ${COLD_CACHE_DB_PATH}"
73+
"export PROJECT_PYTHON_ENV=.runtime-cache/toolchains/python/.venv UV_PROJECT_ENVIRONMENT=.runtime-cache/toolchains/python/.venv DATABASE_URL=sqlite+pysqlite:///${COLD_CACHE_DB_PATH} && uv sync --frozen --extra dev >/dev/null 2>&1 && CI=true pnpm install --frozen-lockfile >/dev/null 2>&1 && rm -f ${COLD_CACHE_DB_PATH} && bash scripts/dev-up.sh && bash scripts/dev-down.sh && rm -f ${COLD_CACHE_DB_PATH}"
7474
"pnpm env:check"
7575
"node --import tsx --test apps/mcp-server/tests/core.constants.test.ts"
7676
)

0 commit comments

Comments
 (0)