deel-local-cli 1.19.4 → 1.20.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 CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  [![Node.js CI](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/test.yml?branch=main&logo=github&logoColor=white&label=Node.js%20CI)](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
22
22
  [![CodeQL](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/codeql.yml?branch=main&logo=github&logoColor=white&label=CodeQL)](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
23
- [![tests](https://img.shields.io/badge/tests-9%2C187%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/ko/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-9%2C212%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/ko/develop.md)
24
24
 
25
25
  [![dependencies](https://img.shields.io/badge/dependencies-0-1a7f37)](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
26
26
  [![ESM](https://img.shields.io/badge/ESM-Node%2020%2B-5FA04E?logo=javascript&logoColor=white)](package.json)
@@ -301,7 +301,7 @@ deel --offline
301
301
  무엇이 어디로 갈 수 있는지는 켤 때 화면 맨 위에 늘 적혀 있습니다.
302
302
 
303
303
  ```
304
- deel 1.19.4 ⌂ 이 안
304
+ deel 1.20.0 ⌂ 이 안
305
305
  보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다
306
306
  ```
307
307
 
@@ -1289,6 +1289,8 @@ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교
1289
1289
 
1290
1290
  | 판 | 무엇이 바뀌었나 |
1291
1291
  |---|---|
1292
+ | [1.20.0](docs/ko/releases/1.20.md#1200) | 대문자로 안 적은 열쇠는 그대로 나가고 있었습니다 |
1293
+ | [1.19.5](docs/ko/releases/1.19.md#1195) | 윈도우 줄바꿈에서는 앞 판의 고침이 통째로 헛돌고 있었습니다 |
1292
1294
  | [1.19.4](docs/ko/releases/1.19.md#1194) | 주석을 달아 둔 자리에서 비밀이 또 샜습니다 |
1293
1295
  | [1.19.3](docs/ko/releases/1.19.md#1193) | YAML 에 적은 비밀이 평문으로 나가고 있었습니다 |
1294
1296
  | [1.19.2](docs/ko/releases/1.19.md#1192) | 울타리를 옮긴 자리에 틈이 생겼습니다 — 1.19.1 이 낸 구멍을 막습니다 |
package/README.md CHANGED
@@ -20,7 +20,7 @@ Vendor APIs connect too — **only when you say so**
20
20
 
21
21
  [![Node.js CI](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/test.yml?branch=main&logo=github&logoColor=white&label=Node.js%20CI)](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
22
22
  [![CodeQL](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/codeql.yml?branch=main&logo=github&logoColor=white&label=CodeQL)](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
23
- [![tests](https://img.shields.io/badge/tests-9%2C187%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/en/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-9%2C212%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/en/develop.md)
24
24
 
25
25
  [![dependencies](https://img.shields.io/badge/dependencies-0-1a7f37)](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
26
26
  [![ESM](https://img.shields.io/badge/ESM-Node%2020%2B-5FA04E?logo=javascript&logoColor=white)](package.json)
@@ -374,7 +374,7 @@ deel --offline
374
374
  The destination is printed at the top of every session:
375
375
 
376
376
  ```
377
- deel 1.19.4 ⌂ inside
377
+ deel 1.20.0 ⌂ inside
378
378
  Sends to this machine 127.0.0.1:11434 ← nowhere else
379
379
  ```
380
380
 
@@ -1350,6 +1350,8 @@ so one run tells you everything.
1350
1350
 
1351
1351
  | Version | What changed |
1352
1352
  |---|---|
1353
+ | [1.20.0](docs/en/releases/1.20.md#1200) | A key not written in capitals was going out as it was |
1354
+ | [1.19.5](docs/en/releases/1.19.md#1195) | On Windows line endings the previous release's fix did nothing at all |
1353
1355
  | [1.19.4](docs/en/releases/1.19.md#1194) | Secrets leaked again wherever a comment was written |
1354
1356
  | [1.19.3](docs/en/releases/1.19.md#1193) | Secrets written in YAML were going out in plaintext |
1355
1357
  | [1.19.2](docs/en/releases/1.19.md#1192) | A gap appeared where the fence was moved — closing the hole 1.19.1 opened |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deel-local-cli",
3
- "version": "1.19.4",
3
+ "version": "1.20.0",
4
4
  "description": "A coding-agent CLI that runs on local models and private gateways. Zero dependencies, Node 20+.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -44,13 +44,49 @@ const 표 = (종류) => `«가림:${종류}»`;
44
44
  * 코드가 조용히 달라진다. 그건 여기서 막으려는 것보다 더 나쁜 고장이다.
45
45
  */
46
46
  /**
47
- * 한 끝에 붙은 `#` 주석.
47
+ * 한 줄에서 `#` 주석을 뗀다.
48
48
  *
49
- * 주석 안은 코드가 아니다. 여기를 떼지 않으면 `# https://api.example.com` 의
50
- * `//`, `# (운영환경용)` 의 괄호, `# type: bearer` 의 `type` 이 전부 「이 줄은
51
- * 코드」 라는 증거로 읽혀 **그 줄의 비밀이 평문으로 나간다**(14차 리뷰).
49
+ * 주석 안은 코드가 아니다. 떼지 않으면 `# https://api.example.com` 의 `//`,
50
+ * `# (운영환경용)` 의 괄호, `# type: bearer` 의 `type` 이 전부 「이 줄은 코드」
51
+ * 라는 증거로 읽혀 **그 줄의 비밀이 평문으로 나간다**(14차 리뷰).
52
+ *
53
+ * 무늬 하나로는 안 된다. 무늬로 하면 둘 중 하나를 고르게 된다(16차 리뷰).
54
+ *
55
+ * - `#` 앞 빈칸을 **요구하면** `API_KEY=prod.v1.secret#(운영)` 이 샌다.
56
+ * - **안 요구하면** `msg = "a # b"; x.API_KEY = config.apiKey;` 처럼 글자열
57
+ * 안의 `#` 부터 잘려 뒤쪽 `;` 이 사라지고, 멀쩡한 코드가 가려진다.
58
+ *
59
+ * 그래서 따옴표를 세면서 걷는다. **따옴표 밖**의 첫 `#` 부터가 주석이다.
60
+ * 앞 글자가 점이면 넘긴다 — 자바스크립트의 `obj.#몰래칸` 이다.
61
+ */
62
+ const 주석떼기 = (줄) => {
63
+ let 따 = '';
64
+ for (let i = 0; i < 줄.length; i += 1) {
65
+ const 자 = 줄[i];
66
+ if (따) {
67
+ if (자 === '\\') i += 1;
68
+ else if (자 === 따) 따 = '';
69
+ continue;
70
+ }
71
+ if (자 === '"' || 자 === "'" || 자 === '`') { 따 = 자; continue; }
72
+ if (자 === '#' && 줄[i - 1] !== '.') return 줄.slice(0, i);
73
+ }
74
+ return 줄;
75
+ };
76
+
77
+ /**
78
+ * `자리` 가 놓인 **한 줄**을 떼어 낸다.
79
+ *
80
+ * 줄바꿈을 `\n` 으로만 찾으면 `\r` 만 쓰는 글에서 파일 통째가 한 줄이 되고,
81
+ * 그러면 저 아래 어딘가의 `;` 하나 때문에 이 줄이 코드로 뒤집힌다(16차 리뷰).
82
+ * CRLF 의 `\r` 도 여기서 같이 떨어진다 — 안 떨어뜨리면 줄 끝을 보는 규칙이
83
+ * 통째로 헛돈다(15차 리뷰). 이 저장소가 도는 자리가 윈도우다.
52
84
  */
53
- const 주석 = /(?:^|[ \t])#.*$/;
85
+ const 줄떼기 = (전체, 자리) => {
86
+ const 앞 = Math.max(전체.lastIndexOf('\n', 자리), 전체.lastIndexOf('\r', 자리)) + 1;
87
+ const 남은 = 전체.slice(자리).search(/[\r\n]/);
88
+ return 전체.slice(앞, 남은 < 0 ? 전체.length : 자리 + 남은);
89
+ };
54
90
 
55
91
  /**
56
92
  * `.env` · YAML 한 줄에는 없고 코드 한 줄에는 있는 것들.
@@ -103,6 +139,12 @@ const 코드표시 = /[()]|=>|\/\/|\/\*|;|,[ \t]*$|\b(?:const|let|var|interface|
103
139
  * 낱말을 점으로 이은 꼴이다. 그러니 값 모양으로 가를 수 있다는 생각을
104
140
  * 버린다. 갈리지 않는 것을 갈리는 척하면 그게 더 위험하다.
105
141
  *
142
+ * 점 뒤의 `#` 도 이름씨의 한 조각이다 — `obj.#몰래칸` 은 자바스크립트다.
143
+ *
144
+ * 이름씨는 영문만이 아니다. `설정.비밀번호` 를 이름씨로 안 보면
145
+ * `const API_KEY = 설정.비밀번호;` 가 가려진다 — 이 저장소 집안 스타일이
146
+ * 한글 이름씨라 제 코드부터 뭉갰다(16차 리뷰). 글자 갈래로 본다.
147
+ *
106
148
  * 점이 없는 맨 값(`const API_KEY = apiKey;`)까지 줄을 묻게 넓혀 봤더니,
107
149
  * 이 저장소가 **가리라고 못 박아 둔** `const API_KEY = ENV-PROD-SECRET-KEY-12345;`
108
150
  * 와 `call(API_KEY = abcd1234)` 가 같이 풀렸다. 점 없는 한 낱말은 이름씨일
@@ -134,11 +176,8 @@ const 코드표시 = /[()]|=>|\/\/|\/\*|;|,[ \t]*$|\b(?:const|let|var|interface|
134
176
  * @returns {boolean} 가릴까
135
177
  */
136
178
  const 점값을가릴까 = (전체, 자리, 값) => {
137
- if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/.test(값)) return true;
138
- const 앞 = 전체.lastIndexOf('\n', 자리) + 1;
139
- const 뒤 = 전체.indexOf('\n', 자리);
140
- const 줄 = 전체.slice(앞, 뒤 < 0 ? 전체.length : 뒤).replace(주석, '');
141
- return !코드표시.test(줄);
179
+ if (!/^[\p{L}_$][\p{L}\p{N}_$]*(?:\.#?[\p{L}_$][\p{L}\p{N}_$]*)+$/u.test(값)) return true;
180
+ return !코드표시.test(주석떼기(줄떼기(전체, 자리)));
142
181
  };
143
182
 
144
183
  export const 갈래 = [
@@ -477,8 +516,28 @@ export const 갈래 = [
477
516
  * 고치는 김에 슬쩍 뒤집으면, 그건 고침이 아니라 다른 결정이다.
478
517
  */
479
518
  // 값 자리가 또 환경변수를 읽는 것이면 참조다 — Node · Vite · 파이썬 · Deno.
519
+ /*
520
+ * ── 이름은 대문자만이 아니다 (15차 리뷰에서 드러난 자리) ──────────
521
+ *
522
+ * 여태 `API_KEY` 같은 **대문자 이름만** 비밀 이름으로 봤다. `.env` 는
523
+ * 대문자가 관례라 그것으로 됐는데, 코드와 JSON·YAML 설정은 아니다.
524
+ *
525
+ * apiKey: 'sk-진짜열쇠-1234' 안 가림 — 평문으로 나갔다
526
+ * api_key: "prod.auth.secret" 안 가림
527
+ *
528
+ * 그래서 낙타등과 밑줄로 이은 이름도 본다. 낱말 사이가 **끊겨 있어야**
529
+ * 한다 — `_key` 아니면 `Key`. 그냥 소문자 `key` 로 끝나는 것까지 받으면
530
+ * `monkey` · `hotkey` 가 걸린다.
531
+ *
532
+ * 재 봤다. 이 저장소 파일 348개에 넣어 보니 21줄이 새로 가려졌고,
533
+ * **전부 진짜 열쇠였다**(`apiKey: 'sk-…'` 꼴).
534
+ *
535
+ * 치르는 값: `cacheKey` · `rowKey` 처럼 비밀이 아닌 낙타등 이름에
536
+ * 따옴표 값이 붙으면 같이 가려진다. 줄이 뭉개지는 것이 비밀이 나가는
537
+ * 것보다 낫다(1.19.0). 검사로 못 박아 둔다.
538
+ */
480
539
  id: '환경변수',
481
- re: /\b([A-Z][A-Z0-9_]{2,}(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|CREDENTIALS?))(?:(["']?[ \t]*(?::[^\n,;]{0,200}?|:[^\n]{0,200}?[>\])}][^\n,;]{0,80}?)[ \t]*=(?!=|>)\s*)((?:\(\s*)+)?(["'`])(?!«)((?:\\[^\n]|(?!\4)[^\n]){4,}?)\4((?:\s*\))+)?|(["']?\s*(?::(?![^\n]{0,200}?=[ \t]*«가림:)|=)\s*)((?:\(\s*)+)?(?:(["'`])(?!«)((?:\\[^\n]|(?!\9)[^\n]){4,}?)\9|(?!«)(?![\w$.]+\s*[([])(?!(?:string|number|boolean|bigint|symbol|object|unknown|never|void|null|undefined|true|false)\b)(?![^\n]{0,200}?}[ \t]*(?:=(?!=|>)|\)))(?!\(*\s*(?:process\.env|import\.meta\.env|globalThis\.process\.env|globalThis\.env|os\.environ|os\.getenv|ENV(?=\s*[[.(])|Deno\.env|Bun\.env)\b)([^\s"'()[\]{},;<>]{4,})(?=[ \t\r]*(?:[;,)\]}\n#]|$)))((?:\s*\))+)?)/g,
540
+ re: /\b((?:[A-Z][A-Z0-9_]{2,}(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|CREDENTIALS?)|[A-Za-z][A-Za-z0-9]*(?:_(?:key|token|secret|password|passwd|pwd|credentials?)|Key|Token|Secret|Password|Passwd|Pwd|Credentials?)))(?:(["']?[ \t]*(?::[^\n,;]{0,200}?|:[^\n]{0,200}?[>\])}][^\n,;]{0,80}?)[ \t]*=(?!=|>)\s*)((?:\(\s*)+)?(["'`])(?!«)((?:\\[^\n]|(?!\4)[^\n]){4,}?)\4((?:\s*\))+)?|(["']?\s*(?::(?![^\n]{0,200}?=[ \t]*«가림:)|=)\s*)((?:\(\s*)+)?(?:(["'`])(?!«)((?:\\[^\n]|(?!\9)[^\n]){4,}?)\9|(?!«)(?![\w$.]+\s*[([])(?!(?:string|number|boolean|bigint|symbol|object|unknown|never|void|null|undefined|true|false)\b)(?![^\n]{0,200}?}[ \t]*(?:=(?!=|>)|\)))(?!\(*\s*(?:process\.env|import\.meta\.env|globalThis\.process\.env|globalThis\.env|os\.environ|os\.getenv|ENV(?=\s*[[.(])|Deno\.env|Bun\.env)\b)([^\s"'()[\]{},;<>]{4,})(?=[ \t]*(?:[;,)\]}\r\n#]|$)))((?:\s*\))+)?)/g,
482
541
  바꾸기: (m, 이름, 타입사이, 타입여는, 따A, 값A, 타입닫는,
483
542
  민사이, 여는, 따B, 값B, 값C, 닫는, 자리, 전체) => {
484
543
  // 따옴표 없는 맨 값만 「코드가 가리키는 이름인가」 를 되묻는다.