haechi 1.1.0 → 1.1.1
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 +8 -4
- package/README.md +8 -4
- package/docs/current/configuration.ko.md +3 -3
- package/docs/current/configuration.md +3 -3
- package/docs/current/open-source-modular-architecture.ko.md +1 -1
- package/docs/current/open-source-modular-architecture.md +1 -1
- package/haechi.config.example.json +1 -1
- package/package.json +1 -1
- package/packages/cli/bin/haechi.mjs +1 -1
- package/packages/cli/runtime.mjs +1 -1
- package/packages/proxy/index.mjs +1 -1
package/README.ko.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Haechi
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/raeseoklee/haechi/main/docs/assets/haechi.jpg" alt="해치 — 게이트를 지키며 디지털 방패로 검문하는 수호 영물" width="820">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
3
7
|
[](https://www.npmjs.com/package/haechi)
|
|
4
8
|
[](https://github.com/raeseoklee/haechi/actions/workflows/ci.yml)
|
|
5
9
|
[](LICENSE)
|
|
@@ -60,7 +64,7 @@ npm run demo:report
|
|
|
60
64
|
node packages/cli/bin/haechi.mjs proxy --config haechi.config.json
|
|
61
65
|
```
|
|
62
66
|
|
|
63
|
-
기존 HTTP JSON 클라이언트를 `http://localhost:
|
|
67
|
+
기존 HTTP JSON 클라이언트를 `http://localhost:11016`으로 지정하고, `haechi.config.json`에서 `target.upstream`을 설정한다. 다른 로컬 포트를 사용하려면 설정에서 `proxy.port`를 변경하거나 `--port`를 전달한다.
|
|
64
68
|
|
|
65
69
|
proxy는 기본적으로 loopback에 바인드된다. `0.0.0.0`, `::`, 또는 다른 non-loopback 호스트에 바인딩하려면 `--allow-remote-bind`를 명시적으로 제공해야 한다. 이 플래그는 명시적인 네트워크 접근 통제 하에서만 사용한다.
|
|
66
70
|
|
|
@@ -92,7 +96,7 @@ Haechi는 OpenAI 호환 서버, vLLM, Ollama, llama.cpp를 위한 프로토콜 a
|
|
|
92
96
|
}
|
|
93
97
|
```
|
|
94
98
|
|
|
95
|
-
그런 다음 OpenAI 호환 클라이언트를 `http://127.0.0.1:
|
|
99
|
+
그런 다음 OpenAI 호환 클라이언트를 `http://127.0.0.1:11016/v1`으로 지정한다. Ollama 네이티브 API의 경우 `target.adapter: "ollama"`를 사용하고 proxy를 통해 `/api/chat` 또는 `/api/generate`를 호출한다.
|
|
96
100
|
|
|
97
101
|
## 토큰 왕복
|
|
98
102
|
|
|
@@ -187,7 +191,7 @@ JWT/JWKS 인증과 KMS 기반 key custody는 `haechi-*` 위성 패키지로 제
|
|
|
187
191
|
| `mode` / `policy.mode` | `dry-run` | `dry-run`과 `report-only`는 탐지 및 audit만 수행하고, `enforce`는 변환/차단을 적용한다. `policy.mode`가 `mode`보다 우선한다 |
|
|
188
192
|
| `target.type` / `target.adapter` | `llm-http` / `openai-compatible` | upstream 프로토콜: `openai-compatible`, `vllm-openai`, `ollama`, `llama-cpp`. 알 수 없는 type은 fail-closed로 처리된다 |
|
|
189
193
|
| `target.upstream` | `http://127.0.0.1:9999` | proxy가 요청을 전달하는 유일한 upstream (절대 URL 요청 대상은 거부된다) |
|
|
190
|
-
| `proxy.host` / `proxy.port` | `127.0.0.1` / `
|
|
194
|
+
| `proxy.host` / `proxy.port` | `127.0.0.1` / `11016` | proxy 바인드 주소. 아래의 remote 바인딩 참고 |
|
|
191
195
|
| `responseProtection.enabled` | `false` | upstream JSON 응답을 검사한다. `failureMode: fail-closed`는 비JSON/압축/대용량 응답을 거부한다 |
|
|
192
196
|
| `responseProtection.maxBytes` | `1048576` | 응답 크기의 상한 — `failureMode: allow` 상태에서도 적용된다 |
|
|
193
197
|
| `streaming.requestMode` | `block` | `block`은 스트리밍을 501 차단; `inspect`는 SSE/NDJSON 응답을 stream-filter; `pass-through`는 검사 없이 전달(audit 기록). Ollama chat/generate는 `stream: false`가 없으면 스트리밍으로 간주된다 |
|
|
@@ -228,7 +232,7 @@ haechi proxy --config haechi.config.json --host 0.0.0.0 --allow-remote-bind
|
|
|
228
232
|
|
|
229
233
|
**proxy는 아직 클라이언트 인증을 제공하지 않는다** (0.6 계획): 포트에 접근할 수 있는 누구든 upstream과 token round-trip 경로를 사용할 수 있다. `--allow-remote-bind`는 명시적인 네트워크 통제 하에서만 사용한다:
|
|
230
234
|
|
|
231
|
-
- **컨테이너**: 컨테이너 내에서 `0.0.0.0`으로 바인딩하는 것은 일반적인 패턴이다 — 포트 매핑에서 노출을 제한한다(예: `-p 127.0.0.1:
|
|
235
|
+
- **컨테이너**: 컨테이너 내에서 `0.0.0.0`으로 바인딩하는 것은 일반적인 패턴이다 — 포트 매핑에서 노출을 제한한다(예: `-p 127.0.0.1:11016:11016`)
|
|
232
236
|
- **LAN/원격**: 방화벽, VPN(예: Tailscale), 또는 인증 reverse proxy를 앞에 둔다
|
|
233
237
|
|
|
234
238
|
## Privacy Profiles
|
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Haechi
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/raeseoklee/haechi/main/docs/assets/haechi.jpg" alt="Haechi — a guardian haechi warding a gateway with a digital shield" width="820">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
3
7
|
[](https://www.npmjs.com/package/haechi)
|
|
4
8
|
[](https://github.com/raeseoklee/haechi/actions/workflows/ci.yml)
|
|
5
9
|
[](LICENSE)
|
|
@@ -60,7 +64,7 @@ The default config runs in `dry-run` mode. It detects sensitive values and write
|
|
|
60
64
|
node packages/cli/bin/haechi.mjs proxy --config haechi.config.json
|
|
61
65
|
```
|
|
62
66
|
|
|
63
|
-
Point an existing HTTP JSON client at `http://localhost:
|
|
67
|
+
Point an existing HTTP JSON client at `http://localhost:11016` and set `target.upstream` in `haechi.config.json`. Change `proxy.port` in the config or pass `--port` to use a different local port.
|
|
64
68
|
|
|
65
69
|
The proxy binds to loopback by default. Binding to `0.0.0.0`, `::`, or another non-loopback host fails unless `--allow-remote-bind` is provided. Use that flag only behind explicit network access controls.
|
|
66
70
|
|
|
@@ -92,7 +96,7 @@ Haechi includes protocol adapter presets for OpenAI-compatible servers, vLLM, Ol
|
|
|
92
96
|
}
|
|
93
97
|
```
|
|
94
98
|
|
|
95
|
-
Then point an OpenAI-compatible client at `http://127.0.0.1:
|
|
99
|
+
Then point an OpenAI-compatible client at `http://127.0.0.1:11016/v1`. For Ollama native APIs, use `target.adapter: "ollama"` and call `/api/chat` or `/api/generate` through the proxy.
|
|
96
100
|
|
|
97
101
|
## Token Round-Trip
|
|
98
102
|
|
|
@@ -187,7 +191,7 @@ The satellites are `node:`-only by default (heavy SDKs are optional peers) and k
|
|
|
187
191
|
| `mode` / `policy.mode` | `dry-run` | `dry-run` and `report-only` detect + audit only; `enforce` transforms/blocks. `policy.mode` wins over `mode` |
|
|
188
192
|
| `target.type` / `target.adapter` | `llm-http` / `openai-compatible` | Upstream protocol: `openai-compatible`, `vllm-openai`, `ollama`, `llama-cpp`. Unknown types fail closed |
|
|
189
193
|
| `target.upstream` | `http://127.0.0.1:9999` | The only upstream the proxy will forward to (absolute-URL request targets are rejected) |
|
|
190
|
-
| `proxy.host` / `proxy.port` | `127.0.0.1` / `
|
|
194
|
+
| `proxy.host` / `proxy.port` | `127.0.0.1` / `11016` | Proxy bind address. See remote binding below |
|
|
191
195
|
| `responseProtection.enabled` | `false` | Inspect upstream JSON responses. `failureMode: fail-closed` rejects non-JSON/compressed/oversized responses |
|
|
192
196
|
| `responseProtection.maxBytes` | `1048576` | Hard response size cap — enforced even in `failureMode: allow` |
|
|
193
197
|
| `streaming.requestMode` | `block` | `block` 501s streaming; `inspect` stream-filters SSE/NDJSON responses; `pass-through` forwards uninspected (audited). Ollama chat/generate count as streaming unless `stream: false` |
|
|
@@ -228,7 +232,7 @@ haechi proxy --config haechi.config.json --host 0.0.0.0 --allow-remote-bind
|
|
|
228
232
|
|
|
229
233
|
**The proxy has no client authentication yet** (planned for 0.6): anyone who can reach the port can use your upstream and the token round-trip path. Use `--allow-remote-bind` only behind explicit network controls:
|
|
230
234
|
|
|
231
|
-
- **Containers**: binding `0.0.0.0` inside a container is the normal pattern — restrict exposure at the port mapping, e.g. `-p 127.0.0.1:
|
|
235
|
+
- **Containers**: binding `0.0.0.0` inside a container is the normal pattern — restrict exposure at the port mapping, e.g. `-p 127.0.0.1:11016:11016`
|
|
232
236
|
- **LAN/remote**: put a firewall, VPN (e.g. Tailscale), or an authenticating reverse proxy in front
|
|
233
237
|
|
|
234
238
|
## Privacy Profiles
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{
|
|
12
12
|
"mode": "dry-run",
|
|
13
13
|
"target": { "type": "llm-http", "adapter": "openai-compatible", "upstream": "http://127.0.0.1:9999" },
|
|
14
|
-
"proxy": { "host": "127.0.0.1", "port":
|
|
14
|
+
"proxy": { "host": "127.0.0.1", "port": 11016 },
|
|
15
15
|
"responseProtection": { "enabled": false, "mode": "enforce", "failureMode": "fail-closed", "allowNonJson": false, "allowCompressed": false, "maxBytes": 1048576 },
|
|
16
16
|
"streaming": { "requestMode": "block" },
|
|
17
17
|
"limits": { "maxRequestBytes": 1048576, "upstreamTimeoutMs": 120000 },
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
| 키 | 타입 / 값 | 기본값 | 설명 |
|
|
45
45
|
|---|---|---|---|
|
|
46
46
|
| `proxy.host` | 비어 있지 않은 문자열 | `127.0.0.1` | 바인드 주소. loopback이 아닌 host를 사용하려면 `--allow-remote-bind` CLI 플래그가 필요하다 — 설정 파일만으로는 시작되지 않는다([loopback 밖으로 바인딩](#binding-beyond-loopback) 참고). |
|
|
47
|
-
| `proxy.port` | 정수 0–65535 | `
|
|
47
|
+
| `proxy.port` | 정수 0–65535 | `11016` | 리슨 포트(`0` = 임시 포트). `--port`로 실행 시마다 덮어쓸 수 있다. |
|
|
48
48
|
|
|
49
49
|
## `responseProtection`
|
|
50
50
|
|
|
@@ -246,7 +246,7 @@ proxy는 CLI 플래그를 명시적으로 전달하지 않으면 loopback이 아
|
|
|
246
246
|
haechi proxy --config haechi.config.json --host 0.0.0.0 --allow-remote-bind
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
-
**proxy는 아직 클라이언트 인증을 제공하지 않는다**(0.6 계획): 포트에 접근할 수 있는 누구든 upstream과 token round-trip 경로를 사용할 수 있다. `--allow-remote-bind`는 명시적인 네트워크 통제 하에서만 사용해야 한다 — 컨테이너 내에서 `0.0.0.0`으로 바인드하고 host 포트 매핑을 제한하거나(`-p 127.0.0.1:
|
|
249
|
+
**proxy는 아직 클라이언트 인증을 제공하지 않는다**(0.6 계획): 포트에 접근할 수 있는 누구든 upstream과 token round-trip 경로를 사용할 수 있다. `--allow-remote-bind`는 명시적인 네트워크 통제 하에서만 사용해야 한다 — 컨테이너 내에서 `0.0.0.0`으로 바인드하고 host 포트 매핑을 제한하거나(`-p 127.0.0.1:11016:11016`), 방화벽/VPN/인증 reverse proxy 뒤에 두어야 한다.
|
|
250
250
|
|
|
251
251
|
## 검증 요약
|
|
252
252
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{
|
|
12
12
|
"mode": "dry-run",
|
|
13
13
|
"target": { "type": "llm-http", "adapter": "openai-compatible", "upstream": "http://127.0.0.1:9999" },
|
|
14
|
-
"proxy": { "host": "127.0.0.1", "port":
|
|
14
|
+
"proxy": { "host": "127.0.0.1", "port": 11016 },
|
|
15
15
|
"responseProtection": { "enabled": false, "mode": "enforce", "failureMode": "fail-closed", "allowNonJson": false, "allowCompressed": false, "maxBytes": 1048576 },
|
|
16
16
|
"streaming": { "requestMode": "block" },
|
|
17
17
|
"limits": { "maxRequestBytes": 1048576, "upstreamTimeoutMs": 120000 },
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
| Key | Type / values | Default | Notes |
|
|
45
45
|
|---|---|---|---|
|
|
46
46
|
| `proxy.host` | non-empty string | `127.0.0.1` | Bind address. Non-loopback hosts require the `--allow-remote-bind` CLI flag — config alone will not start (see [Binding beyond loopback](#binding-beyond-loopback)). |
|
|
47
|
-
| `proxy.port` | integer 0–65535 | `
|
|
47
|
+
| `proxy.port` | integer 0–65535 | `11016` | Listen port (`0` = ephemeral). Override per-run with `--port`. |
|
|
48
48
|
|
|
49
49
|
## `responseProtection`
|
|
50
50
|
|
|
@@ -246,7 +246,7 @@ The proxy refuses non-loopback hosts unless the CLI flag is passed explicitly
|
|
|
246
246
|
haechi proxy --config haechi.config.json --host 0.0.0.0 --allow-remote-bind
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
-
**The proxy has no client authentication yet** (planned for 0.6): anyone who can reach the port can use your upstream and the token round-trip path. Use `--allow-remote-bind` only behind explicit network controls — bind `0.0.0.0` inside a container and restrict the host port mapping (`-p 127.0.0.1:
|
|
249
|
+
**The proxy has no client authentication yet** (planned for 0.6): anyone who can reach the port can use your upstream and the token round-trip path. Use `--allow-remote-bind` only behind explicit network controls — bind `0.0.0.0` inside a container and restrict the host port mapping (`-p 127.0.0.1:11016:11016`), or front it with a firewall/VPN/authenticating reverse proxy.
|
|
250
250
|
|
|
251
251
|
## Validation cheatsheet
|
|
252
252
|
|
|
@@ -83,7 +83,7 @@ docs/
|
|
|
83
83
|
|
|
84
84
|
| Mode | 변경 범위 | 적합한 상황 | 예시 |
|
|
85
85
|
|---|---|---|---|
|
|
86
|
-
| Local proxy | 코드 변경 거의 없음 | LLM HTTP, MCP Streamable HTTP를 빠르게 보호 | base URL을 `http://localhost:
|
|
86
|
+
| Local proxy | 코드 변경 거의 없음 | LLM HTTP, MCP Streamable HTTP를 빠르게 보호 | base URL을 `http://localhost:11016`로 변경 |
|
|
87
87
|
| SDK wrapper | 작은 코드 변경 | 앱 내부 context를 더 정확히 전달 | `haechi.protectMessage(...)` |
|
|
88
88
|
| Middleware | 웹/API 서버에 삽입 | Express/Fastify/FastAPI 같은 gateway | request/response hook |
|
|
89
89
|
| Sidecar | self-hosted service 옆 배치 | 컨테이너/서버 운영 환경 | app -> sidecar -> provider |
|
|
@@ -83,7 +83,7 @@ For the initial public release, `core`, `crypto`, `policy`, `filter`, `audit`, `
|
|
|
83
83
|
|
|
84
84
|
| Mode | Scope of change | When to use | Example |
|
|
85
85
|
|---|---|---|---|
|
|
86
|
-
| Local proxy | Almost no code changes | Quickly protect LLM HTTP or MCP Streamable HTTP | Change base URL to `http://localhost:
|
|
86
|
+
| Local proxy | Almost no code changes | Quickly protect LLM HTTP or MCP Streamable HTTP | Change base URL to `http://localhost:11016` |
|
|
87
87
|
| SDK wrapper | Small code changes | Pass more precise in-app context | `haechi.protectMessage(...)` |
|
|
88
88
|
| Middleware | Insert into web/API server | Gateways like Express/Fastify/FastAPI | request/response hook |
|
|
89
89
|
| Sidecar | Deploy alongside self-hosted service | Container/server runtime environments | app -> sidecar -> provider |
|
package/package.json
CHANGED
|
@@ -92,7 +92,7 @@ async function initCommand(argv) {
|
|
|
92
92
|
mode: result.config.mode,
|
|
93
93
|
warnings: [
|
|
94
94
|
"The generated .haechi/dev.keys.json file is for local development only.",
|
|
95
|
-
"
|
|
95
|
+
"Core ships no production KMS/HSM/Vault key provider; KMS/Vault-backed custody is available via the haechi-crypto-kms satellite (external cryptoProvider)."
|
|
96
96
|
]
|
|
97
97
|
});
|
|
98
98
|
}
|
package/packages/cli/runtime.mjs
CHANGED
|
@@ -306,7 +306,7 @@ export function normalizeConfig(config) {
|
|
|
306
306
|
throw new Error("audit.anchor.everyRecords must be a positive integer");
|
|
307
307
|
}
|
|
308
308
|
if (merged.tokenVault.provider !== "local") {
|
|
309
|
-
throw new Error("
|
|
309
|
+
throw new Error("Only the local token vault provider is supported");
|
|
310
310
|
}
|
|
311
311
|
if (!["disabled", "local-dev"].includes(merged.tokenVault.revealPolicy)) {
|
|
312
312
|
throw new Error(`Invalid tokenVault.revealPolicy: ${merged.tokenVault.revealPolicy}`);
|
package/packages/proxy/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { createServer } from "node:http";
|
|
|
2
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import { inspectResponseStream } from "../stream-filter/index.mjs";
|
|
4
4
|
|
|
5
|
-
export const DEFAULT_PROXY_PORT =
|
|
5
|
+
export const DEFAULT_PROXY_PORT = 11016;
|
|
6
6
|
|
|
7
7
|
export function createHaechiProxy({ runtime, port = DEFAULT_PROXY_PORT, host = "127.0.0.1", allowRemoteBind = false }) {
|
|
8
8
|
assertSafeProxyBind({ host, allowRemoteBind });
|