haechi 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +97 -97
- package/README.md +2 -2
- package/SECURITY.md +12 -10
- package/docs/current/api-stability.ko.md +26 -26
- package/docs/current/configuration.ko.md +101 -101
- package/docs/current/configuration.md +4 -4
- package/docs/current/release-process.ko.md +19 -20
- package/docs/current/release-process.md +1 -2
- package/docs/current/reliability-hardening-track.ko.md +77 -0
- package/docs/current/reliability-hardening-track.md +77 -0
- package/docs/current/risk-register-release-gate.ko.md +25 -27
- package/docs/current/risk-register-release-gate.md +18 -20
- package/docs/current/shared-responsibility.ko.md +33 -24
- package/docs/current/shared-responsibility.md +12 -3
- package/docs/current/threat-model.ko.md +10 -11
- package/docs/current/threat-model.md +1 -2
- package/package.json +2 -1
- package/packages/cli/runtime.mjs +8 -1
- package/packages/core/index.mjs +47 -8
- package/packages/proxy/index.mjs +17 -2
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Haechi Release Process
|
|
2
2
|
|
|
3
|
-
- 문서 상태:
|
|
3
|
+
- 문서 상태: Living document (core 1.1.x 추적)
|
|
4
4
|
- 작성일: 2026-06-10
|
|
5
|
-
- 기준 버전: 0.3.2
|
|
6
5
|
|
|
7
6
|
## 1. 로컬 릴리즈 검증
|
|
8
7
|
|
|
@@ -12,25 +11,25 @@ npm run sbom
|
|
|
12
11
|
npm run bench:payload
|
|
13
12
|
```
|
|
14
13
|
|
|
15
|
-
`release:preflight`는 테스트, 타입 체크, stale-name scan, pack dry-run을
|
|
14
|
+
`release:preflight`는 테스트, 타입 체크, stale-name scan, pack dry-run을 실행합니다. npm 계정 인증과 package ownership 확인까지 포함하려면 다음을 사용하세요.
|
|
16
15
|
|
|
17
16
|
```bash
|
|
18
17
|
npm run release:preflight:npm
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
첫 publish 전에는 `npm view <package> version`이 `E404 Not Found`를 반환하는 것이
|
|
20
|
+
첫 publish 전에는 `npm view <package> version`이 `E404 Not Found`를 반환하는 것이 정상입니다. 이 경우 preflight는 인증된 계정에서 이름을 claim할 준비가 된 상태로 통과합니다. 단, `npm view <package>@<version> version`이 성공하면 같은 버전을 다시 배포할 수 없으므로 실패합니다.
|
|
22
21
|
|
|
23
22
|
## 2. npm provenance와 trusted publishing
|
|
24
23
|
|
|
25
|
-
의도된 publish 경로는 GitHub Actions trusted publishing
|
|
24
|
+
의도된 publish 경로는 GitHub Actions trusted publishing입니다. npm이 release workflow를 OIDC로 인증하고 provenance 증명을 자동 생성합니다. 공식 npm 요구사항에 따라 GitHub-hosted runner, `id-token: write`, 연결된 workflow에서의 publish가 필요합니다.
|
|
26
25
|
|
|
27
|
-
**현재 상태: trusted publishing 구성 및 검증 완료.** `haechi@0.3.2`는 로컬 머신에서 패스키 인증과 `--provenance=false`로 배포되어 해당 버전의 provenance 증명이 존재하지
|
|
26
|
+
**현재 상태: trusted publishing 구성 및 검증 완료.** `haechi@0.3.2`는 로컬 머신에서 패스키 인증과 `--provenance=false`로 배포되어 해당 버전의 provenance 증명이 존재하지 않습니다. 활성화 runbook과 진행 상태는 다음과 같습니다.
|
|
28
27
|
|
|
29
28
|
1. ✅ npmjs.com에서: package settings → Trusted Publisher → `raeseoklee/haechi` 저장소와 `npm-publish.yml` workflow 연결 (2026-06-10).
|
|
30
29
|
2. ✅ `.github/workflows/npm-publish.yml` OIDC 인증 전환 (2026-06-10): `NODE_AUTH_TOKEN`과 `registry-url` 제거, runner의 npm CLI를 `>= 11.5.1`로 업그레이드.
|
|
31
|
-
3. ✅ `haechi@0.4.0`으로 검증 완료 (2026-06-10): `npm view haechi --json`에서 SLSA provenance v1 predicate를 가진 `dist.attestations` 확인. 로컬 패스키로 배포한 `haechi@0.3.2`만 비증명 상태로
|
|
30
|
+
3. ✅ `haechi@0.4.0`으로 검증 완료 (2026-06-10): `npm view haechi --json`에서 SLSA provenance v1 predicate를 가진 `dist.attestations` 확인. 로컬 패스키로 배포한 `haechi@0.3.2`만 비증명 상태로 남습니다.
|
|
32
31
|
|
|
33
|
-
provenance 없이 수행한 publish는 release note에 갭을 명시적으로 기록해야
|
|
32
|
+
provenance 없이 수행한 publish는 release note에 갭을 명시적으로 기록해야 합니다(`CONTRIBUTING.md` 참조).
|
|
34
33
|
|
|
35
34
|
참고:
|
|
36
35
|
|
|
@@ -40,11 +39,11 @@ provenance 없이 수행한 publish는 release note에 갭을 명시적으로
|
|
|
40
39
|
|
|
41
40
|
## 3. 서명된 릴리스 아티팩트
|
|
42
41
|
|
|
43
|
-
**암호학적** 신뢰 앵커는 **npm provenance 증명**(레지스트리 아티팩트)과 **sigstore 증명**(release tarball)이며, 둘 다 GitHub OIDC로 아티팩트를 이 repo의 release workflow 신원에
|
|
42
|
+
**암호학적** 신뢰 앵커는 **npm provenance 증명**(레지스트리 아티팩트)과 **sigstore 증명**(release tarball)이며, 둘 다 GitHub OIDC로 아티팩트를 이 repo의 release workflow 신원에 묶습니다. `SHA256SUMS`는 오프라인 체크섬(`sha256sum -c`)을 위한 **도구 호환 편의 수단**이고, 같은 workflow가 생성·업로드하므로 그 자체로는 신뢰 앵커가 아닙니다. provenance에 더해, publish workflow는 다운로드한 tarball을 설치 전에 검증할 수 있도록 다음 자산을 첨부합니다.
|
|
44
43
|
|
|
45
|
-
- `npm pack` 후 `node scripts/release-checksums.mjs <tarball>`로 `SHA256SUMS` 매니페스트(표준 `<sha256-hex> <name>` 형식)를
|
|
46
|
-
- `actions/attest-build-provenance`로 tarball의 **keyless sigstore 증명**(GitHub OIDC, 서명 키 없음)을
|
|
47
|
-
- tarball + `SHA256SUMS`를 GitHub release에
|
|
44
|
+
- `npm pack` 후 `node scripts/release-checksums.mjs <tarball>`로 `SHA256SUMS` 매니페스트(표준 `<sha256-hex> <name>` 형식)를 생성합니다.
|
|
45
|
+
- `actions/attest-build-provenance`로 tarball의 **keyless sigstore 증명**(GitHub OIDC, 서명 키 없음)을 만듭니다.
|
|
46
|
+
- tarball + `SHA256SUMS`를 GitHub release에 업로드합니다.
|
|
48
47
|
|
|
49
48
|
다운로드한 릴리스 검증:
|
|
50
49
|
|
|
@@ -72,18 +71,18 @@ npm audit signatures
|
|
|
72
71
|
| `.github/workflows/dashboard-publish.yml` | `haechi-dashboard` | `dashboard-v<semver>` | satellite publish, 동일한 서명 아티팩트 경로 |
|
|
73
72
|
| `.github/workflows/auth-oidc-publish.yml` | `haechi-auth-oidc` | `auth-oidc-v<semver>` | satellite publish, 동일한 서명 아티팩트 경로 |
|
|
74
73
|
|
|
75
|
-
각 publish 워크플로는 `release: published`에서 트리거되지만 **가드**되어 둘이 교차 발화하지
|
|
74
|
+
각 publish 워크플로는 `release: published`에서 트리거되지만 **가드**되어 둘이 교차 발화하지 않습니다. core job은 `v`로 시작하는 태그에서만 실행되고(그리고 `^v[0-9]+\.[0-9]+\.[0-9]+$` 재검증), satellite job은 `crypto-kms-v…`에서만 실행됩니다(그리고 `^crypto-kms-v[0-9]+\.[0-9]+\.[0-9]+$` 재검증 **및** 태그 버전이 satellite `package.json` 버전과 일치하는지 검증). npmjs.com Trusted Publisher는 각 패키지의 **특정 워크플로 파일명**에 바인딩됩니다 — 워크플로 파일 rename은 npm 설정을 갱신할 때까지 OIDC publish를 깨뜨립니다.
|
|
76
75
|
|
|
77
76
|
## 5. Satellite 패키지 (unscoped `haechi-*`)
|
|
78
77
|
|
|
79
|
-
Satellite는 npm workspaces 모노레포의 `satellites/*`에 살며 core와 **독립적으로**
|
|
78
|
+
Satellite는 npm workspaces 모노레포의 `satellites/*`에 살며 core와 **독립적으로** 발행됩니다(자체 semver이며, satellite patch가 `haechi`를 bump하지 않습니다). core와 동일한 서명 아티팩트 경로를 재사용합니다(pack → checksum → sigstore attest → OIDC publish → upload). **unscoped** `haechi-*` 이름으로 발행하므로(`@haechi` org/scope는 제3자가 점유) **npm org가 필요 없습니다**.
|
|
80
79
|
|
|
81
80
|
**satellite별 부트스트랩 순서(첫 발행, org 불필요):**
|
|
82
81
|
|
|
83
|
-
1. npmjs.com에서 (아직 미발행) unscoped 이름(예: `haechi-crypto-kms`)에 **Trusted Publisher 설정**: `raeseoklee/haechi` 저장소와 satellite의 **정확한 워크플로 파일명**(예: `crypto-kms-publish.yml`)
|
|
84
|
-
2. 접두사 태그를 push하고 GitHub Release
|
|
82
|
+
1. npmjs.com에서 (아직 미발행) unscoped 이름(예: `haechi-crypto-kms`)에 **Trusted Publisher 설정**: `raeseoklee/haechi` 저장소와 satellite의 **정확한 워크플로 파일명**(예: `crypto-kms-publish.yml`)을 연결합니다. npm은 아직 발행 전인 이름에도 Trusted Publisher 설정을 허용합니다.
|
|
83
|
+
2. 접두사 태그를 push하고 GitHub Release를 발행하면(예: `crypto-kms-v0.1.0`) 워크플로의 OIDC publish가 provenance와 함께 `0.1.0`을 생성하고 첫 발행 시 이름을 확보합니다.
|
|
85
84
|
|
|
86
|
-
노트북에서의 수동 `npm publish`는 필요
|
|
85
|
+
노트북에서의 수동 `npm publish`는 필요 없습니다. 이름이 unscoped이고 비어있으므로 org-membership 선행 요건이 없습니다.
|
|
87
86
|
|
|
88
87
|
**태그 → 워크플로 → 패키지 매핑:**
|
|
89
88
|
|
|
@@ -101,13 +100,13 @@ gh attestation verify haechi-crypto-kms-<version>.tgz --repo raeseoklee/haechi
|
|
|
101
100
|
npm view haechi-crypto-kms --json # dist.attestations 존재 확인; access "public"
|
|
102
101
|
```
|
|
103
102
|
|
|
104
|
-
**의존성 노트:** `haechi-crypto-kms`는 core를 zero-dependency로
|
|
103
|
+
**의존성 노트:** `haechi-crypto-kms`는 core를 zero-dependency로 유지합니다 — `@aws-sdk/client-kms`는 **optional peer dependency**이며, 실제 AWS 클라이언트를 쓰고 주입하지 않을 때만 lazy import됩니다. in-memory 또는 주입형 클라이언트를 쓰는 소비자는 SDK를 설치하지 않습니다. 0.2.0의 `./gcp`(`@google-cloud/kms`)와 `./azure`(`@azure/keyvault-keys` + `@azure/identity`) 백엔드도 동일한 optional-peer/lazy-import 모델을 따르며, `./vault` 백엔드는 optional peer가 없습니다(`node:` `fetch` 전용).
|
|
105
104
|
|
|
106
|
-
**0.9 satellite(새 unscoped 이름 — 첫 태그 *전에* Trusted Publisher 설정):** `haechi-dashboard`와 `haechi-auth-oidc`는 0.9에서 첫 발행되며 위의 satellite별 부트스트랩 순서를 동일하게
|
|
105
|
+
**0.9 satellite(새 unscoped 이름 — 첫 태그 *전에* Trusted Publisher 설정):** `haechi-dashboard`와 `haechi-auth-oidc`는 0.9에서 첫 발행되며 위의 satellite별 부트스트랩 순서를 동일하게 따릅니다. 0.8 satellite와 마찬가지로 unscoped 이름은 첫 OIDC publish 시 확보되므로, 각각의 npmjs.com Trusted Publisher를 첫 태그 **전에** 설정해야 합니다 — `raeseoklee/haechi` 저장소와 정확한 워크플로 파일명(`haechi-dashboard`는 `dashboard-publish.yml`, `haechi-auth-oidc`는 `auth-oidc-publish.yml`)을 연결한 뒤, 접두사 태그(`dashboard-v0.1.0`, `auth-oidc-v0.1.0`)를 push하고 GitHub Release를 발행합니다. 기존 두 satellite는 이미 부트스트랩된 태그/워크플로를 그대로 사용합니다: `haechi-auth-jwt@0.2.0`은 `auth-jwt-v<semver>`(`auth-jwt-publish.yml`), `haechi-crypto-kms@0.2.0`은 `crypto-kms-v<semver>`(`crypto-kms-publish.yml`) — 이 둘은 새 Trusted Publisher 설정이 필요 없습니다.
|
|
107
106
|
|
|
108
107
|
## 6. 배포 차단 조건
|
|
109
108
|
|
|
110
|
-
다음 중 하나라도 실패하면 npm publish를 하지
|
|
109
|
+
다음 중 하나라도 실패하면 npm publish를 하지 않습니다.
|
|
111
110
|
|
|
112
111
|
- `npm run release:preflight` 실패
|
|
113
112
|
- `npm run release:preflight:npm` 실패
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# 신뢰성 하드닝 트랙 (Reliability Hardening Track)
|
|
2
|
+
|
|
3
|
+
- 상태: 계획 (2026-06-12 확정; 1.1.1 코어에 대한 5-렌즈 읽기 전용 감사에 근거)
|
|
4
|
+
- 대상 라인: 1.1.2(patch) → 1.2.0(minor); 신규 제품 표면 없음
|
|
5
|
+
- 목적: Haechi를 **상용 솔루션 수준의 신뢰성**으로 끌어올립니다 — 운영 AI 보안 게이트웨이에 기대되는 신뢰·운영성·탐지 품질의 밀도입니다. 이것은 품질 목표이지 상용화 계획이 아닙니다. 모든 항목은 **이미 존재하는 것을 조이거나, 측정하거나, 문서화**하며, 신규 기능을 추가하지 않습니다.
|
|
6
|
+
|
|
7
|
+
## 1. 이 트랙이 필요한 이유
|
|
8
|
+
|
|
9
|
+
1.1.1 코어에 대한 5-렌즈 감사(탐지 품질, 수평 확장/상태, 운영성, 보안 잔여, 정합성)는 **47개 발견(High 16 / Medium 20 / Low 11)** 을 반환했으며, 각각 코드·설정 규칙·문서 주장·누락 산출물에 근거합니다. 반복되는 주제는 기능 부재가 아니라 **밀도 부재**입니다. 코어는 단일 자체 호스팅 복제본에서는 올바르지만, 운영 신뢰 측면에서는 측정되지 않았고, 계측이 부족하며, 일부는 문서화가 미흡합니다.
|
|
10
|
+
|
|
11
|
+
단적인 신호: 프로젝트 자체의 현행 설계 초안(`docs/current/privacy-filtering-policy-draft.md`)이 `minConfidence` 임계값, 오탐 allowlist, FP/FN 측정을 이미 명세했지만, 출시된 코드는 이를 구현하지 **않았습니다**. 따라서 가장 큰 단일 갭은 범위를 넓히는 것이 아니라, *설계된* 코어와 *출시된* 코어 사이의 거리를 좁히는 것입니다.
|
|
12
|
+
|
|
13
|
+
이 트랙은 신규 기능을 의도적으로 **제외**합니다 — 외부 Redis/DB 공유 상태 구현, ML 기반 탐지, 새 추론 백엔드는 범위 밖입니다. 수평 확장에 운영 상태가 필요한 경우, 이 트랙은 내장 분산 저장소가 아니라 **주입 seam + 정직한 문서**를 추가합니다.
|
|
14
|
+
|
|
15
|
+
## 2. 워크스트림
|
|
16
|
+
|
|
17
|
+
각 워크스트림은 기존 동작을 조입니다. 공수는 감사 기준(S/M/L)입니다.
|
|
18
|
+
|
|
19
|
+
### WS1 — 정직성·정합성 스윕 (1.1.2 patch)
|
|
20
|
+
거버닝 문서가 출시된 1.1.1 라인보다 뒤처져 있으며, 이는 보안 제품의 신뢰를 직접 떨어뜨립니다.
|
|
21
|
+
- stale 주장 정정: README + `configuration.md`의 "the proxy has no client authentication yet (planned for 0.6)"(bearer auth는 0.6에서 출시됨), `SECURITY.md`(0.3.x 제품을 기술 — 스트리밍 검사 없음, 검증 전용 플러그인), `configuration.md`/`threat-model.md`/`risk-register-release-gate.md`의 `Target version: 0.6.0` / `Draft 0.1 / Target 1.0.0` 헤더, risk-register §1/§7의 성숙도 표현, README 보안 노트의 "0.1 crypto provider" 라벨.
|
|
22
|
+
- **doc-freshness preflight 게이트** 추가 — stale-name 스캐너(또는 작은 신규 점검)를 확장해 stale 버전 배너와 알려진 stale 문구(`planned for 0.6`, `Target version: 0.6.0`, `Only the current 0.3.x` 등)를 CI에서 차단합니다. Haechi는 이미 stale 문자열을 세 번 수정했으므로, 이는 재발을 막습니다.
|
|
23
|
+
- 정직한 범위를 명문화(EN + KO): 다중 복제 상태 계약(rate/audit/vault는 단일 프로세스), 단일 호스트 동시성 한정, 유니코드/base64 탐지 제외, 비UTF-8 무음 손상 디코드.
|
|
24
|
+
|
|
25
|
+
### WS2 — 탐지 품질 (1.2.0; 가장 큰 레버리지)
|
|
26
|
+
보안 게이트웨이에서 탐지 정밀도/재현율은 **그 자체가 제품**인데, 지금은 측정되지 않습니다.
|
|
27
|
+
- **WS2a — 측정 먼저 (L):** 라벨링 fixture 코퍼스(타입별 양성 PII/secret 샘플 + 양성처럼 보이는 hard-negative 집합)와 타입별 precision/recall을 보고하는 `bench:detection` 스크립트를 만들어, `release:preflight`와 함께 CI 회귀 게이트로 연결합니다. WS2의 나머지는 모두 이 베이스라인에 대해 측정합니다.
|
|
28
|
+
- **WS2b — 커버리지 (M):** 감사에서 미탐으로 재현된 흔한 자격증명 형식에 대한 고정밀·정밀 앵커 규칙 — AWS(`AKIA`/`ASIA`), GitHub(`ghp_`/`gho_`/`ghs_`), Google(`AIza`), Slack(`xox[baprs]-`), JWT(3-세그먼트), PEM 비밀키 헤더 — 와 `assignment-secret` 키 어휘 확장(`client_secret`, `private_key`, `aws_secret_access_key` 등). 국제 PII(US SSN, IBAN mod-97, E.164)는 검증기와 함께 추가하거나 **KR 로케일 전용임을 명시 문서화**합니다.
|
|
29
|
+
- **WS2c — 정밀도 제어 (M):** *이미 설계된* `filters.minConfidence` 게이트를 구현하고(현재 `confidence` 필드는 기록만 되고 아무것도 게이팅하지 않습니다), 하드블록 타입(`secret`/`api_key`/`kr_rrn`/`card`)을 **억제할 수 없다**는 불변식을 명문화한 `filters.allowlist` 예외 메커니즘을 추가합니다. 감사에서 재현된 고오탐 규칙에 컨텍스트 앵커를 추가합니다(Luhn 통과 주문번호 → `card`, 평문 속 "Bearer …" → `secret`).
|
|
30
|
+
- **WS2d — 우회 방어 (M):** 매칭 전 문자열 리프의 Unicode NFKC 정규화(현재 full-width/혼동 문자 우회가 모든 규칙을 무력화함). 선택적으로 긴 문자열 리프에 대한 bounded base64/percent 디코드-후-재스캔.
|
|
31
|
+
|
|
32
|
+
### WS3 — 수평 확장·상태 안전 (1.2.0; 주입 seam + 정직한 문서)
|
|
33
|
+
rate limiter, audit 체인, token vault, auth store는 단일 프로세스/로컬 파일 설계이며, 로드밸런서 뒤 2개 이상 복제본에서 **무음으로** 약화됩니다.
|
|
34
|
+
- rate limiter를 **주입 가능한 collaborator**(`providers.rateLimiter`, `auditSink`/`cryptoProvider`와 동일 패턴)로 만들어, 공유 저장소 구현을 부재가 아니라 *교체 가능*하게 합니다 — 내장 분산 저장소는 아닙니다.
|
|
35
|
+
- rate-limiter 윈도우 `Map`을 prune(현재 identity 키로 무한 메모리 증가).
|
|
36
|
+
- 다중 복제 현실을 정직하게 문서화(EN + KO + risk register): 프로세스별 rate limit, 공유 파일에서의 audit hash 체인 분기, whole-file-rewrite vault 확장 한계, NFS 파일락 주의, 단일 작성자 anchor 스트림. `shared-responsibility.md`에 "수평 확장 / 다중 복제" 절을 추가합니다.
|
|
37
|
+
|
|
38
|
+
### WS4 — 운영성 / Day-2 (1.2.0)
|
|
39
|
+
유료 운영자가 지금은 이것을 운영 환경에서 실행·모니터링할 수 없습니다.
|
|
40
|
+
- **Health:** `/__haechi/health`를 `/__haechi/live`(프로세스 liveness)와 `/__haechi/ready`(audit sink 쓰기 가능 + provider 로드 + 선택적 캐시 upstream probe → 준비 안 됐으면 503)로 분리하고 버전 필드를 둡니다.
|
|
41
|
+
- **Telemetry:** 최소 `/metrics` 표면(결정/라우트/모드별 요청 수, 차단, `auth_denied`, `rate_limited`, `upstream_timeout`, 응답 미보호, 요청/응답 지연 히스토그램)을 주입 seam으로 제공합니다. audit 쓰기 실패 전용 신호(현재는 stderr 1줄과 함께 요청당 500). 시작/종료/오류에 대한 구조화 JSON 로그와, audit 이벤트에도 나타나는 correlation id. **불변식 가드:** 어떤 metric 라벨이나 로그 필드도 평문/PII를 담아서는 안 됩니다(audit 평문 금지 불변식을 telemetry로 확장).
|
|
42
|
+
- **Resilience:** in-flight 요청을 grace 기간 내에 비우고 keep-alive 연결을 닫는 graceful shutdown. 초과 시 503 + `Retry-After`를 반환하는 전역 max-in-flight 상한(backpressure). 튜닝된 `requestTimeout`/`headersTimeout`.
|
|
43
|
+
- **Deploy:** 비밀이 아닌 운영 키(`HAECHI_PROXY_PORT`/`HAECHI_UPSTREAM`/`HAECHI_MODE` 등)에 대한 fail-closed env-var 오버레이. 하드닝된 레퍼런스 `Dockerfile`(non-root, 고정 Node 22, 읽기 전용 root fs + 쓰기 가능 `.haechi` 볼륨)와 `compose` 예제(전면 TLS/auth proxy) + 운영 runbook. 체인 인식 audit 로그 로테이션/보존 절차. `configVersion` 스탬프 + 업그레이드 노트 맵.
|
|
44
|
+
|
|
45
|
+
### WS5 — 코어 robustness 버그 (1.1.2 patch)
|
|
46
|
+
- **`collectStringEntries` 무한 재귀 (M):** `maxRequestBytes` 이내의 깊게 중첩된 JSON payload가 스택을 오버플로 → 미포착 크래시. 설정 가능한 최대 중첩 깊이 가드(byte-limit 경로와 동일하게 fail-closed 4xx) + 깊은 중첩 테스트를 추가합니다.
|
|
47
|
+
- 비UTF-8 요청 바디: 현재 탐지 전에 U+FFFD로 손실 디코드됩니다. fail-closed로 거부(`Buffer`/`isUtf8` 점검)하거나 수용된 제외로 문서화합니다.
|
|
48
|
+
- `bench-payload.mjs`에 깊은 중첩 + 높은 fan-out 케이스를 추가하고 P1-OPS-004 행에 정직한 최악 케이스를 반영합니다.
|
|
49
|
+
|
|
50
|
+
### WS6 — 신뢰 자산 (상용 보안 검토)
|
|
51
|
+
- **proxy TLS / remote-bind 하드닝 (M):** 대시보드의 fail-closed remote-bind 패턴을 proxy에 이식합니다 — `--allow-remote-bind`가 설정되면 명시적 TLS 컨텍스트(또는 신뢰 hop의 `X-Forwarded-Proto`)를 요구한 뒤에야 수락하여, remote bind가 bearer 토큰 + payload를 평문으로 노출하지 못하게 합니다. 이것은 문서가 아니라 실질 보안 통제입니다.
|
|
52
|
+
- 기존 통제를 OWASP LLM Top 10(2025)과 NIST AI RMF(이미 인용된 프레임워크)에 매핑하는 보안 백서, 그리고 문서화된 구조적 셀프 pen-test.
|
|
53
|
+
- 취약점 공개 채널: `SECURITY.md` 보고 경로 + `security.txt` + GitHub private vulnerability reporting + 분류/대응 시간 목표.
|
|
54
|
+
- 컴플라이언스 통제 매핑과 DSAR/retention 운영 워크플로 문서.
|
|
55
|
+
|
|
56
|
+
## 3. 순서
|
|
57
|
+
|
|
58
|
+
1. **WS1 + WS5 → 1.1.2 (patch).** 저위험, 즉각적 신뢰 상승(정직한 문서 + 실제 크래시 버그 수정 + doc-freshness 게이트). 워밍업.
|
|
59
|
+
2. **WS2 → 1.2.0의 핵심.** WS2a(측정)가 게이트로 먼저 안착하고, WS2b/c/d는 *코퍼스에 대해* 개발되어 모든 변경이 precision/recall 신호를 갖습니다.
|
|
60
|
+
3. **WS3** (주입 seam + 정직한 다중 복제 문서).
|
|
61
|
+
4. **WS4** (운영성: health/metrics/logging/deploy).
|
|
62
|
+
5. **WS6** (신뢰 자산).
|
|
63
|
+
|
|
64
|
+
WS2–WS6은 **1.2.0** 하에 additive·opt-in 조이기로 안착합니다(API freeze 보존: 새 config 키는 additive이며, `minConfidence`/`allowlist`는 정책 *동작*을 바꾸지만 additive하게, 1.1 동작을 보존하는 기본값 뒤에서만 — `tests/api-contract.test.mjs`로 검증).
|
|
65
|
+
|
|
66
|
+
## 4. 가드레일 (회귀 금지)
|
|
67
|
+
- 코어의 **런타임 의존성 0**을 유지합니다. 공유 상태/metrics 구현은 주입 seam이거나 satellite이며, 결코 코어 의존성이 아닙니다.
|
|
68
|
+
- **audit 평문/PII 금지**를 모든 신규 telemetry(metric 라벨, 구조화 로그)로 확장합니다.
|
|
69
|
+
- 모든 신규 경로(깊이 가드, backpressure, readiness, env 오버레이)에 **fail-closed** 자세를 유지합니다.
|
|
70
|
+
- **EN + KO 문서**를 함께 이동하며, 신규 KO 내용은 합쇼체로 작성합니다.
|
|
71
|
+
- 각 워크스트림은 워크플로우로 구축하고 머지 전에 적대적으로 검증하며, test + `check:types` + `release:preflight` 증거와 함께 출하합니다.
|
|
72
|
+
|
|
73
|
+
## 5. 명시적 비목표
|
|
74
|
+
- 내장 분산 rate limiter / audit sink / token vault(Redis/DB). 이 트랙은 **seam + 정직한 문서**까지만 추가하며, 운영 공유 저장소는 향후 satellite입니다.
|
|
75
|
+
- ML/임베딩 기반 탐지. 탐지는 regex + 검증기를 유지하며, 작업은 측정 + 정밀도 제어 + 잘 알려진 형식 커버리지입니다.
|
|
76
|
+
- 새 추론 백엔드나 새 플러그인 종류. 이 트랙은 제품 표면을 넓히지 않습니다.
|
|
77
|
+
- 컴플라이언스 *인증*. WS6은 통제 **매핑**과 공개 자산을 산출하며, 인증 주장은 하지 않습니다.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Reliability Hardening Track
|
|
2
|
+
|
|
3
|
+
- Status: Plan (pinned 2026-06-12; grounded in a 5-lens read-only audit of the 1.1.1 core)
|
|
4
|
+
- Target line: 1.1.2 (patch) → 1.2.0 (minor); no new product surface
|
|
5
|
+
- Purpose: raise Haechi to **commercial-solution-level reliability** — the trust, operability, and detection-quality density a production AI-security gateway is expected to have. This is a quality objective, not a commercialization plan. Every item **tightens, measures, or documents what already exists**; none adds a new feature.
|
|
6
|
+
|
|
7
|
+
## 1. Why this track
|
|
8
|
+
|
|
9
|
+
A 5-lens audit of the 1.1.1 core (detection quality, horizontal-scale/state, operability, security residuals, correctness/consistency) returned **47 findings (16 high / 20 medium / 11 low)**, each grounded in code, a config rule, a doc claim, or a missing artifact. The recurring theme is not missing features — it is **missing density**: the core is correct for a single self-hosted replica but unmeasured, under-instrumented, and partly under-documented for production trust.
|
|
10
|
+
|
|
11
|
+
A telling signal: the project's own current design draft (`docs/current/privacy-filtering-policy-draft.md`) already specifies `minConfidence` thresholds, a false-positive allowlist, and FP/FN measurement — controls the shipped code does **not** implement. So the largest single gap is closing the distance between the *designed* core and the *shipped* core, not extending scope.
|
|
12
|
+
|
|
13
|
+
This track deliberately **excludes** new features: external Redis/DB shared-state implementations, ML-based detection, and new inference backends are out of scope. Where horizontal scale needs production state, the track adds an **injection seam + honest documentation**, not a built-in distributed store.
|
|
14
|
+
|
|
15
|
+
## 2. Workstreams
|
|
16
|
+
|
|
17
|
+
Each workstream tightens existing behavior. Effort is per the audit (S/M/L).
|
|
18
|
+
|
|
19
|
+
### WS1 — Honesty & consistency sweep (1.1.2 patch)
|
|
20
|
+
The governing docs have drifted behind the shipped 1.1.1 line, which directly erodes trust in a security product.
|
|
21
|
+
- Correct stale claims: README + `configuration.md` "the proxy has no client authentication yet (planned for 0.6)" (bearer auth shipped in 0.6); `SECURITY.md` (describes a 0.3.x product — no streaming inspection, validation-only plugins); the `Target version: 0.6.0` / `Draft 0.1 / Target 1.0.0` headers on `configuration.md` / `threat-model.md` / `risk-register-release-gate.md`; the risk-register §1/§7 maturity language; the "0.1 crypto provider" label in README Security Notes.
|
|
22
|
+
- Add a **doc-freshness preflight gate** — extend the stale-name scanner (or a small new check) to fail CI on stale version banners and known-stale phrases (`planned for 0.6`, `Target version: 0.6.0`, `Only the current 0.3.x`, …). Haechi has shipped three stale-string fixes already; this prevents recurrence.
|
|
23
|
+
- Document honest scope explicitly (EN + KO): the multi-replica state contract (rate/audit/vault are single-process), single-host concurrency scoping, the unicode/base64 detection exclusions, and non-UTF-8 lossy decode.
|
|
24
|
+
|
|
25
|
+
### WS2 — Detection quality (1.2.0; highest leverage)
|
|
26
|
+
Detection precision/recall **is** the product for a security gateway, and it is currently unmeasured.
|
|
27
|
+
- **WS2a — Measure first (L):** a labeled fixture corpus (positive PII/secret samples per type + a benign/hard-negative set) and a `bench:detection` script reporting per-type precision/recall, wired as a CI regression gate alongside `release:preflight`. Everything else in WS2 is measured against this baseline.
|
|
28
|
+
- **WS2b — Coverage (M):** high-precision, well-anchored rules for the common credential formats the audit reproduced as MISS — AWS (`AKIA`/`ASIA`), GitHub (`ghp_`/`gho_`/`ghs_`), Google (`AIza`), Slack (`xox[baprs]-`), JWT (three-segment), PEM private-key headers — plus an expanded `assignment-secret` key vocabulary (`client_secret`, `private_key`, `aws_secret_access_key`, …). International PII (US SSN, IBAN mod-97, E.164) is either added with validators or **explicitly documented as KR-locale-only**.
|
|
29
|
+
- **WS2c — Precision control (M):** implement the *already-designed* `filters.minConfidence` gate (the `confidence` field is currently recorded but never gates anything) and a `filters.allowlist` exception mechanism with the documented invariant that it **cannot** suppress hard-block types (`secret`/`api_key`/`kr_rrn`/`card`). Add context anchors to the high-FP rules the audit reproduced (Luhn-passing order numbers → `card`; "Bearer …" in prose → `secret`).
|
|
30
|
+
- **WS2d — Evasion (M):** Unicode NFKC normalization of string leaves before matching (full-width/confusable evasion currently defeats all rules); optionally a bounded base64/percent-decode-and-rescan pass for long string leaves.
|
|
31
|
+
|
|
32
|
+
### WS3 — Horizontal-scale & state safety (1.2.0; injection seam + honest docs)
|
|
33
|
+
The rate limiter, audit chain, token vault, and auth store are single-process / local-file designs that **silently** weaken with 2+ replicas behind a load balancer.
|
|
34
|
+
- Make the rate limiter an **injectable collaborator** (`providers.rateLimiter`, mirroring `auditSink`/`cryptoProvider`) so a shared-store implementation is *replaceable* rather than absent — no built-in distributed store.
|
|
35
|
+
- Prune the rate-limiter window `Map` (currently unbounded memory growth keyed by identity).
|
|
36
|
+
- Document the multi-replica reality honestly (EN + KO + risk register): per-process rate limit, audit hash-chain forking on a shared file, whole-file-rewrite vault scaling limits, NFS file-lock caveats, single-writer anchor stream. Add a "horizontal scale / multiple replicas" subsection to `shared-responsibility.md`.
|
|
37
|
+
|
|
38
|
+
### WS4 — Operability / Day-2 (1.2.0)
|
|
39
|
+
A paying operator cannot run + monitor this in production today.
|
|
40
|
+
- **Health:** split `/__haechi/health` into `/__haechi/live` (process liveness) and `/__haechi/ready` (audit-sink writability + provider load + optional cached upstream probe → 503 when not ready), with a version field.
|
|
41
|
+
- **Telemetry:** a minimal `/metrics` surface (requests by decision/route/mode, blocks, `auth_denied`, `rate_limited`, `upstream_timeout`, response-unprotected, request/response latency histograms) via an injectable seam; a dedicated audit-write-failure signal (today it is a per-request 500 with one stderr line). Structured JSON logs for startup/shutdown/errors with a correlation id that also appears in the audit event. **Invariant guard:** no metric label or log field may carry plaintext/PII (the no-plaintext-in-audit invariant extends to telemetry).
|
|
42
|
+
- **Resilience:** graceful shutdown that drains in-flight requests and closes keep-alive connections within a grace period; a configurable global max-in-flight ceiling returning 503 + `Retry-After` (backpressure); tuned `requestTimeout`/`headersTimeout`.
|
|
43
|
+
- **Deploy:** an env-var configuration overlay for non-secret operational keys (`HAECHI_PROXY_PORT`/`HAECHI_UPSTREAM`/`HAECHI_MODE`/…), fail-closed; a hardened reference `Dockerfile` (non-root, pinned Node 22, read-only root fs + writable `.haechi` volume) + a `compose` example (fronting TLS/auth proxy) + an operations runbook; a chain-aware audit log rotation/retention procedure; a `configVersion` stamp + upgrade-notes map.
|
|
44
|
+
|
|
45
|
+
### WS5 — Core robustness bugs (1.1.2 patch)
|
|
46
|
+
- **`collectStringEntries` unbounded recursion (M):** a deeply nested JSON payload within `maxRequestBytes` can overflow the stack → uncaught crash. Add a configurable max-nesting-depth guard (fail-closed 4xx, mirroring the byte-limit path) + a deep-nesting test.
|
|
47
|
+
- Non-UTF-8 request body: today decoded lossily to U+FFFD before detection. Either reject fail-closed (`Buffer`/`isUtf8` check) or document as an accepted exclusion.
|
|
48
|
+
- Add deep-nesting + high-fan-out cases to `bench-payload.mjs` and reflect the honest worst-case in the P1-OPS-004 row.
|
|
49
|
+
|
|
50
|
+
### WS6 — Trust assets (commercial security review)
|
|
51
|
+
- **Proxy TLS / remote-bind hardening (M):** apply the dashboard's fail-closed remote-bind pattern to the proxy — when `--allow-remote-bind` is set, require an explicit TLS context (or a trusted-hop `X-Forwarded-Proto`) before accepting, so a remote bind cannot expose bearer tokens + payloads in plaintext. This is a real security control, not just docs.
|
|
52
|
+
- A security whitepaper mapping existing controls to OWASP LLM Top 10 (2025) and NIST AI RMF (frameworks already cited), plus a documented structured self-pentest.
|
|
53
|
+
- A vulnerability-disclosure channel: `SECURITY.md` reporting path + `security.txt` + GitHub private vulnerability reporting + a triage/response-time target.
|
|
54
|
+
- A compliance control mapping and a DSAR/retention operational workflow doc.
|
|
55
|
+
|
|
56
|
+
## 3. Sequencing
|
|
57
|
+
|
|
58
|
+
1. **WS1 + WS5 → 1.1.2 (patch).** Low-risk, immediate trust gain (honest docs + a real crash-bug fix + a doc-freshness gate). Warm-up.
|
|
59
|
+
2. **WS2 → the core of 1.2.0.** WS2a (measurement) lands first as a gate; WS2b/c/d are then developed *against the corpus* so every change has a precision/recall signal.
|
|
60
|
+
3. **WS3** (injection seam + honest multi-replica docs).
|
|
61
|
+
4. **WS4** (operability: health/metrics/logging/deploy).
|
|
62
|
+
5. **WS6** (trust assets).
|
|
63
|
+
|
|
64
|
+
WS2–WS6 land under **1.2.0** as additive, opt-in tightenings (API freeze preserved: new config keys are additive; `minConfidence`/`allowlist` change policy *behavior* but only additively and behind defaults that preserve 1.1 behavior — verified against `tests/api-contract.test.mjs`).
|
|
65
|
+
|
|
66
|
+
## 4. Guardrails (do not regress)
|
|
67
|
+
- **Zero runtime dependency** in core stays. Any shared-state/metrics implementation is an injection seam or a satellite, never a core dependency.
|
|
68
|
+
- **No plaintext/PII in audit** extends to all new telemetry (metrics labels, structured logs).
|
|
69
|
+
- **Fail-closed** posture holds for every new path (depth guard, backpressure, readiness, env overlay).
|
|
70
|
+
- **EN + KO docs** move together; the new KO content is written in 합쇼체.
|
|
71
|
+
- Each workstream is workflow-built and adversarially verified before merge; each ships with test + `check:types` + `release:preflight` evidence.
|
|
72
|
+
|
|
73
|
+
## 5. Explicit non-goals
|
|
74
|
+
- A built-in distributed rate limiter / audit sink / token vault (Redis/DB). The track adds the **seam + honest docs**; a production shared-store is a future satellite.
|
|
75
|
+
- ML/embedding-based detection. Detection stays regex + validators; the work is measurement + precision control + coverage of well-known formats.
|
|
76
|
+
- New inference backends or new plugin kinds. This track does not expand product surface.
|
|
77
|
+
- A compliance *certification*. WS6 produces a control **mapping** and disclosure assets, not a certification claim.
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
# Haechi 리스크 레지스터 및 릴리스 게이트
|
|
2
2
|
|
|
3
|
-
- 문서 상태:
|
|
3
|
+
- 문서 상태: Living document(core 1.1.x 추적)
|
|
4
4
|
- 작성일: 2026-06-11
|
|
5
|
-
- 기준 버전: 1.
|
|
5
|
+
- 기준 버전: 1.1.x
|
|
6
6
|
- 기준 브랜치: `main`
|
|
7
7
|
|
|
8
8
|
## 1. 현재 판단
|
|
9
9
|
|
|
10
|
-
0.3.2
|
|
10
|
+
Haechi는 `1.x` stable 라인을 출시했습니다. developer preview 게이트(G2, `haechi@0.3.2`)부터 G6(1.1.0 plugin capability 강제)까지 모든 게이트가 통과되었으며, 아래 게이트 이력은 감사 추적으로 보존합니다. 1.0.0은 strict semver 하의 frozen API 계약을 선언하고(문서화된 deprecation 정책과 freeze 가드 `tests/api-contract.test.mjs` 포함), signed·sandboxed `authProvider` plugin에 한해 dynamic-loading 금지를 좁게 해제했습니다. 1.1.0은 커널 수준 capability 거부를 갖춘 opt-in `process-isolated` plugin 런타임을 추가했습니다. stable 표현을 막던 조건 — 1.0 API 안정성, 외부 `cryptoProvider`/KMS reference adapter(`haechi-crypto-kms`), stream-aware enforcement(`streaming.requestMode: "inspect"`) — 은 모두 갖춰졌습니다. Haechi는 여전히 컴플라이언스를 보장하지 않는 self-hosted 보안 toolkit이며, 운영 배포는 네트워크 접근 통제, upstream 인증, key custody를 직접 책임집니다(threat model §5 참고).
|
|
11
11
|
|
|
12
12
|
| 구분 | 판단 | 이유 |
|
|
13
13
|
|---|---|---|
|
|
14
|
-
| GitHub public | 허용 | 보안 한계, threat model, shared responsibility
|
|
15
|
-
| GitHub release/tag | 허용 |
|
|
16
|
-
| npm
|
|
17
|
-
|
|
|
18
|
-
| production use | 금지 | 0.3.2는 self-hosted developer preview이며 운영 인증/인가/key custody는 사용자 책임 |
|
|
14
|
+
| GitHub public | 허용 | 보안 한계, threat model, shared responsibility가 문서화됨 |
|
|
15
|
+
| GitHub release/tag | 허용 | stable `1.x` 라인; 릴리스 노트가 각 게이트(G0–G6)를 추적 |
|
|
16
|
+
| npm stable | 허용 | 1.0 stable 라벨 조건 — frozen API 계약, 외부 KMS reference adapter, stream-aware enforcement — 충족; core는 provenance와 함께 발행 |
|
|
17
|
+
| production use | 운영자 게이트 | 운영자가 네트워크 접근 통제, 인증/인가, 운영 key custody를 앞단에 두면 self-hosted 게이트웨이로 지원; Haechi는 컴플라이언스 보장이 아님 |
|
|
19
18
|
|
|
20
19
|
## 2. 릴리스 게이트
|
|
21
20
|
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
| P1-SEC-001 | KMS/HSM/Vault 미지원 | Resolved for OSS core | `createRuntime(config, { cryptoProvider })` 외부 crypto provider injection, external provider 없으면 fail-closed |
|
|
48
47
|
| P1-SEC-002 | TokenVault 권한 모델 부족 | Resolved | `revealPolicy: "disabled"` 기본값, `--allow-dev-reveal`, metadata export, retention/purge timestamp |
|
|
49
48
|
| P1-SEC-003 | audit 무결성 부족 | Resolved | JSONL audit SHA-256 hash chain 및 `verifyAuditChain` |
|
|
50
|
-
| P1-SEC-004 | plugin runtime 없음 | Resolved by gating (P1-SEC-024이 대체) | dynamic runtime 거부, `manifest-only` plugin만 통과. **1.0에서 P1-SEC-024(§5.4)이
|
|
49
|
+
| P1-SEC-004 | plugin runtime 없음 | Resolved by gating (P1-SEC-024이 대체) | dynamic runtime 거부, `manifest-only` plugin만 통과. **1.0에서 P1-SEC-024(§5.4)이 대체합니다.** 1.0은 manifest-only-only 입장을 의도적으로 해제하고, 새 신뢰 통제 하에 signed·capability-gated·worker-isolated·audited `authProvider` plugin에 한해 동적 로딩을 **좁게** 허용합니다 |
|
|
51
50
|
| P1-SEC-005 | policy conflict 처리 부족 | Resolved | preset block 등 강한 action을 약한 action으로 낮추면 conflict fail-closed |
|
|
52
51
|
| P1-SEC-006 | regex 중심 필터 정확도 한계 | Resolved for preview | KR RRN checksum, Luhn, unsafe custom regex 제한. ML/classifier plugin은 stable backlog |
|
|
53
52
|
| P1-SEC-007 | AAD/replay/stream 확장 부족 | Resolved for preview | AAD hash mismatch 명시, streaming 기본 차단. stream sequence/replay cache는 stream support 도입 시 필요 |
|
|
@@ -97,11 +96,11 @@
|
|
|
97
96
|
| P2-SEC-028 | proxy 내부 오류 메시지가 클라이언트에 노출 | Resolved | 예기치 못한 오류는 일반화된 메시지 반환, 상세는 stderr |
|
|
98
97
|
| P2-DOC-005 | dry-run + responseProtection off 기본값에서 "보호 중" 오인 가능 | Resolved | proxy 기동/`protect` 출력에 비집행 경고 명시 |
|
|
99
98
|
|
|
100
|
-
base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncation 탐지는 명시적 제외로 threat model에
|
|
99
|
+
base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncation 탐지는 명시적 제외로 threat model에 문서화했습니다 (0.4+ backlog).
|
|
101
100
|
|
|
102
101
|
## 5.3 0.9.0 Observability + Interactive-Auth 리스크 상태
|
|
103
102
|
|
|
104
|
-
이 ID들은 0.9.0 위성 컷(`haechi-dashboard`, `haechi-auth-oidc`, `haechi-crypto-kms@0.2.0`)에 한정되며, 0.9.0 섹션으로 namespace되어 위의 동일 번호 P0/P1 행과
|
|
103
|
+
이 ID들은 0.9.0 위성 컷(`haechi-dashboard`, `haechi-auth-oidc`, `haechi-crypto-kms@0.2.0`)에 한정되며, 0.9.0 섹션으로 namespace되어 위의 동일 번호 P0/P1 행과 구분됩니다. 증거는 위성 소스, 그 테스트 스위트, 그리고 `docs/current/release-0.9-implementation-scope.md` §6에 정리된 adversarial security review입니다.
|
|
105
104
|
|
|
106
105
|
| ID | 리스크 | 상태 | 해소 증거 |
|
|
107
106
|
|---|---|---|---|
|
|
@@ -111,7 +110,7 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
111
110
|
|
|
112
111
|
## 5.4 1.0.0 Stable API Contract + Signed-Plugin Sandbox 리스크 상태
|
|
113
112
|
|
|
114
|
-
이 ID들은 1.0.0 stable 컷(API freeze + Ed25519 signed, worker-isolated `authProvider` plugin sandbox)에
|
|
113
|
+
이 ID들은 1.0.0 stable 컷(API freeze + Ed25519 signed, worker-isolated `authProvider` plugin sandbox)에 한정됩니다. 권위 있는 threat 행과 범위는 `docs/current/release-1.0-implementation-scope.md` §6이며, 증거는 PR(#46–#49), core 소스, 그리고 테스트 스위트입니다.
|
|
115
114
|
|
|
116
115
|
| ID | 리스크 | 상태 | 해소 증거 |
|
|
117
116
|
|---|---|---|---|
|
|
@@ -124,8 +123,8 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
124
123
|
|
|
125
124
|
| ID | Risk | Status | Resolution evidence |
|
|
126
125
|
|---|---|---|---|
|
|
127
|
-
| P1-SEC-027 | Plugin capability *강제*: 1.0 `worker_threads` sandbox는 memory/crash 격리뿐이라 악의적 signed plugin이 `fs`/`net`을 써서 credential을 exfiltrate할 수 있음. **P1-SEC-024의 수용된 worker 잔여를 강화** — 1.1이 새 opt-in 런타임에 실제 강제 추가 | Mitigated | `packages/plugin/process-sandbox.mjs` `createProcessIsolatedAuthProvider`/`…Sync`(PR #54): signed `authProvider`가 `--permission` 하 자식 `node`에서 **부여 0**(fs/child-process/worker/addons/wasi 없음, `--allow-net` 없음)으로, `data:` URL 로드(fs 권한 없음 → TOCTOU/symlink 표면 없음), `stdio:['ignore','ignore','ignore','ipc']`(stdout/stderr/fd 유출 채널 없음), 정화 env, JSON-string 전용 IPC + 공유 null-proto sanitizer + 호스트측 keyed-HMAC identity로
|
|
128
|
-
| P1-SEC-028 | 호스트 중개 키 자료 + SSRF: 키 자료가 필요한 커스텀 자격증명 plugin이 plugin 주도 SSRF 벡터가 될 수 있고, 코어엔 SSRF 가드가 없었음(위성 복사본은 코어에서 도달 불가) | Mitigated | 새 node:-only, 의존성 0 **`haechi/ssrf`** 코어 모듈(PR #55): `isBlockedAddress`(private/loopback/link-local/metadata), `guardedFetch`(https 전용, DNS 후 재확인, `redirect:"error"`, 본문 제한 + timeout), `createGuardedKeyFetcher`(TTL 캐시 + cooldown). `process-isolated` 런타임의 선택적 `keyMaterial:{url}`은 **호스트**가 **운영자 선언** URL에서 이 가드로 가져와 IPC로
|
|
126
|
+
| P1-SEC-027 | Plugin capability *강제*: 1.0 `worker_threads` sandbox는 memory/crash 격리뿐이라 악의적 signed plugin이 `fs`/`net`을 써서 credential을 exfiltrate할 수 있음. **P1-SEC-024의 수용된 worker 잔여를 강화** — 1.1이 새 opt-in 런타임에 실제 강제 추가 | Mitigated | `packages/plugin/process-sandbox.mjs` `createProcessIsolatedAuthProvider`/`…Sync`(PR #54): signed `authProvider`가 `--permission` 하 자식 `node`에서 **부여 0**(fs/child-process/worker/addons/wasi 없음, `--allow-net` 없음)으로, `data:` URL 로드(fs 권한 없음 → TOCTOU/symlink 표면 없음), `stdio:['ignore','ignore','ignore','ipc']`(stdout/stderr/fd 유출 채널 없음), 정화 env, JSON-string 전용 IPC + 공유 null-proto sanitizer + 호스트측 keyed-HMAC identity로 실행됩니다. **Node 26 실측 검증**: plugin의 `fs`/`net`/`fetch`/`dns`/`child_process`/`worker`와 `process.binding('tcp_wrap')` 우회가 모두 `ERR_ACCESS_DENIED`. 네트워크 봉쇄는 **커널 `--allow-net` 거부**(삭제 가능한 JS 하니스가 아님); 기본값 `netEnforcement:"require-permission"`은 강제 못 하는 Node에서 **fail closed**(동작 probe 기능 탐지; PR #54). spawn-storm 서킷 브레이커(PR #56)가 재spawn 제한. lifecycle audit에 호스트 계산/enum 전용 `isolation`/`grants`/`netEnforcement` 추가(PR #56). config: `auth.plugin.isolation:"process"` fail-closed 배선(PR #56). 테스트: fs/net/stdio 레드팀(`--allow-net` 없는 Node에선 fail-closed라 skip) + 상시 실행 fail-closed 계약 + config 매트릭스. **잔여:** `--allow-net` 없는 Node(fail-closed, 미봉쇄); `networkEgress` 부여 plugin; 자식 메모리의 credential/키 자료(core-dump/swap); V8/Node 탈출(런타임 통제일 뿐 OS 샌드박스 아님) |
|
|
127
|
+
| P1-SEC-028 | 호스트 중개 키 자료 + SSRF: 키 자료가 필요한 커스텀 자격증명 plugin이 plugin 주도 SSRF 벡터가 될 수 있고, 코어엔 SSRF 가드가 없었음(위성 복사본은 코어에서 도달 불가) | Mitigated | 새 node:-only, 의존성 0 **`haechi/ssrf`** 코어 모듈(PR #55): `isBlockedAddress`(private/loopback/link-local/metadata), `guardedFetch`(https 전용, DNS 후 재확인, `redirect:"error"`, 본문 제한 + timeout), `createGuardedKeyFetcher`(TTL 캐시 + cooldown). `process-isolated` 런타임의 선택적 `keyMaterial:{url}`은 **호스트**가 **운영자 선언** URL에서 이 가드로 가져와 IPC로 주입하므로, plugin은 URL을 명명하지 않습니다(plugin 주도 SSRF 없음). kid-refetch cooldown이 아웃바운드 비율을 제한하고, blocked-address URL은 fail closed됩니다. 테스트: 표준 `isBlockedAddress` 벡터 테이블 + 코어-대-`auth-jwt` parity 가드, `guardedFetch` SSRF 거부/제한, cooldown fail-closed, 런타임 키 주입 + no-SSRF. **잔여:** 위성은 의도적으로 로컬 복사본을 유지함(crypto/auth 패키지는 core-ssrf에 런타임 의존 금지; `crypto-kms/ssrf-parity.test.mjs`) — 코어 재import는 연기하며, drift는 제거가 아니라 parity로 가드; 가드의 DNS-rebinding 창(resolve-then-connect)은 운영자 선언 URL에 대해 수용 |
|
|
129
128
|
|
|
130
129
|
## 6. P2 제품/문서 리스크 상태
|
|
131
130
|
|
|
@@ -136,14 +135,16 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
136
135
|
| P2-DOC-003 | region/privacy profile 미구현 | Resolved for baseline | `haechi/privacy-profiles`, `privacy.profile` runtime 적용 |
|
|
137
136
|
| P2-DOC-004 | API stability 정책 없음 | Resolved | `docs/current/api-stability.md` |
|
|
138
137
|
|
|
139
|
-
## 7. npm
|
|
138
|
+
## 7. npm 릴리스 배포 전 체크리스트
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
이 체크리스트는 `1.x` stable 라인의 모든 릴리스에 대한 상시 배포 전 템플릿이며, `0.3.2` developer preview에서 처음 적용되었습니다. 그 결과를 아래에 참조 기록으로 보존합니다.
|
|
141
|
+
|
|
142
|
+
외부 npm 게이트 확인 결과(`0.3.2` developer preview, 2026-06-10, 배포 후)는 다음과 같습니다.
|
|
142
143
|
|
|
143
144
|
- `npm whoami`: `raeseoklee`
|
|
144
145
|
- `npm view haechi version`: `0.3.2`
|
|
145
146
|
|
|
146
|
-
아래 체크리스트는 2026-06-10 0.3.2 배포에서 provenance publish 경로를 제외하고
|
|
147
|
+
아래 체크리스트는 2026-06-10 0.3.2 배포에서 provenance publish 경로를 제외하고 완료되었습니다(`v0.3.2` 태그와 GitHub pre-release 완료). provenance는 GitHub Actions trusted publishing으로 이월되었으며, 이후 stable 릴리스는 provenance와 함께 trusted-publishing 경로로 발행합니다.
|
|
147
148
|
|
|
148
149
|
1. `npm run release:preflight`
|
|
149
150
|
2. `npm run sbom`
|
|
@@ -165,23 +166,20 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
165
166
|
| 0.9.0 | observability + interactive auth | `haechi-auth-oidc` 전체 authorization-code flow, `haechi-dashboard` 읽기 전용 audit 뷰어(hash-chain 무결성 표시, 요약/검색/타임라인), `haechi-crypto-kms` 추가 백엔드(Vault/GCP/Azure) |
|
|
166
167
|
| 1.0.0 | stable API contract | migration policy, long-term audit schema, plugin sandbox/runtime conformance 및 allowlist/manifest 통과 외부 auth/classifier package 동적 로딩 |
|
|
167
168
|
|
|
168
|
-
동적 npm package 로딩은 1.0 plugin sandbox 이전까지
|
|
169
|
+
동적 npm package 로딩은 1.0 plugin sandbox 이전까지 금지합니다. 0.4~0.7의 외부 provider는 `createRuntime(config, providers)` 프로그래매틱 주입만 지원합니다.
|
|
169
170
|
|
|
170
171
|
## 9. 현재 허용 가능한 사용 범위
|
|
171
172
|
|
|
172
|
-
|
|
173
|
+
`1.x` stable 라인은 다음 범위에서 사용합니다.
|
|
173
174
|
|
|
174
175
|
- 로컬 개발 환경
|
|
175
176
|
- 샘플 payload 검증
|
|
176
|
-
- OpenAI-compatible/vLLM/Ollama/llama.cpp proxy PoC
|
|
177
|
+
- OpenAI-compatible/vLLM/Ollama/llama.cpp proxy PoC 및 self-hosted 게이트웨이
|
|
177
178
|
- 정책/필터/감사 pipeline 검토
|
|
178
179
|
- GitHub 코드 리뷰와 보안 설계 논의
|
|
179
|
-
-
|
|
180
|
+
- 운영자가 네트워크 접근 통제, 인증/인가, 운영 key custody를 앞단에 두는 **경우**의 self-hosted 운영 게이트웨이(§1 참고)
|
|
180
181
|
|
|
181
|
-
|
|
182
|
+
Haechi는 여전히 다음 용도로는 사용하지 않습니다.
|
|
182
183
|
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
- 실제 고객/환자/결제/인증정보 처리
|
|
186
|
-
- compliance evidence 또는 법적 준수 증명
|
|
187
|
-
- npm stable package
|
|
184
|
+
- 운영자 자체의 네트워크 통제와 인증 없이 인터넷에 직접 노출되는 proxy
|
|
185
|
+
- compliance evidence 또는 법적 준수 증명(Haechi는 컴플라이언스 보장이 아님)
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
# Haechi Risk Register and Release Gates
|
|
2
2
|
|
|
3
|
-
- Status:
|
|
3
|
+
- Status: Living document (tracks core 1.1.x)
|
|
4
4
|
- Date: 2026-06-11
|
|
5
|
-
- Target version: 1.
|
|
5
|
+
- Target version: 1.1.x
|
|
6
6
|
- Branch: `main`
|
|
7
7
|
|
|
8
8
|
## 1. Current Assessment
|
|
9
9
|
|
|
10
|
-
0.3.2
|
|
10
|
+
Haechi has shipped its `1.x` stable line. The developer-preview gate (G2, `haechi@0.3.2`) and every gate through G6 (1.1.0 plugin capability enforcement) are passed; the gate history below is retained as the audit trail. 1.0.0 declared the frozen API contract under strict semver (with a documented deprecation policy and `tests/api-contract.test.mjs` as the freeze guard) and narrowly lifted the dynamic-loading ban for a signed, sandboxed `authProvider` plugin; 1.1.0 added the opt-in `process-isolated` plugin runtime with kernel-enforced capability denial. The previously distribution-blocking conditions for the stable label — 1.0 API stability, the external `cryptoProvider`/KMS reference adapter (`haechi-crypto-kms`), and stream-aware enforcement (`streaming.requestMode: "inspect"`) — are all in place. Haechi remains a self-hosted security toolkit, not a compliance guarantee, and production deployments still own network access control, upstream authentication, and key custody (see §5 of the threat model).
|
|
11
11
|
|
|
12
12
|
| Category | Judgment | Rationale |
|
|
13
13
|
|---|---|---|
|
|
14
|
-
| GitHub public | Allowed | Security limitations, threat model, shared responsibility
|
|
15
|
-
| GitHub release/tag | Allowed |
|
|
16
|
-
| npm
|
|
17
|
-
|
|
|
18
|
-
| Production use | Prohibited | 0.3.2 is a self-hosted developer preview; production auth/authz/key custody is the user's responsibility |
|
|
14
|
+
| GitHub public | Allowed | Security limitations, threat model, and shared responsibility are documented |
|
|
15
|
+
| GitHub release/tag | Allowed | Stable `1.x` line; release notes track each gate (G0–G6) |
|
|
16
|
+
| npm stable | Allowed | The 1.0 stable label conditions — frozen API contract, external KMS reference adapter, and stream-aware enforcement — are met; core publishes with provenance |
|
|
17
|
+
| Production use | Operator-gated | Supported as a self-hosted gateway when the operator supplies network access control, authentication/authorization, and production key custody; Haechi is not a compliance guarantee |
|
|
19
18
|
|
|
20
19
|
## 2. Release Gates
|
|
21
20
|
|
|
@@ -136,14 +135,16 @@ These IDs are scoped to the 1.0.0 stable cut (the API freeze + the Ed25519 signe
|
|
|
136
135
|
| P2-DOC-003 | Region/privacy profile not implemented | Resolved for baseline | `haechi/privacy-profiles`, `privacy.profile` applied at runtime |
|
|
137
136
|
| P2-DOC-004 | No API stability policy | Resolved | `docs/current/api-stability.md` |
|
|
138
137
|
|
|
139
|
-
## 7. npm
|
|
138
|
+
## 7. npm Release Pre-Distribution Checklist
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
This checklist is the standing pre-distribution template for every release on the `1.x` stable line; it was first exercised for the `0.3.2` developer preview, whose results are retained below as the reference record.
|
|
141
|
+
|
|
142
|
+
External npm gate check results (`0.3.2` developer preview, 2026-06-10, post-publish):
|
|
142
143
|
|
|
143
144
|
- `npm whoami`: `raeseoklee`
|
|
144
145
|
- `npm view haechi version`: `0.3.2`
|
|
145
146
|
|
|
146
|
-
All checklist items below were completed for 0.3.2 on 2026-06-10 except the provenance publish path, which
|
|
147
|
+
All checklist items below were completed for 0.3.2 on 2026-06-10 except the provenance publish path, which was deferred to GitHub Actions trusted publishing (`v0.3.2` tag and GitHub pre-release were completed). Subsequent stable releases publish through the trusted-publishing path with provenance.
|
|
147
148
|
|
|
148
149
|
1. `npm run release:preflight`
|
|
149
150
|
2. `npm run sbom`
|
|
@@ -169,19 +170,16 @@ Dynamic npm package loading is prohibited until the 1.0 plugin sandbox. External
|
|
|
169
170
|
|
|
170
171
|
## 9. Current Permitted Use
|
|
171
172
|
|
|
172
|
-
|
|
173
|
+
The `1.x` stable line is intended for use in the following contexts:
|
|
173
174
|
|
|
174
175
|
- Local development environments
|
|
175
176
|
- Sample payload validation
|
|
176
|
-
- OpenAI-compatible/vLLM/Ollama/llama.cpp proxy PoC
|
|
177
|
+
- OpenAI-compatible/vLLM/Ollama/llama.cpp proxy PoC and self-hosted gateway
|
|
177
178
|
- Policy/filter/audit pipeline review
|
|
178
179
|
- GitHub code review and security design discussion
|
|
179
|
-
-
|
|
180
|
+
- A self-hosted production gateway **when** the operator supplies network access control, authentication/authorization, and production key custody in front (see §1)
|
|
180
181
|
|
|
181
|
-
|
|
182
|
+
Haechi is still not intended for the following uses:
|
|
182
183
|
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
- Processing real customer/patient/payment/authentication data
|
|
186
|
-
- Compliance evidence or legal conformance proof
|
|
187
|
-
- npm stable package
|
|
184
|
+
- A proxy directly exposed to the internet without the operator's own network controls and authentication
|
|
185
|
+
- Compliance evidence or legal conformance proof (Haechi is not a compliance guarantee)
|
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
# Haechi Shared Responsibility
|
|
2
2
|
|
|
3
|
-
- 문서 상태:
|
|
3
|
+
- 문서 상태: Living document (core 1.1.x 추적)
|
|
4
4
|
- 작성일: 2026-06-10
|
|
5
|
-
- 기준 버전: 0.3.2
|
|
6
5
|
|
|
7
6
|
## 1. 책임 매트릭스
|
|
8
7
|
|
|
9
8
|
| 영역 | Haechi 제공 | 사용자/운영자 책임 |
|
|
10
9
|
|---|---|---|
|
|
11
|
-
| 로컬 개발 | CLI, default config, dev key 생성 | dev key를
|
|
12
|
-
| 정책 집행 | redact/mask/tokenize/encrypt/block pipeline |
|
|
13
|
-
| HTTP proxy | loopback
|
|
14
|
-
| Streaming | 기본 차단 | pass-through
|
|
15
|
-
| TokenVault | 암호화 저장, reveal 기본 차단, purge | reveal 승인
|
|
16
|
-
| Audit | 평문 제거, hash chain | append-only storage, backup, 보존 기간, 외부
|
|
17
|
-
| Key custody | local dev key, external crypto provider
|
|
18
|
-
| Plugin | manifest validation
|
|
19
|
-
| MCP | JSON-RPC/method allowlist | MCP server auth, resource consent, env secret allowlist |
|
|
20
|
-
| Privacy profile | KR/EU/US baseline
|
|
10
|
+
| 로컬 개발 | CLI, default config, dev key 생성 | dev key를 운영 환경이나 공유 환경에 재사용하지 않습니다 |
|
|
11
|
+
| 정책 집행 | redact/mask/tokenize/encrypt/block pipeline | 규제 정책과 조직 정책에 맞는 action을 선택합니다 |
|
|
12
|
+
| HTTP proxy | loopback 기본값, remote bind guard, body/response limit | 인증, TLS termination, firewall, upstream auth를 담당합니다 |
|
|
13
|
+
| Streaming | 기본 차단 | pass-through를 사용할 때 보호가 적용되지 않는 위험을 감수합니다 |
|
|
14
|
+
| TokenVault | 암호화 저장, reveal 기본 차단, purge | reveal 승인 절차와 DSAR/retention 운영을 담당합니다 |
|
|
15
|
+
| Audit | 평문 제거, hash chain | append-only storage, backup, 보존 기간, 외부 서명을 담당합니다 |
|
|
16
|
+
| Key custody | local dev key, external crypto provider 계약 | KMS/HSM/Vault adapter 구현, rotation, access review를 담당합니다 |
|
|
17
|
+
| Plugin | manifest validation; 서명 + 샌드박스된 `authProvider` 플러그인에 한해 동적 로딩 좁게 허용(worker-isolated 1.0 / process-isolated 1.1) | trust anchor/pin/revocation을 관리하고, `process-isolated`를 우선하며, plugin code review를 수행합니다 |
|
|
18
|
+
| MCP | JSON-RPC/method allowlist | MCP server auth, resource consent, env secret allowlist를 담당합니다 |
|
|
19
|
+
| Privacy profile | KR/EU/US baseline action | 법률 검토, data residency, cross-border transfer 증빙을 담당합니다 |
|
|
21
20
|
|
|
22
21
|
## 2. 금지되는 기본 사용
|
|
23
22
|
|
|
24
|
-
- `--allow-remote-bind`를 네트워크 통제 없이
|
|
25
|
-
- `.haechi/dev.keys.json`을 운영 데이터에
|
|
26
|
-
- `streaming.requestMode: "pass-through"`를
|
|
27
|
-
- `responseProtection.failureMode: "allow"`를 민감 데이터 경로에
|
|
28
|
-
- `token-reveal --allow-dev-reveal`를 운영 복원 절차로
|
|
23
|
+
- `--allow-remote-bind`를 네트워크 통제 없이 사용하는 것
|
|
24
|
+
- `.haechi/dev.keys.json`을 운영 데이터에 사용하는 것
|
|
25
|
+
- `streaming.requestMode: "pass-through"`를 보호가 적용된 것으로 오해하는 것
|
|
26
|
+
- `responseProtection.failureMode: "allow"`를 민감 데이터 경로에 사용하는 것
|
|
27
|
+
- `token-reveal --allow-dev-reveal`를 운영 복원 절차로 사용하는 것
|
|
29
28
|
|
|
30
29
|
## 3. 운영 전환 체크리스트
|
|
31
30
|
|
|
32
|
-
1. 외부 crypto provider 또는 KMS/HSM/Vault adapter를
|
|
33
|
-
2. proxy 앞단에 인증, TLS, firewall, rate limit을
|
|
34
|
-
3. responseProtection을 켜고 fail-closed를
|
|
35
|
-
4. streaming endpoint는
|
|
36
|
-
5. audit sink를 append-only
|
|
37
|
-
6. TokenVault reveal
|
|
38
|
-
7. privacy profile은 법률 검토 결과로
|
|
31
|
+
1. 외부 crypto provider 또는 KMS/HSM/Vault adapter를 연결하세요.
|
|
32
|
+
2. proxy 앞단에 인증, TLS, firewall, rate limit을 두세요.
|
|
33
|
+
3. responseProtection을 켜고 fail-closed를 유지하세요.
|
|
34
|
+
4. streaming endpoint는 별도의 stream-aware gateway가 준비되기 전까지 차단하세요.
|
|
35
|
+
5. audit sink를 append-only 저장소나 외부 서명 저장소로 보내세요.
|
|
36
|
+
6. TokenVault의 reveal 승인, 보존, 삭제 절차를 문서화하세요.
|
|
37
|
+
7. privacy profile은 법률 검토 결과로 보정하세요.
|
|
38
|
+
8. 복제본이 2개 이상이면 §4의 공유 인프라(front-door rate limit, 복제본별 audit 경로, 공유 token vault)를 제공하세요.
|
|
39
|
+
|
|
40
|
+
## 4. 수평 확장 / 다중 복제
|
|
41
|
+
|
|
42
|
+
Haechi의 상태 보유 통제는 설계상 단일 프로세스입니다. 로드밸런서 뒤에서 복제본을 2개 이상 실행하면, 운영자가 공유 인프라를 제공하지 않는 한 이들이 **무음으로 약화**됩니다.
|
|
43
|
+
|
|
44
|
+
- **Rate limit**은 프로세스별·인메모리이므로 전체 처리량이 복제본 수만큼 배가됩니다. identity별 한도를 공유 front door에서 강제하거나, 공유 저장소 기반 `rateLimiter`를 주입하세요.
|
|
45
|
+
- **Audit hash chain + anchor**는 단일 작성자입니다. 각 복제본에 **고유한** `audit.path`(및 anchor 경로)를 주세요. 하나의 audit 파일을 복제본 간에 공유하면 체인이 분기되어 검증 불가 상태가 됩니다.
|
|
46
|
+
- **TokenVault와 auth store**는 whole-file 로컬 저장소입니다 — 단일 호스트에서는 올바르지만 공유 다중 작성자 저장소는 아닙니다. 다중 복제 토큰화에는 공유 `tokenVault`를 주입하세요.
|
|
47
|
+
- 파일 락은 `O_EXCL` + atomic rename에 의존하며 NFS/공유 파일시스템에서는 보장되지 않습니다 — 이 저장소들은 로컬 디스크에 두세요.
|