에이전트 pull request의 merge를 막아야 할 gate는 무엇인가?
안전하지 않은 코드를 막는 7가지 측정 가능한 agent pull request gate를 설명합니다. test, CodeQL, dependency, secret, authorization, migration, rollback을 다룹니다.

에이전트는 깔끔한 diff와 설득력 있는 설명, 짧은 review를 통과하는 코드를 만들고도 애플리케이션을 노출되거나 복구할 수 없는 상태로 남길 수 있습니다. 따라서 merge 결정은 에이전트의 자신감이나 patch의 작은 크기가 아니라 repository가 측정할 수 있는 증거에 따라야 합니다.
저는 7개의 blocking gate를 사용합니다. test, CodeQL, dependency review, secret scanning, authorization check, migration rehearsal, rollback verification입니다. 각 gate는 서로 다른 실패 질문에 답합니다. test suite가 green이어도 새 package가 안전하다는 뜻은 아니며, static analysis가 clean이어도 migration이 가장 바쁜 table을 lock할지는 알 수 없습니다.
이 gate는 사람과 에이전트의 변경에 똑같이 적용됩니다. 에이전트는 실수의 양, 속도, 형태를 바꾸지만 더 약한 별도 경로를 정당화하지 않습니다. 다른 pull request와 같은 증거를 내놓지 못하는 변경은 merge할 준비가 되지 않았습니다.
Gate는 조언이 아니라 증거를 만들어야 한다
merge gate는 protected branch에 들어갈 정확한 commit에 대해 재현 가능한 pass 또는 fail을 반환해야 합니다. “이 dependency를 review하세요”라는 comment는 조언입니다. package, version, advisory, severity threshold를 식별하는 required check는 증거입니다.
이 구분은 중요합니다. 많은 security 기능이 유용한 결정 시점이 지난 뒤에 보고만 하기 때문입니다. scanner가 alert, email, issue를 만들어도 merge button은 계속 쓸 수 있습니다. 그러면 팀은 scanning이 활성화되었다고 말하지만 변경을 막지는 못합니다. 각 gate에서 다음 네 가지를 확인합니다.
- pull request의 현재 head commit에서 실행됩니다.
- branch protection이 해당 이름의 result를 요구합니다.
- skip, timeout, crash한 job을 pass로 처리하지 않습니다.
- 결정을 재현하기에 충분한 내용을 result에 남깁니다.
policy는 repository에 보관합니다. administrator만 아는 설정 모음보다 작은 manifest가 review하기 쉽습니다.
merge_gates:
tests: required
codeql: required
dependency_review: required
secret_scan: required
authorization: required
migration_rehearsal: required_when_changed
rollback_verification: required
required_when_changed는 빠져나갈 구멍이 아닙니다. gate는 관련 file을 먼저 찾은 뒤 rehearsal을 수행하거나 명확한 not applicable result를 기록합니다. path filter가 required check를 영원히 pending 상태로 두어서는 안 됩니다. 에이전트가 자신의 위험한 변경을 면제해서도 안 됩니다.
workflow permission은 각 job이 필요한 최소 범위로 제한합니다. pull request 코드는 branch가 조직 내부에 있어도 신뢰할 수 없는 input입니다. 검사 대상 코드에 write token이나 production secret을 노출하는 gate는 찾으려던 문제보다 더 큰 문제를 만들 수 있습니다.
check의 logic뿐 아니라 identity도 보호합니다. branch rule은 보통 status name을 요구하므로, 같은 이름을 보고하는 workflow가 두 개라면 약한 job이 rule을 만족할 수 있습니다. policy job에 고유한 이름을 붙이고 file 변경 권한을 제한하며 owner review를 요구합니다. merge queue가 새 merge commit을 만들면 gate를 다시 실행하거나 result를 queued revision에 묶습니다. 어제 head의 증거는 오늘 merge의 증거가 아닙니다.
gate configuration 자체도 sensitive code로 다룹니다. threshold 변경, path 삭제, query pack 하향, exception 추가는 이후의 모든 green result 의미를 바꿉니다. policy diff를 눈에 띄게 표시하고 관련 control을 이해하는 maintainer의 review를 받습니다. 에이전트가 변경을 제안할 수는 있지만 자신을 판단하는 장치를 수정했다는 이유로 더 쉽게 통과해서는 안 됩니다.
Test는 관찰 가능한 regression을 막는다
test gate는 지원되는 runtime과 database version에서 지정된 behavior를 깨는 모든 변경을 막아야 합니다. locked dependency, generated file, feature flag, schema state를 포함해 merge commit과 같은 build input을 사용해야 합니다.
에이전트는 가장 가까운 assertion을 만족시키는 데 능합니다. 하나의 test를 green으로 만드는 fallback을 넣고 error handling, pagination, concurrency, 인접 API contract를 깨뜨릴 수 있습니다. behavior가 바뀌면 test 추가나 수정을 요구하되 새 test line 수로 품질을 재지 마십시오. implementation을 제거하거나 revert했을 때 test가 fail하는지 봅니다.
쓸 만한 test gate에는 이름이 분리된 layer가 있습니다.
- local logic과 boundary case를 위한 unit test.
- database, queue, cache, external service contract를 위한 integration test.
- public request와 response shape를 위한 contract test.
- built artifact를 대상으로 한 작은 smoke test.
flaky test는 green이 나올 때까지 retry하지 말고 원인을 고칩니다. 한 번의 retry로 diagnostic evidence를 모을 수 있지만 final status에는 첫 failure가 보여야 합니다. 그렇지 않으면 가끔 작동한다는 사실만 증명된 코드를 merge할 수 있습니다.
smoke test는 artifact를 시작하고 health endpoint와 의미 있는 write path를 실행한 뒤 정상 종료해야 합니다. packaged application을 시작하지 않고 source만 test하면 missing file, 잘못된 environment default, 망가진 migration, startup panic을 놓칩니다. web service result는 다음처럼 간결하게 남길 수 있습니다.
{"commit":"abc123","build":"pass","startup_ms":842,"health":200,"write_read_cycle":"pass"}
일률적인 coverage percentage를 주 gate로 삼지 마십시오. coverage는 test하지 않은 변경을 보여주지만 약한 assertion으로도 높은 숫자를 만들 수 있습니다. required suite와 changed behavior로 gate를 구성하고 coverage 변화는 review evidence로 사용합니다.
판단 대상 implementation으로부터 test를 보호합니다. pull request가 rule과 assertion을 함께 고쳐 새 결과를 받아들이면 suite가 pass하는 동안 contract가 조용히 이동할 수 있습니다. reviewer는 changed test를 public API, issue, acceptance rule과 비교해야 합니다. parser, validator, billing, access check에는 mutation testing이나 의도적으로 잘못된 input을 넣습니다. 그럴듯한 잘못된 구현을 suite가 거부하는지가 중요한 질문입니다.
gate가 fail하면 test artifact를 보관합니다. random test의 failing seed, 정확한 database image, secret을 제거한 service log, 재현 command를 저장합니다. 재현 정보가 없는 status는 다음 agent나 engineer를 추측으로 되돌립니다. repository data rule에 따라 보관 기간을 제한하고 재현하기 쉽다는 이유로 production snapshot을 upload하지 않습니다.
CodeQL은 알려진 취약점 경로를 막는다
CodeQL gate는 CodeQL이 실제로 분석한 language와 generated artifact에서 새 high confidence finding을 막아야 합니다. clean result가 전체 애플리케이션의 안전을 증명하는 것처럼 보여서는 안 됩니다.
GitHub는 CodeQL이 코드를 query 가능한 database로 compile하고 그 위에서 query를 실행한다고 설명합니다. 의심스러운 text만 찾지 않고 코드 안에서 data flow를 추적할 수 있습니다. 하지만 language support, build success, query selection, 분석 당시 코드에 의해 범위가 제한됩니다. database build가 service를 조용히 제외하면 green result의 범위는 reviewer의 예상보다 작습니다.
language와 query policy를 명시한 workflow를 사용합니다.
name: codeql
on: [pull_request]
permissions:
contents: read
security-events: write
jobs:
analyze:
strategy:
matrix:
language: [javascript-typescript, go]
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
실제 repository에서는 third party action을 review한 commit digest에 pin합니다. tag는 예제를 읽기 쉽게 하지만 mutable tag는 required security job의 trust boundary를 넓힙니다.
첫 alert가 나오기 전에 무엇을 block할지 정합니다. 보통 합의한 severity와 precision threshold에서 새 finding을 block하고 기존 debt는 baseline에 표시합니다. 첫날부터 역사적 결과를 전부 block하면 대량 dismissal을 부릅니다. 영원히 무시하면 blind spot이 됩니다. baseline에는 owner와 due date를 지정합니다.
service, language, build command가 바뀌면 analyzed file set을 확인합니다. 새 mobile client, generated resolver, 별도 backend에는 analyzer나 build step이 더 필요할 수 있습니다. reviewer가 무엇을 분석했는지 말할 수 없다면 “CodeQL passed”의 의미는 제한적입니다.
analysis failure와 clean analysis를 구분합니다. autobuild가 package를 compile하지 못하면 job은 infrastructure 또는 configuration failure를 보고해야지 zero finding을 반환해서는 안 됩니다. database creation log와 언어별 analyzed source count를 보관합니다. base branch와 비교해 설명되지 않는 큰 감소를 막습니다. build edit가 취약한 module을 제외하고 더 적은 코드만 보았기 때문에 check가 빠르고 green이 되는 흔한 실패를 찾을 수 있습니다.
dismissal은 정리가 아니라 policy change로 review합니다. false positive에는 code path와 query에 연결된 구체적인 설명이 필요합니다. suppression comment는 범위가 좁고 owner가 있으며 diff에 보여야 합니다. generated file 전체 제외가 맞을 수 있지만 사람이 관리하는 template이나 generator input이 그 directory에 없는지 먼저 확인합니다.
Dependency review는 install 전에 위험을 막는다
dependency diff가 명시적 policy에 위배되는 package나 version을 추가하면 dependency review가 pull request를 막아야 합니다. policy에는 known advisory severity, denied license, 예상하지 않은 package source, owner 없는 direct dependency를 포함할 수 있습니다.
이 gate는 repository vulnerability alert와 다릅니다. alert는 branch에 취약한 dependency가 있다고 말합니다. dependency review는 이 pull request가 graph를 악화시키는지 묻습니다. GitHub의 기능은 manifest와 lockfile을 비교하므로 판단이 적시에 해당 변경과 연결됩니다.
lockfile consistency를 요구합니다. 에이전트가 package.json을 수정하고 lockfile을 바꾸지 않거나, 대응하는 manifest change 없이 lockfile만 바꾸면 job은 fail해야 합니다. CI에서 fresh version을 resolve하는 install command는 결과를 비결정적으로 만들고 reviewer가 본 것과 다른 graph를 test할 수 있습니다.
작은 policy는 다음과 같습니다.
dependency_policy:
fail_on_severity: high
deny_licenses:
- AGPL-3.0
allow_sources:
- registry.npmjs.org
- proxy.golang.org
require_owner_for_direct_additions: true
정확한 license list는 법률과 product 결정이며 그대로 copy할 값이 아닙니다. repository가 이를 선언하고 check가 trigger한 package를 출력해야 합니다.
package 이름이 제안된 library와 비슷하다고 auto approve하지 않습니다. 에이전트는 존재하지 않는 이름, 방치된 fork, 작은 helper를 위한 거대한 client를 고를 수 있습니다. output에는 새 direct와 transitive package, registry, resolved version, license, advisory status가 보여야 합니다. reviewer는 기존 코드나 더 작은 dependency로 충분한지 판단할 수 있습니다.
dependency service가 diff를 만들지 못하면 fail closed합니다. advisory feed가 없다는 것은 merge를 보류할 이유이지 불확실성을 green으로 만들 이유가 아닙니다. 긴급 절차는 named maintainer의 기록된 override를 허용할 수 있으며 이유를 commit에 붙입니다.
approved registry만 network로 접근하는 isolated job에서 install behavior를 검사합니다. lifecycle script와 build plugin은 installation 중 code를 실행하므로 app이 import하지 않아도 위험할 수 있습니다. 새 install script, native binary, 낯선 registry를 기록합니다. publishing credential, cloud token, trusted build와 공유하는 writable cache를 주지 않습니다.
vendored code와 container image도 같은 판단에 포함됩니다. 일반 manifest review가 놓치더라도 image digest, base image name, Git submodule, checked-in archive를 비교합니다. release input에는 immutable digest를 요구합니다. latest 같은 tag는 새 diff 없이 bytes가 바뀌므로 나중에 pull request를 재현할 수 없습니다.
Secret scanning은 diff와 history를 모두 검사한다
pull request가 credential pattern이나 검증된 live secret을 추가하면 test fixture, deleted file, generated bundle, 이전 commit에 있더라도 scanning gate가 merge를 막아야 합니다.
push protection과 pull request scanning은 관련 있지만 다른 문제를 풉니다. push protection은 알려진 secret이 remote에 도달하기 전에 막습니다. pull request gate는 이미 도착한 content를 검사하고 앞에서 놓친 contributor나 token type을 다룹니다. branch protection에 required로 연결되지 않은 alert는 merge를 막지 않습니다.
final filesystem만 보지 말고 base branch부터 전체 commit range를 scan합니다. 에이전트가 한 commit에서 token을 넣고 다음 commit에서 제거해도 Git history에 남고 log나 cache에 도달했을 수 있습니다. exposed로 처리합니다. credential을 revoke 또는 rotate하고 proposed history에서 제거한 뒤 check를 다시 실행합니다.
authenticate할 수 없는 synthetic fixture를 사용합니다. fixture는 test임을 분명히 밝히고 real cloud key의 형태를 복사하지 말고 local test pattern과 일치해야 합니다. 넓은 allowlist는 사고와 공격자가 ignored directory를 결국 찾기 때문에 위험합니다. exception은 정확하고 review되며 detector configuration 가까이에 둡니다.
pattern detector와 entropy check를 결합하고 provider가 안전하게 지원할 때만 credential verification을 사용합니다. pattern matching은 network와 disclosure risk가 적지만 custom token을 놓칩니다. verification은 불확실성을 줄이지만 candidate secret 일부를 다른 service로 보냅니다. pull request가 제공한 untrusted endpoint에는 절대 연결하지 않습니다. 어느 detector가 verify하는지, 어느 것이 local인지, 어떤 data가 CI 밖으로 나가는지 문서화합니다.
모든 random string을 credential로 취급하지 않으면서 일반 encoding과 generated output을 scan합니다. Base64, URL encoding, minified bundle은 source step에서 평문이었던 secret을 숨길 수 있습니다. tested fixture로 blocking threshold를 정하고 detector update를 policy change로 review합니다. noisy scanner는 maintainer에게 dismissal을 학습시키고 silent scanner는 거짓 안도감을 줍니다.
gate output은 값을 노출하지 않고 위치를 알려야 합니다.
{"result":"fail","detector":"generic-api-token","commit":"abc123","path":"config/dev.env","line":7,"fingerprint":"sha256:8f2c..."}
full match를 CI log나 pull request comment에 출력하지 않습니다. scanner 출력 후 masking하면 늦을 수 있습니다. log system, notification, job artifact가 이미 복사했을 수 있기 때문입니다.
secret scanning은 repository permission review를 대체하지 않습니다. workflow는 diff에 secret을 넣지 않고도 production credential을 읽을 수 있고, 에이전트는 deployment job을 바꿔 빼낼 수 있습니다. pull request job에서 secret을 제거하고 workflow permission을 제한하며 CI definition change에 human review를 요구합니다.
Authorization check는 금지된 행동을 계속 막는다
authorization gate는 각 protected operation이 service boundary에서 잘못된 actor를 거부하고 의도한 actor를 허용한다는 것을 증명해야 합니다. login test만으로 authorization을 test할 수 없습니다.
팀은 authentication, authorization, UI visibility를 자주 혼동합니다. authentication은 누가 request를 보냈는지 확인합니다. authorization은 그 identity가 이 object에 이 action을 할 수 있는지 결정합니다. React에서 admin button을 숨겨도 Go API의 결정은 변하지 않습니다. backend가 request를 받으면 애플리케이션은 여전히 노출됩니다.
변경된 endpoint와 business action에 ownership과 tenant boundary를 포함한 permission matrix를 만듭니다.
read_private_project:
anonymous: deny
member: deny
other_tenant: deny
owner: allow
admin: allow
update_project:
anonymous: deny
other_tenant: deny
owner: allow
matrix에서 test를 생성하거나 service language로 table-driven case를 작성합니다. 각 deny case는 현실적인 identifier로 real handler를 호출해야 합니다. authorization middleware를 교체한 mock은 route가 동작함을 보여주지만 검사할 control을 skip합니다.
role만이 아니라 object-level access를 test합니다. 두 user가 같은 member role이면서 다른 organization에 속할 수 있습니다. resource identifier와 tenant identifier를 별도로 바꿔 insecure direct object reference를 찾습니다. 일반 REST handler check를 우회하기 쉬운 bulk endpoint, export, background job, GraphQL resolver도 test합니다.
새 protected route에 policy mapping이 없으면 gate를 fail시킵니다. missing authorization이 reviewer의 직감에서 측정 가능한 defect로 바뀝니다. server default는 deny로 둡니다. 몇 가지 known bad case만 막는 흩어진 code보다 explicit allow rule이 audit하기 쉽습니다.
에이전트는 인접 handler를 reuse하며 happy path를 남기고 ownership check를 떨어뜨릴 수 있습니다. matrix는 이 누락을 보이게 하고 role이나 tenant rule이 바뀌어도 stable contract를 제공합니다.
input normalization 후 authorization도 실행합니다. 대소문자, 대체 identifier 형식, 중복 query parameter, nested object reference는 같은 request를 다른 code path로 보낼 수 있습니다. direct endpoint와 같은 operation에 도달하는 batch 또는 import route를 test합니다. background worker가 마지막 write를 수행하면 actor와 tenant context를 job에 전달하고 전권을 가진 trusted user로 취급하지 않습니다.
expected decision과 이를 만든 policy rule을 기록하되 private object data는 노출하지 않습니다. 좋은 failure는 actor class, action, object class, expected status를 말하고 access token이나 full record를 dump하지 않습니다. reviewer는 broken fixture와 실제 privilege change를 구분할 수 있습니다.
Migration rehearsal은 lock과 가역성을 측정한다
migration gate는 제안된 schema change를 production 형태의 copy에 적용하고 compatibility probe를 실행하며 merge 전에 duration, lock, rollback behavior를 기록해야 합니다. 빈 test database에서 성공한 migration은 거의 아무것도 증명하지 않습니다.
비슷한 table size, index, constraint, data skew를 가진 sanitized snapshot이나 generated dataset을 사용합니다. 정확한 production data는 pull request infrastructure에 두지 않습니다. 개인 또는 기밀 record를 복사하지 않고 운영 압력을 재현하는 것이 목적입니다.
실제 deployment sequence를 rehearse합니다. migration 중 old app instance가 계속 동작한다면 old code를 new schema에서, new code를 transitional schema에서 test합니다. nullable column 추가는 보통 compatible합니다. 한 단계에서 column을 rename하면 traffic을 처리하는 old instance가 모두 깨질 수 있습니다.
machine-readable evidence를 기록합니다.
{"migration":"20260727_add_project_state","apply_ms":18420,"max_lock_ms":310,"old_app_probe":"pass","new_app_probe":"pass","down":"pass"}
database와 table class별로 threshold를 정합니다. 300 millisecond lock이 어떤 table에는 무해하고 다른 곳에는 장애가 될 수 있습니다. reviewer는 selected limit, measured result, rehearsal database version을 함께 봐야 합니다.
PostgreSQL에서는 table rewrite, constraint validation, write를 block하는 index build를 검사합니다. expand and contract를 선호합니다. 새 shape를 추가하고 두 shape를 다루는 code를 deploy하며 controlled batch로 backfill하고 read를 바꾼 뒤 나중에 old shape를 삭제합니다. pull request 하나를 더 만드는 편이 outage 중 즉흥 대응보다 저렴합니다.
모든 migration에 안전한 down operation이 있는 것은 아닙니다. column drop은 data를 잃고 transformation 역변환은 모호할 수 있습니다. 이 경우 tested forward recovery와 backup restore point를 요구합니다. down file이 있다는 이유로 irreversible migration을 rollback safe라고 부르면 안 됩니다.
retry와 partial failure를 test합니다. deploy는 index를 만든 후 migration 완료를 기록하기 전에 멈출 수 있으며 다음 시도는 state를 망가뜨리거나 영원히 fail해서는 안 됩니다. controlled boundary에서 rehearsal을 멈추고 다시 실행해 schema와 ledger가 일치하는지 확인합니다. 긴 backfill은 recorded cursor에서 재개하고 같은 batch를 두 번 실행해도 data를 duplicate 또는 delete하지 않아야 합니다.
시간 외에 disk와 replication 영향도 확인합니다. table rewrite는 temporary space를 사용하고 write ahead log를 키우며 main operation이 끝난 뒤에도 replica를 지연시킵니다. gate가 완벽한 production 예측을 할 필요는 없지만 rehearsal dataset에서 값을 기록하고 database owner의 limit과 비교해야 합니다. 그렇지 않으면 local에서 빠른 migration이 production volume을 채울 수 있습니다.
Rollback verification은 recovery path를 실행한다
rollback gate는 candidate를 isolated environment에 deploy하고 representative state를 만들며 supported rollback method를 실행한 뒤 previous version이 올바르게 read와 write할 수 있음을 증명해야 합니다. 글로 쓴 rollback plan은 verification이 아닙니다.
application rollback과 data rollback을 분리합니다. traffic을 previous binary로 돌리는 데는 몇 초면 되지만 destructive schema나 data transformation은 되돌릴 수 없을 수 있습니다. gate는 둘 다 보고합니다. old app이 new schema에서 동작하지 않으면 candidate를 nonreversible로 표시하고 staged deployment plan을 요구합니다.
실용적인 순서는 다음과 같습니다.
- 현재 main commit을 deploy하고 representative record를 seed합니다.
- pull request artifact로 upgrade하고 changed path를 실행합니다.
- upgraded state에서 새 record를 만듭니다.
- documented control로 previous artifact 또는 snapshot을 restore합니다.
- read, write, queue, background job probe를 실행합니다.
check는 artifact identifier, snapshot identifier, timestamp, probe result를 보관해야 합니다. credential이나 복사한 customer data는 보관하지 않습니다. recovery time은 자체 operating target의 증거이지 보편적인 약속이 아닙니다.
snapshot은 애플리케이션이 필요한 모든 것을 포함한다고 증명했을 때만 유용합니다. file, object storage, queue state, schema change, external side effect가 server snapshot 밖에 있을 수 있습니다. result에 이 경계를 적습니다. 이미 보낸 payment, email, webhook은 database restore로 취소할 수 없습니다.
rollback probe를 health check보다 강하게 만듭니다. upgrade 전과 후에 만든 record를 읽고 compatibility가 허용하면 둘 다 update하며 각 app version이 만든 queued job을 처리합니다. status code뿐 아니라 user-visible output을 비교합니다. 새 field를 누락하거나 enum을 잘못 읽으면서 200을 반환하는 server는 복구되지 않았습니다.
on-call 담당자가 사용할 control을 test합니다. production rollback에 artifact 선택, snapshot restore, traffic 전환이 필요하면 isolated rehearsal도 같은 interface와 permission path를 사용해야 합니다. 한 engineer의 laptop에 있는 private script는 operational control이 아닙니다. designated operator role이 permanent admin access 없이 recovery를 완료할 수 있음을 보여야 합니다.
Koder.ai는 source export, deployment와 hosting, snapshot, rollback을 지원하므로 그곳에서 만든 애플리케이션은 recovery를 pull request의 문단으로 끝내지 않고 구체적인 artifact를 gate에서 사용할 수 있습니다. 어느 platform이든 규칙은 같습니다. recovery control을 실행하고 restored application을 probe합니다.
하나의 required check가 7개를 요약해야 한다
최종 merge 결정은 정확한 head commit의 7개 result를 검증하는 stable policy check 하나를 요구해야 합니다. job name은 바뀌고 matrix job은 늘며 optional path는 작업을 skip합니다. 작은 aggregator가 branch protection이 policy에서 벗어나는 것을 막습니다.
각 gate는 commit, policy version, outcome, evidence location을 포함하는 signed 또는 platform-attested result를 만들어야 합니다. aggregator는 missing, stale, neutral, cancelled result를 거부합니다. 보고하지 않은 job에서 success를 추론해서는 안 됩니다.
{
"commit": "abc123",
"policy": "merge-gates-v3",
"results": {
"tests": "pass",
"codeql": "pass",
"dependency_review": "pass",
"secret_scan": "pass",
"authorization": "pass",
"migration_rehearsal": "not_applicable",
"rollback_verification": "pass"
},
"decision": "allow"
}
긴급 상황을 위한 override path는 좁게 둡니다. named maintainer, 두 번째 approver, written reason, expiry, follow-up issue를 요구합니다. 에이전트가 자신의 exception을 요청하거나 승인하면 안 됩니다. override를 일반 gate result와 같은 곳에 보고해 incident가 끝난 뒤에도 보이게 합니다.
이 check는 일부 pull request에 몇 분, migration change에는 훨씬 긴 시간을 추가합니다. 구체적인 증거를 얻는다면 괜찮습니다. cheap gate를 먼저 실행하고 superseded commit을 cancel하며 trusted build input을 cache하고 full environment rehearsal은 관련 path에만 사용합니다. dashboard를 빨리 green으로 만들기 위해 gate를 약화하지 않습니다.
현재 behavior를 관찰 가능하게 만드는 것부터 시작합니다. 하나의 policy file에 7개 이름을 모두 넣고 각각을 required result에 연결하며 skipped work가 이유를 설명하도록 합니다. 그 record를 만들지 못하는 첫 agent pull request는 production보다 먼저 delivery system의 구멍을 찾은 것입니다.
자주 묻는 질문
Agent pull request에는 사람보다 엄격한 rule이 필요합니까?
둘 다 같은 blocking evidence를 사용합니다. 에이전트의 속도 때문에 automatic check를 더 두는 것은 타당하지만 사람의 diff도 같은 secret, authorization bug, 위험한 migration을 넣을 수 있습니다.
사람 reviewer가 실패한 merge gate를 override할 수 있습니까?
가능하지만 책임자 두 명, 이유, 만료가 있는 좁고 기록된 exception만 허용합니다. 변경을 만든 에이전트가 자신의 override를 승인해서는 안 됩니다.
CodeQL이 pass하면 pull request가 안전합니까?
아닙니다. 선택한 query가 성공적으로 분석된 code에서 blocking result를 찾지 못했다는 뜻입니다. dependency, runtime authorization, secret, configuration, recovery에는 별도 증거가 필요합니다.
Required scanner를 사용할 수 없으면 어떻게 합니까?
check를 fail closed하거나 merge를 block한 채로 둡니다. 긴급 변경이라면 unknown result를 pass로 바꾸지 말고 documented override path를 사용합니다.
Secret scanning은 삭제된 commit도 검사해야 합니까?
pull request의 전체 commit range를 검사해야 합니다. 추가했다 삭제한 secret도 history에 남으므로 cleaned change를 받아들이기 전에 rotate해야 합니다.
Pull request에서 authorization을 어떻게 test합니까?
identity, role, tenant, object, action matrix로 real service handler를 호출합니다. login과 hidden UI는 server authorization을 증명하지 않으므로 deny case와 ownership change를 포함합니다.
모든 database migration에 down script가 필요합니까?
아닙니다. 일부 destructive change는 정직하게 되돌릴 수 없습니다. tested forward recovery나 backup restore procedure를 요구하고 nonreversible로 표시합니다.
Rollback planning과 verification의 차이는 무엇입니까?
planning은 의도한 recovery step을 설명합니다. verification은 candidate artifact와 representative state에서 step을 실행하고 previous version이 올바르게 read와 write하는지 기록합니다.
7개 gate가 모든 pull request를 늦추지 않게 하려면 어떻게 합니까?
cheap check를 먼저 실행하고 superseded commit을 cancel하며 trusted input을 cache하고 관련 change에만 migration rehearsal을 실행합니다. 각 gate는 명시적인 pass 또는 not applicable을 냅니다.
Branch protection은 어떤 result를 요구해야 합니까?
정확한 head commit의 7개 gate를 집계한 stable policy result를 요구합니다. missing, stale, skipped, cancelled, neutral result를 거부해야 합니다.