Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ec89c6f
fix(noema): bind central handoff to live PR base identity
seonghobae Sep 12, 2026
f993700
merge(main): resolve #2111 conflicts; keep noema live-base handoff
seonghobae Sep 18, 2026
a83d6d3
fix(security): allowlist https://api.github.com before urllib urlopen
seonghobae Sep 18, 2026
225260a
test(security): pin GitHub API redirect credential boundary
seonghobae Sep 18, 2026
0ae2204
fix(security): contain GitHub API redirects to admitted origin
seonghobae Sep 18, 2026
062663a
test(security): pin Strix redirect credential boundary
seonghobae Sep 18, 2026
2708a6b
fix(security): contain Strix GitHub API redirects
seonghobae Sep 18, 2026
3758b89
chore(deps): bump anyio from 4.14.0 to 4.14.2
dependabot[bot] Sep 18, 2026
4dcd25c
test(security): align Strix transport seam with dedicated opener
seonghobae Sep 19, 2026
834d285
test(security): bind authenticated openers at owned seams
seonghobae Sep 19, 2026
6d10002
merge(security): carry #2269 urllib GitHub API opener into #2278
seonghobae Sep 19, 2026
545648e
chore(deps): isolate AnyIO security owner delta
seonghobae Sep 19, 2026
c51c8d2
merge: carry AnyIO lock update onto protected owner
seonghobae Sep 19, 2026
e43a75b
fix(opencode): materialize every coverage lock input
seonghobae Sep 19, 2026
c4a73a1
docs(gap): bind coverage repair to canonical PR
seonghobae Sep 19, 2026
513302a
test(strix): bind evidence helper to trusted source root
seonghobae Sep 19, 2026
c08b13d
fix(strix): resolve evidence binder from trusted source
seonghobae Sep 19, 2026
ca7e1e7
test(strix): materialize trusted binder fixtures
seonghobae Sep 19, 2026
db1fd61
fix(strix): restore complete verified fixture tree
seonghobae Sep 19, 2026
fb9c0e2
test(strix): require consumer-free trusted binder fixture
seonghobae Sep 19, 2026
78b33a8
repair(strix): restore executable harness after binary blob corruption
seonghobae Sep 19, 2026
191bd63
test(strix): require binder-free consumer fixture
seonghobae Sep 19, 2026
ef1a866
test(strix): separate trusted gate from consumer root
seonghobae Sep 19, 2026
abc9a7d
docs(strix): bind consumer isolation evidence to exact commits
seonghobae Sep 19, 2026
00082e8
docs(strix): describe separated trusted runtime fixture
seonghobae Sep 19, 2026
782d67b
test(strix): retain canonical gate source under scan
seonghobae Sep 20, 2026
8a5251b
fix(deps): restore AnyIO owner isolation
seonghobae Sep 20, 2026
a8d6261
test(strix): red specialized fixture owner boundary
seonghobae Sep 20, 2026
bbe225d
test(strix): materialize specialized fixtures' trusted runtime outsid…
Sep 21, 2026
1794626
test(strix): pin trusted evidence-binder path
seonghobae Sep 21, 2026
657d104
repair(codeql): restore exact endpoint-set assertion
seonghobae Sep 23, 2026
f1a8dc8
chore(foundation): converge dependency and CodeQL repairs
seonghobae Sep 23, 2026
42e4198
fix(opencode): adopt AnyIO security prerequisite
seonghobae Sep 24, 2026
38cfcae
fix(test-gate): restore full branch coverage
seonghobae Sep 24, 2026
21247ef
test(queue-health): scope permission assertion to workflow token
seonghobae Sep 24, 2026
57c168b
test(queue-health): isolate collector edge cases
seonghobae Sep 24, 2026
f229816
repair(foundation): converge CodeQL endpoint contract into coverage o…
seonghobae Sep 24, 2026
3b3ce16
fix(security): update AnyIO lock for audit gate
seonghobae Sep 25, 2026
14fe2b6
fix(codeql): unblock CodeQL scan dispatch for all .github PRs
seonghobae Sep 26, 2026
950ab88
repair(foundation): converge coverage, dependency, and CodeQL owners
seonghobae Sep 26, 2026
8e1aba9
fix(ci): bind AnyIO security pin to Strix input
seonghobae Sep 26, 2026
361a9eb
merge: adopt current CI owner and repair CodeQL URL oracle
seonghobae Sep 26, 2026
1fd22f4
test(strix): require Job Analysis authority context
seonghobae Sep 26, 2026
808a8a7
fix(strix): include Job Analysis authority context
seonghobae Sep 26, 2026
b90d873
docs(strix): record Job Analysis authority context
seonghobae Sep 26, 2026
125d488
merge(owner): restack Noema handoff on current security stack
seonghobae Sep 26, 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
47 changes: 46 additions & 1 deletion .github/workflows/codeql-scan-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,56 @@ jobs:
id: gate
run: python3 "$RUNNER_TEMP/codeql_sarif_gate.py" codeql-results-dispatch

- name: Select target CodeQL analysis-read credential
id: ghas_analysis_token
if: steps.gate.outcome == 'success'
env:
TARGET_REPOSITORY: ${{ needs.validate-dispatch.outputs.target_repository }}
TARGET_APP_TOKEN: ${{ steps.target_app_token.outputs.token || '' }}
PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || '' }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || '' }}
WORKFLOW_TOKEN: ${{ github.token }}
run: |
set -euo pipefail

probe_analysis_read() {
token_label="$1"
token="$2"
if [ -z "$token" ]; then
return 1
fi
if GH_TOKEN="$token" gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"repos/${TARGET_REPOSITORY}/code-scanning/analyses?per_page=1&tool_name=CodeQL" \
>/dev/null 2>&1; then
echo "::add-mask::$token"
{
printf 'token=%s\n' "$token"
printf 'source=%s\n' "$token_label"
} >>"$GITHUB_OUTPUT"
echo "Selected ${token_label} after proving target CodeQL analysis-read access."
return 0
fi
echo "::notice::${token_label} cannot read target CodeQL analyses; trying the next configured credential."
return 1
}

if probe_analysis_read "target-app-token" "$TARGET_APP_TOKEN" ||
probe_analysis_read "pr-review-merge-token" "$PR_REVIEW_MERGE_TOKEN" ||
probe_analysis_read "opencode-approve-token" "$OPENCODE_APPROVE_TOKEN" ||
probe_analysis_read "github-token" "$WORKFLOW_TOKEN"; then
exit 0
fi

echo "::error::no configured credential can read target CodeQL analyses; GHAS configuration identity cannot be proven."
exit 1

- name: Verify GHAS base/head CodeQL configuration identity
id: ghas_configuration_identity
if: steps.gate.outcome == 'success'
env:
GH_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
GH_TOKEN: ${{ steps.ghas_analysis_token.outputs.token }}
TARGET_REPOSITORY: ${{ needs.validate-dispatch.outputs.target_repository }}
PR_NUMBER: ${{ needs.validate-dispatch.outputs.pr_number }}
BASE_REF: ${{ needs.validate-dispatch.outputs.base_ref }}
Expand Down
48 changes: 45 additions & 3 deletions .github/workflows/noema-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,41 @@ jobs:
TARGET_REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.event.client_payload.target_repository || github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.client_payload.pr_number || '' }}
EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.client_payload.pr_head_sha || '' }}
EXPECTED_BASE_REF: ${{ github.event.pull_request.base.ref || github.event.client_payload.pr_base_ref || '' }}
LEGACY_BASE_REF: ${{ github.event.client_payload.base_branch || '' }}
EXPECTED_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.client_payload.pr_base_sha || '' }}
steps:
- name: Admit only the exact live Noema head
id: live_head
run: |
set -euo pipefail
echo "admitted=false" >>"$GITHUB_OUTPUT"
resolved_base_ref="${EXPECTED_BASE_REF:-${LEGACY_BASE_REF:-}}"
if [ -n "${EXPECTED_BASE_REF:-}" ] && [ -n "${LEGACY_BASE_REF:-}" ] &&
[ "$EXPECTED_BASE_REF" != "$LEGACY_BASE_REF" ]; then
echo "::error::Noema admission rejected conflicting base references."
exit 1
fi
if ! [[ "$TARGET_REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]] ||
! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] ||
! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]; then
! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] ||
! [[ "${EXPECTED_BASE_SHA:-}" =~ ^[0-9a-f]{40}$ ]] ||
[ -z "$resolved_base_ref" ] ||
! git check-ref-format "refs/heads/$resolved_base_ref" >/dev/null; then
echo "::error::Noema admission rejected malformed pull request metadata."
exit 1
fi
live_pr="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"
live_head="$(jq -r '.head.sha // empty' <<<"$live_pr")"
live_state="$(jq -r '.state // empty' <<<"$live_pr")"
if ! jq -e --arg target "$TARGET_REPOSITORY" --argjson number "$PR_NUMBER" \
--arg ref "$resolved_base_ref" --arg sha "$EXPECTED_BASE_SHA" '
.number == $number and .base.repo.full_name == $target
and .base.ref == $ref and .base.sha == $sha
' <<<"$live_pr" >/dev/null; then
echo "::error::Noema admission rejected missing or mismatched live base identity."
exit 1
fi
if [ "${live_head,,}" != "${EXPECTED_HEAD_SHA,,}" ] || [ "$live_state" != "open" ]; then
echo "::notice::Noema admission retired a stale trigger before review queue entry."
exit 0
Expand Down Expand Up @@ -373,6 +393,9 @@ jobs:
# diff.
PR_NUMBER: ${{ (needs.changed-scope.outputs.code != 'false' && (github.event.pull_request.number || github.event.client_payload.pr_number)) || '' }}
EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.client_payload.pr_head_sha || '' }}
EXPECTED_BASE_REF: ${{ github.event.pull_request.base.ref || github.event.client_payload.pr_base_ref || '' }}
LEGACY_BASE_REF: ${{ github.event.client_payload.base_branch || '' }}
EXPECTED_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.client_payload.pr_base_sha || '' }}
steps:
- name: Skip events without pull request context
if: env.PR_NUMBER == ''
Expand Down Expand Up @@ -663,11 +686,30 @@ jobs:
GH_TOKEN: ${{ secrets.NOEMA_REVIEW_TOKEN || steps.noema_github_app_token.outputs.token || steps.noema_oidc_token.outputs.token }}
run: |
set -euo pipefail
if ! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "::error::Noema expected head must be a full commit SHA."
resolved_base_ref="${EXPECTED_BASE_REF:-${LEGACY_BASE_REF:-}}"
if [ -n "${EXPECTED_BASE_REF:-}" ] && [ -n "${LEGACY_BASE_REF:-}" ] &&
[ "$EXPECTED_BASE_REF" != "$LEGACY_BASE_REF" ]; then
echo "::error::Noema review rejected conflicting base references."
exit 1
fi
if ! [[ "$TARGET_REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]] ||
! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] ||
! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] ||
! [[ "${EXPECTED_BASE_SHA:-}" =~ ^[0-9a-f]{40}$ ]] ||
[ -z "$resolved_base_ref" ] ||
! git check-ref-format "refs/heads/$resolved_base_ref" >/dev/null; then
echo "::error::Noema review rejected malformed pull request metadata."
exit 1
fi
pull_request_json="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"
if ! jq -e --arg target "$TARGET_REPOSITORY" --argjson number "$PR_NUMBER" \
--arg ref "$resolved_base_ref" --arg sha "$EXPECTED_BASE_SHA" '
.number == $number and .base.repo.full_name == $target
and .base.ref == $ref and .base.sha == $sha
' <<<"$pull_request_json" >/dev/null; then
echo "::error::Noema review rejected missing or mismatched live base identity."
exit 1
fi
live_state="$(jq -r '.state // empty' <<<"$pull_request_json")"
live_head_sha="$(jq -r '.head.sha // empty' <<<"$pull_request_json")"
if [ "$live_state" != "open" ] || [ "${live_head_sha,,}" != "${EXPECTED_HEAD_SHA,,}" ]; then
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/opencode-review-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -632,12 +632,17 @@ jobs:
coverage_tool_image="opencode-coverage-tools:${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
coverage_build_dir="${RUNNER_TEMP}/opencode-coverage-tool-build"
trusted_ci_requirements="${GITHUB_WORKSPACE}/requirements-opencode-review-ci-hashes.txt"
trusted_noema_document_requirements="${GITHUB_WORKSPACE}/requirements-noema-document-ci-hashes.txt"
trusted_base_python_installer="${GITHUB_WORKSPACE}/scripts/ci/install_base_python_locks.py"
trusted_vcs_import_root_resolver="${GITHUB_WORKSPACE}/scripts/ci/resolve_opencode_base_vcs_import_root.sh"
if [ ! -f "$trusted_ci_requirements" ] || [ -L "$trusted_ci_requirements" ]; then
echo "::error::Trusted coverage requirements must be a regular non-symlink file."
exit 1
fi
if [ ! -f "$trusted_noema_document_requirements" ] || [ -L "$trusted_noema_document_requirements" ]; then
echo "::error::Trusted Noema document requirements must be a regular non-symlink file."
exit 1
fi
if [ ! -f "$trusted_base_python_installer" ] || [ -L "$trusted_base_python_installer" ]; then
echo "::error::Trusted base Python lock installer must be a regular non-symlink file."
exit 1
Expand All @@ -651,6 +656,8 @@ jobs:
chmod 0700 "$coverage_build_dir"
install -m 0644 "$trusted_ci_requirements" \
"$coverage_build_dir/requirements-opencode-review-ci-hashes.txt"
install -m 0644 "$trusted_noema_document_requirements" \
"$coverage_build_dir/requirements-noema-document-ci-hashes.txt"
install -m 0755 "$trusted_base_python_installer" \
"$coverage_build_dir/install-base-python-locks.py"
install -m 0755 "$trusted_vcs_import_root_resolver" \
Expand Down Expand Up @@ -7731,20 +7738,24 @@ jobs:
GH_REPOSITORY: ${{ needs.validate-pr-metadata.outputs.target_repository }}
PR_NUMBER: ${{ needs.validate-pr-metadata.outputs.pr_number }}
PR_HEAD_SHA: ${{ needs.validate-pr-metadata.outputs.head_sha }}
PR_BASE_REF: ${{ needs.validate-pr-metadata.outputs.base_ref }}
PR_BASE_SHA: ${{ needs.validate-pr-metadata.outputs.base_sha }}
OPENCODE_CHANGED_FILES_FILE: ${{ runner.temp }}/opencode-changed-files.txt
OPENCODE_ARTIFACT_MANIFEST_SHA256: ${{ steps.seal_artifacts.outputs.manifest_sha256 }}
OPENCODE_SOURCE_WORKDIR: ${{ runner.temp }}/opencode-pr-head
OPENCODE_REQUIRE_ADVERSARIAL_VALIDATION: "true"
run: |
set -euo pipefail
if [ -z "${GH_TOKEN:-}" ]; then
echo "::warning::Noema handoff skipped because no target-repository dispatch credential was available."
echo "::warning::Noema handoff skipped because no central dispatch credential was available."
exit 1
fi
python3 scripts/ci/noema_review_handoff.py \
--repo "$GH_REPOSITORY" \
--pr-number "$PR_NUMBER" \
--head-sha "$PR_HEAD_SHA" \
--base-ref "$PR_BASE_REF" \
--base-sha "$PR_BASE_SHA" \
--attempts 90 \
--interval-seconds 10

Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ The materialization contract is also covered by [`docs/doctoring/exact-artifact-

## Verification discipline

- Noema handoff는 중앙 `repository_dispatch` 수신 위치와 target PR의 base ref/SHA·head를 함께 검증한다. `pr_base_ref`와 기존 `base_branch`가 함께 있으면 일치해야 하며, admission 이후 모델 실행 직전에도 live base를 다시 확인한다. HTTP 204는 리뷰 완료 증거가 아니다. 재현과 한계는 [handoff runbook](docs/doctoring/noema-central-handoff-base-binding.md)을 따른다.

- producer가 안전한 로그 필드를 추가하면 exact revision 쌍으로 consumer sanitizer를 통과시켜 allowlist의 누락을 확인한다. producer 단위 테스트 성공만으로 CI artifact 보존을 주장하지 않으며, 연결 검증에서도 raw 본문 비출력을 유지한다.

Many agent sessions work this organization concurrently under the same standing
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.d/20260920-strix-trusted-binder-runtime-fixture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### Strix keeps trusted evidence binding outside consumer workspaces

- The Strix gate resolves its evidence binder beside the trusted gate source.
The executable core harness now materializes that trusted runtime under a
separate source directory, passes a binder-free consumer workspace through
`STRIX_REPO_ROOT`, and invokes the trusted gate by its absolute path.
- OpenCode coverage assertions follow the consolidated
`validate-pr-metadata` owner instead of the removed
`coverage-source-tree` job and failure-report step.
- The commercial-readiness receipt contract now compares the complete parsed
harden-runner endpoint set instead of treating an expected hostname as a URL
substring. This closes the exact CodeQL
`py/incomplete-url-substring-sanitization` finding without suppressing it or
widening egress.
- The branch adopts the current central dependency owner, including the
explicit AnyIO 4.14.2 source-to-hash pin required by the Python security
gate.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
### Strix supplies bounded Job Analysis authority context from the trusted base

- Orgmetra #63 changes `packages/hris-kernel/src/orgmetra_hris_kernel/job_analysis.py`, but the Strix scan workspace previously omitted the unchanged authorization, HTTP, snapshot, and persistence collaborators that establish its resource-ownership boundary. That incomplete context produced a false HIGH IDOR finding even though the product reconstructs owner scope and authorizes resource fields before port access. A source-first executable fixture now requires the changed PR-head module, exactly five unchanged Job Analysis authority files from the authenticated trusted base, and exclusion of an unrelated administration file. RED `1fd22f4e` failed because `auth.py` was absent; the gate now recognizes only the normalized Job Analysis trigger and adds the five fixed context paths through the existing trusted-base materialization boundary. No consumer source, provider/model policy, severity gate, timeout, or write authority changes.

### OpenCode coverage image materializes every Dockerfile lock input

- Required OpenCode run `35370902053` for `.github#2266@12621f75e` failed before executing PR code because its trusted Dockerfile copied `requirements-noema-document-ci-hashes.txt` while the isolated build context contained only the OpenCode lockfile. The coverage owner now validates both lockfiles as regular non-symlink files and copies both into the trusted build context before the networked image build. `tests/test_opencode_agent_contract.py` pins the complete input boundary. Hosted exact-head acceptance remains Proposed until the new run reaches the image-build and coverage steps.

### Noema transport capacity schedules a bounded continuation re-dispatch

- After gateway failover, HTTP 429/5xx no longer end only as a permanent required-check failure with `caller attempts=1`. ADR-0031 classifies that class as `provider_capacity_unavailable`, keeps the single gateway request per job, surfaces `provider_attempt_count` from the orchestrator error envelope, and authorizes at most two same-head `repository_dispatch` retries after a capped `Retry-After` or deterministic 60–180 s jitter. Review is never skipped. Refs #2165.
Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ repeatable compile command.

## Conventions and gotchas specific to this repo

- Noema handoff의 중앙 수신 위치와 target PR base/head를 함께 확인한다. 기존 `base_branch` 호환성을 유지하되 `pr_base_ref`와 충돌하면 거절한다. Dispatch 접수는 완료가 아니며, [handoff runbook](docs/doctoring/noema-central-handoff-base-binding.md)의 실제 shell 회귀와 exact-head 리뷰 검증을 유지한다.

- **Contract tests pin workflows AND prose.** `tests/` asserts exact strings and structure of
`PR_GOVERNANCE_AUDIT.md`, `docs/org-required-workflow-rollout.md`, `opencode.jsonc`, and several
workflow files (e.g. `test_pr_governance_audit_contract.py`, `test_codeql_pr_workflow_contract.py`,
Expand Down
Loading
Loading