diff --git a/.github/workflows/strix.yml b/.github/workflows/strix.yml index f15b29f564..5539d4a247 100644 --- a/.github/workflows/strix.yml +++ b/.github/workflows/strix.yml @@ -543,8 +543,8 @@ jobs: EVENT_REPOSITORY_VISIBILITY: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.repo.visibility || github.event_name != 'repository_dispatch' && github.event.repository.visibility || '' }} run: | set -euo pipefail - if [[ ! "$TARGET_REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]]; then - echo "::error::Strix target repository must belong to ContextualWisdomLab." + if [[ ! "$TARGET_REPOSITORY" =~ ^(ContextualWisdomLab/[A-Za-z0-9_.-]+|HYOSUNG-ITX-AI-Business-Department/llm-gateway-console(-design)?)$ ]]; then + echo "::error::Strix target repository is outside the approved consumer scope." exit 1 fi case "$EVENT_REPOSITORY_VISIBILITY" in @@ -617,7 +617,7 @@ jobs: SUPPLIED_HEAD_SHA: ${{ github.event.client_payload.pr_head_sha }} run: | set -euo pipefail - if ! [[ "$REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]] || + if ! [[ "$REPOSITORY" =~ ^(ContextualWisdomLab/[A-Za-z0-9_.-]+|HYOSUNG-ITX-AI-Business-Department/llm-gateway-console(-design)?)$ ]] || ! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] || ! [[ "$SUPPLIED_BASE_SHA" =~ ^[0-9a-fA-F]{40}$ ]] || ! [[ "$SUPPLIED_HEAD_SHA" =~ ^[0-9a-fA-F]{40}$ ]] || diff --git a/docs/doctoring/hyosung-strix-consumer-admission.md b/docs/doctoring/hyosung-strix-consumer-admission.md new file mode 100644 index 0000000000..138d6bbaf8 --- /dev/null +++ b/docs/doctoring/hyosung-strix-consumer-admission.md @@ -0,0 +1,50 @@ +# Hyosung Strix consumer admission + +Status: Proposed; no runtime authorization or successful cross-organization scan. + +The MLLO consumer `HYOSUNG-ITX-AI-Business-Department/llm-gateway-console` +currently uses a local review workflow whose GitHub Models request returned +HTTP 410 (`github_models_retirement_brownout`, run 34690093150, job +103543712323). The central main Strix workflow already selects +`contextual-orchestrator/orchestrator/free`, but its visibility and dispatch +metadata checks reject the Hyosung repository before a governed scan can run. + +This change adds exactly the console repository and its UI owner +`HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-design` to both existing +checks. The design owner supplies the MLLO navigation surface; reviewing its +change is required for the key-management UI integration. Other Hyosung +repositories and similarly prefixed names remain rejected. The shared review admission controller is not on +this workflow's direct path and is unchanged. No credentials, installation +permissions, provider routes, review verdicts or branch rules are changed. +Existing live PR base/head comparison, private-target handling and separated +status credentials remain mandatory. An allowlisted name is not proof of access. + +The extracted workflow regexes failed both regression cases before the change. +After the change, 97 focused tests and one subtest passed, including repository +visibility, orchestrator, queue and documentation-only admission contracts; +actionlint passed. These tests do not prove target App installation, cross-org +read/status permissions, private-target ZDR or a valid current-head scan. + +Before adoption, independently review and merge the owner change, establish the +existing scoped credential's target access without exposing its value, and run +one exact-revision dispatch. Require matching source/base/head and authoritative +review evidence before replacing the consumer's local workflow. Do not broaden +an App installation, copy central source, suppress failed checks or treat a +successful dispatch response as completed review. If access is unavailable, +retain the failed/incomplete integration state and repair the owner capability. +Rollback removes this exact consumer alternative from both checks; it does not +revoke or alter any credential. No dispatch has been sent by this change. + +## Design-owner extension + +Both extracted shell admission expressions rejected the exact design-owner +repository before this extension (two RED cases). The extension admits only the +optional literal `-design` suffix, retaining anchored owner/name matching. +Tests reject extra suffixes, paths, trailing newlines, and another owner. + +OpenCode remains a separate integration gap: the current dispatch workflow +rejects non-ContextualWisdomLab targets at its metadata guard, and the required +caller has the same organization restriction. The dispatch-target inventory also +lacks both Hyosung consumers. Strix admission does not repair those boundaries +or establish App installation/read/status authority; no OpenCode adoption or +cross-organization scan is claimed by this change. diff --git a/tests/test_strix_hyosung_repository_admission.py b/tests/test_strix_hyosung_repository_admission.py new file mode 100644 index 0000000000..77285b3bd8 --- /dev/null +++ b/tests/test_strix_hyosung_repository_admission.py @@ -0,0 +1,36 @@ +"""The two Strix repository checks admit only the scoped Hyosung consumer.""" + +import os +from pathlib import Path +import re +import subprocess + +import pytest + + +@pytest.mark.parametrize('variable', ['TARGET_REPOSITORY', 'REPOSITORY']) +def test_strix_repository_boundary(variable): + """Execute each workflow regex against legitimate and out-of-scope names.""" + workflow = Path('.github/workflows/strix.yml').read_text() + patterns = [pattern for pattern in re.findall(r'"\$' + variable + r'" =~ (\^[^ ]+)', workflow) + if 'ContextualWisdomLab' in pattern] + assert len(patterns) == 1 + for repository, accepted in ( + ('ContextualWisdomLab/.github', True), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console', True), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-design', True), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-design-extra', False), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-design/extra', False), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-design\n', False), + ('other/llm-gateway-console-design', False), + ('HYOSUNG-ITX-AI-Business-Department/another-service', False), + ('other/llm-gateway-console', False), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console-extra', False), + ('HYOSUNG-ITX-AI-Business-Department/llm-gateway-console\n', False), + ): + result = subprocess.run( + ['bash', '-c', '[[ "$REPOSITORY" =~ ' + patterns[0] + ' ]]'], + env=dict(os.environ, REPOSITORY=repository), capture_output=True, + text=True, timeout=5, + ) + assert (result.returncode == 0) == accepted, repository