Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
77910ff
fix(security): update Strix Python dependency locks
seonghobae Aug 4, 2026
60b6dd9
fix(ci): restore central security baseline
seonghobae Aug 4, 2026
c73ee47
fix(ci): let dependency upgrades self-heal coverage
seonghobae Aug 4, 2026
880486b
fix(deps): constrain patched aiohttp floor in Strix lock
seonghobae Aug 4, 2026
bb5e436
test(ci): reject mixed fatal pip preflight evidence
seonghobae Aug 4, 2026
b326f65
fix(ci): keep mixed pip integrity failures fatal
seonghobae Aug 4, 2026
5b4929a
fix(ci): restore coverage contract wording
seonghobae Aug 4, 2026
0b6a188
fix(ci): snapshot dependencies on default-branch pushes so dependency…
seonghobae Aug 4, 2026
69fc4d2
ci: run securely pinned review repair every hour (#745)
seonghobae Aug 4, 2026
6b705b3
test(ci): fail closed on mixed unknown pip errors
seonghobae Aug 4, 2026
83b9d50
fix(ci): reject mixed unknown pip failures
seonghobae Aug 4, 2026
ced08de
test(ci): preserve pip stale-pin context lines
seonghobae Aug 4, 2026
98dc0b5
docs(doctoring): record central security baseline evidence
seonghobae Aug 4, 2026
5c5c032
fix(ci): preserve verified pip stale-pin context
seonghobae Aug 4, 2026
a0a84f7
fix(ci): recognize pip incompatible-version context
seonghobae Aug 4, 2026
4aefeb1
docs(doctoring): correct APA 7 standards provenance
seonghobae Aug 4, 2026
cfa6893
docs(automation): correct APA 7 dates for living GitHub documentation
seonghobae Aug 4, 2026
03a95a4
test(ci): prove exact-pair stale-pin classification
seonghobae Aug 4, 2026
3e92ae9
chore(ci): remove branch-pushing one-shot workflow
seonghobae Aug 4, 2026
0160d65
build(ci): add bounded stale-pin patch helper
seonghobae Aug 4, 2026
a900f51
test(ci): require exact-pair stale-pin evidence
seonghobae Aug 4, 2026
0d22ee8
fix(ci): simplify one-shot stale-pin verification
seonghobae Aug 4, 2026
98ef79e
fix(security): remove branch-controlled write workflow
seonghobae Aug 4, 2026
044030b
fix(ci): require paired exact-requirement stale-pin diagnostics
seonghobae Aug 4, 2026
b61878f
chore(ci): remove completed one-shot patch helper
seonghobae Aug 4, 2026
f2c5333
docs(doctoring): record paired stale-pin evidence contract
seonghobae Aug 4, 2026
13e8d72
ci(security): advance CodeQL baseline to v4.37.5
seonghobae Aug 4, 2026
2ad1fc0
ci(security): use latest immutable CodeQL v4.37.5
seonghobae Aug 4, 2026
c61bdd7
test(ci): reject non-version index evidence
seonghobae Aug 4, 2026
d20072a
fix(ci): require concrete version evidence before deferral
seonghobae Aug 4, 2026
13c12cc
docs(doctoring): define concrete stale-pin version evidence
seonghobae Aug 4, 2026
3dff404
test(ci): reject duplicate malformed resolver evidence
seonghobae Aug 4, 2026
c3b16d0
fix(ci): validate every paired resolver line independently
seonghobae Aug 4, 2026
60f6009
docs(doctoring): require concrete evidence on every resolver line
seonghobae Aug 4, 2026
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
8 changes: 4 additions & 4 deletions .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:${{ matrix.language }}"
upload: false
Expand Down Expand Up @@ -197,13 +197,13 @@ jobs:
ref: ${{ format('refs/pull/{0}/merge', github.event.pull_request.number) }}

- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:${{ matrix.language }}-merge"
upload: false
Expand Down
25 changes: 15 additions & 10 deletions .github/workflows/pr-review-fix-scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ on:
retry_hours:
description: Minimum hours before redispatching autofix for the same head
required: false
default: "24"
default: "1"
type: string
autofix_workflow:
description: Autofix workflow file to dispatch
Expand All @@ -44,14 +44,16 @@ on:
default: ""
type: string
canonical_ref:
description: Ref of ContextualWisdomLab/.github to use for scheduler code
description: Deprecated compatibility input; accepted and ignored because privileged source is bound to the called workflow SHA
required: false
default: "main"
default: ""
type: string
repository_dispatch:
types: [pr-review-fix-scheduler]
schedule:
- cron: "23 */2 * * *"
# Run away from minute zero, where scheduled GitHub Actions are more likely
# to be delayed, while preserving a bounded one-dispatch-per-run repair loop.
- cron: "23 * * * *"

concurrency:
group: central-pr-review-fix-scheduler-${{ github.event.client_payload.target_repository || inputs.target_repository || vars.PR_REVIEW_FIX_TARGET_REPOSITORY || github.repository }}
Expand Down Expand Up @@ -80,16 +82,19 @@ jobs:
DRY_RUN: ${{ github.event.client_payload.dry_run == true || github.event.client_payload.dry_run == 'true' || inputs.dry_run == true }}
MAX_PRS: ${{ github.event.client_payload.max_prs || inputs.max_prs || '50' }}
MAX_DISPATCHES: ${{ github.event.client_payload.max_dispatches || inputs.max_dispatches || '1' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '24' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '1' }}
AUTOFIX_WORKFLOW: pr-review-autofix.yml
AUTOFIX_REPOSITORY: ContextualWisdomLab/.github
CANONICAL_REF: main
steps:
- name: Checkout canonical scheduler
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Checkout immutable called-workflow source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ContextualWisdomLab/.github
ref: ${{ env.CANONICAL_REF }}
# In a reusable workflow the ordinary github context belongs to the
# caller. The job workflow context identifies the called workflow's
# repository and immutable resolved SHA, preventing a caller input or
# mutable branch from selecting the privileged scheduler code.
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
fetch-depth: 1
persist-credentials: false

Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/sbom-generation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,30 @@
# NOTE: contents: write is required for release-asset upload and for the
# dependency submission API. Fork PR heads run without write and simply skip
# those side effects; the artifact is still produced.
#
# NOTE on the push trigger: it exists so the DEFAULT BRANCH has a dependency
# snapshot. dependency-review compares base...head in the dependency graph; with
# PR-only runs the base commit never has one, so every comparison reports "the
# number of snapshots compared for the base SHA (0) and the head SHA (1) do not
# match" and the whole dependency set reads as newly added. That re-flags
# pre-existing vulnerabilities on every PR instead of only the ones the PR adds.
# Snapshotting pushes to the default branch gives the comparison a real base.
name: SBOM Generation

on:
push:
branches: [main, master, develop]
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]
release:
types: [published]

concurrency:
group: sbom-generation-${{ github.event.pull_request.base.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.event.release.tag_name || github.ref }}
# Final fallback is the SHA, not the ref, so two pushes landing close together
# do not cancel each other: a cancelled push run leaves that commit without a
# snapshot, which is exactly the base-side gap this trigger exists to close.
group: sbom-generation-${{ github.event.pull_request.base.repo.full_name || github.repository }}-${{ github.event.pull_request.number || github.event.release.tag_name || github.sha }}
cancel-in-progress: true

permissions:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/scheduled-security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ jobs:
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
- name: Perform CodeQL Analysis
continue-on-error: true
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:${{ matrix.language }}-scheduled"

Expand Down Expand Up @@ -131,7 +131,7 @@ jobs:
- name: Upload Trivy SARIF to code scanning
if: always() && hashFiles('trivy-results.sarif') != ''
continue-on-error: true
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/upload-sarif@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
sarif_file: trivy-results.sarif
category: trivy-fs-scheduled
72 changes: 72 additions & 0 deletions docs/automation/hourly-review-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Hourly PR review-repair scheduler

The central `PR Review Fix Scheduler` provides a bounded organization-wide
review → fix → revalidate → merge support loop. It runs at minute 23 of every
hour and may dispatch at most one existing autofix workflow per run. Merge
eligibility remains owned by the separate merge scheduler, branch protection,
required checks, independent review, and unresolved-thread policy.

## Execution and compatibility contract

- The scheduled heartbeat is `23 * * * *`.
- The default same-head retry floor is one hour.
- `max_dispatches` remains one by default.
- Repository-scoped concurrency and `cancel-in-progress: true` prevent two
superseded scheduler runs from mutating the same repository concurrently.
- `canonical_ref` remains an accepted deprecated input only so callers pinned to
older workflow interfaces can upgrade without a coordinated breaking change.
It is never read and cannot choose executable scheduler code.

## Immutable reusable-workflow source

GitHub associates the ordinary `github` context in a reusable workflow with the
caller. Consequently, a called privileged workflow must not use caller-derived
`github.sha`, a caller payload, or a mutable branch such as `main` to select its
co-located implementation.

The checkout step instead uses:

```yaml
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
```

`job.workflow_repository` identifies the repository that contains the called
workflow and `job.workflow_sha` identifies its immutable resolved commit. This
keeps the scheduler implementation aligned with the exact workflow revision
selected by the caller's `uses: ...@<sha>` reference. Checkout credentials are
not persisted.

## Security and MSA boundary

The scheduler can inspect review state and dispatch the already-reviewed bounded
autofix workflow. It cannot approve its own changes, lower branch protection,
convert queued checks to success, publish releases, or bypass independent
review. Product repositories remain independently operable and consume the
central policy as a reusable module rather than copying privileged automation.

CWL repositories and naruon retain their own product tests, authorization,
release, deployment, data-governance, and runtime responsibilities. The central
workflow owns only organization-level queue inspection and bounded repair
dispatch.

## Verification

Dependency-free static tests pin the hourly cron, one-hour retry default,
one-dispatch budget, single-flight concurrency, immutable called-workflow
checkout, ignored compatibility input, and least-privilege token boundary. The
exact PR head must also pass all central security, coverage, workflow-contract,
and independent-review gates before merge.

## References (APA 7th edition)

GitHub. (n.d.). *Contexts reference: Job context*. GitHub Docs. Retrieved August
4, 2026, from
https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#job-context

GitHub. (n.d.). *Reusing workflow configurations*. GitHub Docs. Retrieved August
4, 2026, from
https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations

GitHub. (n.d.). *Reusing workflows*. GitHub Docs. Retrieved August 4, 2026, from
https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows
114 changes: 114 additions & 0 deletions docs/doctoring/central-security-and-review-baseline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Central security and review baseline: evidence record

## Decision

The organization-level `.github` repository owns reusable review, security,
dependency-snapshot, and bounded repair workflows. Product repositories remain
independently operable and consume those controls as modules; they retain their
own application tests, authorization, deployment, release, and data-governance
responsibilities.

The baseline repair makes five controls atomic because they participate in the
same protected-branch decision:

1. CodeQL initialization, analysis, and SARIF upload use one immutable action
revision within each affected workflow.
2. The central Strix dependency closure removes known-vulnerable package pins
and remains fully hash-pinned.
3. Trusted-base Python dependency preflight defers only narrowly classified
incomplete closures, interpreter incompatibility, or binary-unavailable and
stale pins proven by paired diagnostics for the same exact requirement on a
reachable index. Every resolver line must carry a comma-separated list whose
alternatives are concrete, conservatively recognized PEP 440 versions;
blank values, `none`, arbitrary prose, mixed version/prose lists, duplicate
malformed evidence, integrity, transport, and unknown errors fail closed.
4. Default-branch pushes submit dependency snapshots so pull-request dependency
review compares a head snapshot with a real base snapshot.
5. Review repair runs once per hour, dispatches at most one bounded repair job,
and resolves privileged code from the reusable workflow's immutable source
identity rather than caller data or mutable `main`.

## Standards and current-platform rationale

NIST SSDF version 1.1 is the current final publication; version 1.2 remained a
public draft at the time of this decision. The baseline follows SSDF's final
risk-reduction direction by integrating vulnerability detection, dependency
integrity, repeatable verification, and root-cause regression controls into the
software lifecycle without claiming formal conformance.

The approved SLSA specification is version 1.2. Its source model distinguishes
trusted automation whose identity and codebase cannot be unilaterally
influenced. Immutable action pins, exact-revision dependency materialization,
and called-workflow source binding reduce mutable control-plane inputs in line
with that model without claiming a SLSA level.

GitHub documents that a reusable workflow's ordinary `github` context belongs
to the caller, while reusable-workflow permissions can only remain equal or
become more restrictive through a nested chain. The scheduler therefore binds
its checkout to `job.workflow_repository` and `job.workflow_sha`, rejects caller
or compatibility inputs as executable-source selectors, and omits contents-write
and pull-requests-write permissions.

GitHub also documents that scheduled events can be delayed at the start of an
hour. The hourly heartbeat therefore runs at minute 23. A one-hour same-head
retry floor matches the requested cadence while the one-dispatch budget and
repository-scoped concurrency keep mutation bounded.

GitHub's dependency submission API associates snapshots with commit SHAs and can
submit build-time or SBOM-derived dependencies that static manifest analysis
misses. Snapshotting default-branch pushes supplies the base-side evidence that
pull-request dependency review needs and prevents the entire existing graph from
appearing newly introduced.

## Verification contract

The exact pull-request head must prove:

- one immutable CodeQL revision per affected workflow;
- the central hash lock installs and vulnerability scanners accept it;
- stale-pin deferral requires paired exact-requirement resolver diagnostics and
a nonempty list on every matching resolver line in which every alternative is
a conservatively valid PEP 440 version, including epoch, prerelease,
postrelease, development, and local forms used by pip;
- blank, `none`, arbitrary prose, mixed version/prose lists, duplicate malformed
lines, single-sided or mismatched resolver evidence, integrity, retry,
transport, mixed-unknown, and unclassified installer failures remain fatal;
- the changed installer has 100% statement and branch coverage and 100%
production docstrings;
- default-branch snapshot triggers, commit-SHA concurrency, and job-scoped write
permissions remain pinned by tests;
- hourly cadence, one-hour retry, single dispatch, immutable called-workflow
source, and least-privilege permissions remain pinned by tests; and
- every current-head security, review, unresolved-thread, and branch-protection
gate succeeds before merge.

## References

Booth, H., Ogata, M., Kent, K., Souppaya, M., & Dodson, D. (2025). *Secure
software development framework (SSDF) version 1.2: Recommendations for
mitigating the risk of software vulnerabilities* (Initial Public Draft, NIST SP
800-218 Rev. 1). National Institute of Standards and Technology.
https://doi.org/10.6028/NIST.SP.800-218r1.ipd

GitHub. (n.d.). *Reusing workflow configurations*. GitHub Docs. Retrieved August
4, 2026, from
https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations

GitHub. (n.d.). *Troubleshooting workflows*. GitHub Docs. Retrieved August 4,
2026, from https://docs.github.com/en/actions/how-tos/troubleshoot-workflows

GitHub. (n.d.). *Using the dependency submission API*. GitHub Docs. Retrieved
August 4, 2026, from
https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/secure-your-dependencies/use-dependency-submission-api

Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure software development
framework (SSDF) version 1.1: Recommendations for mitigating the risk of software
vulnerabilities* (NIST SP 800-218). National Institute of Standards and
Technology. https://doi.org/10.6028/NIST.SP.800-218

Supply-chain Levels for Software Artifacts. (2025). *SLSA specification
(version 1.2)*. https://slsa.dev/spec/v1.2/

Supply-chain Levels for Software Artifacts. (2025). *Source: Requirements for
producing source (version 1.2)*.
https://slsa.dev/spec/v1.2/source-requirements
Loading
Loading