tillerhand 3.49.5 → 3.49.7
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/.claude/hooks/destructive-guard.mjs +2 -1
- package/.claude/hooks/guard-secrets.mjs +23 -11
- package/.claude/hooks/preview.mjs +2 -2
- package/.claude/hooks/shared.mjs +2 -1
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/kit/CHANGELOG.md +16 -0
- package/kit/VERSION +1 -1
- package/kit/guide.html +2 -2
- package/kit/guide.tr.html +2 -2
- package/package.json +1 -1
|
@@ -54,7 +54,8 @@ const NEEDS_APPROVAL = [
|
|
|
54
54
|
|
|
55
55
|
// The test guard runs on file tools; changing a test or test config file from the shell (sed -i, rm, >, mv, git checkout) is asked.
|
|
56
56
|
// Each part of a command chain is checked alone: "rm -r node_modules && npx vitest run a.test.ts" does not change a test.
|
|
57
|
-
|
|
57
|
+
// A flag is not a command name: grep -ln, ls -rd, tar -rm are not writers
|
|
58
|
+
const WRITER = /(?<![\w-])(rm|del|erase|rmdir|rd|unlink|mv|move|cp|copy|tee|truncate|touch|ln|dd|Set-Content|Add-Content|Out-File|Remove-Item|Move-Item|Copy-Item|Clear-Content)\b|\bcurl\b[^;&|]*\s(-o|--output)\b|\bwget\b[^;&|]*\s(-O|--output-document)\b|\bsed\b[^;&|]*\s(-[a-zA-Z]*i\S*|--in-place\b)|\bperl\b[^;&|]*\s-[a-zA-Z]*i|\bgit\s+(checkout|restore|rm|mv)\b/i;
|
|
58
59
|
// Dependency and git internals are not the project's tests; a URL (curl … https://x/tests/a) or a dd input is not a target
|
|
59
60
|
// Normalized first: node_modules/../tests/a.test.ts is a test path; only a path that stays under them is skipped
|
|
60
61
|
const isTestCode = (t) => {
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
import { execSync } from 'node:child_process';
|
|
8
8
|
import { readInput, decide, isMain } from './shared.mjs';
|
|
9
9
|
|
|
10
|
+
// (?<![A-Za-z0-9]) instead of \b: a key right after _ (OPENAI_sk-…, prod_sk_live_…) is found too.
|
|
11
|
+
// Lookaheads and runs are bounded: an unbounded one is quadratic on a long run (-sb_secret_ × 50 000) and a hook
|
|
12
|
+
// that times out lets the write through.
|
|
10
13
|
export const PATTERNS = [
|
|
11
|
-
['Anthropic/OpenAI key',
|
|
12
|
-
['Stripe secret key',
|
|
13
|
-
['
|
|
14
|
-
['
|
|
15
|
-
['
|
|
16
|
-
['
|
|
17
|
-
['
|
|
18
|
-
['
|
|
14
|
+
['Anthropic/OpenAI key', /(?<![A-Za-z0-9])sk-(?:ant-|proj-)?[A-Za-z0-9_-]{32,}/],
|
|
15
|
+
['Stripe secret key', /(?<![A-Za-z0-9])(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{20,}/],
|
|
16
|
+
['Stripe webhook secret', /(?<![A-Za-z0-9])whsec_[A-Za-z0-9+/]{24,}/],
|
|
17
|
+
['AWS access key', /(?<![A-Za-z0-9])(?:AKIA|ASIA)[0-9A-Z]{16}\b/],
|
|
18
|
+
['GitHub token', /(?<![A-Za-z0-9])(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}|(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}/],
|
|
19
|
+
['GitLab token', /(?<![A-Za-z0-9])glpat-[\w-]{20,}/],
|
|
20
|
+
['Google API key', /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}/],
|
|
21
|
+
['Hugging Face token', /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{34,}/],
|
|
22
|
+
['npm token', /(?<![A-Za-z0-9])npm_[A-Za-z0-9]{36,}/],
|
|
23
|
+
['SendGrid key', /(?<![A-Za-z0-9])SG\.[\w-]{22}\.[\w-]{43}/],
|
|
24
|
+
['Slack token', /(?<![A-Za-z0-9])(?:xox[abprse]|xapp)-[A-Za-z0-9-]{10,}/],
|
|
25
|
+
['Private key', /-----BEGIN (?:[A-Z]+ ){0,4}PRIVATE KEY(?: BLOCK)?-----/],
|
|
26
|
+
['Resend key', /(?<![A-Za-z0-9])re_[A-Za-z0-9]{8,}_[A-Za-z0-9]{16,}/],
|
|
27
|
+
['Supabase secret key', /(?<![A-Za-z0-9])sb_secret_(?=[\w-]{0,100}\d)[\w-]{16,}/],
|
|
19
28
|
];
|
|
20
29
|
|
|
21
30
|
export function findSecrets(text) {
|
|
@@ -41,11 +50,14 @@ function hookMode() {
|
|
|
41
50
|
|
|
42
51
|
function stagedMode() {
|
|
43
52
|
const diff = execSync('git diff --cached -U0 --no-color', { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
44
|
-
let file = '';
|
|
53
|
+
let file = '', hunk = false;
|
|
45
54
|
const findings = [];
|
|
55
|
+
// Inside a hunk every + line is content, "+++ …" included (a line starting with ++); headers come before the first @@
|
|
46
56
|
for (const line of diff.split('\n')) {
|
|
47
|
-
if (line.startsWith('
|
|
48
|
-
else if (line.startsWith('
|
|
57
|
+
if (line.startsWith('diff --git ')) hunk = false;
|
|
58
|
+
else if (!hunk && line.startsWith('+++ ')) file = line.slice(6);
|
|
59
|
+
else if (line.startsWith('@@')) hunk = true;
|
|
60
|
+
else if (hunk && line.startsWith('+')) {
|
|
49
61
|
const f = findSecrets(line);
|
|
50
62
|
if (f.length) findings.push(`${file}: ${f.join(', ')}`);
|
|
51
63
|
}
|
|
@@ -9,7 +9,7 @@ import fs from 'node:fs';
|
|
|
9
9
|
import os from 'node:os';
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { spawn, spawnSync } from 'node:child_process';
|
|
12
|
-
import { approvedCommands, approvalNeeded, isApproved } from './gate.mjs';
|
|
12
|
+
import { approvedCommands, approvalNeeded, isApproved, unknownCommandKeys, readAgents } from './gate.mjs';
|
|
13
13
|
import { findRoot, isMain } from './shared.mjs';
|
|
14
14
|
|
|
15
15
|
const CLI = 'npx -y @playwright/cli@0.1.22';
|
|
@@ -56,7 +56,7 @@ export async function preview(root, task) {
|
|
|
56
56
|
const url = command('preview'), dev = command('dev');
|
|
57
57
|
if (!url) return fail('AGENTS.md → Commands has no `preview:` line, or it is empty. Add it (example: `preview: http://localhost:3000`) or produce the evidence by hand in this task.');
|
|
58
58
|
if (!LOCAL.test(url)) return fail(`the preview address must be local (http://localhost:<port>, 127.0.0.1 or [::1]). Now: ${url}`);
|
|
59
|
-
if (!isApproved(root, list)) return { code: 1, text: `Preview · ${approvalNeeded(list)}` };
|
|
59
|
+
if (!isApproved(root, list)) return { code: 1, text: `Preview · ${approvalNeeded(list, unknownCommandKeys(readAgents(root)))}` };
|
|
60
60
|
const dir = `.previews/${String(task || 'latest').replace(/[^\w-]/g, '-')}`;
|
|
61
61
|
// A linked folder from the repo would send the files elsewhere
|
|
62
62
|
for (const d of ['.previews', dir]) {
|
package/.claude/hooks/shared.mjs
CHANGED
|
@@ -104,7 +104,8 @@ export function parseInput(g) {
|
|
|
104
104
|
const text = isText(t.content) ? t.content
|
|
105
105
|
: isText(t.new_string) ? t.new_string
|
|
106
106
|
: Array.isArray(t.edits) ? t.edits.map((e) => e?.new_string ?? '').join('\n')
|
|
107
|
-
: isText(t.new_source) ? t.new_source
|
|
107
|
+
: isText(t.new_source) ? t.new_source
|
|
108
|
+
: JSON.stringify(t); // an unexpected shape (content or new_source as an array): every argument is scanned
|
|
108
109
|
const before = isText(t.old_string) ? t.old_string
|
|
109
110
|
: Array.isArray(t.edits) ? t.edits.map((e) => e?.old_string ?? '').join('\n') : undefined;
|
|
110
111
|
const edits = isText(t.old_string) ? [{ old: t.old_string, new: isText(t.new_string) ? t.new_string : '', all: t.replace_all === true }]
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
|
-
<a href="kit/CHANGELOG.md"><img alt="Version" src="https://img.shields.io/badge/version-3.49.
|
|
9
|
+
<a href="kit/CHANGELOG.md"><img alt="Version" src="https://img.shields.io/badge/version-3.49.7-2a78d6?style=flat-square"></a>
|
|
10
10
|
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-2a78d6?style=flat-square"></a>
|
|
11
11
|
<img alt="Claude Code" src="https://img.shields.io/badge/Claude%20Code-ready-d97757?style=flat-square">
|
|
12
12
|
<img alt="Also Codex and Antigravity" src="https://img.shields.io/badge/also-Codex%20%C2%B7%20Antigravity-5b6577?style=flat-square">
|
package/README.tr.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
|
-
<a href="kit/CHANGELOG.md"><img alt="Sürüm" src="https://img.shields.io/badge/s%C3%BCr%C3%BCm-3.49.
|
|
9
|
+
<a href="kit/CHANGELOG.md"><img alt="Sürüm" src="https://img.shields.io/badge/s%C3%BCr%C3%BCm-3.49.7-2a78d6?style=flat-square"></a>
|
|
10
10
|
<a href="LICENSE"><img alt="Lisans: MIT" src="https://img.shields.io/badge/lisans-MIT-2a78d6?style=flat-square"></a>
|
|
11
11
|
<img alt="Claude Code" src="https://img.shields.io/badge/Claude%20Code-haz%C4%B1r-d97757?style=flat-square">
|
|
12
12
|
<img alt="Codex ve Antigravity" src="https://img.shields.io/badge/ayr%C4%B1ca-Codex%20%C2%B7%20Antigravity-5b6577?style=flat-square">
|
package/kit/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
The kit version is in `kit/VERSION`. To update a project, run `/kit-update` in it.
|
|
4
4
|
Items with an "Adapt by hand" note concern files owned by the project; the update does not touch them.
|
|
5
5
|
|
|
6
|
+
## [3.49.7] - 2026-10-30
|
|
7
|
+
|
|
8
|
+
### Security
|
|
9
|
+
- **The secret guard can no longer be timed out.** A long run of `-sb_secret_` made one pattern quadratic; a hook that times out lets the write through. The patterns are bounded now.
|
|
10
|
+
- **More key formats are stopped:** Google API keys (`AIza…`), GitLab (`glpat-`), Hugging Face (`hf_`), npm (`npm_`), SendGrid (`SG.…`), Stripe webhook secrets (`whsec_`), Slack app and refresh tokens (`xapp-`, `xoxe-`) and PGP private key blocks. A key right after `_` or a letter (`OPENAI_sk-…`, `prod_sk_live_…`) is found too. JWTs and database URLs with a password are still not matched: local dev values would raise false alarms.
|
|
11
|
+
- A write whose content is not plain text (a `content` or notebook `new_source` array) is scanned as a whole instead of skipped.
|
|
12
|
+
- The pre-commit scan (`guard-secrets.mjs --staged`) also checks added lines that start with `++`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- `grep -ln`, `ls -rd` and other commands with a flag that spells a file command no longer count as writing a test file.
|
|
16
|
+
|
|
17
|
+
## [3.49.6] - 2026-10-30
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- `/preview` before the command approval names the `## Commands` keys the gate does not read (`deploy:`…), like the gate run and the approval prompt already do.
|
|
21
|
+
|
|
6
22
|
## [3.49.5] - 2026-10-30
|
|
7
23
|
|
|
8
24
|
### Security
|
package/kit/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.49.
|
|
1
|
+
3.49.7
|
package/kit/guide.html
CHANGED
|
@@ -361,7 +361,7 @@ footer .container { display: flex; flex-wrap: wrap; gap: 16px; justify-content:
|
|
|
361
361
|
<section class="hero">
|
|
362
362
|
<div class="container">
|
|
363
363
|
<div>
|
|
364
|
-
<span class="pill"><b>v3.49.
|
|
364
|
+
<span class="pill"><b>v3.49.7</b> Starter kit for Claude Code · MIT</span>
|
|
365
365
|
<h1>The AI builds.<br><em>You steer.</em></h1>
|
|
366
366
|
<p class="sub">TillerHand takes a product from idea to production and maintenance with Claude Code. At every important decision the AI gives you the options, its recommendation and the cost of each option. An expert board reviews the work, and guardrails stop mistakes before they happen.</p>
|
|
367
367
|
<div class="setup">
|
|
@@ -1241,7 +1241,7 @@ Next: G-013 password reset · pending decision: email service</pre>
|
|
|
1241
1241
|
<footer>
|
|
1242
1242
|
<div class="container">
|
|
1243
1243
|
<a class="brand" href="#top" style="font-size:16px"><svg class="mark" style="width:22px;height:22px"><use href="#mark"/></svg>TillerHand</a>
|
|
1244
|
-
<span>Version 3.49.
|
|
1244
|
+
<span>Version 3.49.7 · <a href="https://github.com/burakdogrul/TillerHand">GitHub</a> · <a href="https://github.com/burakdogrul/TillerHand/blob/main/LICENSE">MIT license</a> · The KVKK section is a checklist, not legal advice.</span>
|
|
1245
1245
|
</div>
|
|
1246
1246
|
</footer>
|
|
1247
1247
|
|
package/kit/guide.tr.html
CHANGED
|
@@ -361,7 +361,7 @@ footer .container { display: flex; flex-wrap: wrap; gap: 16px; justify-content:
|
|
|
361
361
|
<section class="hero">
|
|
362
362
|
<div class="container">
|
|
363
363
|
<div>
|
|
364
|
-
<span class="pill"><b>v3.49.
|
|
364
|
+
<span class="pill"><b>v3.49.7</b> Claude Code için başlangıç kiti · MIT</span>
|
|
365
365
|
<h1>Kodu AI yazar.<br><em>Dümen sende.</em></h1>
|
|
366
366
|
<p class="sub">TillerHand, Claude Code ile bir ürünü fikirden canlıya ve bakıma kadar götürür. Her önemli kararda AI sana seçenekleri, önerisini ve her seçeneğin bedelini sunar. Bir uzman kurulu işi denetler, korumalar hatayı daha olmadan durdurur.</p>
|
|
367
367
|
<div class="setup">
|
|
@@ -1245,7 +1245,7 @@ Sıradaki: G-013 şifre sıfırlama · bekleyen karar: e-posta servisi</pre>
|
|
|
1245
1245
|
<footer>
|
|
1246
1246
|
<div class="container">
|
|
1247
1247
|
<a class="brand" href="#top" style="font-size:16px"><svg class="mark" style="width:22px;height:22px"><use href="#mark"/></svg>TillerHand</a>
|
|
1248
|
-
<span>Sürüm 3.49.
|
|
1248
|
+
<span>Sürüm 3.49.7 · <a href="https://github.com/burakdogrul/TillerHand">GitHub</a> · <a href="https://github.com/burakdogrul/TillerHand/blob/main/LICENSE">MIT lisansı</a> · KVKK bölümü kontrol listesidir, hukuki görüş değildir.</span>
|
|
1249
1249
|
</div>
|
|
1250
1250
|
</footer>
|
|
1251
1251
|
|