Skip to content

post-merge Strix 보안 경로 강화 - #209

Closed
seonghobae wants to merge 7 commits into
masterfrom
fix/postmerge-strix-security-20260522
Closed

post-merge Strix 보안 경로 강화#209
seonghobae wants to merge 7 commits into
masterfrom
fix/postmerge-strix-security-20260522

Conversation

@seonghobae

@seonghobae seonghobae commented May 22, 2026

Copy link
Copy Markdown
Contributor

No linked issue.

목적

PR #202 병합 이후 master의 Strix 보안 검사 실패를 후속 보완합니다.

주요 변경

  • LLM draft에서 사용자 지시문과 이메일 본문을 system prompt 밖으로 분리하고 JSON으로 직렬화했습니다.
  • 브라우저 API 클라이언트는 Web Storage token/bearer Authorization 대신 HttpOnly naruon_session_token cookie + credentials: include를 사용합니다.
  • 브라우저 요청에서 public identity header 및 caller Authorization header를 제거합니다.
  • Cookie 인증 unsafe method는 Origin/RefererALLOWED_BROWSER_ORIGINS와 일치해야 하며, production은 localhost/loopback allowlist를 거부합니다.
  • 비브라우저 클라이언트용 bearer session 경로는 유지했습니다.
  • /api/auth/context를 추가해 frontend가 header spoofing 없이 현재 user context를 조회합니다.
  • 최종 Docker image에서 gcc/libpq-dev 설치를 제거하고 Dockerfile regression을 추가했습니다.
  • AGENTS, ARCHITECTURE, README, auth key management, CHANGELOG 문서를 갱신했습니다.

검증

  • Red-green regressions: CSRF origin gate, prompt JSON boundary, Dockerfile package install guard.
  • uvx black --check backend/api/auth.py backend/core/config.py backend/main.py backend/services/llm_service.py backend/tests/test_auth_real.py backend/tests/test_llm_service.py backend/tests/test_dockerfile_security.py && uvx ruff check ... passed.
  • DISABLE_BACKGROUND_WORKERS=1 uv run pytest backend/tests/test_llm_service.py backend/tests/test_dockerfile_security.py backend/tests/test_auth_real.py backend/tests/test_llm_api.py → 60 passed.
  • npm test -- src/lib/api-client.test.ts src/app/tasks/page.test.tsx src/components/EmailDetail.test.tsx && npm run lint -- src/lib/api-client.ts src/lib/api-client.test.ts src/app/tasks/page.test.tsx src/components/EmailDetail.test.tsx src/app/settings/page.tsx && npm run typecheck passed.
  • docker build --platform linux/amd64 -t naruon-backend:security-check-amd64 -f Dockerfile . && docker run --rm naruon-backend:security-check-amd64 sh -c '! command -v gcc && ! dpkg -s libpq-dev >/dev/null 2>&1' passed.
  • git diff --check passed.
  • Review subagent final blocker re-check: resolved, no remaining blocker.

참고

Failed post-merge Strix run: https://github.com/Seongho-Bae/naruon/actions/runs/26262389253

Summary by CodeRabbit

  • New Features

    • Session-based authentication via HttpOnly cookies and a new auth-context endpoint
    • Full Settings page with tabbed sections, provider/runner management, and constrained scroll container
  • Security

    • CSRF origin checks for browser writes; stronger encryption key validation
    • SMTP egress defaults to deny-by-default and requires explicit allowlisting
  • Improvements

    • Default LLM routing adjusted for reliability
    • Docker image no longer installs unnecessary build dependencies
  • UI

    • Tasks and Settings UI tests and accessibility/scroll fixes included

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Failed to post review comments

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key: "version"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

This PR hardens security and governance across the app: HttpOnly cookie-based sessions with CSRF origin checks, stricter Fernet ENCRYPTION_KEY validation, deny-by-default SMTP egress checks, frontend ApiClient using credentials: include and dropping stored Authorization, safer LLM draft payloads, Strix CI routing to GitHub Models with threshold/fallback fail-closed behavior, tests, and documentation updates.

Changes

Security & Governance Hardening

Layer / File(s) Summary
Configuration & Encryption Key Validation
.env.example, backend/core/config.py, backend/db/models.py, backend/tests/test_config.py, backend/tests/test_tenant_config_model.py
ENCRYPTION_KEY validation added (Fernet-format, length, uniqueness, per-byte entropy, weak-key rejection). ALLOWED_SMTP_HOSTS defaults to a deny-all marker and ALLOWED_SMTP_PORTS are validated. allowed_browser_origins normalization added; Settings model now validates on finalize. get_fernet() validates key before constructing Fernet. .env.example documents key generation.
Browser Session Auth & CSRF Enforcement
backend/api/auth.py, backend/main.py, backend/tests/test_auth_real.py
get_auth_context accepts Request, Authorization header, and naruon_session_token cookie; enforces Origin/Referer against ALLOWED_BROWSER_ORIGINS for cookie-based unsafe methods; introduces _extract_session_token, refactors signed-session verification, adds AuthContextResponse and GET /api/auth/context. CORS now derives allow_origins from settings. Tests cover cookie auth and origin rules.
Frontend API Client & Cookie Credentials
frontend/src/lib/api-client.ts, frontend/src/lib/api-client.test.ts, frontend/src/app/tasks/page.test.tsx, frontend/src/components/EmailDetail.test.tsx
ApiClient no longer derives Authorization from stored tokens and always includes credentials: 'include'. getSessionToken()/getCurrentUserId() return null. Tests updated to seed legacy localStorage tokens separately and assert requests use credentials: include and omit Authorization and identity headers.
Settings Page Auth Context & Layout
frontend/src/app/settings/page.tsx, frontend/src/app/settings/page.test.tsx
SettingsPage rewritten to fetch /api/auth/context, gate personal config load on auth, add AccountField wrapper for SMTP/IMAP inputs, include data-testid hooks and scroll containment inside DashboardLayout. Tests validate rendering and scroll containment.
SMTP Egress & LLM Prompt Handling
backend/services/email_client.py, backend/services/llm_service.py, backend/tests/test_llm_service.py
Email client filters deny-all marker from allowlist parsing. draft_reply tightened: system prompt clarified to treat inputs as untrusted and avoid hidden-prompt disclosure; user message now JSON-encodes {drafting_instruction,email_body}. Tests verify system/user message separation and JSON serialization of untrusted inputs.
Strix CI Gate – GitHub Models & Error Handling
.github/workflows/strix.yml, scripts/ci/strix_quick_gate.sh
Default Strix LLM provider set to GitHub Models (github/gpt-5.4 family) when unset; gate secret checks adjusted to enable/disable behavior; THRESHOLD_FINDING_DETECTED flag added to track threshold findings and enforce fail-closed on fallback success; GitHub-specific fallback model handling and GitHub API key propagation to child process when using github/* routes; classification of Gemini/GitHub BadRequest as model-route errors to enable fallback retries; PR-scan retry/batch tightened for pull_request_target.
Strix Gate Testing – GitHub & Gemini Scenarios
scripts/ci/test_strix_quick_gate.sh
Test harness extended to validate GitHub Models defaults, ensure GitHub API key forwarding to child only, add fake scenarios for GitHub route errors and Gemini BadRequest/threshold variants, and cover PR budget/timeouts and fallback-blocking cases.
Documentation & Governance Updates
AGENTS.md, ARCHITECTURE.md, CHANGELOG.md, README.md, backend/README.md, docs/operations/auth-key-management.md, docs/operations/email-relay-proxy-boundary.md, docs/plans/2026-05-26-branding-settings-source-gap-roadmap.md
Docs updated to require HttpOnly naruon_session_token cookie with credentials: include, strip caller identity headers and forbid localStorage/sessionStorage session tokens, enforce ALLOWED_BROWSER_ORIGINS for cookie writes, document SMTP deny-by-default and DNS/routability checks, strengthen ENCRYPTION_KEY requirements, and describe Strix GitHub Models routing and threshold rules. New roadmap added for branding/settings.
Infrastructure & Cleanup
.gitignore, Dockerfile, backend/tests/test_dockerfile_security.py
.gitignore cleaned and duplicate entry removed; Dockerfile removed build deps (gcc,libpq-dev); new test asserts final Dockerfile does not install build-time dependencies. Numerous formatting-only changes across many files and tests are included.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code to lock the gate,
Cookies tucked away, Origin checks great,
Fernet keys must sparkle, never weak,
SMTP doors closed until hosts we seek,
Models routed tidy, tests sing—secure and sleek!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/postmerge-strix-security-20260522

@github-actions

github-actions Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for 5b08f2790b4bb84e08cef19ca47bc418f7a4cecd:

@seonghobae

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Superseded: Strix security hardening already landed on master and is included in #214.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
backend/core/config.py (1)

109-118: ⚡ Quick win

Consider blocking IPv4/IPv6 loopback addresses in SMTP host validation.

The validation blocks localhost and localhost.localdomain but allows loopback IP addresses like 127.0.0.1 or ::1. This could allow SSRF to local SMTP services.

🛡️ Proposed fix to block loopback IPs
+from ipaddress import ip_address as parse_ip_address
+
+def _is_loopback_address(host: str) -> bool:
+    try:
+        return parse_ip_address(host).is_loopback
+    except ValueError:
+        return False
+
 def validate_allowed_smtp_hosts_value(value: str) -> None:
     # ... existing code ...
     for host_value in host_values:
         if (
             "*" in host_value
             or "://" in host_value
             or any(character in host_value for character in " \t\r\n/")
             or host_value in {"localhost", "localhost.localdomain"}
+            or _is_loopback_address(host_value)
         ):
             raise ValueError(
                 "ALLOWED_SMTP_HOSTS must contain only explicit relay hostnames or public IPs"
             )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/core/config.py` around lines 109 - 118, The loop that validates
ALLOWED_SMTP_HOSTS (iterate over host_values) currently blocks names like
"localhost" but still permits loopback IPs (e.g., 127.0.0.1, ::1); update the
validation inside the for host_value in host_values loop to detect and reject
loopback IP addresses by attempting to parse host_value with the ipaddress
module (ipaddress.ip_address) and, if parsing succeeds and address.is_loopback
is True, raise the same ValueError; preserve existing checks for wildcards,
schemes, whitespace and literal hostnames by only applying the ipaddress check
for parseable IPs and catching ipaddress.AddressValueError for non-IP hostnames.
backend/tests/test_dockerfile_security.py (1)

11-14: ⚡ Quick win

Consider adding an assertion message for clearer test failures.

The assertion would be more debuggable with a custom error message indicating which package was found.

💬 Proposed enhancement
     for package_name in ("gcc", "libpq-dev"):
         assert not re.search(
             rf"\bapt-get\s+install\b[^;&\n]*\b{re.escape(package_name)}\b",
             normalized_dockerfile,
-        )
+        ), f"Found '{package_name}' in Dockerfile apt-get install command"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/test_dockerfile_security.py` around lines 11 - 14, The test's
negative assertion lacks a helpful failure message; modify the assertion around
re.search(...) so it reports which package was found and where by capturing the
search result (e.g., using a variable like match = re.search(...,
normalized_dockerfile)) and then asserting match is None with a message that
includes package_name and match.group(0) or normalized_dockerfile snippet;
update the assertion in backend/tests/test_dockerfile_security.py that currently
references package_name and normalized_dockerfile to provide this informative
message.
scripts/ci/test_strix_quick_gate.sh (2)

224-231: ⚡ Quick win

Strengthen the GitHub child-env leak check.

This only proves GITHUB_API_KEY is present in the GitHub Models path. A regression that also forwards LLM_API_KEY or other parent-step secrets on that branch would still pass. Please log/assert the generic key path stays unset here too, since the existing runtime-env-forwarding case does not exercise the GitHub-specific env wiring.

Also applies to: 2112-2117

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/test_strix_quick_gate.sh` around lines 224 - 231, The current leak
check only logs GITHUB_API_KEY; extend it to also log and assert the generic
parent-step secret variables (e.g., LLM_API_KEY and any other upstream secret
names used in the pipeline) into the same FAKE_STRIX_RUNTIME_ENV_LOG so
regressions that forward parent-step secrets are caught; update the print/append
block that references GITHUB_API_KEY and FAKE_STRIX_RUNTIME_ENV_LOG to include
LLM_API_KEY (and any other relevant parent secrets) with the same
"${VAR:-<unset>}" pattern and add an assertion in the test script after writing
the log to fail if those generic secret entries are set, mirroring the existing
check for runtime-env-forwarding.

4551-4595: ⚡ Quick win

Isolate the Gemini fallback source in the new BadRequest cases.

These cases pass the same fallback list through fallback_models, which also populates STRIX_VERTEX_FALLBACK_MODELS. If the gate accidentally consults the Vertex fallback list for Gemini BadRequest handling, these tests would still go green. Mirror the GitHub-specific setup here by unsetting Vertex/generic fallbacks and setting only STRIX_GEMINI_FALLBACK_MODELS.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/test_strix_quick_gate.sh` around lines 4551 - 4595, The new Gemini
BadRequest test cases reuse the generic fallback list via the fallback_models
argument which also populates STRIX_VERTEX_FALLBACK_MODELS—masking whether
Gemini-specific fallback logic is used; update the four run_gate_case
invocations ("gemini-primary-badrequest-fallback-success",
"gemini-badrequest-low-report-reaches-fallback",
"gemini-badrequest-threshold-report-blocks-fallback-success",
"gemini-badrequest-inline-threshold-blocks-fallback-success") to unset or clear
STRIX_VERTEX_FALLBACK_MODELS before running and instead set
STRIX_GEMINI_FALLBACK_MODELS to the intended fallback string (e.g.,
"gemini/fallback-one gemini/fallback-two"), or change the call so it passes an
explicit STRIX_GEMINI_FALLBACK_MODELS env value rather than using
fallback_models; ensure fallback_models is not used to populate
STRIX_VERTEX_FALLBACK_MODELS for these cases so the tests truly validate
Gemini-only fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend/core/config.py`:
- Around line 109-118: The loop that validates ALLOWED_SMTP_HOSTS (iterate over
host_values) currently blocks names like "localhost" but still permits loopback
IPs (e.g., 127.0.0.1, ::1); update the validation inside the for host_value in
host_values loop to detect and reject loopback IP addresses by attempting to
parse host_value with the ipaddress module (ipaddress.ip_address) and, if
parsing succeeds and address.is_loopback is True, raise the same ValueError;
preserve existing checks for wildcards, schemes, whitespace and literal
hostnames by only applying the ipaddress check for parseable IPs and catching
ipaddress.AddressValueError for non-IP hostnames.

In `@backend/tests/test_dockerfile_security.py`:
- Around line 11-14: The test's negative assertion lacks a helpful failure
message; modify the assertion around re.search(...) so it reports which package
was found and where by capturing the search result (e.g., using a variable like
match = re.search(..., normalized_dockerfile)) and then asserting match is None
with a message that includes package_name and match.group(0) or
normalized_dockerfile snippet; update the assertion in
backend/tests/test_dockerfile_security.py that currently references package_name
and normalized_dockerfile to provide this informative message.

In `@scripts/ci/test_strix_quick_gate.sh`:
- Around line 224-231: The current leak check only logs GITHUB_API_KEY; extend
it to also log and assert the generic parent-step secret variables (e.g.,
LLM_API_KEY and any other upstream secret names used in the pipeline) into the
same FAKE_STRIX_RUNTIME_ENV_LOG so regressions that forward parent-step secrets
are caught; update the print/append block that references GITHUB_API_KEY and
FAKE_STRIX_RUNTIME_ENV_LOG to include LLM_API_KEY (and any other relevant parent
secrets) with the same "${VAR:-<unset>}" pattern and add an assertion in the
test script after writing the log to fail if those generic secret entries are
set, mirroring the existing check for runtime-env-forwarding.
- Around line 4551-4595: The new Gemini BadRequest test cases reuse the generic
fallback list via the fallback_models argument which also populates
STRIX_VERTEX_FALLBACK_MODELS—masking whether Gemini-specific fallback logic is
used; update the four run_gate_case invocations
("gemini-primary-badrequest-fallback-success",
"gemini-badrequest-low-report-reaches-fallback",
"gemini-badrequest-threshold-report-blocks-fallback-success",
"gemini-badrequest-inline-threshold-blocks-fallback-success") to unset or clear
STRIX_VERTEX_FALLBACK_MODELS before running and instead set
STRIX_GEMINI_FALLBACK_MODELS to the intended fallback string (e.g.,
"gemini/fallback-one gemini/fallback-two"), or change the call so it passes an
explicit STRIX_GEMINI_FALLBACK_MODELS env value rather than using
fallback_models; ensure fallback_models is not used to populate
STRIX_VERTEX_FALLBACK_MODELS for these cases so the tests truly validate
Gemini-only fallback behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 66ff7d1f-58e9-4acc-9f02-814f50dab44c

📥 Commits

Reviewing files that changed from the base of the PR and between 7a0bf28 and d7dfb70.

⛔ Files ignored due to path filters (29)
  • frontend/branding/brand_assets/1.png is excluded by !**/*.png
  • frontend/branding/brand_assets/2.png is excluded by !**/*.png
  • frontend/branding/brand_assets/3.png is excluded by !**/*.png
  • frontend/branding/brand_assets/4.png is excluded by !**/*.png
  • frontend/branding/brand_assets/5.png is excluded by !**/*.png
  • frontend/branding/brand_assets/6.png is excluded by !**/*.png
  • frontend/branding/naruon_branding.png is excluded by !**/*.png
  • frontend/branding/uiux/10.png is excluded by !**/*.png
  • frontend/branding/uiux/11.png is excluded by !**/*.png
  • frontend/branding/uiux/12.png is excluded by !**/*.png
  • frontend/branding/uiux/13.png is excluded by !**/*.png
  • frontend/branding/uiux/14.png is excluded by !**/*.png
  • frontend/branding/uiux/15.png is excluded by !**/*.png
  • frontend/branding/uiux/16.png is excluded by !**/*.png
  • frontend/branding/uiux/17.png is excluded by !**/*.png
  • frontend/branding/uiux/18.png is excluded by !**/*.png
  • frontend/branding/uiux/19.png is excluded by !**/*.png
  • frontend/branding/uiux/20.png is excluded by !**/*.png
  • frontend/branding/uiux/21.png is excluded by !**/*.png
  • frontend/branding/uiux/22.png is excluded by !**/*.png
  • frontend/branding/uiux/9.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux1.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux2.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux3.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux4.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux5.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux6.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux7.png is excluded by !**/*.png
  • frontend/branding/uiux/uiux8.png is excluded by !**/*.png
📒 Files selected for processing (31)
  • .env.example
  • .github/workflows/strix.yml
  • .gitignore
  • AGENTS.md
  • ARCHITECTURE.md
  • CHANGELOG.md
  • Dockerfile
  • README.md
  • backend/README.md
  • backend/api/auth.py
  • backend/core/config.py
  • backend/db/models.py
  • backend/main.py
  • backend/services/email_client.py
  • backend/services/llm_service.py
  • backend/tests/test_auth_real.py
  • backend/tests/test_config.py
  • backend/tests/test_dockerfile_security.py
  • backend/tests/test_llm_service.py
  • backend/tests/test_tenant_config_model.py
  • docs/operations/auth-key-management.md
  • docs/operations/email-relay-proxy-boundary.md
  • docs/plans/2026-05-26-branding-settings-source-gap-roadmap.md
  • frontend/src/app/settings/page.test.tsx
  • frontend/src/app/settings/page.tsx
  • frontend/src/app/tasks/page.test.tsx
  • frontend/src/components/EmailDetail.test.tsx
  • frontend/src/lib/api-client.test.ts
  • frontend/src/lib/api-client.ts
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
💤 Files with no reviewable changes (1)
  • Dockerfile

…-security-20260522

# Conflicts:
#	.github/workflows/strix.yml
#	.gitignore
#	AGENTS.md
#	backend/main.py
#	frontend/src/app/settings/page.tsx
#	frontend/src/app/tasks/page.test.tsx
@seonghobae

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@@ -1,20 +1,21 @@
from unittest.mock import AsyncMock, patch
from unittest.mock import AsyncMock, MagicMock, patch
@seonghobae

Copy link
Copy Markdown
Contributor Author

PR 게이트 차단 증거

현재 head 5b08f2790b4bb84e08cef19ca47bc418f7a4cecd 기준으로 PR #209는 코드 충돌은 해소됐지만 strix required check가 실패해 merge blocked 상태입니다.

  • 실패 check: strix
  • 실패 job: https://github.com/Seongho-Bae/naruon/actions/runs/26432738923/job/77809087851
  • 실패 원인: pull_request_target가 base SHA ebf26085aad03fd05838bba76218db6601dfee71의 trusted workflow/script를 실행해, PR head의 GitHub Models github/gpt-5.4 수정이 아직 적용되지 않습니다. 실패 로그는 base workflow가 github/gpt-4o/기존 provider path를 사용하면서 GithubException - Bad credentials로 종료한 것을 보여줍니다.
  • PR head의 로컬 검증: bash scripts/ci/test_strix_quick_gate.sh, frontend lint/test/build, backend pytest, git diff --check 통과.

보안 check를 숨기거나 admin merge하지 않고, base trusted Strix workflow가 현재 PR의 수정 사항을 반영할 수 없는 bootstrap blocker로 기록합니다. 다음 안전한 해소 경로는 repo 정책에 따른 임시 ruleset 조정 후 merge 및 즉시 복구, 또는 base branch에 동일 Strix workflow fix를 먼저 land하는 것입니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Closing this PR as stale/unmergeable against current master.

Current evidence:

  • The PR is DIRTY/CONFLICTING and carries roughly 130 files of stale product/frontend/backend/docs changes in addition to the Strix work.
  • Current master already has the newer Strix GPT-5.4 policy, GitHub Models permission path, provider-mode gate, and related AGENTS/README policy updates.
  • Keeping this PR open would make the PR queue harder to converge because unrelated old product changes would need to be re-reviewed together with Strix logic.

Preserved follow-up notes:

  • If still desired, salvage only the branch-only Strix fallback/threshold hardening from scripts/ci/strix_quick_gate.sh and scripts/ci/test_strix_quick_gate.sh into a fresh focused branch from current master.
  • Do not carry over stale .github/workflows/strix.yml or unrelated frontend/backend/docs/assets from this branch.

This is a stale PR cleanup, not a security-check bypass. Required Strix remains enforced on active PRs.

@seonghobae seonghobae closed this May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant