docs: strengthen DDS protection review criteria

This commit is contained in:
devmrko
2026-06-30 20:13:09 +09:00
parent eea7bf0974
commit 699a1ac127
5 changed files with 227 additions and 34 deletions

View File

@@ -0,0 +1,41 @@
# #606 설계 보완 기준 — 보호 상태·증거 계약
## 목적
DDS 보호 객체 × 집행 경로의 상태를 재현 가능하게 계산한다. 이 계약은 #608 구현의 선행 조건이다.
## 상태 계약
각 상태 응답에는 아래 세 축을 반드시 포함한다.
| 축 | 값 |
|---|---|
| 관측 가능성 | `OBSERVED`, `PARTIAL`, `UNAVAILABLE` |
| 선언 동기화 | `MATCHED`, `NOT_PUBLISHED`, `DRIFTED`, `UNKNOWN` |
| 실행 검증 | `PASSED`, `FAILED`, `STALE`, `NOT_RUN`, `UNKNOWN` |
대표 상태는 `확인 불가 → 조치 필요 → 재검증 필요 → 보호 확인` 순으로 결정하되, 근거 축을 감추지 않는다. `PARTIAL`은 보호 확인으로 승격할 수 없다.
## 기대 명세와 실제 관측
- 토큰 서비스 경로는 기술 사용자, 객체, DATA GRANT/함수/공통 권한 schema version을 immutable 명세로 남긴다.
- 직접 비교 경로는 사용자·Role별 컴파일 결과를 게시 계획 snapshot으로 남긴다.
- 명세에는 `protectionObjectId`, 집행 경로, 객체·컬럼 범위, Role/기술 사용자, canonical predicate hash, 작성 시각, 작성자, 승인 참조, 명세 version을 포함한다.
- canonicalization/hash 정규화 규칙 자체도 schema version으로 보존한다.
- 실제 관측은 catalog capability matrix를 거친다. `DBA_DATA_GRANTS`로 확인되는 grant/object/grantee와 predicate·컬럼 범위를 비교하는 승인된 추가 원천을 구분한다.
- 비교할 수 없는 필드는 `PARTIAL`/`UNKNOWN`으로 처리하며 `MATCHED`로 표시하지 않는다.
## 오류·감사·최신성
- dictionary 권한 부족, 연결 오류, timeout, 빈 inventory, 실제 Grant 없음은 별도의 안전한 오류 code로 구분한다.
- 마지막 관측·마지막 정상 관측·correlation ID·관측 권한 범위를 기록한다.
- 토큰 공통 권한 변경은 런타임 반영, 직접 비교 권한 변경은 별도 게시라는 최신성 계산 규칙을 명시한다.
- 게시 이력은 명세 version/hash, 실행자, 사유, 승인, DB 결과, rollback 참조를 append-only로 보존한다.
## 검증 증거
fixture version, 명세 hash, 집행 경로, 주체 유형, control query, 반환/제외 수, 결과, 시각, 안전한 오류 분류를 기록한다. 검색 0건만으로 권한 차단을 판정하지 않는다.
## 완료 기준
상태 전이/우선순위표, API·persistence schema, catalog capability matrix, hash normalizer, fixture manifest와 sample record를 제공한다. #607·#608·#609가 동일한 contract를 소비할 수 있어야 한다.

View File

@@ -0,0 +1,32 @@
# #607 UX 보완 기준 — 객체 상태와 고급 검증 분리
## 기본 구조
- 기본 화면은 토큰 기반 서비스 경로만 보여 준다.
- 객체 행에는 대표 상태, 동기화/검증 근거 배지, 마지막 관측·검증, 추천 조치 하나만 둔다.
- DDS END USER 직접 비교는 명시적인 `고급 검증` 진입 뒤에만 제공한다.
- `dds_demo_*`는 제품 계정이 아닌 `직접 비교용 검증 프로필`로 표기하며 자격증명은 보이지 않는다.
## 필수 상태
`보호 확인`, `조치 필요`, `재검증 필요`, `확인 불가`, `반영 중`의 대표 상태와 `드리프트`, `검증 실패`, `관측 일부` 등의 근거 배지를 함께 설계한다. #606의 세 상태 축을 한 값으로 축소하지 않는다.
객체 0개, 다수 객체 필터·정렬, 오래된 검증, 일부 catalog만 관측됨, inventory 오류, 권한 없는 상세, 390px 화면, 200% 확대, 키보드/스크린리더 탭 상태를 포함한다.
## 정보 노출
| 권한 | 제공 정보/행동 |
|---|---|
| 상태 조회 | 대표 상태, 안전한 사유, 마지막 관측 |
| 진단 | 객체명·Role·안전한 diff 요약 |
| 게시 | 미리보기, 사유·영향·승인 뒤 게시/회수 |
raw predicate, catalog 원문, 비밀, 차단 TAG, 원문 청크, DB 오류 원문은 일반 화면에 제공하지 않는다.
## URL·용어
DDS canonical route와 기존 `/vpd-policies` redirect/호환 기간을 제안한다. `0건 검색``차단`이라는 상태 문구로 사용하지 않는다.
## 산출물과 완료 기준
화면 지도, 상태 매트릭스, 와이어프레임, CTA/빈/오류/처리 상태, 권한별 정보 노출표, 표준 용어, 접근성 명세를 낸다. 운영자는 설명을 열지 않고 상태·관측 시각·다음 행동을 이해하고, 두 집행 경로를 같은 계정이나 같은 기능으로 오해하지 않아야 한다.

View File

@@ -0,0 +1,25 @@
# #608 개발 보완 기준 — 보호 연결 화면
## 선행 조건
#606의 상태·증거 contract와 #607의 UX 설계가 승인된 뒤 시작한다.
## 구현 범위
- 보호 객체 × 집행 경로 상태 조회 service/controller/view model
- 관측 가능성, 선언 동기화, 실행 검증의 세 상태 축과 대표 상태·근거 배지 렌더링
- 기본 토큰 서비스 화면과 고급 DDS END USER 직접 비교 분리, 기본 표면의 `dds_demo_*` 제거
- catalog 오류의 안전한 메시지, correlation ID, 마지막 정상 관측, 반영 중 처리
- 권한별 안전한 diff 요약과 객체 상세
- DDS canonical route 및 기존 URL redirect
- token/context/credential/raw predicate/차단 TAG/원문이 browser와 감사 메모에 노출되지 않도록 처리
## 제약
- DATA GRANT DDL 정책 변경이나 운영 객체 회수는 이 이슈의 범위가 아니다.
- `DBA_DATA_GRANTS`만으로 비교할 수 없는 필드를 정상으로 선언하지 않는다.
- connection pool을 사용하거나 도입할 때에는 Context reset/잔류 검증을 포함한다.
## 완료 기준
#581의 구현 완료 조건과 #609의 fixture 기반 회귀가 통과한다. 토큰 권한 변경의 런타임 반영과 직접 비교 Grant의 별도 게시 상태를 혼동하지 않아야 한다.

View File

@@ -0,0 +1,30 @@
# #609 QA 보완 기준 — 증거 기반 회귀 검증
## 목적
검색 0건을 권한 차단으로 오판하지 않고 DDS 보호 연결 상태를 검증한다.
## 필수 fixture
| fixture | 확인할 사실 |
|---|---|
| 허용 TAG 문서 | 권한 있는 주체가 결정적으로 1건 이상 본다. |
| 거부 TAG 문서 | 같은 조건에서 노출되지 않는다. |
| 경계 TAG 문서 | 다중 TAG OR, DENY 우선, 역할 상속이 맞다. |
| 권한 없음 주체 | default deny가 안전한 제품 오류 분류로 보인다. |
fixture manifest/version과 control query를 버전 관리한다.
## 검증 매트릭스
- 토큰 서비스와 END USER 직접 비교 각각
- `OBSERVED/PARTIAL/UNAVAILABLE`, `MATCHED/NOT_PUBLISHED/DRIFTED/UNKNOWN`, `PASSED/FAILED/STALE/NOT_RUN` 및 대표 상태 우선순위
- dictionary 권한 부족, timeout, 빈 inventory, 실제 Grant 없음, publish 중
- 권한 변경 뒤 토큰 런타임 반영과 직접 비교의 게시 필요 여부
- connection pool 또는 재사용 세션에서 Context가 다음 요청에 잔류하지 않음
- credential/token/raw predicate/차단 TAG/DB 오류 원문 비노출
- 기본/고급 탭 분리, keyboard/screen reader, 390px, 200% 확대, canonical/legacy URL redirect
## 증거와 완료 기준
실행마다 fixture version, 명세 hash, 경로, 주체 유형, control query, 반환/제외 수, 시각, correlation ID를 남긴다. 결과 0건만으로 보호 성공/실패를 판정하는 테스트가 없어야 하며, `PARTIAL`/`UNAVAILABLE`이 정상으로 표시되면 실패다.

View File

@@ -6,13 +6,15 @@
> >
> **목적** — 구현 전, 보호 객체 상태와 DDS 집행 경계를 운영자가 판단할 수 있는지 검토한다. > **목적** — 구현 전, 보호 객체 상태와 DDS 집행 경계를 운영자가 판단할 수 있는지 검토한다.
> **하위 실행 기준** — [#606 설계](606-security-design.md) · [#607 UX](607-ux.md) · [#608 개발](608-implementation.md) · [#609 QA](609-qa.md)
## 1. 이 페이지에서 사용자가 끝내야 하는 일 ## 1. 이 페이지에서 사용자가 끝내야 하는 일
이 페이지의 1차 사용자는 보안 설계자와 권한 운영자다. 사용자는 다음 네 질문에 답을 얻고 화면을 떠나야 한다. 이 페이지의 1차 사용자는 보안 설계자와 권한 운영자다. 사용자는 다음 네 질문에 답을 얻고 화면을 떠나야 한다.
1. 어떤 보호 객체가 실제로 DDS에 의해 보호되고 있는가? 1. 어떤 보호 객체가 실제로 DDS에 의해 보호되고 있는가?
2. 그 객체 토큰 기반 서비스 경로인지, DDS END USER 직접 비교 경로인지? 2. 그 객체 토큰 기반 서비스 경로 DDS END USER 직접 비교 경로 중 어느 집행 방식이 선언됐는가? 한 객체가 두 경로를 함께 가질 수 있는가?
3. 공통 권한의 변경이 DATA GRANT에 반영됐고 최근 검증까지 통과했는가? 3. 토큰 경로의 런타임 권한 기준과 직접 비교 경로의 마지막 게시 스냅샷은 각각 최신이며, 최근 검증까지 통과했는가?
4. 정상·미게시·드리프트·실패 중 어떤 조치를 해야 하는가? 4. 정상·미게시·드리프트·실패 중 어떤 조치를 해야 하는가?
현재 화면은 공통 권한, 보호 객체, 역할 규칙, 검증 사용자 설명을 모두 보여 주지만 위 질문에 직접 답하지 못한다. 현재 화면은 공통 권한, 보호 객체, 역할 규칙, 검증 사용자 설명을 모두 보여 주지만 위 질문에 직접 답하지 못한다.
@@ -28,41 +30,54 @@
| 역할·규칙 표가 중심 | 실제 DATA GRANT의 존재, 최신성, 검증 결과를 알 수 없다. | | 역할·규칙 표가 중심 | 실제 DATA GRANT의 존재, 최신성, 검증 결과를 알 수 없다. |
| 상태/차이/게시 이력이 없음 | 운영자가 다음 행동을 고를 수 없다. | | 상태/차이/게시 이력이 없음 | 운영자가 다음 행동을 고를 수 없다. |
## 3. 반드시 분리할 두 경로 ## 3. 반드시 분리할 두 경로와 게시 경계
| 구분 | 토큰 기반 서비스 경로 | DDS END USER 직접 비교 | | 구분 | 토큰 기반 서비스 경로 | DDS END USER 직접 비교 |
|---|---|---| |---|---|---|
| 목적 | 제품의 권한 기반 지식 검색 | DDS 선언형 identity/Data Role 동작 검증 | | 목적 | 제품의 권한 기반 지식 검색 | DDS 선언형 identity/Data Role 동작 검증 |
| identity | 기술 사용자 세션 + Bearer로 만든 애플리케이션 Context | DDS `END USER` | | identity | 기술 사용자 세션 + Bearer로 만든 애플리케이션 Context | DDS `END USER` |
| 집행 | 객체별 `DATA GRANT` predicate가 공통 권한 테이블 평가 | `END USER → DATA ROLE → DATA GRANT` | | 집행 | 기술 사용자에 연결된 객체별 `DATA GRANT` predicate가 `CB_AGENT_CTX` 공통 권한 테이블을 요청 시 평가 | `END USER → DATA ROLE → DATA GRANT` |
| 권한 변경 반영 | 토큰 해석 뒤 predicate가 공통 권한을 읽으므로, 공통 권한 변경은 다음 요청에 반영된다. 단, Grant/함수/객체 선언 자체는 별도 게시·관찰 대상이다. | 유효 권한을 사용자별 predicate로 컴파일한 뒤 별도 게시한다. 공통 권한 변경만으로 기존 Grant는 갱신되지 않는다. |
| 기본 노출 | 기본 화면 | 고급 검증 | | 기본 노출 | 기본 화면 | 고급 검증 |
| 주 사용 빈도 | 일상 운영 | 정책/장애 조사 | | 주 사용 빈도 | 일상 운영 | 정책/장애 조사 |
Bearer 값을 DB 변수나 사용자명으로 매핑하는 것만으로 순수 DDS END USER Context가 만들어지지는 않는다. 그래서 기본 서비스 경로와 직접 비교 경로는 같은 탭, 같은 카드, 같은 용어로 다루면 안 된다. Bearer 값을 DB 변수나 사용자명으로 매핑하는 것만으로 순수 DDS END USER Context가 만들어지지는 않는다. 그래서 기본 서비스 경로와 직접 비교 경로는 같은 탭, 같은 카드, 같은 용어로 다루면 안 된다.
## 4. 보호 객체 상태 모델 이 표는 **보호 객체가 둘 중 하나만 선택해야 한다**는 뜻이 아니다. 같은 VIEW에 토큰용 `DATA GRANT`와 직접 비교용 `DATA GRANT`가 함께 있을 수 있다. 상태·검증 이력·조치도 객체 단위만이 아니라 `보호 객체 × 집행 경로` 단위로 보관한다.
| 상태 | 판정 근거 | 화면 문구 | 조치 | ## 4. 보호 객체 상태 계약
`정상/드리프트/검증 실패`를 서로 배타적인 하나의 값으로 두면 운영 사실이 사라진다. 예를 들어 Grant가 드리프트이면서 마지막 검증도 실패할 수 있다. 따라서 서버는 아래 세 축을 독립적으로 반환하고, UI는 대표 상태와 근거 배지를 함께 보여 준다.
| 상태 축 | 값 | 판정 근거 | 대표 조치 |
|---|---|---|---| |---|---|---|---|
| 정상 | 기대 Grant 정의와 실제 inventory가 일치하고 최근 검증 통과 | 보호 중 | 검색 검증 또는 상세 보기 | | 관측 가능성 | `OBSERVED` / `PARTIAL` / `UNAVAILABLE` | DDS catalog·권한 원천·검증 이력 중 필요한 원천을 모두 읽었는지 | 원천 연결/권한 점검 |
| 미게시 | 기대 Grant는 있으나 실제 inventory에 없음 | 권한 변경 반영 필요 | 변경 미리보기 | | 선언 동기화 | `MATCHED` / `NOT_PUBLISHED` / `DRIFTED` / `UNKNOWN` | 기대 명세와 실제 객체·Role·컬럼 범위·비교 가능한 predicate 표현의 차이 | 미리보기·재게시·차이 조사 |
| 드리프트 | 객체/Role/predicate/컬럼 범위 중 하나가 기대와 다름 | DDS 선언 차이 발견 | 차이 확인 후 재게시 | | 실행 검증 | `PASSED` / `FAILED` / `STALE` / `NOT_RUN` / `UNKNOWN` | 결정적 허용/거부/경계 시나리오가 현재 명세 이후에 통과했는지 | 검증 실행·접근 근거 조사 |
| 검증 실패 | Grant는 있으나 허용·차단 시나리오가 실패 | 보호 결과 확인 필요 | 접근 근거 조사 |
| 검증 만료 | 마지막 검증이 권한 또는 Grant 변경보다 이전 | 재검증 필요 | 검색 검증 |
| 메타데이터 오류 | inventory 또는 권한 원천 조회 불가 | 상태를 확인할 수 없음 | DB/권한 연결 점검 |
역할 수와 권한 규칙 수는 상태를 보조하는 지표일 뿐, 정상 판정 근거가 아니다. 대표 상태는 다음 우선순위로 정한다. 다만 보조 축의 값을 숨기지 않는다.
## 5. 필요한 데이터 계약 1. `확인 불가` — 관측 가능성이 `UNAVAILABLE`이거나, 정상 판정에 필요한 비교 원천이 없다.
2. `조치 필요``NOT_PUBLISHED`, `DRIFTED`, 또는 `FAILED`가 하나 이상 있다. 원인을 배지로 병기한다.
3. `재검증 필요` — 선언은 `MATCHED`지만 검증이 `STALE` 또는 `NOT_RUN`이다.
4. `보호 확인``OBSERVED`, `MATCHED`, `PASSED`가 모두 충족되고, 검증 시각이 마지막 관련 변경보다 뒤다.
| 데이터 | 최소 필드 | 원천 | 용도 | `PARTIAL` 관측은 상세에 부족한 비교 필드를 표시하되, `보호 확인`으로 승격할 수 없다. 역할·권한 규칙의 건수도 보조 지표일 뿐, 이 계약의 정상 판정 근거가 아니다.
## 5. 기대값·실제값·검증 증거 데이터 계약
| 데이터 | 최소 필드 | 권위 있는 원천 | 용도 |
|---|---|---|---| |---|---|---|---|
| 기대 Grant 정의 | 보호 객체, Data Role, predicate hash, 제외 컬럼, 권한 기준 버전 | 권한 게시 계획/객체 매핑 | 실제와의 비교 | | 기대 명세 | `protectionObjectId`, 집행 경로, Data Role/기술 사용자, 객체·컬럼 범위, predicate의 canonical hash, 공통 권한/함수/객체 버전, 작성 시각 | **승인된 게시 계획의 immutable snapshot**. 현재 권한 화면의 즉시 조회값이 아니다. | 실제와의 비교, 검증 대상 고정 |
| 실제 Grant inventory | Grant 이름, 객체, Data Role, predicate, 컬럼 범위, 조회 시각 | `DBA_DATA_GRANTS`, 관련 dictionary | 정상/드리프트 판정 | | 실제 관측 | Grant 이름, 객체, grantee, 컬럼 범위, 비교 가능한 선언 fingerprint, catalog 조회 시각·권한 범위 | DDS catalog adapter. 현재 `DBA_DATA_GRANTS` 조회만으로 확인할 수 있는 필드와 별도 비교 원천을 명시한다. | 동기화·관측 가능성 판정 |
| 게시 이력 | 계획 ID, 실행자, 사유, 전후 버전, DB 결과 | 게시 감사 기록 | 변경 추적/복구 | | 게시 이력 | 계획 ID, 명세 version/hash, 실행자, 사유·승인 참조, 전후 version, DB 결과, rollback 참조 | append-only 게시 감사 기록 | 변경 추적/복구 |
| 검증 이력 | 시나리오, 경로, 시각, 결과, 안전한 실패 분류 | 검증 기록 | 최근성/실패 판정 | | 검증 증거 | fixture ID, 경로, 주체 유형, 명세 version/hash, query/control query, 허용·거부·경계 결과, 반환/제외 수, 시각, 안전한 실패 분류, correlation ID | 검증 실행 기록 | 실행 검증·최근성 판정 |
상태 계산이 실패했을 때 0건이나 정상으로 폴백하면 안 된다. 메타데이터 오류는 독립 상태다. canonical hash는 비교에 의미 없는 공백·대소문자·정렬 차이로 드리프트가 발생하지 않게 정규화한 명세에서 계산한다. 다만 정규화 규칙의 변경도 schema version으로 기록한다. raw predicate를 모든 운영자에게 보여 주거나 browser에 저장해서는 안 된다.
`DBA_DATA_GRANTS`는 현재 SQL에서 Grant 이름·객체·grantee를 확인하는 용도로 쓰인다. 이 정보만으로 predicate 또는 컬럼 범위까지 동일하다고 판정할 수 없다. 해당 Database release에서 허용된 추가 catalog/DDL fingerprint 조회가 없으면 관측 상태는 `PARTIAL`이어야 하며, `MATCHED``보호 확인`으로 표시하지 않는다.
상태 계산이 실패했을 때 0건이나 정상으로 폴백하면 안 된다. `UNAVAILABLE`은 연결 오류, dictionary 권한 부족, timeout을 구분한 안전한 오류 분류와 마지막 정상 관측 시각을 동반한다.
## 6. 제안 정보 구조 ## 6. 제안 정보 구조
@@ -70,12 +85,14 @@ Bearer 값을 DB 변수나 사용자명으로 매핑하는 것만으로 순수 D
상단에는 전체 상태와 추천 행동 하나를 둔다. 예시는 `1개 보호 객체 반영 필요 → 변경 미리보기`다. 상단에는 전체 상태와 추천 행동 하나를 둔다. 예시는 `1개 보호 객체 반영 필요 → 변경 미리보기`다.
그 아래 객체 표는 다음 열을 사용한다. 그 아래 객체 표는 **토큰 기반 서비스 경로**의 현재 보호 상태만 기본으로 보여 준다. 행을 열면 객체 상세에서 다른 집행 경로와 기술 근거를 볼 수 있다.
| 보호 객체 | 업무 권한 대상 | DATA GRANT 상태 | 마지막 게시 | 마지막 검증 | 조치 | | 보호 객체 | 대표 상태 | 동기화/검증 근거 | 마지막 관측 | 마지막 검증 | 조치 |
|---|---|---|---|---|---| |---|---|---|---|---|---|
기술 SQL, predicate 전체 텍스트, dictionary 원문은 객체 상세에서만 펼친다. 대표 상태는 `보호 확인`, `조치 필요`, `재검증 필요`, `확인 불가` 중 하나이며, `드리프트`, `검증 실패`, `관측 일부` 같은 근거 배지를 병기한다. 기본 표면에는 기술 SQL, raw predicate, dictionary 원문, 비밀·원문 데이터를 두지 않는다.
객체가 0개면 보호 범위가 아직 정의되지 않았다는 빈 상태와 `보호 객체 등록` 경로를 보인다. 다수 객체에서는 대표 상태, 이름, 마지막 관측/검증, 집행 경로로 필터·정렬하고, 게시 중인 객체에는 stale 데이터를 정상으로 보이지 않게 `반영 중` 처리를 한다.
### 고급: DDS END USER 직접 비교 ### 고급: DDS END USER 직접 비교
@@ -86,26 +103,74 @@ Bearer 값을 DB 변수나 사용자명으로 매핑하는 것만으로 순수 D
- Data Role 매핑 여부 - Data Role 매핑 여부
- 마지막 직접 비교 결과 - 마지막 직접 비교 결과
직접 비교 탭은 기본 화면과 URL을 분리하거나, 최소한 명시적인 `고급 검증` 진입과 탭 역할·선택 상태를 제공한다. 데모 프로필은 제품 계정처럼 보이지 않게 fixture 목적과 만료/비활성 상태를 함께 표시한다.
### 객체 상세과 조치 권한
| 정보 또는 조치 | 일반 보호 상태 조회자 | 진단 권한자 | 게시 권한자 |
|---|---|---|---|
| 대표 상태·안전한 사유·마지막 관측 | 가능 | 가능 | 가능 |
| 객체명·Role·안전한 diff 요약 | 정책상 허용된 범위만 | 가능 | 가능 |
| raw predicate·catalog 원문·진단 로그 상관관계 | 불가 | 승인된 별도 화면/로그 | 필요 시 별도 감사 |
| 미리보기 | 불가 또는 요약만 | 가능 | 가능 |
| 게시·회수 | 불가 | 불가 | 사유·영향 확인·승인/감사 후 가능 |
위 권한명은 제품에서 구현할 개념적 capability다. 기존 관리자 로그인 권한과 동일하다고 가정하지 않으며, 실제 role mapping은 권한 설계에서 별도로 결정한다.
## 7. 오류와 누설 방지 ## 7. 오류와 누설 방지
- 일반 운영 화면에는 권한이 없는 객체의 이름, 금지된 TAG, 원문, predicate 상세를 오류 원인으로 노출하지 않는다. - 일반 운영 화면에는 권한이 없는 객체의 이름, 금지된 TAG, 원문, predicate 상세를 오류 원인으로 노출하지 않는다.
- 토큰 경로에서 Grant 정보가 부족하더라도 `권한을 확인할 수 없음`처럼 안전한 상태와 운영자 조치만 표시한다. - 토큰 경로에서 Grant 정보가 부족하더라도 `권한을 확인할 수 없음`처럼 안전한 상태와 운영자 조치만 표시한다.
- 직접 비교 프로필의 비밀번호 누락은 서비스 경로의 보호 실패가 아니라 고급 검증 구성 문제로 분리한다. - 직접 비교 프로필의 비밀번호 누락은 서비스 경로의 보호 실패가 아니라 고급 검증 구성 문제로 분리한다.
- inventory 조회 실패는 반드시 조회 시각과 오류 범위를 표시하고, 정상 상태 배지로 덮지 않는다. - inventory 조회 실패는 반드시 조회 시각과 오류 범위를 표시하고, 정상 상태 배지로 덮지 않는다. browser에는 DB 오류 원문 대신 correlation ID와 안전한 조치만 표시한다.
- Bearer 원문, END USER 비밀번호, 원문 청크, 차단된 TAG, 전체 predicate는 화면·감사 메모·URL query string에 기록하지 않는다.
- 토큰 Context는 요청 단위로 설정·해제되고, connection pool을 도입할 경우 다음 요청에 Context가 잔류하지 않는 검증을 필수로 한다.
## 8. 페르소나 최종 판정 ## 8. 검증 증거와 0건 해석
벡터 검색의 0건은 권한 차단, 관련 문서 부재, embedding 차이, 상위 N 제한 중 무엇 때문인지 알 수 없다. 따라서 `반환 0건`만으로 `검증 실패` 또는 `차단 성공`을 판정하면 안 된다.
각 집행 경로에는 다음처럼 결정적인 fixture를 둔다.
| fixture | 목적 | 검증 방식 |
|---|---|---|
| 허용 TAG 문서 | 올바른 주체가 최소 1건을 볼 수 있음 | fixture 문서 ID를 포함하는 control query 또는 객체 조회를 사용해 1건 이상 반환 확인 |
| 거부 TAG 문서 | 허용되지 않은 자료가 노출되지 않음 | 같은 조건에서 fixture ID가 결과에 없는지 확인 |
| 경계 TAG 문서 | 다중 TAG OR, DENY 우선, 역할 상속의 경계를 검증 | 기대 결과 집합을 fixture manifest와 비교 |
| 권한 없음 주체 | default deny가 예상대로 동작 | 객체 미노출/권한 오류를 제품이 정한 안전한 분류로 확인 |
검증 이력에는 검색 결과만이 아니라 fixture manifest version, 명세 version/hash, query/control query, 반환 수·제외 수, 주체 유형, 시각, 실행 경로를 저장한다. 검색 관련도 자체를 검증하는 시나리오와 권한 집행을 검증하는 시나리오는 분리한다.
## 9. URL·용어 이전 기준
사용자 표면에서 VPD 잔재를 없애려면 제목만 바꾸면 안 된다. DDS canonical route를 먼저 정하고 메뉴·공유 링크·breadcrumb·감사 표기에 같은 명칭을 쓴다. 기존 `/vpd-policies`는 호환 기간 동안 DDS canonical route로 redirect하되, redirect 기간·북마크 영향·운영 로그의 옛 경로 표기 방식을 릴리스 결정으로 남긴다.
## 10. 페르소나 최종 판정
| 페르소나 | 최종 요구 | | 페르소나 | 최종 요구 |
|---|---| |---|---|
| UI/UX 전문가 | 설명을 줄이는 것만으로 부족하다. 객체 상태와 다음 행동을 최상단으로 올려야 한다. | | UI/UX 전문가 | 설명을 줄이는 것만으로 부족하다. 객체 상태와 다음 행동을 최상단으로 올려야 한다. |
| 보안 설계자 | 두 identity model을 분리하고 기대/실제/검증의 세 원천을 비교해야 한다. | | 보안 설계자 | 두 identity model과 두 반영 방식을 분리하고, immutable 기대 명세·실제 관측·검증 증거를 비교해야 한다. |
| 운영 사용자 | 데모 계정이 아니라 객체별 보호 상태, 마지막 게시·검증, 즉시 실행할 조치를 원한다. | | 운영 사용자 | 데모 계정이 아니라 객체×집행 경로별 보호 상태, 관측 신선도, 마지막 게시·검증, 즉시 실행할 조치를 원한다. |
## 9. 완료 조건 ## 11. 구현 착수 게이트와 완료 조건
1. 기본 화면에는 `dds_demo_*` 카드가 없다. 다음 항목이 #606 설계와 #607 UX에서 승인되기 전에는 #608 화면 구현을 시작하지 않는다.
2. 각 보호 객체는 정상·미게시·드리프트·검증 실패·검증 만료·메타데이터 오류 중 하나로 표시된다.
3. 토큰 기반 서비스 경로와 DDS END USER 직접 비교가 탭/배지/도움말로 분리된다. 1. 상태 세 축·대표 상태 우선순위·`PARTIAL`의 승격 금지 규칙을 API contract와 fixture로 확정한다.
4. 기대 Grant와 실제 Grant의 차이를 사용자 영향과 함께 확인할 수 있다. 2. 토큰 경로와 직접 비교 경로 각각의 immutable 기대 명세, canonical hash, catalog adapter 범위, 게시/권한 변경의 최신성 규칙을 확정한다.
5. 사용자 표면에서 VPD route/용어가 노출되지 않는다. 3. 실제 catalog가 비교하지 못하는 필드는 `PARTIAL`로 표기하는 방식을 확정한다.
6. 상태 계산, 드리프트, 오류, 탭 분리에 대한 unit·integration·UI 회귀 검증이 있다. 4. 허용·거부·경계·권한 없음 fixture와 control query, 검증 증거 보존 기간을 확정한다.
5. 대표 상태/근거 배지/다객체·빈·반영 중/오류 상태와 권한별 상세 노출을 와이어프레임으로 확정한다.
6. DDS canonical route와 기존 `/vpd-policies`의 redirect·호환 방식을 릴리스 계획에 기록한다.
구현 완료 조건은 다음과 같다.
1. 기본 화면에는 `dds_demo_*` 카드가 없고, 토큰 기반 서비스 경로의 객체 상태와 추천 조치만 보인다.
2. 동일 객체의 토큰/직접 비교 상태는 분리해 추적할 수 있으며, 한 객체가 두 경로를 함께 지원해도 혼동되지 않는다.
3. 대표 상태는 관측·동기화·검증의 근거 배지와 마지막 관측 시각을 동반하며, 불완전 관측을 정상으로 표시하지 않는다.
4. 기대/실제 선언의 차이는 raw predicate를 불필요하게 노출하지 않고 사용자 영향과 함께 확인할 수 있다.
5. 0건 검색을 권한 차단으로 단정하지 않으며, fixture 기반 허용·거부·경계 검증이 자동화되어 있다.
6. 토큰·비밀번호·차단 TAG·원문·DB 오류 원문이 브라우저와 감사 메모에 누설되지 않는다.
7. 사용자 표면에서 VPD route/용어가 노출되지 않고, 기존 URL은 정의된 호환 정책에 따라 처리된다.
8. 상태 계산, catalog 오류, drift, 검증 freshness, Context 잔류, 기본/고급 탭 분리에 대한 unit·integration·UI 회귀 검증이 있다.