1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
---
name: quality-gates
# Merge-time quality gates: a thin caller of the zircote/.github central
# reusable workflows. Each gate normalizes on SARIF and lands in the
# code-scanning hub; the "Code scanning results" required check is the merge
# gate. Pins resolve to the central repo's default-branch HEAD at wiring time;
# Dependabot (github-actions ecosystem) keeps them fresh.
#
# Deploy-time attestation — the "seam" that signs each gate's verdict bound to
# a release subject — lives in release.yml (publish-gated, tag-triggered).
#
# SAST (CodeQL) here supersedes a standalone codeql-analysis workflow; the SCA
# (OSV) gate is an independent second opinion that complements the RustSec
# cargo-audit run in security-audit.yml, not a replacement for it.
"on":
push:
branches:
pull_request:
branches:
schedule:
# Weekly Monday 06:23 UTC — scattered minute (avoid GitHub's :00 load
# spike) for the scheduled supply-chain posture + SAST sweep.
- cron: "23 6 * * 1"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
# SAST — CodeQL (Rust, build-mode none). Net-new SAST coverage for nsip.
# packages: read — the reusable's analyze job declares it (CodeQL package
# resolution); a caller must grant >= the reusable's permissions or the call
# fails at startup.
sast:
permissions:
security-events: write
contents: read
actions: read
packages: read
# zircote/.github main @ 77a87549 (resolved 2026-06-16)
uses: >-
zircote/.github/.github/workflows/reusable-sast-codeql.yml@740cb8efb57af0187f88e9b4f939355b871a5895
with:
languages: rust
build-mode: none
# SCA — OSV-Scanner (independent second opinion vs RustSec/cargo-audit) plus
# dependency review (PR merge gate). Complements the cargo Dependabot setup
# and security-audit.yml's RustSec run.
sca:
permissions:
actions: read
contents: read
security-events: write
pull-requests: write
# zircote/.github main @ 77a87549 (resolved 2026-06-16)
uses: >-
zircote/.github/.github/workflows/reusable-sca-osv.yml@77a87549a65c6c978a0e87efe0168ed3517f7ca4
with:
fail-on-severity: high
# Scope OSV to the Rust crate lockfile so the gate characterizes exactly
# the dependencies the crate ships; --config applies the shared ignore
# policy (osv-scanner.toml) that mirrors deny.toml / cargo-audit.
scan-args: |-
--config=osv-scanner.toml
--lockfile=Cargo.lock
# Supply-chain posture — OpenSSF Scorecard. Requires the default branch, so
# it does not run on pull_request.
posture:
if: github.event_name == 'push' || github.event_name == 'schedule'
permissions:
security-events: write
id-token: write
contents: read
actions: read
# zircote/.github main @ 77a87549 (resolved 2026-06-16)
uses: >-
zircote/.github/.github/workflows/reusable-scorecard.yml@77a87549a65c6c978a0e87efe0168ed3517f7ca4
# IaC + license — Trivy filesystem scan (Dockerfile, manifests, licenses).
# No image-ref here: the container image is scanned + attested on the release
# path. packages: read — the reusable's (skipped) image job declares it; the
# caller must still grant >= all the reusable's job permissions or the call
# fails at startup, even for conditional jobs.
trivy:
permissions:
contents: read
security-events: write
actions: read
packages: read
# zircote/.github main @ 77a87549 (resolved 2026-06-16)
uses: >-
zircote/.github/.github/workflows/reusable-trivy.yml@77a87549a65c6c978a0e87efe0168ed3517f7ca4
with:
scan-iac: true