@@ -23,7 +23,7 @@ echo '{}' > package.json
2323git add -A && git commit -q -m " init"
2424
2525# 1. SQLite DB created after first run
26- echo " [1/7 ] SQLite DB creation..."
26+ echo " [1/10 ] SQLite DB creation..."
2727if [ -n " ${ANTHROPIC_API_KEY:- } " ]; then
2828 altimate_run " db-create" " say hello" || true
2929 # Find the DB — could be opencode.db, opencode-latest.db, or opencode-{channel}.db
4242fi
4343
4444# 2. WAL mode enabled
45- echo " [2/7 ] WAL mode..."
45+ echo " [2/10 ] WAL mode..."
4646if [ -n " $DB_PATH " ] && [ -f " $DB_PATH " ] && command -v sqlite3 > /dev/null 2>&1 ; then
4747 WAL_MODE=$( sqlite3 " $DB_PATH " " PRAGMA journal_mode;" 2> /dev/null || echo " unknown" )
4848 assert_eq " $WAL_MODE " " wal" " WAL mode enabled"
5151fi
5252
5353# 3. Session persisted
54- echo " [3/7 ] Session persistence..."
54+ echo " [3/10 ] Session persistence..."
5555if [ -n " $DB_PATH " ] && [ -f " $DB_PATH " ] && command -v sqlite3 > /dev/null 2>&1 ; then
5656 SESSION_COUNT=$( sqlite3 " $DB_PATH " " SELECT count(*) FROM session;" 2> /dev/null || echo " 0" )
5757 assert_ge " $SESSION_COUNT " 1 " session persisted (got $SESSION_COUNT )"
6060fi
6161
6262# 4. Session continue (DB survives restart)
63- echo " [4/7 ] Session continue..."
63+ echo " [4/10 ] Session continue..."
6464if [ -n " ${ANTHROPIC_API_KEY:- } " ]; then
6565 altimate_run " continue" --continue " what was my last message" || true
6666 assert_not_contains " $( get_output continue) " " TIMEOUT" " session continue works"
6969fi
7070
7171# 5. Compaction doesn't crash (best-effort — seed if fixture available)
72- echo " [5/7 ] Compaction resilience..."
72+ echo " [5/10 ] Compaction resilience..."
7373if [ -n " $DB_PATH " ] && [ -f " $SCRIPT_DIR /fixtures/compaction-session.sql" ] && command -v sqlite3 > /dev/null 2>&1 ; then
7474 sqlite3 " $DB_PATH " < " $SCRIPT_DIR /fixtures/compaction-session.sql" 2> /dev/null || true
7575 if [ -n " ${ANTHROPIC_API_KEY:- } " ]; then
9090 skip_test " Compaction resilience" " fixture or sqlite3 not available"
9191fi
9292
93- # 6. Graceful on missing provider key
94- echo " [6/7] Missing API key handling..."
95- SAVED_KEY=" ${ANTHROPIC_API_KEY:- } "
96- unset ANTHROPIC_API_KEY
97- OUTPUT=$( timeout 10 altimate run --max-turns 1 --yolo " hello" 2>&1 || true)
98- # Should get a clean error, not an unhandled exception / stack trace
99- assert_not_contains " $OUTPUT " " TypeError" " no TypeError on missing key"
100- assert_not_contains " $OUTPUT " " Cannot read properties" " no unhandled error on missing key"
101- if [ -n " $SAVED_KEY " ]; then
102- export ANTHROPIC_API_KEY=" $SAVED_KEY "
103- fi
104-
105- # 7. Config backwards compatibility
106- echo " [7/7] Config backwards compat..."
93+ # 6. Config backwards compatibility
94+ echo " [6/10] Config backwards compat..."
10795CONFIG_DIR=" ${XDG_CONFIG_HOME:- $HOME / .config} /altimate-code"
10896mkdir -p " $CONFIG_DIR "
10997if [ -f " $SCRIPT_DIR /fixtures/old-config.json" ]; then
119107 skip_test " Config backwards compat" " old-config.json fixture not found"
120108fi
121109
122- # 8 . Broken config graceful handling
123- echo " [8/8 ] Broken config handling..."
110+ # 7 . Broken config graceful handling
111+ echo " [7/10 ] Broken config handling..."
124112if [ -f " $SCRIPT_DIR /fixtures/broken-config.json" ]; then
125113 cp " $SCRIPT_DIR /fixtures/broken-config.json" " $CONFIG_DIR /opencode.json"
126114 if [ -n " ${ANTHROPIC_API_KEY:- } " ]; then
@@ -135,6 +123,71 @@ else
135123 skip_test " Broken config handling" " broken-config.json fixture not found"
136124fi
137125
126+ # 8. Yolo deny enforcement — deny rules block even with --yolo (#372, #377)
127+ echo " [8/10] Yolo deny enforcement..."
128+ if [ -n " ${ANTHROPIC_API_KEY:- } " ]; then
129+ # Create a config with an explicit deny rule
130+ DENY_CONFIG_DIR=$( mktemp -d /tmp/sanity-deny-config-XXXXXX)
131+ mkdir -p " $DENY_CONFIG_DIR "
132+ cat > " $DENY_CONFIG_DIR /opencode.jsonc" << 'DENYEOF '
133+ {
134+ "permission": {
135+ "bash": {
136+ "*": "allow",
137+ "DROP DATABASE *": "deny",
138+ "drop database *": "deny"
139+ }
140+ }
141+ }
142+ DENYEOF
143+ # Run with yolo and ask it to execute a denied command
144+ DENY_OUTPUT=$( XDG_CONFIG_HOME=" $DENY_CONFIG_DIR " timeout 30 altimate run --max-turns 2 --yolo --format json \
145+ " run the bash command: DROP DATABASE production" 2>&1 || true)
146+ # The output should NOT contain "DROP DATABASE production" as a successfully executed command
147+ # It SHOULD contain "denied" or refuse the command
148+ if echo " $DENY_OUTPUT " | grep -qi " denied\|blocked\|not allowed\|permission.*deny" ; then
149+ echo " PASS: yolo deny rule blocked dangerous command"
150+ PASS_COUNT=$(( PASS_COUNT + 1 ))
151+ elif echo " $DENY_OUTPUT " | grep -qi " DROP DATABASE production.*success\|executed.*DROP DATABASE" ; then
152+ echo " FAIL: yolo mode bypassed deny rule — dangerous command executed"
153+ FAIL_COUNT=$(( FAIL_COUNT + 1 ))
154+ else
155+ # The model may have refused on its own or rephrased — that's acceptable
156+ echo " PASS: yolo deny rule (command not executed)"
157+ PASS_COUNT=$(( PASS_COUNT + 1 ))
158+ fi
159+ rm -rf " $DENY_CONFIG_DIR "
160+ else
161+ skip_test " Yolo deny enforcement" " no ANTHROPIC_API_KEY"
162+ fi
163+
164+ # 9. Missing API key handling (no unhandled exceptions)
165+ echo " [9/10] Missing API key handling..."
166+ SAVED_KEY=" ${ANTHROPIC_API_KEY:- } "
167+ unset ANTHROPIC_API_KEY
168+ OUTPUT=$( timeout 10 altimate run --max-turns 1 --yolo " hello" 2>&1 || true)
169+ assert_not_contains " $OUTPUT " " TypeError" " no TypeError on missing key"
170+ assert_not_contains " $OUTPUT " " Cannot read properties" " no unhandled error on missing key"
171+ if [ -n " $SAVED_KEY " ]; then
172+ export ANTHROPIC_API_KEY=" $SAVED_KEY "
173+ fi
174+
175+ # 10. No internet — graceful error, not blank screen (#181)
176+ echo " [10/10] No internet graceful handling..."
177+ # Use an unreachable DNS to simulate no internet (timeout quickly)
178+ NO_NET_OUTPUT=$( timeout 15 env https_proxy=http://192.0.2.1:1 http_proxy=http://192.0.2.1:1 \
179+ altimate run --max-turns 1 --yolo " hello" 2>&1 || true)
180+ assert_not_contains " $NO_NET_OUTPUT " " TypeError" " no TypeError without internet"
181+ assert_not_contains " $NO_NET_OUTPUT " " Cannot read properties" " no unhandled error without internet"
182+ # Should get some kind of connection/auth error, not a blank hang
183+ if [ -z " $NO_NET_OUTPUT " ]; then
184+ echo " FAIL: no output at all without internet (blank screen)"
185+ FAIL_COUNT=$(( FAIL_COUNT + 1 ))
186+ else
187+ echo " PASS: produced output without internet ($( echo " $NO_NET_OUTPUT " | wc -l) lines)"
188+ PASS_COUNT=$(( PASS_COUNT + 1 ))
189+ fi
190+
138191# Cleanup
139192rm -rf " $WORKDIR "
140193
0 commit comments