deel-local-cli 1.19.1 → 1.19.3

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%2C122%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/ko/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-9%2C155%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.1 ⌂ 이 안
304
+ deel 1.19.3 ⌂ 이 안
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.19.3](docs/ko/releases/1.19.md#1193) | YAML 에 적은 비밀이 평문으로 나가고 있었습니다 |
1293
+ | [1.19.2](docs/ko/releases/1.19.md#1192) | 울타리를 옮긴 자리에 틈이 생겼습니다 — 1.19.1 이 낸 구멍을 막습니다 |
1292
1294
  | [1.19.1](docs/ko/releases/1.19.md#1191) | 열두 번째 눈이 본 것, 그리고 오탐 열넷 — 지적 27건 중 13건이 진짜였습니다 |
1293
1295
  | [1.19.0](docs/ko/releases/1.19.md#1190) | 한쪽을 맞히면 반대쪽이 틀렸습니다 — 검사 9,093개로 양쪽을 같이 잽니다 |
1294
1296
  | [1.18.0](docs/ko/releases/1.18.md#1180) | 있는 것과 걸리는 것은 다릅니다 — 검사 8,404개가 초록인 채로 열려 있던 자리들 |
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%2C122%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/en/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-9%2C155%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.1 ⌂ inside
377
+ deel 1.19.3 ⌂ 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.19.3](docs/en/releases/1.19.md#1193) | Secrets written in YAML were going out in plaintext |
1354
+ | [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 |
1353
1355
  | [1.19.1](docs/en/releases/1.19.md#1191) | What the twelfth pair of eyes found, and the fourteen false alarms — 13 of 27 findings survived |
1354
1356
  | [1.19.0](docs/en/releases/1.19.md#1190) | Getting one side right broke the other — 9,093 checks that measure both sides |
1355
1357
  | [1.18.0](docs/en/releases/1.18.md#1180) | Having a rule is not the same as the rule firing — what was open while 8,404 checks stayed green |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deel-local-cli",
3
- "version": "1.19.1",
3
+ "version": "1.19.3",
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",
@@ -255,7 +255,7 @@
255
255
  * 세 갈래에 같은 「띄운 줄표」 잣대를 넣어 맞춘다.
256
256
  */
257
257
  const 영어시킴말 =
258
- /(?:^\s*|(?<!\b(?:e\.g|i\.e|vs|cf|approx|Fig|Dr|Mr|Mrs|Ms|St|Jr|Sr))[.!?]\s+|\n\s*|^\s*\d+[.)]\s*|^\s*[-*]\s*)(?:(?:first|then|next|after\s+that|also|now|finally|second|third|lastly|afterwards?)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:could|can|would|will)\s+(?:you|we)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:build|make|create|update|write|migrate|generate|set\s*up)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|broken|crash|crashes|timeouts?)\b(?=\s*(?:[,:;!?)\]]|$)|\s*[([][^)\]\n]*[)\]][ \t]*[.!?]?[ \t]*$|\s*\.(?!\w)|\s+-{1,2}\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-{1,2}[ \t]|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:modify|change|develop|rewrite)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=\s*(?:[,:;!?)\]]|$)|\s*[([][^)\]\n]*[)\]][ \t]*[.!?]?[ \t]*$|\s*\.(?!\w)|\s+-{1,2}\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-{1,2}\s)))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-{1,2}[ \t]|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:implement|add|fix|refactor|remove|delete|rename|scaffold)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=\s*(?:[,:;!?)\]]|$)|\s*[([][^)\]\n]*[)\]][ \t]*[.!?]?[ \t]*$|\s*\.(?!\w)|\s+-{1,2}\s|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-{1,2}\s))))(?!\()(?![-\w]*[ \t]*:)(?![ \t]+[\w.-]+[ \t]*:[ \t])(?!(?<=\bdelete)\s+from\s+[\w."`]+\s*(?:where\b|order\s+by\b|limit\b|;|$))(?!(?<=\bupdate)\s+[\w."`]+\s+set\b)/im;
258
+ /(?:^\s*|(?<!\b(?:e\.g|i\.e|vs|cf|approx|Fig|Dr|Mr|Mrs|Ms|St|Jr|Sr))[.!?]\s+|\n\s*|^\s*\d+[.)]\s*|^\s*[-*]\s*)(?:(?:first|then|next|after\s+that|also|now|finally|second|third|lastly|afterwards?)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:could|can|would|will)\s+(?:you|we)\s*,?\s+)?(?:please\s*,?\s+)?(?:(?:build|make|create|update|write|migrate|generate|set\s*up)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|(?:failures?|errors?|broken|crash|crashes|timeouts?)\b(?=(?:[ \t]*[([][^)\]\n]*[)\]])?(?:\s*(?:[,:;!?)\]]|$)|\s*\.(?!\w)|\s+-{1,2}(?:\s|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b))))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-{1,2}(?:[ \t]|$)|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:modify|change|develop|rewrite)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=(?:[ \t]*[([][^)\]\n]*[)\]])?(?:\s*(?:[,:;!?)\]]|$)|\s*\.(?!\w)|\s+-{1,2}(?:\s|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b))|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-{1,2}(?:\s|$))))(?!(?:[ \t]+[\w'-]+){0,3}[ \t]+(?:[\w']+-)*(?:plans?|roadmaps?|strateg(?:y|ies)|outlines?)(?=[ \t]*(?:[!?,;:)]|\.(?!\w)|$)|[ \t]+-{1,2}(?:[ \t]|$)|[ \t]+(?:now|today|tonight|tomorrow|first|soon|asap|again)\b|[ \t]+(?:for|to|of|on|about|around|that|which|we|with|before|after|regarding|covering)\b))|(?:implement|add|fix|refactor|remove|delete|rename|scaffold)\b(?![\s:-]+(?:(?:failed|failing|fails|errored|broke|crashed|succeeded|succeeds|timed[\s-]+out)\b(?=\s*(?:[.,:;!?()\[\]-]|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b)|broken\b(?=(?:[ \t]*[([][^)\]\n]*[)\]])?(?:\s*(?:[,:;!?)\]]|$)|\s*\.(?!\w)|\s+-{1,2}(?:\s|$)|\s+(?:with|at|after|in|on|to|before|during|because|due|while|when|for|since|from)\b))|(?:failures?|errors?|crash|crashes|timeouts?)\b(?:\s*[:(]|\s+-{1,2}(?:\s|$)))))(?!\()(?![-\w]*[ \t]*:)(?![ \t]+[\w.-]+[ \t]*:[ \t])(?!(?<=\bdelete)\s+from\s+[\w."`]+\s*(?:where\b|order\s+by\b|limit\b|;|$))(?!(?<=\bupdate)\s+[\w."`]+\s+set\b)/im;
259
259
 
260
260
  export const 표 = {
261
261
  debug: [
@@ -43,6 +43,65 @@ const 표 = (종류) => `«가림:${종류}»`;
43
43
  * 넓게 잡지 않는다. 코드에 흔한 글자를 비밀로 오인해 가려 버리면, 모델이 보는
44
44
  * 코드가 조용히 달라진다. 그건 여기서 막으려는 것보다 더 나쁜 고장이다.
45
45
  */
46
+ /** `.env` · YAML 한 줄에는 없고 코드 한 줄에는 있는 것들. */
47
+ const 코드표시 = /[;{}()]|=>|\/\/|\/\*|\b(?:const|let|var|interface|type|class|enum|function|def|readonly|declare|public|private|protected|static|final)\b/;
48
+
49
+ /**
50
+ * 점으로 이은 값이 **비밀인가 코드인가**.
51
+ *
52
+ * ── 빈칸은 가르는 신호가 아니었다 (13차 리뷰) ──────────────────────────
53
+ *
54
+ * 여태 「값 앞에 빈칸이 있으면 코드」 로 갈랐다. `.env` 는 `NAME=값` 으로
55
+ * 붙여 쓰니 빈칸이 있으면 코드라는 셈이었다. 재 보니 **넷 중 하나만**
56
+ * 맞혔다.
57
+ *
58
+ * API_KEY=prod.v1.secret 가림 맞음
59
+ * API_KEY: token.v1.secret (YAML) 그대로 비밀이 평문으로 남음
60
+ * API_KEY= prod.v1.secret (.env) 그대로 같은 자리
61
+ * interface Cfg { API_KEY:types.ApiKey; } 가림 코드를 망가뜨림
62
+ *
63
+ * YAML 은 문법이 쌍점 뒤 빈칸을 **요구한다.** 그러니 빈칸을 코드의 표시로
64
+ * 읽는 한 YAML 에 적힌 비밀은 언제까지고 샌다. 그리고 붙여 쓴 타입
65
+ * 표기(`API_KEY:types.ApiKey`)는 거꾸로 코드인데 가려졌다.
66
+ *
67
+ * ── 그 줄이 코드인가만 본다 ───────────────────────────────────────────
68
+ *
69
+ * `.env` 와 YAML 한 줄에는 이름과 값밖에 없다. 세미콜론·중괄호·괄호·
70
+ * 화살표·주석표·선언 낱말 중 하나라도 그 줄에 있으면 코드다.
71
+ * `export` 는 **넣지 않는다** — `.env` 도 `export FOO=bar` 를 쓴다.
72
+ *
73
+ * ── 값 모양으로 가르려다 물러섰다 ─────────────────────────────────────
74
+ *
75
+ * 처음엔 값도 같이 봤다 — 「숫자가 끼거나 마디가 길면 비밀」. 그러면
76
+ * `config.api_key` 를 놔두면서 `token.v1.secret` 을 가릴 수 있다. 그런데
77
+ * 이 저장소에 이미 박혀 있는 검사가 **`API_KEY=my.secret.value` 를 가리라고**
78
+ * 한다. 그것과 `config.api_key` 는 문법으로 구별이 안 된다 — 둘 다 짧은
79
+ * 낱말을 점으로 이은 꼴이다. 그러니 값 모양으로 가를 수 있다는 생각을
80
+ * 버린다. 갈리지 않는 것을 갈리는 척하면 그게 더 위험하다.
81
+ *
82
+ * ── 그래서 치르는 값 ──────────────────────────────────────────────────
83
+ *
84
+ * 세미콜론이 없는 파이썬 대입은 설정 줄과 똑같이 생긴다.
85
+ *
86
+ * API_KEY = config.api_key 파이썬 코드인데 가려진다
87
+ *
88
+ * 이건 알고 받는 값이다. 줄이 망가지는 것보다 **비밀이 나가는 것이 훨씬
89
+ * 나쁘다**(1.19.0 에 적어 둔 대로). 가려도 줄은 읽힌다 —
90
+ * `API_KEY = «가림:환경변수»` 로 남고, 무엇이 있었는지도 보인다.
91
+ *
92
+ * @param {string} 전체 가리는 글 통째로
93
+ * @param {number} 자리 이 짝이 시작한 자리
94
+ * @param {string} 값 점으로 이어졌을 수 있는 값
95
+ * @returns {boolean} 가릴까
96
+ */
97
+ const 점값을가릴까 = (전체, 자리, 값) => {
98
+ if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/.test(값)) return true;
99
+ const 앞 = 전체.lastIndexOf('\n', 자리) + 1;
100
+ const 뒤 = 전체.indexOf('\n', 자리);
101
+ const 줄 = 전체.slice(앞, 뒤 < 0 ? 전체.length : 뒤);
102
+ return !코드표시.test(줄);
103
+ };
104
+
46
105
  export const 갈래 = [
47
106
  {
48
107
  id: '사설키',
@@ -380,11 +439,15 @@ export const 갈래 = [
380
439
  */
381
440
  // 값 자리가 또 환경변수를 읽는 것이면 참조다 — Node · Vite · 파이썬 · Deno.
382
441
  id: '환경변수',
383
- 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)(?:(?<=[ \t])(?![A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+\b)|(?<![ \t]))(?![^\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,
442
+ 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,
384
443
  바꾸기: (m, 이름, 타입사이, 타입여는, 따A, 값A, 타입닫는,
385
- 민사이, 여는, 따B, 값B, 값C, 닫는) => (타입사이 === undefined
386
- ? `${이름}${민사이}${여는 ?? ''}${표('환경변수')}${닫는 ?? ''}`
387
- : `${이름}${타입사이}${타입여는 ?? ''}${표('환경변수')}${타입닫는 ?? ''}`),
444
+ 민사이, 여는, 따B, 값B, 값C, 닫는, 자리, 전체) => {
445
+ // 따옴표 없는 값만 「코드가 가리키는 이름인가」 를 되묻는다.
446
+ if (값C !== undefined && !점값을가릴까(전체, 자리, 값C)) return m;
447
+ return 타입사이 === undefined
448
+ ? `${이름}${민사이}${여는 ?? ''}${표('환경변수')}${닫는 ?? ''}`
449
+ : `${이름}${타입사이}${타입여는 ?? ''}${표('환경변수')}${타입닫는 ?? ''}`;
450
+ },
388
451
  },
389
452
  ];
390
453