앞의 일곱 장은 WIA-ENE-057 구현체가 무엇을 하는지를 설명했다. 구현체는 SAHEL-REGION-001 같은 위치에 대한 식생·토양·강수·토지이용 레코드를 받아들이고, 사막화 위험을 점수화하고, 복원 사업을 추적하고, 경보를 스트리밍하며, GIS 도구와 보고 프레임워크와 데이터를 주고받는다. 이 마지막 장은 다른 질문을 던진다. 구현체 바깥의 누군가가 그 일들이 올바르게 수행된다고 믿게 되는 근거는 무엇인가? 토지 모니터링 플랫폼은 그 산출물을 공급업체의 말에 기대지 않고 확인할 수 있을 때에만 정부 부처, 공여 기관, 감사인에게 쓸모가 있다.
표준은 세 개의 적합성 등급, 시험 벡터 원칙, 서명된 증거 패키지, 그리고 작은 명령줄 도구로 이 질문에 답한다. 동시에 명세가 언급하는 산출물 가운데 일부가 저장소에 실제로 들어 있지 않기 때문에, 성실한 구현자가 스스로 메워야 할 공백도 남겨 둔다. 이 장은 두 가지를 모두 다룬다. 명세 본문이 요구하는 것과, 구현자가 직접 만들어야 하는 것이다. 마지막으로 사막화 모니터링이 나아가는 방향과, 잘 설계된 데이터 표준이 줄일 수는 있어도 없앨 수는 없는 위험을 살펴본다. 이 장에 대응하는 시뮬레이터 탭은 다섯 번째 탭인 「QR & VC」이며, 예시용 복원 인증서를 발급한다. 8.7절에서 검증 가능한 자격 증명을 논의할 때 이 탭을 함께 보면 도움이 된다.
README와 PHASE-2 API-INTERFACE §3은 같은 세 등급을 각각 한 문장으로 정의한다. Surface는 “데이터 형식 수용, 자기 선언”, Verified는 “연 1회 제3자 감사”, Anchored는 “Annex G에 따른 지속적 증거 패키지”이다. 실무에서 세 등급은 누적적이다. Surface 점검조차 통과하지 못하는 Anchored 주장은 의미가 없으므로, 감사인은 각 등급이 그 아래 등급의 의무를 포함하는 것으로 보아야 한다. 또한 모든 PHASE 문서의 Annex E는 감사인이 배포를 “Annex A의 올바른 적합성 등급”에 비추어 평가하도록 적고 있으나, 저장소에는 Annex A가 없다. 등급의 정의는 README의 표와 API-INTERFACE §3뿐이다.
등급은 모니터링이 얼마나 훌륭한지를 나타내지 않는다. Surface 구현체가 뛰어난 데이터를 보유할 수도 있고, Verified 구현체가 부실한 데이터를 보유할 수도 있다. 등급이 매기는 것은 구현체가 표준대로 동작한다는 증거의 강도이다. 즉 구현자 이외의 누군가가 들여다보았는지, 그리고 동작이 어긋나기 시작할 때 알아챌 만큼 증거가 자주 갱신되는지를 본다.
| 등급 | 요구되는 증거 | 주기 | 서명 주체 |
|---|---|---|---|
| Surface | 등급을 선언한 매니페스트, x-wia-conformance-tier를 담은 OpenAPI 문서, 디스커버리 문서, PHASE-1 데이터 형식에 대한 자체 실행 시험 벡터 매트릭스 | 선언된 요건을 바꾸는 릴리스마다 | 구현자 단독 |
| Verified | Surface의 전부에 더해, 독립된 제3자가 벡터를 재실행하거나 입회하고, 배포 정책을 검토하고, 운영 레코드를 표본 조사한 감사 보고서 | 연 1회 감사, 감사 후 매니페스트 재서명 | 매니페스트는 구현자가, 감사 보고서는 감사인이 서명 |
| Anchored | Verified의 전부에 더해, CI가 생성하고 Rekor 투명성 로그에 기록된 Annex G 증거 패키지(SBOM, OpenAPI, 벡터 매트릭스, 서명된 매니페스트) | 모든 릴리스마다, 그리고 코드 변경이 없어도 최소 분기마다 | 구현자의 Sigstore 신원. 로그 항목이 독립적인 타임스탬프를 제공 |
이 표의 두 칸은 명세 문구를 넘어서는 내용이므로 권고로 읽어야 한다. 명세는 Verified 등급에서 누가 “제3자”로 인정되는지 말하지 않으며, Surface 등급의 갱신 주기도 정하지 않는다. 위의 선택은 나머지 두 등급의 논리를 따른 것이다. 다른 선택을 하는 구현자는 감사인이 무엇이 약속되었는지 알 수 있도록 그 내용을 배포 정책에 적어 두어야 한다.
§3은 OpenAPI 문서에서 x-wia-conformance-tier 확장 필드로 등급을 선언하도록 요구한다. OpenAPI 3.1은 대부분의 객체에 x- 확장을 허용하며, 가장 자연스러운 위치는 API 버전 옆의 info 객체이다. Annex E는 여기에 더해 운용 범위(단일 테넌트, 멀티 테넌트, 연합)도 같은 문서에 선언할 것(SHOULD)을 권고한다. 그래야 감사인이 올바른 기대치로 배포를 평가할 수 있다.
openapi: 3.1.0
info:
title: Sahel land-monitoring API (example deployment)
version: 1.0.0
x-wia-conformance-tier: Verified
x-wia-operational-scope: single-tenant
servers:
- url: https://monitoring.example.org/api
paths: {} # 실제 문서에는 배포가 제공하는 모든 연산을 나열한다
두 번째 확장 이름인 x-wia-operational-scope는 표준이 정한 것이 아니며 여기서는 예시로 쓴 것이다. 저장소에 포함된 api/openapi.yaml은 범용 /resource 경로 하나만 기술한 7줄짜리 골격이어서 적합성 문서로 쓸 수 없다. 각 구현체는 실제로 제공하는 모니터링·평가·복원·위치·경보·보고서 연산을 모두 담은 완전한 OpenAPI 문서를 스스로 공개해야 한다.
Surface 등급에서 감사인이나 꼼꼼한 고객은 일관성을 확인한다. OpenAPI 문서의 등급이 매니페스트와 /.well-known/wia/desertification-prevention의 디스커버리 문서에 적힌 등급과 일치하는지, 디스커버리 응답이 매니페스트와 같은 키로 서명되었는지(§4), 그리고 벡터 매트릭스가 매니페스트에서 지원한다고 표시한 모든 요건을 포괄하는지를 본다.
Verified 등급에서 감사인은 시연용 환경이 아니라 매니페스트의 implementation.build 다이제스트가 가리키는 운영 빌드를 대상으로 벡터를 재실행하거나 실행 과정에 입회한다. 또한 표준이 배포 정책에 맡겨 둔 항목들을 검토한다. 개인정보에 적용되는 규제 체계(§7), 키 회전 주기, 시각 동기화(§5는 NTPv4 stratum 2 이상을 요구한다), 감사 로그 보존 기간, Rekor 앵커링 주기가 그것이다. 이 단계에서는 운영 레코드 표본 조사가 중요하다. 플랫폼은 모든 부정 벡터를 통과하면서도 애초에 받아들여서는 안 되었던 레코드를 보유할 수 있다. 예를 들어 검증 로직이 생기기 전에 데이터베이스에 직접 적재된 배치가 그렇다.
Anchored 등급에서 감사인의 일은 점검에서 사슬의 검증으로 옮겨 간다. 증거 패키지의 서명이 검증되는지, 로그 항목이 존재하는지, SBOM이 배포된 이미지와 일치하는지, 연속된 분기 패키지 사이에 설명되지 않은 변화가 없는지를 확인한다. 감사인의 현장 방문은 여전히 필요하지만, 증거 대부분은 누구나 상시로 열람할 수 있다.
각 PHASE 문서의 Annex G는 모든 규범적 요건에 최소 하나의 긍정 벡터와 하나의 부정 벡터가 있으며, 이들이 tests/phase-vectors/phase-1-data-format/ 같은 디렉터리에 저장된다고 적는다. 또한 적합성을 주장하는 구현체는 모든 벡터를 CI에서 실행하고 통과/실패 매트릭스를 공개해야 한다(MUST). 그러나 현재 저장소에는 그 디렉터리가 없다. README가 참조 SDK로 소개하는 api/typescript/도 마찬가지다. 워킹그룹이 공식 벡터를 공개할 때까지는 구현자마다 자신의 벡터를 작성해야 한다. 생각만큼 낭비는 아니다. 부정 벡터를 작성하다 보면 자기 시스템에서 “거부”가 무엇을 뜻하는지(HTTP 상태 코드인지, RFC 9457 Problem Details 본문인지, 격리 플래그인지)를 정해야 하며, 그 결정은 어차피 매니페스트에 들어가야 하는 내용이다.
긍정 벡터는 구현체가 반드시 받아들여야 하는 입력과 그에 따른 저장 또는 반환 결과의 쌍이다. 부정 벡터는 구현체가 거부하거나 플래그를 달아야 하는 입력과 그 기대 처리의 쌍이다. 거부와 플래그의 구분은 필드마다 다른 오류 처리를 정한 PHASE-1 §7.2에서 나온다. NDVI가 −1~1 범위를 벗어나거나 좌표가 유효하지 않으면 거부하고, 토양 수분이 60 %를 넘거나 강수량이 음수이면 검토 대상으로 플래그를 단다. “어떤 오류든 발생했는지”만 확인하는 벡터는 우기의 그럴듯한 토양 측정값까지 거부하는 구현체도 통과시킨다. 표준은 그런 값을 보존하고 검토하라고 분명히 말한다.
| 벡터 ID | 입력 | 기대 결과 | 근거 |
|---|---|---|---|
P1-NDVI-001-NEG | NDVI 1.5인 vegetationData | 거부. 오류에 필드와 값이 명시됨 | PHASE-1 §7.2 (NDVI는 −1~1) |
P1-NDVI-001-POS | 같은 레코드에 NDVI −0.05 (수면 또는 젖은 나지) | 변경 없이 수용 | PHASE-1 §7.2 |
P1-COORD-001-NEG | 위도 95인 위치 | 거부 | PHASE-1 §7.2 (유효한 위경도) |
P1-SOILM-001-FLAG | 토양 수분 70 %인 soilData | 거부하지 않고 수용하되 검토 표시 | PHASE-1 §7.2 (60 % 초과 시 플래그) |
P1-RAIN-001-FLAG | 일 강수량 −3 mm인 rainfallData | 플래그. 검토 전까지 집계에서 제외 | PHASE-1 §7.2 (음수 값 플래그) |
P1-COVER-001-NEG | 토지피복 비율 합계가 112인 레코드 | 매니페스트 선언에 따라 거부 또는 플래그 | 구현자 도출 규칙: 한 면적의 구성비는 100을 넘을 수 없음 |
P1-LOCID-001-NEG | locationId가 없는 임의의 레코드 | 거부 | 레코드는 locationId로 결합되며, 고아 레코드는 보고할 수 없음 |
P3-HOOK-001-NEG | X-WIA-Signature가 변조된 웹훅 본문 | 수신 측이 폐기. 이벤트 처리 없음 | PHASE-3 웹훅 HMAC-SHA256 |
P2-AUTH-001-NEG | 만료된 베어러 토큰을 쓴 요청 | HTTP 401, 본문에 데이터 없음 | PHASE-2 상태 코드, §5 시간 제한 토큰 |
P2-TLS-001-NEG | TLS 1.2만 제시하는 클라이언트 | 핸드셰이크 거절 | API-INTERFACE §7 (TLS 1.3 MUST) |
마지막 행에는 설명이 필요하다. API-INTERFACE §7은 TLS 1.3을 요구하지만 PHASE-3 §5.1은 TLS 1.2 이상을 허용한다. 이 책은 더 엄격하고 MUST로 표현된 쪽인 TLS 1.3을 요건으로 본다. 오래된 현장 게이트웨이 때문에 아직 TLS 1.2를 받아야 하는 구현체는 약화된 벡터로 조용히 통과시키지 말고, 프로파일 매니페스트에 해당 요건을 사유와 함께 partial로 기록해야 한다.
출력이 결정적인 경우에는 벡터에 설명 대신 정확한 기대값을 넣어야 한다. 웹훅 서명이 가장 분명한 사례다. PHASE-3는 원시 요청 본문에 대한 HMAC-SHA256을 X-WIA-Signature: sha256=<hex> 형식으로 보내도록 규정한다. 아래 벡터는 이 책을 위해 일회용 비밀값으로 계산한 것이다. 올바른 송신 측이라면 같은 바이트에 대해 반드시 같은 문자열을 만들어야 한다.
{
"vectorId": "P3-HOOK-001-POS",
"secret": "test-secret-do-not-use",
"body": "{\"eventId\":\"evt-20251225-001\",\"eventType\":\"alert.triggered\"}",
"bodyLength": 60,
"expectedHeader": "sha256=ce4ae670bcfc61f9965a25941f90b73d920f3f3e8e973d86d3600abda86a0996"
}
본문은 공백도, 끝의 줄바꿈도 없는 60바이트이다. 이 벡터의 핵심이 바로 그 세부 사항이다. JSON을 파싱했다가 다시 직렬화한 뒤 검증하는 수신 측은 송신 측이 공백 하나만 넣어도 다른 다이제스트를 계산하게 된다. 짝이 되는 부정 벡터 P3-HOOK-001-NEG는 헤더의 16진수 한 자리를 바꾸고 이벤트가 폐기되기를 기대한다. 세 번째로 추가할 만한 벡터는 길이가 틀린 헤더를 보내는 것이다. PHASE-3의 참조 검증 코드는 두 버퍼를 곧바로 crypto.timingSafeEqual에 넘기는데, 이 함수는 길이가 다르면 예외를 던진다. 그 코드를 그대로 옮긴 구현체는 먼저 길이를 확인하지 않으면 “거부”가 처리되지 않은 예외로 바뀐다.
벡터는 어느 계층을 시험하는지에 따라 정리하는 것이 좋다. 계층마다 실패하는 방식이 다르기 때문이다.
startDate가 endDate보다 앞설 것, 토양 수분 값을 거부하지 않고 플래그로 처리할 것 등이다. 실제 결함 대부분이 여기에 있다.locationId에 대한 접근.Annex G는 두 가지 점에서 이례적으로 단호하며, 둘 다 검토자에게 맡기지 말고 CI 파이프라인에 넣어 두어야 한다. 공급업체는 부정 결과를 긍정 결과와 같은 충실도로 보고해야 하며(MUST), 기록된 정당화 없이 건너뛴 시험은 실패로 간주된다. 실무에서 이는 공개 매트릭스에 모든 벡터가 세 가지 결과 중 하나로 들어가야 하고, 건너뛰기는 프로파일 매니페스트의 excluded 또는 partial 항목을 가리킬 때에만 허용된다는 뜻이다.
{
"matrixFor": "sha256:4f1c...e09a",
"generatedAt": "2026-01-15T03:10:00Z",
"results": [
{ "vectorId": "P1-NDVI-001-NEG", "outcome": "pass" },
{ "vectorId": "P1-SOILM-001-FLAG", "outcome": "fail",
"observed": "HTTP 400 (record rejected)", "expected": "accepted + review flag" },
{ "vectorId": "P2-TLS-001-NEG", "outcome": "skip",
"justification": "requirement marked partial in profile manifest: legacy field gateways" }
]
}
위 매트릭스는 예시이다. 필드 이름은 표준이 정한 것이 아니며, 다이제스트는 읽기 쉽도록 줄였다. 실패한 행은 현실적인 사례다. 높은 토양 수분 값을 아예 거부하는 것은 흔한 지름길이며, 그 실패를 공개하는 것이 바로 이 부속서가 요구하는 바이다.
Annex G는 적합성 패키지를 네 가지를 담은 tarball로 설명한다. 소프트웨어 자재명세서(SBOM, CycloneDX 1.5 또는 SPDX 2.3), OpenAPI 문서, 시험 벡터 매트릭스, 서명된 매니페스트이다. 서명에는 Sigstore를 쓴다. 서명 대상을 DSSE(Dead Simple Signing Envelope) 봉투로 감싸고 Rekor 투명성 로그에 항목을 남기므로, 누구나 사설 인증기관을 신뢰하지 않고도 출처를 검증할 수 있다. CLI 도움말은 in-toto Attestation Framework 1.0도 함께 나열한다. 이 프레임워크는 “이 진술은 정확히 이 파일들에 관한 것이다”라고 말하기 위한 표준 형식을 제공한다.
evidence-2026Q1.tar.gz
├── manifest.json 서명된 매니페스트 (§2)
├── manifest.dsse.json manifest.json에 대한 DSSE 봉투
├── profile-manifest.json 요건별 지원 상태 (Annex I)
├── openapi.yaml x-wia-conformance-tier를 포함한 전체 API 기술
├── discovery.json /.well-known/wia/desertification-prevention 사본
├── sbom/
│ └── sbom.cdx.json CycloneDX 1.5 (또는 sbom.spdx.json, SPDX 2.3)
├── vectors/
│ ├── matrix.json 모든 벡터의 pass / fail / skip
│ └── logs/ PHASE별 CI 원본 출력
├── attestations/
│ └── evidence.intoto.jsonl 위 모든 파일을 다이제스트로 지목하는 in-toto 진술
└── transparency/
└── rekor-entry.json 서명에 대한 로그 인덱스와 포함 증명
SBOM은 소비자가 자신의 데이터를 처리하는 라이브러리를 확인하고 공개된 취약점과 대조할 수 있게 한다. 토지 모니터링 플랫폼이라면 웹 프레임워크만큼이나 래스터·투영 라이브러리가 중요하다. OpenAPI 문서는 벡터가 무엇을 대상으로 실행되었는지를 고정한다. 매트릭스는 그 결과이다. 매니페스트는 이들을 하나의 빌드 다이제스트와 하나의 프로파일에 묶는다. 넷 중 어느 하나만으로는 설득력이 없다. 넷이 함께 서명될 때 소비자는 정확한 질문을 던지고 검증 가능한 답을 얻을 수 있다. 이 SBOM과 이 API로 기술된 이 빌드가 이 벡터로 시험되어 이 결과를 냈는가?
in-toto 진술은 이 결합을 명시적으로 만든다. subject에는 파일을 다이제스트와 함께 나열하고, predicate에는 그 파일들에 관해 주장하는 내용을 담는다. 표준이 predicate 유형을 정하지 않았으므로 아래의 유형 URI는 이 예시를 위해 만든 것이다.
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{ "name": "manifest.json", "digest": { "sha256": "9b2e...71c4" } },
{ "name": "sbom/sbom.cdx.json", "digest": { "sha256": "c03a...5d18" } },
{ "name": "vectors/matrix.json", "digest": { "sha256": "e6f0...02ab" } }
],
"predicateType": "https://example.org/wia-ene-057/evidence/v1",
"predicate": {
"standardSlug": "desertification-prevention",
"tier": "Anchored",
"period": "2026-Q1"
}
}
Sigstore 프로젝트의 cosign 도구로 파일을 서명하고 검증하는 과정은 예를 들어 다음과 같다. 신원과 발급자 값은 자리표시자이다. 키 없는 서명에서는 이 값들이 CI 시스템의 OpenID Connect 토큰에서 오며, 검증자는 반드시 이 값을 고정해야 한다. 그렇지 않으면 유효한 Sigstore 신원이면 누구든 통과한다.
$ cosign sign-blob --bundle evidence-2026Q1.sigstore.json evidence-2026Q1.tar.gz
$ cosign verify-blob --bundle evidence-2026Q1.sigstore.json \
--certificate-identity "https://ci.example.org/release@refs/heads/main" \
--certificate-oidc-issuer "https://issuer.example.org" \
evidence-2026Q1.tar.gz
Verified OK
Annex G는 소스가 바뀌지 않았더라도 매 분기 패키지를 다시 공개하도록 요구한다. 이유는 환경 표류(drift)이다. 베이스 이미지가 새 시스템 라이브러리를 받아들이고, 의존성이 더 새로운 마이너 버전으로 해석되고, 투영 데이터베이스가 갱신되어 좌표 변환이 미세하게 달라진다. 이 가운데 어느 것도 구현자 자신의 커밋 이력에는 나타나지 않지만, 모두 동작을 바꿀 수 있다. 새 SBOM과 새 벡터 실행은 그 표류를 드러낸다. 연속된 두 패키지를 비교하는 일은 자동화하기 쉽다. 바뀐 SBOM 구성 요소와 결과가 바뀐 벡터를 나열하고, 그 차이를 새 패키지와 함께 공개하면 된다. SBOM은 그대로인데 결과가 바뀐 경우가 가장 흥미로우며, 대개 코드가 아니라 데이터나 설정 쪽을 가리킨다.
Annex G는 워킹그룹이 관리하는 공급업체 간 대조표(crosswalk), 즉 각 벡터를 인접 프로그램의 동등한 검증 항목에 대응시킨 표도 언급한다. 이 글을 쓰는 시점에 그 대조표는 저장소에 없다. 공개되기 전까지 구현자는 그것을 근거로 적합성을 주장해서는 안 된다.
API-INTERFACE §2는 서명된 매니페스트에 들어갈 내용을 나열한다. 상수값 "desertification-prevention"을 갖는 standardSlug, 시맨틱 버저닝을 따르는 version, implementation(이름, 빌드 다이제스트, SBOM URL), profile(이름과 버전), 요건별 지원 상태, 그리고 배포 정책이 선언한 주기로 Rekor에 앵커링되는 Sigstore DSSE 서명이다. CLI의 manifest-template 명령은 앞의 네 항목을 담은 골격을 출력한다. 요건별 상태와 서명은 빠져 있으므로 구현자가 추가해야 한다. 서명은 보통 매니페스트 내부가 아니라 그 옆의 DSSE 봉투에 둔다.
CLI는 cli/desertification-prevention.sh라는 짧은 셸 스크립트이다. 아래 기록은 이 스크립트를 실제로 실행해 얻은 것이며, 색상 코드만 지웠다. 도구가 무엇을 하는지와 어디서 멈추는지가 함께 드러난다.
$ ./desertification-prevention.sh info
WIA desertification-prevention
Version: 1.0.0
Conformance tiers (see README.md): Surface / Verified / Anchored.
Conformance package follows CycloneDX 1.5 + Sigstore (DSSE + Rekor).
弘益人間 (Benefit All Humanity)
$ ./desertification-prevention.sh profiles
Supported conformance profiles for desertification-prevention:
- single-tenant one runtime per organization
- multi-tenant shared runtime, header-based isolation
- federated peer-to-peer mesh of runtimes
- air-gapped batch evidence package, no live connectivity
Profile manifests are signed using Sigstore (DSSE envelope) and the
signing key is rotated per the deployment policy.
$ ./desertification-prevention.sh manifest-template > manifest.json
$ cat manifest.json
{
"documentId": "wia-desertification-prevention-XXXX",
"standardSlug": "desertification-prevention",
"version": "1.0.0",
"implementation": {
"name": "REPLACE_ME",
"build": "git-sha-or-image-digest",
"sbom": "https://example.com/sbom.cdx.json"
},
"profile": { "named": "single-tenant", "version": 1 },
"issuedAt": "2026-04-26T00:00:00Z"
}
$ ./desertification-prevention.sh validate manifest.json
OK: manifest.json declares standardSlug=desertification-prevention
$ echo '{"standardSlug":"desertification-prevention","version":"banana"}' > odd.json
$ ./desertification-prevention.sh validate odd.json
OK: odd.json declares standardSlug=desertification-prevention
$ echo '{"standardSlug":"x"}' > wrong.json
$ ./desertification-prevention.sh validate wrong.json
standardSlug mismatch: got 'x', expected 'desertification-prevention'
$ echo $?
1
validate가 하지 않는 일기록을 보면 한계가 분명하다. validate는 파일의 standardSlug가 desertification-prevention과 같은지 단 하나만 확인한다. REPLACE_ME와 자리표시자 빌드 문자열이 그대로 남은 템플릿도 통과시켰고, 버전이 "banana"인 문서도 통과시켰다. SemVer 문법을 확인하지 않고, 빌드 값이 실제 다이제스트인지 보지 않으며, SBOM을 가져오지 않고, 요건별 상태를 살피지 않으며, 어떤 서명도 검증하지 않는다. PHASE-1 레코드에 대해서도 아무것도 모른다. NDVI가 1.5인 vegetationData 파일에 실행하면 slug가 없다는 불평만 한다. 이 명령은 매니페스트에 대한 연기 시험(smoke test)으로만 다루어야 하며, 결코 적합성 검사로 여겨서는 안 된다.
이 도구를 자동화에 재사용한다면 한 가지를 더 알아야 한다. jq가 설치되어 있지 않으면 스크립트는 파일 이름을 그대로 끼워 넣은 Python 한 줄 코드로 대신 검사한다. 따옴표가 들어간 파일 이름은 그 문자열을 깨고 나올 수 있다. 직접 만든 파일에는 문제가 없지만, 업로드된 파일을 검증하는 CI 작업이라면 jq를 설치하거나 이 대체 경로를 바꿔야 한다.
같은 취지로 빠진 검사를 보태는 로컬 확장이 유용하다. version을 SemVer 2.0.0 문법으로 검사하고, implementation.build가 sha256: 뒤에 16진수 64자가 오는 형태인지 확인하고, REPLACE_ME 문자열이 남아 있으면 거부하고, 프로파일 매니페스트의 모든 요건 ID가 벡터 매트릭스에 나타나는지 확인하는 것이다. 서명 검증은 이 스크립트가 아니라 cosign의 몫이다.
Annex I는 두 번째 문서인 프로파일 매니페스트를 추가한다. 이 문서는 규범적 요건 ID를 나열하고 각각에 supported, 사유를 붙인 partial, 정당화를 붙인 excluded 중 하나의 상태를 부여하며, SBOM과 같은 키로 서명된다. 목적도 분명히 적혀 있다. 범위가 다른 배포들이 자신이 충족하는 부분을 알리되 “부분 적합성을 완전한 적합성으로 잘못 표시하지 않도록” 하는 것이다. 표준이 아직 요건에 번호를 매기지 않았으므로 아래 요건 ID는 예시이다.
{
"standardSlug": "desertification-prevention",
"profile": { "named": "WIA-P2-API-INTERFACE-Edge-only", "version": 2 },
"requirements": [
{ "id": "P1-7.2-NDVI", "status": "supported" },
{ "id": "P2-7-TLS13", "status": "partial",
"reason": "two legacy field gateways negotiate TLS 1.2; replacement scheduled" },
{ "id": "P3-MQTT", "status": "excluded",
"justification": "edge deployment receives sensor data by file transfer only" }
]
}
두 가지 이름 체계가 공존하며 서로 혼동해서는 안 된다. CLI의 profiles 명령은 네 가지 배포 형태, 곧 single-tenant, multi-tenant, federated, air-gapped를 나열한다. Annex I는 “Edge-only”나 “Federated-with-replay” 같은 이름 붙은 프로파일의 공개 등록부를 설명하며, 이 이름들은 SemVer 규칙으로 버전이 매겨진다. 따라서 WIA-P2-API-INTERFACE-Edge-only/2는 그 이름 붙은 프로파일의 두 번째 메이저 버전을 뜻한다. 등록부 항목은 변경할 수 없으며, 형태가 바뀌면 새 이름을 받는다. 연합 배포는 구성원 프로파일의 합집합과 교집합을 요약한 집계 매니페스트를 공개하고, 디렉터리 서비스는 이를 이용해 호출자에게 필요한 기능을 지원하는 피어로 요청을 보낸다. 통신이 불안정한 지역의 에어갭 모니터링 거점에서는 증거 패키지 자체가 전달 수단이 된다. 패키지를 대역 외 경로로 옮겨 도착지에서 검증하고, 연결된 시스템에 닿았을 때 Rekor 항목을 만든다.
표준은 자기 자신과 구현체 모두에 Semantic Versioning 2.0.0을 적용한다. 메이저 증가는 규범적 요건의 하위 호환되지 않는 변경을, 마이너 증가는 기존 구현체를 깨뜨리지 않는 새 규범적 요건의 추가를, 패치는 편집상의 변경만을 뜻한다. 정오표(errata)는 패치 릴리스로 발행되어 공개 정오표 등록부에 기록되며, 각 항목에는 워킹그룹 의장이 서명한다.
알아 두어야 할 내부 모순이 하나 있다. Annex E는 필드의 이름을 바꾸거나 삭제하는 것은 “오류 페이로드에서라도” 마이너 버전 증가를 일으켜야 한다(MUST)고 적지만, §8과 Annex H는 하위 호환되지 않는 변경이 메이저 증가를 일으킨다고 적는다. 클라이언트가 읽는 필드를 삭제하는 것은 어떻게 읽어도 호환성을 깨는 변경이므로, 구현자는 메이저 증가 규칙을 따르고 Annex E의 문구는 보고해야 할 오류로 다루어야 한다.
명세 문서들은 이전 메이저 버전을 새 버전과 나란히 지원하는 기간을 두 가지로 적는다. API-INTERFACE §6과 Annex F는 최소 90일의 병행 기간을 말하고, Annex H는 이전 메이저 버전을 최소 180일 동안 병행 유지하며 그동안 두 버전 모두 등록부에 Stable로 표시된다고 말한다. 이 책은 어느 쪽도 확정된 값으로 다루지 않는다. 워킹그룹이 정오표를 낼 때까지는 더 긴 180일을 지키는 편이 안전하다. 그 기간이 지나면 폐기 예고된 버전은 12개월의 일몰 기간에 들어가며, 등록부는 그 버전을 Deprecated로 표시하고 대체 요건을 가리키는 마이그레이션 안내와 변경 사유를 함께 싣는다.
통신 수준에서 폐기 예고는 HTTP 헤더로 알린다. PHASE-3는 Sunset 날짜, 대체 경로를 가리키는 Link와 함께 Deprecation: true를 보여 준다. Sunset 헤더는 RFC 8594에 정의되어 있다. Deprecation 헤더는 이후 RFC 9745로 표준화되었는데, 그 값은 true가 아니라 구조화된 날짜이다. 새 구현체는 RFC 9745 형식을 보내고, 클라이언트는 두 형식을 모두 받아들이는 것이 바람직하다.
HTTP/1.1 200 OK
Deprecation: @1767225600
Sunset: Thu, 31 Dec 2026 23:59:59 GMT
Link: </api/v2/monitoring/vegetation>; rel="successor-version"
여기서 @1767225600은 2026년 1월 1일 00:00 UTC의 유닉스 시각으로, 예시로 든 폐기 예고 날짜이다. 명세의 예시는 일몰일의 요일을 “Wed”로 적었지만 2026년 12월 31일은 목요일이다. 일부 클라이언트는 HTTP 날짜를 엄격하게 파싱하므로, 날짜 문자열은 손으로 쓰지 말고 생성하는 편이 낫다.
Annex H는 또한 구현체가 지원하는 PHASE 버전마다 그것을 충족하는 정확한 빌드, 컨테이너 다이제스트, SDK 버전을 대응시킨 변경 이력을 공개하도록 권고한다. 여러 배포를 운영하는 모니터링 플랫폼에서는 비용이 적고 효과가 크다. 감사인이 보고서 생성일을 그 보고서를 만든 빌드와 해당 빌드의 증거 패키지에 대응시킬 수 있기 때문이다.
이슈, 정오 요청, 제안은 WIA-Official 조직의 GitHub 이슈 트래커에 desertification-prevention 레이블을 달아 제출한다. 워킹그룹은 매 마이너 릴리스 사이클의 시작 시점에 열린 이슈를 검토하고 결정 로그를 릴리스 노트와 함께 공개한다. 이 책에서 지적한 불일치들, 곧 “Annex A”로 언급되는 등급 정의, 제공되지 않는 벡터 디렉터리, 90일 대 180일, TLS 1.2 대 1.3, 필드 삭제의 마이너 대 메이저 문제는 바로 그곳에 올라가야 할 발견이다. 이를 제출하는 것도 적합성 문화의 일부다. 결함을 조용히 우회하는 구현자는 다음 구현자에게 같은 발견을 되풀이하게 만든다.
WIA 적합성은 이미 자리 잡은 여러 인증 체계 사이에 놓여 있다. 각 체계가 무엇을 인증하는지 알아 두는 것이 중요하다. 이 분야에서 가장 흔한 과장은 한 체계의 권위를 빌려 다른 체계에 속하는 주장을 하는 것이기 때문이다.
| 체계 | 인증·기술 대상 | WIA 적합성과의 관계 |
|---|---|---|
| ISO/IEC 17065:2012 | 제품·프로세스·서비스를 인증하는 기관에 대한 요구사항 | Verified 등급 감사인이 일하는 방식(공정성, 문서화된 인증 체계)의 모델. WIA가 감사인을 인정(accreditation)하지는 않는다. |
| ISO/IEC 27001:2022 | 조직의 정보보안 경영시스템 | API의 동작이 아니라 운영 조직을 다룬다. §7 보안 통제의 유용한 증거가 된다. |
| ISO/IEC 27018:2019 | 공용 클라우드 처리자의 개인정보 보호 | 현장 양식에 토지 보유자나 조사원의 이름이 담길 때 관련된다. |
| ISO 19115(지리 메타데이터)와 OGC WMS/WFS/WCS | 메타데이터 모델과 웹 지도·피처·커버리지 서비스. OGC는 자체 적합성 시험 프로그램을 운영한다 | WIA 본문은 정합성을 선언할 뿐이다. OGC 적합성은 해당 서비스가 OGC 시험을 통과했을 때에만 주장한다. |
| UNCCD 국가 보고 (SDG 15.3.1 / LDN) | 토지피복, 토지 생산성, 토양유기탄소에 대한 국가 단위 보고 | WIA 데이터는 국가 절차에 투입될 수 있지만, 국가의 공식 제출을 대신하지 않는다. |
| 탄소 등록부의 타당성 평가·검증 (예: ISO 14064-3에 따라, ISO 14065를 충족하는 기관이 수행) | 등록부 방법론에 따른 온실가스 진술과 사업 주장 | WIA 복원 레코드는 모니터링 데이터로 쓰일 수 있다. 크레딧은 등록부 자체 절차를 거친 뒤에야 존재한다. |
명세의 몇몇 표현은 대외 주장에서 신중하게 바꿔 말해야 한다. 준수 목록은 ISO 19115, OGC 서비스, HTTP/2 같은 항목에 체크 표시를 달아 두었지만, 이는 저자들의 정합성 선언이지 인증서가 아니다. HTTP에 인용된 RFC 일부는 이미 대체되었다. RFC 7230–7235와 RFC 7540은 RFC 9110–9113으로 대체되었다. README는 RFC 9700을 “OAuth 2.1”이라고 부르지만 정확하지 않다. RFC 9700은 OAuth 2.0 보안 모범 사례(Security Best Current Practice)이며, OAuth 2.1은 아직 인터넷 초안(Internet-Draft) 단계이다. 제품 설명에는 README의 표현을 되풀이하지 말고 “OAuth 2.0 보안 BCP(RFC 9700)에 정합”이라고 써야 한다.
LDN과의 관계에 대해 한 가지를 더 말해 둔다. LDN은 세 하위 지표로 평가하며, 그중 하나라도 유의미하게 감소하면 황폐화로 본다(“one out, all out”). WIA 레코드는 현장이나 사업 규모에서 그 판단을 위한 증거를 제공할 수 있다. 일부 연계 예시에 나오는 “LDN 진행률” 같은 요약 수치는 UNCCD 지표가 아니므로 그렇게 제시해서는 안 된다.
탄소 주장에도 같은 절제가 필요하다. restorationProject에 바이오매스 증가를 기록한 복원 사업은 모니터링 데이터를 가진 것이다. 등록부 방법론이 기준선, 추가성 검토, 누출과 버퍼 공제와 함께 적용되고, 인정받은 기관이 그 결과를 검증하기 전까지 그것은 탄소 크레딧이 아니다. 적합한 WIA 플랫폼은 모든 수치를 추적 가능하게 유지함으로써 그 검증을 쉽게 만들 수는 있지만, 검증 절차를 줄여 주지는 못한다.
두 가지 기술적 변화가 이미 이 표준의 구현체가 할 수 있는 일을 바꾸고 있다. 첫째는 조화된(harmonised) 광학 자료다. NASA의 HLS(Harmonized Landsat and Sentinel-2) 산출물처럼 Landsat과 Sentinel-2를 일관된 지표 반사율 시계열로 결합하면, 같은 필지를 구름 없이 관측하는 간격이 짧아지고 화소 크기도 MODIS 식생지수의 250 m에서 수십 m 수준으로 줄어든다. 그 결과 개별 필지와 복원 구획이 위성 모니터링의 범위 안에 들어온다. 둘째는 레이더다. 합성개구레이더(SAR)는 구름을 투과하고 지표의 수분과 구조에 민감하므로, SMAP 같은 저해상도 수동 마이크로파 산출물 사이를 메우는 필지 규모 토양 수분 추정의 후보가 된다. 두 변화 모두 플랫폼이 저장하는 데이터의 양을 늘리고, 노력의 중심을 수집에서 품질 관리로 옮긴다. PHASE-1 레코드의 qualityMetrics와 출처 필드는 덜 중요해지는 것이 아니라 더 중요해진다.
황폐화 탐지는 점점 더 학습된 모델로 이루어진다. 토지피복 분류기, 협곡과 나지 패치를 찾는 변화 탐지 모델, 바이오매스 회귀 모델 등이다. 표준은 이미 추세 상태 옆에 confidence 값을 둔다. 다음 단계는 모델의 불확실성을 데이터로 다루는 것이다. 모델 버전, 학습 데이터의 지역과 기간, 화소별 또는 필지별 불확실성을 기록하고, 신호가 그 불확실성을 넘는 곳에서만 황폐화를 보고한다. 한 경관에서 학습한 모델은 다른 경관에서 자신 있게 틀릴 수 있다. 여기서도 적합성 벡터가 회귀 시험으로 쓰일 수 있다. 정답 라벨이 알려진 기준 타일 세트를 고정해 두고 모델이 바뀔 때마다 다시 돌리는 것이다.
ODK 계열 도구로 수집하는 현장 양식은 목축민, 농민, 지역 기술자가 위성이 보지 못하는 생존 본수, 방목 압력, 침식 지형을 기록할 수 있게 한다. 데이터 모델은 이런 레코드를 다른 레코드와 똑같이 다루지만, 그 거버넌스는 다르다. 데이터를 수집한 사람들은 자기 땅에 관해 저장된 내용을 보고 바로잡을 수 있어야 하며, 그 데이터가 뒷받침하는 결정에 참여할 수 있어야 한다. 관습적 토지 이용과 관련된 배포에서는 원주민 데이터 거버넌스를 위한 CARE 원칙(집단적 이익, 통제 권한, 책임, 윤리)이 유용한 참고가 된다.
시뮬레이터의 다섯 번째 탭은 QR 코드가 붙은 복원 인증서를 발급한다. 탭의 “블록체인 기반”이라는 표현은 예시에 불과하지만, 그 바탕의 발상은 타당하다. 예컨대 “위치 SAHEL-REGION-001에서 사업 REST-2025-SAHEL-001이 어느 날짜에 어느 생존율을 기록했다”는 복원 성과를 W3C 검증 가능한 자격 증명(Verifiable Credential)으로 발급하고, 모니터링 기관이 서명하며, 공여 기관이나 지역 공동체가 오프라인에서도 확인할 수 있게 하는 것이다. 이 표준에서 앵커링 수단은 공개 블록체인의 토큰이 아니라 Sigstore와 Rekor이다. 나무 토큰과 스마트 계약은 연계 문서에 선택적인 예시 설계로만 등장한다. 자격 증명은 그 뒤의 증거만큼만 믿을 수 있으므로, 맥락 없이 숫자를 다시 적기보다 모니터링 보고서와 증거 패키지를 참조해야 한다.
SDG 세부목표 15.3은 2030년까지 토지 황폐화 중립 세계를 지향하며, 자발적 LDN 목표를 설정한 국가들은 UNCCD의 정기 국가 보고를 통해 그 진척을 보고한다. 2030년이 가까워질수록 재처리 없이 상위 단위로 집계할 수 있는 현장 수준 증거에 대한 수요가 커질 것이며, 일관된 레코드와 서명된 증거가 제공하는 것이 바로 그것이다. 지표 15.3.1에 대한 UNCCD 모범 실무 지침과 Trends.Earth 같은 공개 도구가 이미 국가 단위 계산 방법을 정의하고 있다. WIA 플랫폼은 독자적인 국가 지표를 만들어 내기보다, 자신의 데이터를 그 방법에 쉽게 투입할 수 있게 할 때 가장 큰 가치를 낸다.
x-wia-conformance-tier로 선언한다.validate는 standardSlug만 확인한다. 프로파일 매니페스트는 요건별 상태를 밝혀 부분 적합성이 완전한 적합성으로 비치지 않게 한다.