contexa-core contexa-iam contexa-autoconfigure

프롬프트 검수와 번들 버전

보안 판단 프롬프트는 버전이 붙은 프롬프트 번들로 실행됩니다. 이 문서는 번들을 무엇으로 식별하는지, 요청마다 번들을 어떻게 고르는지, 번들 버전이 릴리스 게이트를 거쳐 레지스트리 상태를 어떻게 옮겨 가는지, 섀도 실행·카나리·롤백이 어떻게 동작하는지, 그리고 프롬프트 검수기가 봉인된 프롬프트를 어떻게 검사하는지 설명합니다. 프롬프트 자체는 보안 판단 프롬프트 파이프라인을 참고하세요.

프롬프트 번들

번들은 거버넌스 디스크립터(프롬프트 키, 템플릿 키, 프롬프트 버전, 계약 버전, 릴리스 상태, 롤백 버전 등)와 그 코드가 그리는 사용자 프롬프트 레이아웃을 묶은 것입니다. 프롬프트 버전이 곧 번들 버전이며, 클래스패스의 매니페스트 prompt-bundles/manifests/<promptKey>/<version>.json 을 가리킵니다. 한 빌드는 cortex.security-decision 번들을 정확히 두 개 실행합니다. 빌드 기본(v19 섹션)과 v20 번들(사전 블록)입니다. 이전 매니페스트는 지난 번들의 기록으로 남을 뿐 실행할 수 없습니다.

B1
시스템 글
L1·L2 예산 프로파일로 그린 시스템 글
B2
사전
모든 사전 항목과 그 필드
B3
골든 렌더
골든 입력을 그린 결과의 다이제스트
B4
출력 형식
형식 지시와 응답 필드
B5
최소 대응 규칙
규칙 원천과 기본 설정
B6
응답 검사기
응답 검사기 정의 원천
B7
검색
검색 건수·임계값·대기·문서 잘림 기본값
B8
예산
모든 프롬프트 예산 프로파일
B9
검사기 계약
ABSENT 표지: 프롬프트에 속하지 않음
B10
어휘
어휘 버전과 그 분류기 원천
B11
2차 분석
INCLUDED: B3 안에서 그림
  • 요소 상태 — PRESENT 는 요소 내용을 해시하고, ABSENT·UNVERSIONED·INCLUDED 는 고정 표지를 해시하므로 상태 자체가 식별의 일부가 됩니다. 번들 해시는 모든 요소를 덮습니다. 예를 들어 v19 번들은 B2(사전 없음)와 B5(최소 대응 규칙 없음)를 ABSENT 로 둡니다.
  • 읽을 때 검증 — 번들 해시가 요소와 맞지 않는 매니페스트나, 이름은 같고 해시가 다른 매니페스트 두 개가 있으면 바로 실패합니다.
  • 매니페스트 필드 — 요소 말고도 골든 입력, 부모 버전, 어휘 버전과 호환 어휘 버전, 롤백 대상, 선언한 모델 프로파일을 적습니다.

요청의 번들 고르기

요청마다 실행할 번들은 선택기 하나가 고르며, 선택기는 contexa.security.tiered.prompt-bundle.selector 로 정합니다. 이벤트의 첫 프롬프트가 이벤트에 번들을 고정하고, 뒤 프롬프트(Layer2 나 2차 분석)는 같은 번들을 씁니다. 이 빌드가 실행하지 않는 번들 버전을 고르면 빌드 기본 번들로 돌아가며, 버전마다 한 번 기록합니다.

선택 출처언제
BUILD_DEFAULT아무것도 고르지 않았거나, 선택기가 실패했거나, 고른 버전을 이 빌드가 실행하지 않을 때.
CONFIGURATIONselector=configuration(기본): contexa.security.tiered.prompt-bundle.active 의 버전을 모든 요청에 똑같이 씁니다.
REGISTRYselector=registry: 요청 범위의 최신 ACTIVE 릴리스, 범위에 없으면 PLATFORM_GLOBAL 의 것.
CANARYselector=registry: 비율과 대상 안에 드는 요청에 범위의 CANARY 릴리스.
SHADOW범위의 SHADOW 릴리스. 판정과 떨어진 표본 복사본에서 실행합니다(섀도 실행 참고).
레지스트리 읽기. 레지스트리 선택기는 범위의 릴리스를 최대 60 초 캐시하고 5 초마다 무효화를 확인합니다. 상태 전환이나 롤백이 무효화를 알립니다. 레지스트리를 읽지 못하는 동안에는 빌드 기본 번들이 실행됩니다.

레지스트리 상태

PromptBundleState 가 레지스트리의 단일 수명 주기 어휘입니다. 예전에 저장된 값도 이것으로 읽으므로 게이트·조회·화면이 릴리스를 같은 방식으로 분류합니다. 런타임에 집행되는 상태는 ACTIVE 와 CANARY 뿐입니다.

1
AVAILABLE
DRAFT
검증된 매니페스트로 빌드에 있음. 실행하지 않음
2
SHADOW
EVAL_ONLY
표본 요청에서 실행하고 기록만 함
3
CANARY
CANARY
범위의 비율 안에서 집행
4
ACTIVE
PRODUCTION
기본으로 집행
5
DEPRECATED
ROLLED_BACK
더는 고를 수 없음. 롤백 대상이자 기록
6
RETIRED
RETIRED
빌드에서 빠짐. 기록만 남음

상태 아래의 작은 글자는 예전 릴리스 상태 이름입니다. 전환 API 는 두 이름을 모두 받아 PromptBundleState 로 읽고, 영수증과 화면은 위의 정본 이름으로 적습니다.

릴리스를 ACTIVE 로 옮기면 같은 범위·프롬프트 키·템플릿의 다른 ACTIVE 릴리스가 DEPRECATED 가 되어 활성 릴리스는 하나만 남습니다. DEPRECATED 로는 같은 범위에 다른 활성 릴리스가 있을 때만 옮길 수 있습니다(NO_OTHER_ACTIVE_RELEASE).

현재 상태옮길 수 있는 상태
AVAILABLESHADOW, RETIRED
SHADOWCANARY, RETIRED
CANARYACTIVE, DEPRECATED, RETIRED
ACTIVECANARY, DEPRECATED, RETIRED
DEPRECATEDCANARY, RETIRED
RETIRED없음
기동 시 등록. 기동할 때 빌드의 번들을 PLATFORM_GLOBAL 범위에 등록합니다. 새 행은 디스크립터의 상태로 시작하므로 v19 번들은 ACTIVE, v20 초안은 AVAILABLE 로 시작합니다. 다만 ACTIVE 로 선언된 새 행은 같은 범위에 이 빌드가 실행하는 번들의 ACTIVE 릴리스가 이미 있으면 AVAILABLE 로 시작합니다. 코드 동기화가 게이트가 활성화한 릴리스의 기본 선택을 빼앗지 않게 하려는 것이며, 이 빌드가 더는 실행하지 않는 번들의 ACTIVE 행은 새 빌드 기본값을 막지 않습니다. 이후의 동기화는 없는 행을 만들고 코드가 소유한 내용을 갱신할 뿐, 운영 필드는 바꾸지 않습니다.

릴리스 게이트

모든 상태 전환은 PromptGovernanceReleaseGateService 를 거칩니다. 현재 상태에서 허용되지 않는 전환은 ILLEGAL_STATE_TRANSITION 으로 막히고, 그 밖에는 목표 상태에 필요한 증거를 확인합니다. 막힌 전환은 아무것도 바꾸지 않고 차단 사유와 함께 기록되며, 적용된 전환은 레지스트리 상태를 바꾸고 승인·롤백 상태를 기록한 뒤 런타임 캐시에 알립니다.

목표막히는 경우
SHADOWCHANGE_LEDGER_MISSING — 변경 기록이 없음
CANARYEVALUATION_NOT_FOR_BUNDLE_HASH, CHANGE_LEDGER_MISSING, MODEL_COMPATIBILITY_MISSING, BUDGET_PROFILE_MISSING, ROLLBACK_TARGET_MISSING
ACTIVECANARY 의 차단 사유에 더해 PROMPT_INJECTION_GATE_FAILED, NON_FUNCTIONAL_GATE_FAILED(지연·비용), EMPIRICAL_EVAL_MISSING, TEVV_GATE_NOT_READY(평가가 번들 매니페스트의 evaluationScenarioFamilies가 밝힌 시나리오 묶음을, 밝히지 않았으면 기본 묶음 PROMPT_INJECTION·TOOL_MISUSE·MEMORY_POISONING을 덮어야 함), TOKEN_COUNTING_POLICY_MISSING, CACHE_POLICY_MISSING, COMPACTION_POLICY_MISSING
DEPRECATEDROLLBACK_TARGET_MISSING

EVALUATION_NOT_FOR_BUNDLE_HASH 는 기록된 평가가 이 번들의 해시로 한 것이 아니라는 뜻입니다. 번들의 증거는 그 번들로 한 평가뿐입니다.

POST /contexa/admin/api/prompt-quality/releases/transition
Content-Type: application/json

{
  "registryScope": "PLATFORM_GLOBAL",
  "promptKey": "cortex.security-decision",
  "promptVersion": "<bundle version>",
  "targetReleaseStatus": "EVAL_ONLY",
  "rationale": "Open the shadow run of the candidate bundle"
}

응답은 전환 영수증입니다. 적용되면 200, 막히면 차단 사유와 함께 422 입니다. registryScope 를 비우면 PLATFORM_GLOBAL 입니다.

섀도 실행과 카나리

섀도 실행

섀도 실행은 후보 번들을 실제 요청에 돌려 보되 아무것도 결정하지 않게 합니다. 판정 번들을 어느 선택기가 고르든 레지스트리의 SHADOW 릴리스를 읽으므로, 설정 번들을 쓰는 호스트도 후보를 시험할 수 있습니다.

  • 표본 — 이벤트 ID 의 고정 해시가 contexa.security.tiered.prompt-bundle.shadow.sample-percent(0~100, 기본 0 은 실행 안 함)보다 작은 요청이 표본입니다. 섀도 실행기는 이 속성을 설정했을 때만 생깁니다.
  • 일일 상한 — UTC 하루에 shadow.daily-call-cap(기본 100)회까지 실행하며, 한 번에 모델 호출 하나입니다.
  • 판정과 분리 — 판정 전에 이벤트를 복사하고, 판정 뒤에 별도 실행기에서 분석해 SHADOW 단계로 봉인합니다. 복사본은 집행 처리기에 닿지 않으므로 아무것도 집행·학습되지 않고, 세션 컨텍스트에도 아무것도 더하지 않습니다.
  • 실행 가능한 번들만 — 이 빌드가 실행하지 않는 버전의 SHADOW 릴리스는 건너뜁니다.

카나리

selector=registry 일 때 CANARY 릴리스는 비율 안의 요청에 실행되고, 나머지는 최신 ACTIVE 릴리스를 씁니다. 비율은 레지스트리 행의 canary_percent(0~100, 값이 없으면 범위 전체)이며, 요청자(사용자, 없으면 세션, 없으면 이벤트)의 고정 해시에 적용합니다. 선택 항목인 canary_tenants 와 canary_resource_families 는 카나리를 그 테넌트와, 자원 주소가 목록의 계열로 시작하거나 자원 ID 가 같은 요청으로 좁힙니다.

롤백

PromptBundleRollbackService 는 범위에서 실행 중인 번들을 그 매니페스트가 선언한 롤백 대상으로 즉시 바꿉니다. 원래 번들은 DEPRECATED, 대상은 ACTIVE 가 되고, 런타임 캐시에 알린 뒤 확인한 조건과 함께 실행을 기록합니다. 거부된 롤백은 사유와 함께 기록되며 아무것도 바꾸지 않습니다.

거부 사유조건
SOURCE_NOT_EXECUTING원래 버전이 범위에서 ACTIVE 나 CANARY 가 아님
TARGET_NOT_IN_BUILD대상 매니페스트가 이 빌드에 없음
TARGET_NOT_DECLARED원래 매니페스트의 rollbackTargets 에 대상이 없음
VOCABULARY_INCOMPATIBLE대상 매니페스트가 지금 어휘 버전을 읽지 못함
TARGET_NOT_REGISTERED대상이 범위에 레지스트리 행이 없음
POLICY_SET_MISSING대상의 정책 세트가 없음(정책 세트가 없는 호스트는 NOT_APPLICABLE 로 기록)
POST /contexa/admin/api/prompt-quality/releases/rollback
Content-Type: application/json

{
  "registryScope": "PLATFORM_GLOBAL",
  "promptKey": "cortex.security-decision",
  "fromVersion": "<executing version>",
  "toVersion": "<rollback target>",
  "reason": "Decision quality dropped after the release",
  "emergency": false
}

결과에는 실행 키(RBX-...), 상태, 확인한 조건이 담깁니다. 상태는 EXECUTED 이거나 HTTP 422 와 함께 REFUSED 입니다. 긴급 중지("emergency": true)도 같은 방식으로 실행되고 AWAITING_APPROVAL 로 끝나며, 다른 관리자가 POST .../rollback/{executionKey}/approve 로 승인합니다. 실행한 운영자는 승인할 수 없습니다.

프롬프트 검수기

PromptInspector 는 봉인 증거 묶음에서 모델이 받은 사용자 프롬프트를 읽고, 검사마다 일치한 것·일치하지 않은 것·확인할 수 없는 것을 셉니다. 사람이 검토할 문제를 가리킬 뿐 프롬프트·판정·규칙은 바꾸지 않습니다. 자동 검수는 스케줄러 스레드에서 인스턴스 전체에 걸친 잠금 하나로 돌며, 아직 검수하지 않은 가장 오래된 묶음을 배치 크기만큼 검수합니다. 판정 스레드는 이를 실행하지 않습니다.

검사레이아웃대조하는 것
SEAL_INTEGRITY전체묶음 해시가 봉인 필드를 모두 덮는지, 시스템·사용자 프롬프트가 수집되어 해시와 맞는지, 그린 프롬프트와의 차이가 기록되었는지, 요청·상관 ID 가 있는지.
BUNDLE_TRACE전체봉인된 디스크립터가 레지스트리 릴리스를 가리키고, 계약 버전·아티팩트 해시·승인이 그 릴리스의 것인지. 릴리스 레지스트리가 없으면 모두 확인 불가입니다.
DICTIONARY_CONTRACTv20줄바꿈, 사전 순서의 블록 머리, 블록에 속한 항목 줄만 순서대로, 항목 형식이나 결측 문구의 값, 상한까지의 번호 줄, 그린 순서의 사실 ID.
DECISION_FACT_MATCHv20사전이 그리는 봉인 판정 사실마다 줄이 있고, 값이 글자 그대로 같고, 함께 봉인된 사실 ID 가 붙었는지.
FACT_ACCURACYv20프롬프트가 그린 사실을 봉인 원천과 필드 단위로 대조합니다(프롬프트를 다시 그리지 않음). REQUEST 블록에서는 주체, 시각, 역할, 권한, 행동, 대상, 크기, 등급, 네트워크, 기기를 봅니다. 원천이 봉인되지 않은 줄은 확인 불가로 셉니다.
UNKNOWN_DECLAREDv20엔진이 확정하지 못한 사실이 모두 종류와 함께 UNKNOWN 줄에 있고, 거기 적힌 사실이 다른 곳에 값으로 그려지지 않았는지. 값이 없을 때는 사전의 결측 표기대로 그렸는지도 봅니다. 결측 문구를 그리는 항목은 자기 줄에 그 문구를 그려야 합니다(세션이 없을 때처럼 렌더 규칙이 스스로 모름으로 정한 경우는 예외). 사전이 줄을 빼는 항목은 호출자가 표시하지 않았다면 UNKNOWN 줄에 이름이 없어야 합니다(과거 기록은 봉인된 검색이 가져오지 못했을 때만). 나머지 항목은 자기 줄이나 UNKNOWN 줄의 이름 가운데 하나가 있어야 합니다.
PAST_RECORD_NOTATIONv20PAST RECORDS 상태 줄이 그린 기록 수를 세는지, 기록 줄마다 12 칸이 있는지, 같은 대상 먼저·최신 먼저 순서인지.
SOURCE_TRUTHv20호스트의 PromptFactSourceVerifier 가 돌려준 호스트 자체 기록과 사실을 대조합니다. 없으면 호스트 원천이 연동되지 않았다고 기록합니다.
SAME_FACTv20프롬프트가 두 번 말하는 한 사실이 하나의 값인지.
REASON_MATCHv20봉인된 판정의 근거 코드마다 프롬프트 줄의 ID 를 인용하는지, 그 줄이 코드가 인용하는 줄인지, 코드의 조건이 봉인 컨텍스트에서 성립하는지.
  • 레이아웃 — v20 검사는 v20-dictionary-blocks 로 그린 묶음에서만 돕니다. 다른 번들의 사전이나 렌더로 그린 v20 묶음은 그 검사들에서 확인 불가로 셉니다.
  • 판정 — PASS(모두 일치), FAIL(불일치 하나 이상), INCOMPLETE(불일치는 없고 확인 불가가 있음), NOT_APPLICABLE(사전 프롬프트가 아니어서 레이아웃과 무관한 검사만 돔), ERROR(검수할 수 없음).
  • 발견 — MISMATCH 또는 UNVERIFIABLE. 확인 불가는 통과로 세지 않습니다.
  • 버전 — 결과마다 검수기 버전(prompt-inspector/N)과 사전 버전(v20@ 와 사전 다이제스트 앞부분)을 남깁니다. 검수기 버전이 바뀌면 묶음을 다시 검수합니다.

봉인 증거 표본과 보관

OSS 설치(contexa.enterprise.enabled 가 true 가 아님)에서 수집이 켜져 있으면(contexa.pqa.oss.sealed-evidence.capture-enabled, 기본 true) 판정을 증거 묶음으로 봉인합니다. 묶음에는 보낸 그대로의 시스템·사용자 프롬프트, 표준 컨텍스트, 실행 메타데이터가 들어갑니다. 엔터프라이즈는 봉인 묶음을 자체 스키마에 두므로, 엔터프라이즈가 켜져 있으면 OSS 검수기 빈은 만들어지지 않습니다.

  • 변경 뒤 구간 — 기동 뒤, 또는 실행 중 번들이 바뀐 뒤 첫 full-capture-after-change(기본 1000)건의 판정은 모두 봉인합니다.
  • 표본 — 그 구간이 지나면 상관 ID 의 고정 해시로 요청의 sample-percent(기본 1, 1~100)를 봉인합니다.
  • 보관 — 묶음은 retention.period(기본 90 일) 동안 보관합니다. 마지막 검수에서 문제가 없었던 묶음은 retention.clean-period(기본 30 일)가 지나면 지웁니다. 검수에서 무언가 찾은 묶음은 기본 보관 기간을 따릅니다.
  • 검수 표본 — 묶음 ID 의 고정 해시로 봉인 묶음의 contexa.prompt-inspection.sample-percent(기본 100)를 검수합니다.

콘솔과 API

모든 화면과 엔드포인트는 ADMIN 역할이 필요합니다.

메서드경로용도
GET/contexa/admin/prompt-inspection검수 개요 화면(/packages, /packages/{packageId} 도 있음)
GET/contexa/admin/api/prompt-inspection/overview기간별 집계(from, to. 기본은 최근 7 일)
GET/contexa/admin/api/prompt-inspection/packages검수한 묶음 목록. 판정·검사 코드·블록·항목으로 거름
GET/contexa/admin/api/prompt-inspection/packages/{packageId}묶음 하나와 그 발견
POST/contexa/admin/api/prompt-inspection/packages/{packageId}/reinspect묶음 하나 재검수
POST / GET/contexa/admin/api/prompt-inspection/reinspections수집 기간 재검수를 자동 검수에 요청하고, 진행 상황을 읽음
GET/contexa/admin/api/prompt-quality/releases레지스트리 릴리스(registryScope 선택)
POST/contexa/admin/api/prompt-quality/releases/transition릴리스 게이트를 거치는 상태 전환
POST/contexa/admin/api/prompt-quality/releases/rollback롤백 또는 긴급 중지
POST/contexa/admin/api/prompt-quality/releases/rollback/{executionKey}/approve긴급 중지의 두 번째 승인

설정

속성타입기본값설명
contexa.security.tiered.prompt-bundle.activeString(비움)설정 선택기가 실행할 번들 버전. 비우면 빌드 기본 번들.
contexa.security.tiered.prompt-bundle.selectorEnumCONFIGURATIONCONFIGURATION 또는 REGISTRY.
contexa.security.tiered.prompt-bundle.shadow.sample-percentint0섀도 릴리스를 실행할 요청 비율(0~100).
contexa.security.tiered.prompt-bundle.shadow.daily-call-capint100UTC 하루에 허용하는 섀도 실행 수.
contexa.prompt.governance.enabledbooleantrue레지스트리·릴리스 게이트·롤백·릴리스 API 를 함께 켜고 끔.
contexa.prompt-inspection.enabledbooleantrue검수기, 자동 검수, 재검수, 콘솔(OSS 전용).
contexa.prompt-inspection.intervalDurationPT30S자동 검수 사이 간격.
contexa.prompt-inspection.initial-delayDurationPT30S첫 검수 전 대기.
contexa.prompt-inspection.batch-sizeint50한 번에 검수할 묶음 수(1 이상).
contexa.prompt-inspection.sample-percentint100검수할 봉인 묶음 비율(1~100).
contexa.pqa.oss.sealed-evidence.capture-enabledbooleantrue판정을 증거 묶음으로 봉인(OSS 전용).
contexa.pqa.oss.sealed-evidence.sample-percentint1변경 뒤 구간이 지난 뒤 봉인할 요청 비율(1~100).
contexa.pqa.oss.sealed-evidence.full-capture-after-changeint1000기동이나 번들 변경 뒤 모두 봉인할 판정 수.
contexa.pqa.oss.sealed-evidence.retention.enabledbooleantrue보관 작업 실행.
contexa.pqa.oss.sealed-evidence.retention.periodDuration90d봉인 묶음 보관 기간.
contexa.pqa.oss.sealed-evidence.retention.clean-periodDuration30d마지막 검수에서 문제가 없던 묶음의 보관 기간.
contexa:
  security:
    tiered:
      prompt-bundle:
        selector: registry
        shadow:
          sample-percent: 5
          daily-call-cap: 100
  prompt-inspection:
    batch-size: 50
    sample-percent: 100
  pqa:
    oss:
      sealed-evidence:
        sample-percent: 1
        full-capture-after-change: 1000

최소 대응 규칙과 프롬프트 예산 설정은 AI 엔진 구성에 있습니다.