@tyhld/conductor 0.12.18 → 0.12.20
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/package.json +1 -1
- package/scripts/hooks/README.md +63 -9
- package/scripts/hooks/policy.py +669 -63
- package/scripts/hooks/summary_ja.py +2 -1
- package/scripts/hooks/test_autorun.py +33 -13
- package/scripts/hooks/test_bypass_deny.py +299 -0
- package/scripts/hooks/test_gate_real_commands.py +202 -0
- package/scripts/hooks/test_gate_wait.py +3 -1
- package/scripts/hooks/test_policy.py +23 -31
|
@@ -40,11 +40,8 @@ def check(label, got, want):
|
|
|
40
40
|
# (a) 3関門は必ず gate(=人へ)
|
|
41
41
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
42
42
|
GATE_CASES = [
|
|
43
|
-
# 関門1
|
|
44
|
-
|
|
45
|
-
('git push -u origin main', policy.GATE_MERGE),
|
|
46
|
-
('git push origin HEAD:master', policy.GATE_MERGE),
|
|
47
|
-
('git push origin production', policy.GATE_MERGE),
|
|
43
|
+
# ★旧 関門1(main など保護ブランチへの直接 push)は便 fc22bc34 で deny へ移した
|
|
44
|
+
# → test_bypass_deny.py で確かめる。PRのマージは関門ではない → (a4)。
|
|
48
45
|
# 関門2 本番確認
|
|
49
46
|
('vercel --prod', policy.GATE_RELEASE),
|
|
50
47
|
('vercel deploy --prod', policy.GATE_RELEASE),
|
|
@@ -56,14 +53,10 @@ GATE_CASES = [
|
|
|
56
53
|
('supabase functions deploy hello', policy.GATE_RELEASE),
|
|
57
54
|
('npm run deploy -- --production', policy.GATE_RELEASE),
|
|
58
55
|
# 関門3 DB実行
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
('supabase db push', policy.GATE_DB),
|
|
63
|
-
('supabase migration up', policy.GATE_DB),
|
|
64
|
-
('npx drizzle-kit push', policy.GATE_DB),
|
|
56
|
+
# ★本番 DB を直接変える道具(psql・prisma db push / migrate deploy・supabase db push /
|
|
57
|
+
# migration up・drizzle-kit push 等)は便 fc22bc34 で deny へ移した(設定の deny と揃える)
|
|
58
|
+
# → test_bypass_deny.py。ここに残るのは、それ以外の DB 実行(見分けられないので人に聞く)。
|
|
65
59
|
('createdb newdb', policy.GATE_DB),
|
|
66
|
-
('echo "CREATE TABLE x (id uuid)" | psql', policy.GATE_DB),
|
|
67
60
|
('supabase db query "GRANT SELECT ON x TO authenticated"', policy.GATE_DB),
|
|
68
61
|
('run-sql "ALTER TABLE x ENABLE ROW LEVEL SECURITY"', policy.GATE_DB),
|
|
69
62
|
('apply "CREATE POLICY p ON x"', policy.GATE_DB),
|
|
@@ -109,9 +102,8 @@ class GuardDatalink:
|
|
|
109
102
|
self.decisions.append((tool_name, decision, gate))
|
|
110
103
|
|
|
111
104
|
|
|
112
|
-
GATE_CMDS = ['
|
|
113
|
-
'
|
|
114
|
-
'psql -c "select 1"']
|
|
105
|
+
GATE_CMDS = ['vercel --prod', 'npm publish', 'createdb newdb',
|
|
106
|
+
'supabase db query "select 1"', 'run-sql "ALTER TABLE x ADD COLUMN y int"']
|
|
115
107
|
|
|
116
108
|
print('\n=== (a2) 関門は入口の番人がその場で管制に聞き、答えで allow / deny を返す(便 ab6e36ca) ===')
|
|
117
109
|
gd_ok = GuardDatalink({'url': 'http://x', 'token': 't'}, reachable=True)
|
|
@@ -138,7 +130,7 @@ for cmd in GATE_CMDS:
|
|
|
138
130
|
check(f'{cmd} → deny(管制不通)', got, 'deny')
|
|
139
131
|
|
|
140
132
|
gd_unset = GuardDatalink(None, reachable=False) # 管制未設定(load_config が None)
|
|
141
|
-
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': '
|
|
133
|
+
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': 'npm publish'}},
|
|
142
134
|
datalink=gd_unset)
|
|
143
135
|
check('管制未設定でも関門は deny', out['hookSpecificOutput']['permissionDecision'], 'deny')
|
|
144
136
|
|
|
@@ -153,11 +145,11 @@ check('危険は管制不通でも deny のまま', out['hookSpecificOutput']['p
|
|
|
153
145
|
# ★便 ab6e36ca: 以前の無効化フラグ(CC2_GATE_FAILCLOSE=0 で止めずに ask)は外した。
|
|
154
146
|
# ask は auto モードでは人の答えを待たずに実行されうる(便 c525bb2b)=止めが消える回避路になるため。
|
|
155
147
|
os.environ['CC2_GATE_FAILCLOSE'] = '0'
|
|
156
|
-
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': '
|
|
148
|
+
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': 'npm publish'}},
|
|
157
149
|
datalink=gd_unset)
|
|
158
150
|
check('★CC2_GATE_FAILCLOSE=0 でも関門は deny(回避路を作らない)',
|
|
159
151
|
out['hookSpecificOutput']['permissionDecision'], 'deny')
|
|
160
|
-
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': '
|
|
152
|
+
out = cc2_guard.build_output({'tool_name': 'Bash', 'tool_input': {'command': 'npm publish'}},
|
|
161
153
|
datalink=gd_ng)
|
|
162
154
|
check('★CC2_GATE_FAILCLOSE=0 でも管制不通の関門は deny',
|
|
163
155
|
out['hookSpecificOutput']['permissionDecision'], 'deny')
|
|
@@ -179,7 +171,8 @@ MERGE_ALLOW = [
|
|
|
179
171
|
'gh pr merge --auto 12',
|
|
180
172
|
'gh pr merge 3 --merge --delete-branch',
|
|
181
173
|
'gh pr merge --rebase 7',
|
|
182
|
-
|
|
174
|
+
# ★API での合流(gh api -X PUT …/pulls/N/merge)は便 fc22bc34 で deny へ移した
|
|
175
|
+
# (保護の迂回・えふさん確定 2026-09-18)→ test_bypass_deny.py。
|
|
183
176
|
'cd /srv/app && gh pr merge 12 --squash', # 複合コマンドでも自走
|
|
184
177
|
'bash -c "gh pr merge 12 --squash"', # 包んでも自走
|
|
185
178
|
'gh pr merge 12 --squash && git pull',
|
|
@@ -220,12 +213,12 @@ for _gd in (GuardDatalink({'url': 'http://x', 'token': 't'}, reachable=True),
|
|
|
220
213
|
out['hookSpecificOutput']['permissionDecision'], 'allow')
|
|
221
214
|
|
|
222
215
|
# ★マージを外しても、他の関門と危険は一切緩めていない(取り違え防止の回帰テスト)。
|
|
223
|
-
check('main 直 push
|
|
224
|
-
policy.decide_bash('git push origin main')['
|
|
216
|
+
check('main 直 push は deny(便 fc22bc34 で関門から移した)',
|
|
217
|
+
policy.decide_bash('git push origin main')['decision'], policy.DENY)
|
|
225
218
|
check('force push は deny のまま',
|
|
226
219
|
policy.decide_bash('git push --force origin main')['decision'], policy.DENY)
|
|
227
|
-
check('DB
|
|
228
|
-
policy.decide_bash('
|
|
220
|
+
check('DB実行(見分けられないもの)は関門のまま',
|
|
221
|
+
policy.decide_bash('createdb newdb')['gate'], policy.GATE_DB)
|
|
229
222
|
check('SQL DDL は関門のまま',
|
|
230
223
|
policy.decide_bash('run-sql "CREATE TABLE x (id int)"')['gate'], policy.GATE_DB)
|
|
231
224
|
check('本番反映は関門のまま',
|
|
@@ -566,12 +559,11 @@ check('枝への push は通常の文言',
|
|
|
566
559
|
summary_ja.summarize_bash('git push origin feat/main-fix'),
|
|
567
560
|
'作業内容をGitHubへ送ってよいですか')
|
|
568
561
|
# ★見出しは「関門に当たったセグメント」から作る(複合コマンドの先頭語 cd に引きずられない)。
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
'【お客さまの確認:データベースの変更】データベースの構造を変更してよいですか')
|
|
562
|
+
# ★main 直 push と本番 DB を直接変える道具は、便 fc22bc34 で関門から deny へ移した
|
|
563
|
+
# (カードは出ない)。見出しの作り方は、今も関門のままの操作で確かめる。
|
|
564
|
+
check('複合コマンドでも関門セグメントから見出し(公開)',
|
|
565
|
+
summary_ja.summarize_bash('cd /srv/app && npm publish', 'release'),
|
|
566
|
+
'【お客さまの確認:本番へ反映】部品を公開(配布)してよいですか')
|
|
575
567
|
|
|
576
568
|
|
|
577
569
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -663,7 +655,7 @@ check('保存先は session(設定を汚さない)', up[0]['destination'], '
|
|
|
663
655
|
|
|
664
656
|
# 関門には恒久許可を与えない。
|
|
665
657
|
fd = FakeDatalink('allow_always')
|
|
666
|
-
GATE_EV = {'tool_name': 'Bash', 'tool_input': {'command': '
|
|
658
|
+
GATE_EV = {'tool_name': 'Bash', 'tool_input': {'command': 'npm publish'},
|
|
667
659
|
'cwd': '/home/fshim/projects/conductor', 'session_id': 's1'}
|
|
668
660
|
out = permission_request_hook.decide(GATE_EV, cfg={'url': 'http://x', 'token': 't'}, datalink=fd)
|
|
669
661
|
check('関門に恒久許可を与えない',
|
|
@@ -693,7 +685,7 @@ check('送る payload に choices が入る(3択)',
|
|
|
693
685
|
|
|
694
686
|
# ★フェイルクローズ: 関門は「聞けない」とき deny を返す(委譲=素通りにしない)。
|
|
695
687
|
print('\n=== (g2) PermissionRequest フックのフェイルクローズ(関門のみ) ===')
|
|
696
|
-
GATE_PR_EV = {'tool_name': 'Bash', 'tool_input': {'command': '
|
|
688
|
+
GATE_PR_EV = {'tool_name': 'Bash', 'tool_input': {'command': 'npm publish'},
|
|
697
689
|
'cwd': '/home/fshim/projects/conductor', 'session_id': 's1'}
|
|
698
690
|
|
|
699
691
|
|