haechi 0.3.2 → 0.5.0
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 +227 -0
- package/README.md +126 -1
- package/docs/README.md +3 -6
- package/docs/current/api-stability.ko.md +11 -4
- package/docs/current/api-stability.md +11 -4
- package/docs/current/configuration.ko.md +210 -0
- package/docs/current/configuration.md +210 -0
- package/docs/current/release-0.3.2-hardening-scope.ko.md +2 -1
- package/docs/current/release-0.3.2-hardening-scope.md +2 -1
- package/docs/current/release-0.4-implementation-scope.ko.md +2 -1
- package/docs/current/release-0.4-implementation-scope.md +2 -1
- package/docs/current/release-0.5-implementation-scope.ko.md +69 -0
- package/docs/current/release-0.5-implementation-scope.md +69 -0
- package/docs/current/release-process.ko.md +14 -4
- package/docs/current/release-process.md +14 -4
- package/docs/current/risk-register-release-gate.ko.md +11 -11
- package/docs/current/risk-register-release-gate.md +12 -12
- package/docs/current/threat-model.ko.md +8 -4
- package/docs/current/threat-model.md +8 -4
- package/haechi.config.example.json +7 -2
- package/package.json +8 -2
- package/packages/audit/index.mjs +3 -1
- package/packages/cli/bin/haechi.mjs +310 -21
- package/packages/cli/runtime.mjs +28 -3
- package/packages/core/index.mjs +128 -10
- package/packages/crypto/index.mjs +13 -1
- package/packages/filter/index.mjs +52 -3
- package/packages/mcp-stdio/index.mjs +103 -22
- package/packages/policy/index.mjs +6 -0
- package/packages/protocol-adapters/index.mjs +33 -14
- package/packages/proxy/index.mjs +149 -4
- package/packages/stream-filter/index.mjs +194 -0
- package/packages/token-vault/index.mjs +70 -2
|
@@ -12,7 +12,7 @@ npm run sbom
|
|
|
12
12
|
npm run bench:payload
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
`release:preflight`는 테스트, stale-name scan, pack dry-run을 실행한다. npm 계정 인증과 package ownership 확인까지 포함하려면 다음을 사용한다.
|
|
15
|
+
`release:preflight`는 테스트, 타입 체크, stale-name scan, pack dry-run을 실행한다. npm 계정 인증과 package ownership 확인까지 포함하려면 다음을 사용한다.
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm run release:preflight:npm
|
|
@@ -20,13 +20,22 @@ npm run release:preflight:npm
|
|
|
20
20
|
|
|
21
21
|
첫 publish 전에는 `npm view <package> version`이 `E404 Not Found`를 반환하는 것이 정상이다. 이 경우 preflight는 인증된 계정에서 이름을 claim할 준비가 된 상태로 통과한다. 단, `npm view <package>@<version> version`이 성공하면 같은 버전을 다시 배포할 수 없으므로 실패한다.
|
|
22
22
|
|
|
23
|
-
## 2. npm provenance
|
|
23
|
+
## 2. npm provenance와 trusted publishing
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
의도된 publish 경로는 GitHub Actions trusted publishing이다: npm이 release workflow를 OIDC로 인증하고 provenance 증명을 자동 생성한다. 공식 npm 요구사항에 따라 GitHub-hosted runner, `id-token: write`, 연결된 workflow에서의 publish가 필요하다.
|
|
26
|
+
|
|
27
|
+
**현재 상태: trusted publishing 구성 및 검증 완료.** `haechi@0.3.2`는 로컬 머신에서 패스키 인증과 `--provenance=false`로 배포되어 해당 버전의 provenance 증명이 존재하지 않는다. 활성화 runbook과 진행 상태:
|
|
28
|
+
|
|
29
|
+
1. ✅ npmjs.com에서: package settings → Trusted Publisher → `raeseoklee/haechi` 저장소와 `npm-publish.yml` workflow 연결 (2026-06-10).
|
|
30
|
+
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`만 비증명 상태로 남는다.
|
|
32
|
+
|
|
33
|
+
provenance 없이 수행한 publish는 release note에 갭을 명시적으로 기록해야 한다(`CONTRIBUTING.md` 참조).
|
|
26
34
|
|
|
27
35
|
참고:
|
|
28
36
|
|
|
29
37
|
- https://docs.npmjs.com/generating-provenance-statements/
|
|
38
|
+
- https://docs.npmjs.com/trusted-publishers/
|
|
30
39
|
- https://docs.github.com/actions/publishing-packages/publishing-nodejs-packages
|
|
31
40
|
|
|
32
41
|
## 3. GitHub Actions
|
|
@@ -34,7 +43,7 @@ npm provenance는 GitHub Actions release workflow에서 생성한다. 공식 npm
|
|
|
34
43
|
| Workflow | 목적 |
|
|
35
44
|
|---|---|
|
|
36
45
|
| `.github/workflows/ci.yml` | test, release preflight, SBOM artifact |
|
|
37
|
-
| `.github/workflows/npm-publish.yml` | GitHub release published 이벤트에서 npm provenance
|
|
46
|
+
| `.github/workflows/npm-publish.yml` | GitHub release published 이벤트에서 npm publish (trusted publishing 구성 후 provenance 경로) |
|
|
38
47
|
|
|
39
48
|
## 4. 배포 차단 조건
|
|
40
49
|
|
|
@@ -46,3 +55,4 @@ npm provenance는 GitHub Actions release workflow에서 생성한다. 공식 npm
|
|
|
46
55
|
- SBOM 생성 실패
|
|
47
56
|
- npm package name ownership 불확실
|
|
48
57
|
- README/SECURITY가 developer preview와 production 제한을 명시하지 않음
|
|
58
|
+
- trusted publishing/provenance가 미구성인데 release note에 provenance 갭을 명시하지 않음
|
|
@@ -12,7 +12,7 @@ npm run sbom
|
|
|
12
12
|
npm run bench:payload
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
`release:preflight` runs tests, a stale-name scan, and a pack dry-run. To also verify npm account authentication and package ownership, use:
|
|
15
|
+
`release:preflight` runs tests, a type check, a stale-name scan, and a pack dry-run. To also verify npm account authentication and package ownership, use:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm run release:preflight:npm
|
|
@@ -20,13 +20,22 @@ npm run release:preflight:npm
|
|
|
20
20
|
|
|
21
21
|
Before the first publish, it is normal for `npm view <package> version` to return `E404 Not Found`. In that case, preflight passes with the package name ready to be claimed from an authenticated account. However, if `npm view <package>@<version> version` succeeds, the same version cannot be published again and preflight will fail.
|
|
22
22
|
|
|
23
|
-
## 2. npm provenance
|
|
23
|
+
## 2. npm provenance and trusted publishing
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
The intended publish path is GitHub Actions trusted publishing: npm authenticates the release workflow via OIDC and generates a provenance statement automatically. Per the official npm requirements this needs a GitHub-hosted runner, `id-token: write`, and a publish from the linked workflow.
|
|
26
|
+
|
|
27
|
+
**Current state: trusted publishing is configured and verified.** `haechi@0.3.2` was published from a local machine using passkey authentication with `--provenance=false`, so no provenance attestation exists for that version. The enablement runbook and its status:
|
|
28
|
+
|
|
29
|
+
1. ✅ On npmjs.com: package settings → Trusted Publisher → linked the `raeseoklee/haechi` repository and the `npm-publish.yml` workflow (2026-06-10).
|
|
30
|
+
2. ✅ `.github/workflows/npm-publish.yml` authenticates via OIDC (2026-06-10): `NODE_AUTH_TOKEN` and `registry-url` removed, npm CLI upgraded to `>= 11.5.1` in the runner.
|
|
31
|
+
3. ✅ Verified with `haechi@0.4.0` (2026-06-10): `npm view haechi --json` shows `dist.attestations` with a SLSA provenance v1 predicate. Only `haechi@0.3.2` remains unattested (published via local passkey).
|
|
32
|
+
|
|
33
|
+
Any publish performed without provenance must record the gap explicitly in the release notes (see `CONTRIBUTING.md`).
|
|
26
34
|
|
|
27
35
|
References:
|
|
28
36
|
|
|
29
37
|
- https://docs.npmjs.com/generating-provenance-statements/
|
|
38
|
+
- https://docs.npmjs.com/trusted-publishers/
|
|
30
39
|
- https://docs.github.com/actions/publishing-packages/publishing-nodejs-packages
|
|
31
40
|
|
|
32
41
|
## 3. GitHub Actions
|
|
@@ -34,7 +43,7 @@ References:
|
|
|
34
43
|
| Workflow | Purpose |
|
|
35
44
|
|---|---|
|
|
36
45
|
| `.github/workflows/ci.yml` | Tests, release preflight, SBOM artifact |
|
|
37
|
-
| `.github/workflows/npm-publish.yml` | npm
|
|
46
|
+
| `.github/workflows/npm-publish.yml` | npm publish on GitHub release published event (provenance path once trusted publishing is configured) |
|
|
38
47
|
|
|
39
48
|
## 4. Deployment block conditions
|
|
40
49
|
|
|
@@ -46,3 +55,4 @@ npm publish is not performed if any of the following fail.
|
|
|
46
55
|
- SBOM generation fails
|
|
47
56
|
- npm package name ownership is uncertain
|
|
48
57
|
- README/SECURITY does not explicitly state developer preview and production restrictions
|
|
58
|
+
- Trusted publishing/provenance is not configured and the release notes do not explicitly record the provenance gap
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
- 문서 상태: Draft 0.3
|
|
4
4
|
- 작성일: 2026-06-10
|
|
5
|
-
- 기준 버전: 0.
|
|
6
|
-
- 기준 브랜치: `
|
|
5
|
+
- 기준 버전: 0.5.0
|
|
6
|
+
- 기준 브랜치: `main`
|
|
7
7
|
|
|
8
8
|
## 1. 현재 판단
|
|
9
9
|
|
|
10
|
-
0.3.2는 0.3.1 전체 코드 리뷰에서 식별된 추가 보안/운영 리스크를 developer preview 기준으로 해소했다.
|
|
10
|
+
0.3.2는 0.3.1 전체 코드 리뷰에서 식별된 추가 보안/운영 리스크를 developer preview 기준으로 해소했다. 외부 운영자 게이트(npm 계정 인증, package ownership, GitHub tag/release)는 2026-06-10에 통과했다: `haechi@0.3.2`가 로컬 패스키 인증으로 npm에 배포되었고, `v0.3.2` 태그와 GitHub pre-release가 생성되었다. npm provenance는 GitHub Actions trusted publishing 경로로 이월한다.
|
|
11
11
|
|
|
12
12
|
| 구분 | 판단 | 이유 |
|
|
13
13
|
|---|---|---|
|
|
14
14
|
| GitHub public | 허용 | 보안 한계, threat model, shared responsibility, developer preview 문구가 문서화됨 |
|
|
15
15
|
| GitHub release/tag | 허용 | production-ready가 아닌 developer preview로 표현해야 함 |
|
|
16
|
-
| npm developer preview |
|
|
16
|
+
| npm developer preview | 허용 (배포 완료) | 2026-06-10 인증된 계정에서 `haechi@0.3.2` publish 완료, provenance는 trusted publishing으로 이월 |
|
|
17
17
|
| npm stable | 보류 | 1.0 API 안정성, 운영 KMS/HSM/Vault reference adapter, stream-aware enforcement 전까지 stable 표현 금지 |
|
|
18
18
|
| production use | 금지 | 0.3.2는 self-hosted developer preview이며 운영 인증/인가/key custody는 사용자 책임 |
|
|
19
19
|
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
|---|---|---|---|
|
|
24
24
|
| G0 | GitHub source 공개 | 테스트 통과, 보안 한계 문서화, 평문 audit leak 없음 | Pass |
|
|
25
25
|
| G1 | GitHub pre-release | P0 코드 리스크 해결, production-ready 표현 없음 | Pass |
|
|
26
|
-
| G2 | npm developer preview | P0 해결, preflight/SBOM/provenance 경로 준비, npm auth 확인 |
|
|
26
|
+
| G2 | npm developer preview | P0 해결, preflight/SBOM/provenance 경로 준비, npm auth 확인 | Pass (`haechi@0.3.2` 2026-06-10 배포) |
|
|
27
27
|
| G3 | npm stable | P1 운영 reference, stream-aware enforcement, API stability 강화 | Blocked |
|
|
28
28
|
|
|
29
29
|
## 3. P0 배포 차단 리스크 상태
|
|
30
30
|
|
|
31
31
|
| ID | 기존 리스크 | 상태 | 해소 증거 |
|
|
32
32
|
|---|---|---|---|
|
|
33
|
-
| P0-REL-001 | npm 인증/권한 미해결 |
|
|
33
|
+
| P0-REL-001 | npm 인증/권한 미해결 | Resolved | 2026-06-10 로컬 패스키 인증으로 `haechi@0.3.2` publish 성공, npm 인증·package ownership 확정 |
|
|
34
34
|
| P0-REL-002 | proxy 외부 노출 위험 | Resolved | non-loopback bind는 기본 실패, `--allow-remote-bind` 필요 |
|
|
35
35
|
| P0-REL-003 | streaming 요청 처리 불명확 | Resolved | `stream: true` 기본 501 fail-closed, `streaming.requestMode: "pass-through"` 명시 필요 |
|
|
36
36
|
| P0-REL-004 | responseProtection 실패 모드 불명확 | Resolved | 비JSON/invalid JSON/압축/대용량 응답 fail-closed, 명시 allow 정책 분리 |
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
| P1-OPS-002 | SBOM/provenance 부재 | Resolved | `npm run sbom`, `.github/workflows/npm-publish.yml`, `publishConfig.provenance` |
|
|
59
59
|
| P1-OPS-003 | 실제 vLLM/Ollama/llama.cpp 통합 테스트 부재 | Resolved for preview | env-gated optional local inference integration tests 추가. CI는 외부 모델 서버 없이 skip |
|
|
60
60
|
| P1-OPS-004 | 성능/대용량 payload 미측정 | Resolved for preview | request/response byte limit, `npm run bench:payload` |
|
|
61
|
-
| P1-OPS-005 | npm ownership 미확정 |
|
|
61
|
+
| P1-OPS-005 | npm ownership 미확정 | Resolved | `npm view haechi version`이 `0.3.2` 반환, 최초 publish 성공으로 ownership 확정 |
|
|
62
62
|
|
|
63
63
|
## 5.1 추가 보안 검토 리스크 해소 상태
|
|
64
64
|
|
|
@@ -110,9 +110,9 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
110
110
|
현재 외부 npm 게이트 확인 결과:
|
|
111
111
|
|
|
112
112
|
- `npm whoami`: `raeseoklee`
|
|
113
|
-
- `npm view haechi version`: `
|
|
113
|
+
- `npm view haechi version`: `0.3.2`
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
아래 체크리스트는 2026-06-10 0.3.2 배포에서 provenance publish 경로를 제외하고 완료되었다(`v0.3.2` 태그와 GitHub pre-release 완료). provenance는 GitHub Actions trusted publishing으로 이월하며, 체크리스트는 이후 릴리스의 템플릿으로 유지한다.
|
|
116
116
|
|
|
117
117
|
1. `npm run release:preflight`
|
|
118
118
|
2. `npm run sbom`
|
|
@@ -126,8 +126,8 @@ base64/인코딩 값 디코딩 검사, query string 검사, audit tail truncatio
|
|
|
126
126
|
|
|
127
127
|
| 버전 | 목표 | 남은 범위 |
|
|
128
128
|
|---|---|---|
|
|
129
|
-
| 0.4.0 | token round-trip and adoption | 요청 스코프 response detokenization, deterministic tokenization(파생 키), `haechi mcp-wrap
|
|
130
|
-
| 0.5.0 | streaming hardening | SSE/NDJSON
|
|
129
|
+
| 0.4.0 ✅ | token round-trip and adoption | 2026-06-10 구현 완료: 요청 스코프 response detokenization, deterministic tokenization(파생 키), `haechi mcp-wrap`, `haechi audit-verify`/`haechi status`, injection detection type(기본 allow), `identity`/`authProvider` 계약 예약. `docs/current/release-0.4-implementation-scope.md` 참조 |
|
|
130
|
+
| 0.5.0 ✅ | streaming hardening | 2026-06-10 출시: bounded cross-frame 버퍼를 사용한 SSE/NDJSON 스트리밍 응답 검사(`streaming.requestMode: inspect`). stream sequence AAD, replay cache, 강화된 원격 배포 가이드는 0.6+으로 이월. `docs/current/release-0.5-implementation-scope.md` 참조 |
|
|
131
131
|
| 0.6.0 | auth and 운영 통제 | built-in bearer auth, client별 policy scope, model allowlist/rate budget, Vault/AWS KMS reference adapter, external append-only audit sink, signed release artifacts, npm org(`@haechi/*`) 확보 |
|
|
132
132
|
| 0.7.0 | observability | npm workspaces 전환, `@haechi/dashboard` read-only audit viewer (hash chain 무결성 표시, 요약/검색/타임라인) |
|
|
133
133
|
| 1.0.0 | stable API contract | migration policy, long-term audit schema, plugin sandbox/runtime conformance 및 allowlist/manifest 통과 외부 auth/classifier package 동적 로딩 |
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
- Status: Draft 0.3
|
|
4
4
|
- Date: 2026-06-10
|
|
5
|
-
- Target version: 0.
|
|
6
|
-
- Branch: `
|
|
5
|
+
- Target version: 0.5.0
|
|
6
|
+
- Branch: `main`
|
|
7
7
|
|
|
8
8
|
## 1. Current Assessment
|
|
9
9
|
|
|
10
|
-
0.3.2 resolves the additional security and operational risks identified during the full 0.3.1 code review, meeting the bar for developer preview.
|
|
10
|
+
0.3.2 resolves the additional security and operational risks identified during the full 0.3.1 code review, meeting the bar for developer preview. The external operator gates (npm account authentication, package ownership, GitHub tag/release) were passed on 2026-06-10: `haechi@0.3.2` is published to npm via local passkey authentication, tagged `v0.3.2`, and released as a GitHub pre-release. npm provenance remains deferred to the GitHub Actions trusted publishing path.
|
|
11
11
|
|
|
12
12
|
| Category | Judgment | Rationale |
|
|
13
13
|
|---|---|---|
|
|
14
14
|
| GitHub public | Allowed | Security limitations, threat model, shared responsibility, and developer preview language are documented |
|
|
15
15
|
| GitHub release/tag | Allowed | Must be presented as developer preview, not production-ready |
|
|
16
|
-
| npm developer preview |
|
|
16
|
+
| npm developer preview | Allowed (published) | `haechi@0.3.2` published from an authenticated account on 2026-06-10; provenance deferred to trusted publishing |
|
|
17
17
|
| npm stable | On hold | Stable label prohibited until 1.0 API stability, production KMS/HSM/Vault reference adapter, and stream-aware enforcement are in place |
|
|
18
18
|
| Production use | Prohibited | 0.3.2 is a self-hosted developer preview; production auth/authz/key custody is the user's responsibility |
|
|
19
19
|
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
|---|---|---|---|
|
|
24
24
|
| G0 | GitHub source publication | Tests pass, security limitations documented, no plaintext audit leak | Pass |
|
|
25
25
|
| G1 | GitHub pre-release | P0 code risks resolved, no production-ready language | Pass |
|
|
26
|
-
| G2 | npm developer preview | P0 resolved, preflight/SBOM/provenance paths ready, npm auth confirmed |
|
|
26
|
+
| G2 | npm developer preview | P0 resolved, preflight/SBOM/provenance paths ready, npm auth confirmed | Pass (`haechi@0.3.2` published 2026-06-10) |
|
|
27
27
|
| G3 | npm stable | P1 production reference, stream-aware enforcement, API stability hardened | Blocked |
|
|
28
28
|
|
|
29
29
|
## 3. P0 Distribution-Blocking Risk Status
|
|
30
30
|
|
|
31
31
|
| ID | Risk | Status | Resolution evidence |
|
|
32
32
|
|---|---|---|---|
|
|
33
|
-
| P0-REL-001 | npm authentication/authorization unresolved |
|
|
33
|
+
| P0-REL-001 | npm authentication/authorization unresolved | Resolved | `haechi@0.3.2` published via local passkey authentication on 2026-06-10; npm authentication and package ownership confirmed |
|
|
34
34
|
| P0-REL-002 | Proxy exposed to external network | Resolved | Non-loopback bind fails by default; `--allow-remote-bind` must be specified explicitly |
|
|
35
35
|
| P0-REL-003 | Streaming request handling unclear | Resolved | `stream: true` defaults to 501 fail-closed; `streaming.requestMode: "pass-through"` must be set explicitly |
|
|
36
36
|
| P0-REL-004 | `responseProtection` failure mode unclear | Resolved | Non-JSON, invalid JSON, compressed, and oversized responses are fail-closed; explicit allow policies are separated |
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
| P1-OPS-002 | No SBOM/provenance | Resolved | `npm run sbom`, `.github/workflows/npm-publish.yml`, `publishConfig.provenance` |
|
|
59
59
|
| P1-OPS-003 | No real vLLM/Ollama/llama.cpp integration tests | Resolved for preview | Env-gated optional local inference integration tests added. CI skips when no external model server is present |
|
|
60
60
|
| P1-OPS-004 | Performance/large payload not measured | Resolved for preview | Request/response byte limits, `npm run bench:payload` |
|
|
61
|
-
| P1-OPS-005 | npm ownership unconfirmed |
|
|
61
|
+
| P1-OPS-005 | npm ownership unconfirmed | Resolved | `npm view haechi version` returns `0.3.2`; ownership confirmed by the first successful publish |
|
|
62
62
|
|
|
63
63
|
## 5.1 Additional Security Review Risk Resolution Status
|
|
64
64
|
|
|
@@ -107,12 +107,12 @@ Base64/encoded-value decode inspection, query-string inspection, and audit tail
|
|
|
107
107
|
|
|
108
108
|
## 7. npm Developer Preview Pre-Distribution Checklist
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
External npm gate check results (2026-06-10, post-publish):
|
|
111
111
|
|
|
112
112
|
- `npm whoami`: `raeseoklee`
|
|
113
|
-
- `npm view haechi version`: `
|
|
113
|
+
- `npm view haechi version`: `0.3.2`
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
All checklist items below were completed for 0.3.2 on 2026-06-10 except the provenance publish path, which is deferred to GitHub Actions trusted publishing (`v0.3.2` tag and GitHub pre-release were completed). The checklist remains the template for future releases.
|
|
116
116
|
|
|
117
117
|
1. `npm run release:preflight`
|
|
118
118
|
2. `npm run sbom`
|
|
@@ -126,8 +126,8 @@ The `haechi` name appears to be available, but package ownership is confirmed on
|
|
|
126
126
|
|
|
127
127
|
| Version | Goal | Remaining scope |
|
|
128
128
|
|---|---|---|
|
|
129
|
-
| 0.4.0 | Token round-trip and adoption |
|
|
130
|
-
| 0.5.0 | Streaming hardening | SSE/NDJSON
|
|
129
|
+
| 0.4.0 ✅ | Token round-trip and adoption | Shipped 2026-06-10: request-scoped response detokenization, deterministic tokenization (derived key), `haechi mcp-wrap`, `haechi audit-verify`/`haechi status`, injection detection type (default allow), `identity`/`authProvider` contracts reserved. See `docs/current/release-0.4-implementation-scope.md` |
|
|
130
|
+
| 0.5.0 ✅ | Streaming hardening | Shipped 2026-06-10: SSE/NDJSON streaming response inspection with bounded cross-frame buffer (`streaming.requestMode: inspect`). Stream sequence AAD, replay cache, stronger remote deployment guide deferred to 0.6+. See `docs/current/release-0.5-implementation-scope.md` |
|
|
131
131
|
| 0.6.0 | Auth and operational controls | Built-in bearer auth, per-client policy scope, model allowlist/rate budget, Vault/AWS KMS reference adapter, external append-only audit sink, signed release artifacts, npm org (`@haechi/*`) acquisition |
|
|
132
132
|
| 0.7.0 | Observability | npm workspaces migration, `@haechi/dashboard` read-only audit viewer (hash chain integrity display, summary/search/timeline) |
|
|
133
133
|
| 1.0.0 | Stable API contract | Migration policy, long-term audit schema, plugin sandbox/runtime conformance, and dynamic loading of external auth/classifier packages that pass allowlist/manifest |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
- 문서 상태: Draft 0.1
|
|
4
4
|
- 작성일: 2026-06-10
|
|
5
|
-
- 기준 버전: 0.
|
|
5
|
+
- 기준 버전: 0.5.0
|
|
6
6
|
|
|
7
7
|
## 1. 보호 대상
|
|
8
8
|
|
|
@@ -24,7 +24,7 @@ Haechi가 보호하려는 주요 자산은 다음이다.
|
|
|
24
24
|
| CLI local process | 개발자 로컬 신뢰 | dev key 경고, dry-run 기본값 |
|
|
25
25
|
| HTTP proxy listener | 비신뢰 client 입력 | loopback bind 기본, remote bind 명시 플래그 |
|
|
26
26
|
| Upstream model/tool server | 비신뢰 또는 부분 신뢰 | request/response protection, uninspectable response fail-closed |
|
|
27
|
-
| Streaming response |
|
|
27
|
+
| Streaming response | 검사(bounded) 또는 차단 | `inspect` 모드는 bounded cross-frame 버퍼로 SSE/NDJSON을 stream-filter함; `block`(기본값)은 거부 |
|
|
28
28
|
| MCP stdio peer | 부분 신뢰 | JSON-RPC 2.0 요구, method allowlist |
|
|
29
29
|
| Local filesystem | 부분 신뢰 | local key/token vault 0600, audit hash chain |
|
|
30
30
|
| External provider/plugin | 비신뢰 | provider method contract, plugin manifest-only gate |
|
|
@@ -34,7 +34,7 @@ Haechi가 보호하려는 주요 자산은 다음이다.
|
|
|
34
34
|
| 위협 | 영향 | 현재 통제 |
|
|
35
35
|
|---|---|---|
|
|
36
36
|
| 인터넷 노출 proxy | 인증 없는 LLM gateway | non-loopback bind 기본 실패 |
|
|
37
|
-
| streaming 우회 | SSE/NDJSON 평문 유출 |
|
|
37
|
+
| streaming 우회 | SSE/NDJSON 평문 유출 | `inspect` 모드는 SSE/NDJSON을 stream-filter함; `block`(기본값)은 거부; `pass-through`는 명시적으로 감사된 opt-out |
|
|
38
38
|
| Ollama 암묵 streaming 우회 | `stream` 생략 시 NDJSON 평문 유출 | `/api/chat`·`/api/generate`는 `stream: false` 명시 없으면 streaming으로 간주해 기본 차단 |
|
|
39
39
|
| 비JSON/압축/대용량 응답 | responseProtection 우회 | fail-closed response policy |
|
|
40
40
|
| token reveal 남용 | tokenized PII 복원 | revealPolicy 기본 disabled, reveal/purge 결정 audit 기록 |
|
|
@@ -47,6 +47,8 @@ Haechi가 보호하려는 주요 자산은 다음이다.
|
|
|
47
47
|
| 행 걸린 upstream | proxy 연결 고갈 | `limits.upstreamTimeoutMs` 기본 120s, 초과 시 504 fail |
|
|
48
48
|
| signing/encryption 키 혼용 | key separation 위반 | policy bundle 서명 키를 domain-separated 파생 키로 분리 |
|
|
49
49
|
| JSON number/object key 은닉 | 카드번호 등 비문자열 leaf 미탐지 | number leaf와 object key도 detection/transform 대상 |
|
|
50
|
+
| token round-trip의 타 토큰 복원 | 클라이언트/요청 간 평문 복구 | detokenization은 opt-in(`detokenizeResponses`)이며 요청 스코프: 같은 요청을 보호하며 발급된 토큰만 복원 |
|
|
51
|
+
| tool result/응답 내 간접 prompt injection | 심어진 지시문에 의한 agent 조작 | 응답 방향 휴리스틱, 기본 report-only(`injection` action `allow`), 격상은 명시적 정책 선택. 완전 방어 아님 |
|
|
50
52
|
|
|
51
53
|
## 4. 명시적 제외
|
|
52
54
|
|
|
@@ -54,7 +56,9 @@ Haechi가 보호하려는 주요 자산은 다음이다.
|
|
|
54
56
|
|
|
55
57
|
- 운영 KMS/HSM/Vault adapter 자체 제공
|
|
56
58
|
- internet-facing gateway 인증/인가
|
|
57
|
-
-
|
|
59
|
+
- `streaming.maxMatchBytes`보다 긴 cross-frame 매칭(스트림 프레임에 걸쳐 분할될 수 있음)
|
|
60
|
+
- `block`이 발동되기 전에 이미 방출된 스트림 바이트의 회수
|
|
61
|
+
- 스트림에서 choice별(`n > 1`) cross-frame 버퍼링(보조 choice는 프레임 내 보호만 적용)
|
|
58
62
|
- 법적 컴플라이언스 인증
|
|
59
63
|
- 모델 hallucination, prompt injection 완전 방어
|
|
60
64
|
- 외부 MCP server의 OAuth/resource binding 검증
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
- Status: Draft 0.1
|
|
4
4
|
- Date: 2026-06-10
|
|
5
|
-
- Target version: 0.
|
|
5
|
+
- Target version: 0.4.0
|
|
6
6
|
|
|
7
7
|
## 1. Assets Under Protection
|
|
8
8
|
|
|
@@ -24,7 +24,7 @@ The primary assets Haechi protects are:
|
|
|
24
24
|
| CLI local process | Developer local trust | Dev key warning, dry-run default |
|
|
25
25
|
| HTTP proxy listener | Untrusted client input | Loopback bind by default, remote bind requires explicit flag |
|
|
26
26
|
| Upstream model/tool server | Untrusted or partially trusted | Request/response protection, uninspectable response fail-closed |
|
|
27
|
-
| Streaming response |
|
|
27
|
+
| Streaming response | Inspected (bounded) or blocked | `inspect` stream-filters SSE/NDJSON with a bounded cross-frame buffer; `block` (default) refuses |
|
|
28
28
|
| MCP stdio peer | Partially trusted | JSON-RPC 2.0 required, method allowlist |
|
|
29
29
|
| Local filesystem | Partially trusted | Local key/token vault at 0600, audit hash chain |
|
|
30
30
|
| External provider/plugin | Untrusted | Provider method contract, plugin manifest-only gate |
|
|
@@ -34,7 +34,7 @@ The primary assets Haechi protects are:
|
|
|
34
34
|
| Threat | Impact | Current Control |
|
|
35
35
|
|---|---|---|
|
|
36
36
|
| Internet-exposed proxy | Unauthenticated LLM gateway | Non-loopback bind fails by default |
|
|
37
|
-
| Streaming bypass | SSE/NDJSON plaintext leak |
|
|
37
|
+
| Streaming bypass | SSE/NDJSON plaintext leak | `inspect` mode stream-filters SSE/NDJSON; `block` (default) refuses; `pass-through` is an explicit audited opt-out |
|
|
38
38
|
| Ollama implicit streaming bypass | NDJSON plaintext leak when `stream` is omitted | `/api/chat` and `/api/generate` are treated as streaming unless `stream: false` is explicit; blocked by default |
|
|
39
39
|
| Non-JSON / compressed / oversized response | responseProtection bypass | Fail-closed response policy |
|
|
40
40
|
| Token reveal abuse | Restoration of tokenized PII | `revealPolicy` disabled by default; reveal/purge decisions recorded in audit |
|
|
@@ -47,6 +47,8 @@ The primary assets Haechi protects are:
|
|
|
47
47
|
| Hung upstream | Proxy connection exhaustion | `limits.upstreamTimeoutMs` default 120 s; 504 fail on timeout |
|
|
48
48
|
| Signing/encryption key conflation | Key separation violation | Policy bundle signing key isolated as a domain-separated derived key |
|
|
49
49
|
| JSON number / object key concealment | Undetected non-string leaves such as card numbers | Number leaves and object keys included in detection/transform scope |
|
|
50
|
+
| Token round-trip restoring foreign tokens | Cross-client/request plaintext recovery | Detokenization is opt-in (`detokenizeResponses`) and request-scoped: only tokens issued while protecting the same request are restored |
|
|
51
|
+
| Indirect prompt injection in tool results/responses | Agent manipulation via planted instructions | Response-direction heuristics, report-only by default (`injection` action `allow`); escalation is an explicit policy choice. Not a complete defense |
|
|
50
52
|
|
|
51
53
|
## 4. Explicit Exclusions
|
|
52
54
|
|
|
@@ -54,7 +56,9 @@ The primary assets Haechi protects are:
|
|
|
54
56
|
|
|
55
57
|
- A production KMS/HSM/Vault adapter
|
|
56
58
|
- Authentication/authorization for internet-facing gateways
|
|
57
|
-
-
|
|
59
|
+
- Cross-frame matches longer than `streaming.maxMatchBytes` (may still split across stream frames)
|
|
60
|
+
- Retraction of stream bytes already emitted before a `block` fires
|
|
61
|
+
- Per-choice (`n > 1`) cross-frame buffering in streams (secondary choices get within-frame protection only)
|
|
58
62
|
- Legal compliance certification
|
|
59
63
|
- Complete defense against model hallucination or prompt injection
|
|
60
64
|
- OAuth/resource binding validation for external MCP servers
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
"maxBytes": 1048576
|
|
19
19
|
},
|
|
20
20
|
"streaming": {
|
|
21
|
-
"requestMode": "block"
|
|
21
|
+
"requestMode": "block",
|
|
22
|
+
"responseMode": "enforce",
|
|
23
|
+
"maxMatchBytes": 256
|
|
22
24
|
},
|
|
23
25
|
"limits": {
|
|
24
26
|
"maxRequestBytes": 1048576,
|
|
@@ -51,7 +53,10 @@
|
|
|
51
53
|
"provider": "local",
|
|
52
54
|
"path": ".haechi/token-vault.json",
|
|
53
55
|
"revealPolicy": "disabled",
|
|
54
|
-
"retentionDays": 30
|
|
56
|
+
"retentionDays": 30,
|
|
57
|
+
"deterministic": false,
|
|
58
|
+
"deterministicTypes": null,
|
|
59
|
+
"detokenizeResponses": false
|
|
55
60
|
},
|
|
56
61
|
"privacy": {
|
|
57
62
|
"profile": null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "haechi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Experimental developer preview for self-hosted AI context enforcement across LLM, MCP, vLLM, Ollama, and agent traffic.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"./protocol-adapters": "./packages/protocol-adapters/index.mjs",
|
|
45
45
|
"./proxy": "./packages/proxy/index.mjs",
|
|
46
46
|
"./runtime": "./packages/cli/runtime.mjs",
|
|
47
|
-
"./token-vault": "./packages/token-vault/index.mjs"
|
|
47
|
+
"./token-vault": "./packages/token-vault/index.mjs",
|
|
48
|
+
"./stream-filter": "./packages/stream-filter/index.mjs"
|
|
48
49
|
},
|
|
49
50
|
"files": [
|
|
50
51
|
"README.md",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
],
|
|
58
59
|
"scripts": {
|
|
59
60
|
"test": "node --test",
|
|
61
|
+
"check:types": "tsc -p jsconfig.json --noEmit",
|
|
60
62
|
"pack:dry": "npm pack --dry-run",
|
|
61
63
|
"scan:stale-names": "node scripts/stale-name-scan.mjs",
|
|
62
64
|
"sbom": "node scripts/generate-sbom.mjs",
|
|
@@ -70,5 +72,9 @@
|
|
|
70
72
|
},
|
|
71
73
|
"engines": {
|
|
72
74
|
"node": ">=22"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/node": "^22.19.20",
|
|
78
|
+
"typescript": "^5.7.3"
|
|
73
79
|
}
|
|
74
80
|
}
|
package/packages/audit/index.mjs
CHANGED
|
@@ -127,7 +127,9 @@ export async function verifyAuditChain(path) {
|
|
|
127
127
|
records += 1;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
// headHash anchors the chain externally: publishing it out-of-band is the
|
|
131
|
+
// only defense against tail truncation, which the chain alone cannot detect.
|
|
132
|
+
return { valid: true, records, headHash: expectedPreviousHash };
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
async function buildIntegrityRecord(path, event) {
|