ltcai 0.1.9 → 0.1.11
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.md +141 -313
- package/docs/CHANGELOG.md +227 -0
- package/docs/architecture.md +121 -0
- package/docs/mcp-tools.md +116 -0
- package/docs/privacy.md +74 -0
- package/docs/public-deploy.md +137 -0
- package/docs/security-model.md +121 -0
- package/ltcai_cli.py +2 -2
- package/package.json +1 -1
- package/server.py +997 -261
- package/skills/SKILL_TEMPLATE.md +61 -29
- package/skills/code_review/SKILL.md +28 -0
- package/skills/code_review/examples.md +59 -0
- package/skills/code_review/risk.json +9 -0
- package/skills/code_review/schema.json +65 -0
- package/skills/data_analysis/SKILL.md +28 -0
- package/skills/data_analysis/examples.md +62 -0
- package/skills/data_analysis/risk.json +9 -0
- package/skills/data_analysis/schema.json +61 -0
- package/skills/file_edit/SKILL.md +33 -0
- package/skills/file_edit/examples.md +45 -0
- package/skills/file_edit/risk.json +9 -0
- package/skills/file_edit/schema.json +60 -0
- package/skills/summarize_document/SKILL.md +68 -0
- package/skills/summarize_document/examples.md +65 -0
- package/skills/summarize_document/risk.json +9 -0
- package/skills/summarize_document/schema.json +71 -0
- package/skills/web_search/SKILL.md +28 -0
- package/skills/web_search/examples.md +61 -0
- package/skills/web_search/risk.json +9 -0
- package/skills/web_search/schema.json +62 -0
- package/tests/integration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tests/integration/__pycache__/test_api.cpython-314-pytest-9.0.3.pyc +0 -0
- package/tests/unit/__pycache__/test_tools.cpython-314-pytest-9.0.3.pyc +0 -0
- package/tests/unit/test_tools.py +194 -1
- package/tools.py +264 -4
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Lattice AI — 보안 모델
|
|
2
|
+
|
|
3
|
+
## 설계 원칙
|
|
4
|
+
|
|
5
|
+
Lattice AI는 **개인 AI 워크스페이스**로 설계되었습니다. 기본값은 최대한 안전하게, 네트워크 노출은 명시적 opt-in으로만 허용합니다.
|
|
6
|
+
|
|
7
|
+
## 네트워크 바인딩
|
|
8
|
+
|
|
9
|
+
| 설정 | 바인딩 | 용도 |
|
|
10
|
+
|------|--------|------|
|
|
11
|
+
| 기본 | `127.0.0.1:4825` | 로컬 전용, 외부 접근 불가 |
|
|
12
|
+
| `LATTICEAI_HOST=0.0.0.0` | `0.0.0.0:4825` | 같은 Wi-Fi 기기 접근 허용 |
|
|
13
|
+
| 퍼블릭 배포 | nginx/Caddy 뒤에 두기 | HTTPS 종단 + 리버스 프록시 |
|
|
14
|
+
|
|
15
|
+
## 인증
|
|
16
|
+
|
|
17
|
+
### 비밀번호
|
|
18
|
+
|
|
19
|
+
- scrypt 해싱 (`hashlib.scrypt`, N=2^14, r=8, p=1)
|
|
20
|
+
- `users.json`에 `{"hash": "<scrypt hex>"}` 형식 저장
|
|
21
|
+
- 평문 비밀번호는 메모리에도 저장되지 않음
|
|
22
|
+
|
|
23
|
+
### 세션
|
|
24
|
+
|
|
25
|
+
- UUID 토큰, `~/.ltcai/sessions.json` 파일 저장
|
|
26
|
+
- TTL: 24시간 + sliding refresh (활동 시 자동 연장, 15분 단위 디스크 쓰기)
|
|
27
|
+
- 쿠키: `HttpOnly; SameSite=Lax; Path=/`
|
|
28
|
+
- 서버 재시작 후에도 유지 (파일 기반)
|
|
29
|
+
|
|
30
|
+
### SSO (선택적)
|
|
31
|
+
|
|
32
|
+
- Entra ID / Okta OIDC (`OIDC_DISCOVERY_URL`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`)
|
|
33
|
+
- 콜백 후 내부 세션 토큰으로 변환
|
|
34
|
+
- 어드민 핸드오프: `sessionStorage` 1회 읽기 (URL 파라미터 노출 방지)
|
|
35
|
+
|
|
36
|
+
## API 키 보안
|
|
37
|
+
|
|
38
|
+
- OS keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service) 저장
|
|
39
|
+
- 평문 디스크 저장은 `LATTICEAI_ALLOW_PLAINTEXT_API_KEYS=true` 명시 시에만
|
|
40
|
+
- 채팅 히스토리 저장 전 API key/token/password 패턴 자동 마스킹
|
|
41
|
+
|
|
42
|
+
## CORS
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
CORS_ALLOWED_ORIGINS = ["http://localhost:4825", "http://127.0.0.1:4825"]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- 기본: localhost만 허용
|
|
49
|
+
- `LATTICEAI_CORS_ALLOW_NETWORK=true`: 같은 Wi-Fi 기기 허용
|
|
50
|
+
- 퍼블릭 배포: 리버스 프록시 도메인만 허용 권장
|
|
51
|
+
|
|
52
|
+
## Rate Limiting
|
|
53
|
+
|
|
54
|
+
토큰 버킷 알고리즘, per-user:
|
|
55
|
+
|
|
56
|
+
| 엔드포인트 | burst | 지속 |
|
|
57
|
+
|-----------|-------|------|
|
|
58
|
+
| `/chat` | 30 | 30/분 |
|
|
59
|
+
| `/agent` | 10 | 6/분 |
|
|
60
|
+
| `/upload` | 20 | 12/분 |
|
|
61
|
+
|
|
62
|
+
`LATTICEAI_RATE_LIMIT=0`으로 비활성화 (개발 환경용).
|
|
63
|
+
|
|
64
|
+
## 파일 업로드
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
MAGIC_NUMBERS = {
|
|
68
|
+
".pdf": b"%PDF",
|
|
69
|
+
".docx": b"PK\x03\x04",
|
|
70
|
+
".xlsx": b"PK\x03\x04",
|
|
71
|
+
".pptx": b"PK\x03\x04",
|
|
72
|
+
".png": b"\x89PNG",
|
|
73
|
+
".jpg": b"\xff\xd8\xff",
|
|
74
|
+
".zip": b"PK\x03\x04",
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- 업로드 시 파일 첫 바이트와 확장자 매핑 검증
|
|
79
|
+
- 불일치 시 400 에러
|
|
80
|
+
|
|
81
|
+
## 에이전트 도구 샌드박스
|
|
82
|
+
|
|
83
|
+
### `run_command()` 위험 플래그 차단
|
|
84
|
+
|
|
85
|
+
다음 패턴이 포함된 명령 실행 거부:
|
|
86
|
+
- `rm -rf`, `sudo`, `chmod 777`, `curl | bash`, `wget | sh`
|
|
87
|
+
- `> /dev/sda`, `dd if=`, `mkfs`
|
|
88
|
+
|
|
89
|
+
### `edit_file()` 유일성 검증
|
|
90
|
+
|
|
91
|
+
- `old_string`이 파일에 정확히 한 번만 존재해야 성공
|
|
92
|
+
- `replace_all=true`로 전체 치환 허용
|
|
93
|
+
- 워크스페이스 외부 경로 접근 차단 (`../../../etc/passwd` 등)
|
|
94
|
+
|
|
95
|
+
### `grep()` 이진 디렉토리 제외
|
|
96
|
+
|
|
97
|
+
`node_modules`, `.git`, `venv`, `dist`, `__pycache__` 자동 제외
|
|
98
|
+
|
|
99
|
+
## 감사 로그
|
|
100
|
+
|
|
101
|
+
- 어드민 세션 핸드오프 이벤트 로깅
|
|
102
|
+
- 평문 비밀번호 마이그레이션 이벤트: `password_migrated_from_plaintext`
|
|
103
|
+
- `server.log` 파일에 모든 요청 기록
|
|
104
|
+
|
|
105
|
+
## 텔레메트리
|
|
106
|
+
|
|
107
|
+
**없음.** 모든 데이터는 로컬에만 저장됩니다. 외부 서버로 어떠한 사용 데이터도 전송되지 않습니다.
|
|
108
|
+
|
|
109
|
+
예외: 사용자가 직접 설정한 클라우드 API(OpenAI, Groq 등)로의 프롬프트 전송은 해당 제공업체의 정책을 따릅니다.
|
|
110
|
+
|
|
111
|
+
## 퍼블릭 배포 체크리스트
|
|
112
|
+
|
|
113
|
+
- [ ] `LATTICEAI_MODE=public`
|
|
114
|
+
- [ ] `LATTICEAI_INVITE_CODE` 비공개 값 설정
|
|
115
|
+
- [ ] HTTPS 리버스 프록시 (nginx/Caddy)
|
|
116
|
+
- [ ] `LATTICEAI_ENABLE_GRAPH=false` (필요 시)
|
|
117
|
+
- [ ] `/data` 영구 볼륨 마운트
|
|
118
|
+
- [ ] `LATTICEAI_ALLOW_LOCAL_MODELS=false`
|
|
119
|
+
- [ ] 방화벽에서 4825 포트 직접 노출 차단 (리버스 프록시 통해서만)
|
|
120
|
+
|
|
121
|
+
자세한 내용: [public-deploy.md](public-deploy.md)
|
package/ltcai_cli.py
CHANGED
|
@@ -89,8 +89,8 @@ def main() -> None:
|
|
|
89
89
|
parser = argparse.ArgumentParser(prog="LTCAI", description="Run the Lattice AI local server.")
|
|
90
90
|
subparsers = parser.add_subparsers(dest="command")
|
|
91
91
|
subparsers.add_parser("doctor", help="Check local runtime dependencies and configuration.")
|
|
92
|
-
# Default to 0.0.0.0
|
|
93
|
-
parser.add_argument("--host", default=os.getenv("LATTICEAI_HOST") or "
|
|
92
|
+
# Default to 127.0.0.1; set LATTICEAI_HOST=0.0.0.0 to expose to the local network
|
|
93
|
+
parser.add_argument("--host", default=os.getenv("LATTICEAI_HOST") or "127.0.0.1")
|
|
94
94
|
parser.add_argument("--port", type=int, default=int(os.getenv("LATTICEAI_PORT") or "4825"))
|
|
95
95
|
parser.add_argument("--reload", action="store_true", help="Enable uvicorn reload for local development.")
|
|
96
96
|
args = parser.parse_args()
|