Add safe artifact migration and status fixes

This commit is contained in:
phamnazage-jpg
2026-05-25 10:48:04 +08:00
parent 5e76fb20d0
commit 497e5d91b4
10 changed files with 875 additions and 70 deletions

View File

@@ -135,8 +135,6 @@ EOF
PACK_PATH="/tmp/openai-pack" \
PROVIDER_ID="deepseek" \
HOST_API_KEY="host-key" \
REMOTE_PG_CONTAINER="fresh-pg" \
REMOTE_REDIS_CONTAINER="fresh-redis" \
MODE="partial" \
ACCESS_MODE="subscription" \
ACCESS_API_KEY="user-key" \
@@ -152,14 +150,17 @@ EOF
assert_contains "$hook_contents" "123:"
assert_contains "$hook_contents" "05a-batch-detail-pre-access.json:subscription"
local guide_contents stdout_contents
local guide_contents stdout_contents import_json
guide_contents="$(cat "$guide_file")"
stdout_contents="$(cat "$stdout_file")"
import_json="$(cat "$artifact_dir/05-import.json")"
assert_contains "$guide_contents" "清单 4必须分层留证据不可混用"
assert_contains "$guide_contents" "/api/v1/admin/accounts/:id/models 正确 ≠ /v1/models 正确"
assert_contains "$guide_contents" "/v1/models 正确 ≠ /v1/chat/completions 正确"
assert_contains "$guide_contents" "artifact security mode: safe"
assert_contains "$guide_contents" "repository-safe: yes"
assert_contains "$stdout_contents" "artifact guide: $artifact_dir/00-artifact-guide.txt"
assert_contains "$stdout_contents" "checklist layered evidence: see 05b-after-import-hook.stdout.txt / 05b-after-import-hook.stderr.txt"
assert_not_contains "$import_json" "host-key"
assert_not_contains "$import_json" "user-key"
}
run_test_check_deepseek_completion_split() {
@@ -236,28 +237,39 @@ Content-Type: text/event-stream
EOF
chmod +x "$fakebin/curl"
PATH="$fakebin:$PATH" ARTIFACT_DIR="$artifact_dir" HOST_BASE="http://host.example.com" HOST_MANAGED_KEY="managed-key" UPSTREAM_BASE="https://upstream.example.com/v1" UPSTREAM_API_KEY="upstream-key" MODEL="deepseek-v4-flash" bash "$ROOT_DIR/scripts/check_deepseek_completion_split.sh" >"$stdout_file"
PATH="$fakebin:$PATH" \
ARTIFACT_DIR="$artifact_dir" \
HOST_BASE="http://host.example.com" \
HOST_MANAGED_KEY="managed-key" \
UPSTREAM_BASE="https://upstream.example.com/v1" \
UPSTREAM_API_KEY="upstream-key" \
MODEL="deepseek-v4-flash" \
bash "$ROOT_DIR/scripts/check_deepseek_completion_split.sh" >"$stdout_file"
[[ -f "$summary_file" ]] || fail "missing summary file: $summary_file"
local summary stdout_contents
local summary stdout_contents host_headers upstream_headers
summary="$(cat "$summary_file")"
stdout_contents="$(cat "$stdout_file")"
host_headers="$(cat "$artifact_dir/01-host-models.headers.txt")"
upstream_headers="$(cat "$artifact_dir/05-upstream-chat.headers.txt")"
assert_contains "$summary" '"classification": "host_compatibility_gap"'
assert_contains "$summary" '"host_models_status": 200'
assert_contains "$summary" '"host_chat_status": 502'
assert_contains "$summary" '"upstream_chat_status": 200'
assert_contains "$summary" '"upstream_chat_content_type": "text/event-stream"'
assert_contains "$stdout_contents" '"classification": "host_compatibility_gap"'
assert_not_contains "$host_headers" "Authorization:"
assert_not_contains "$upstream_headers" "Authorization:"
}
run_test_import_remote43_provider_subscription_prep() {
local tmpdir fakebin artifact_dir ssh_log psql_sql pack_dir
local tmpdir fakebin artifact_dir ssh_log summary_file pack_dir
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' RETURN
fakebin="$tmpdir/bin"
artifact_dir="$tmpdir/artifacts"
ssh_log="$artifact_dir/ssh-log.txt"
psql_sql="$artifact_dir/prep.sql"
summary_file="$artifact_dir/run/05-subscription-access-prep.summary.json"
pack_dir="$tmpdir/pack"
mkdir -p "$fakebin"
mkdir -p "$pack_dir/providers"
@@ -349,7 +361,7 @@ if [[ "$cmd" == *'***'* ]]; then
echo "unexpected redacted auth placeholder in ssh command: $cmd" >&2
exit 1
fi
case "$cmd" in
case "$cmd" in
"sudo -n docker ps --format '{{.Names}}\t{{.Ports}}'"*)
printf '%s\n' 'sub2api-fresh-deepseek-20260519_115244-app-1 127.0.0.1:18093->8080/tcp'
;;
@@ -441,9 +453,8 @@ fi
;;
*"sudo -n docker exec -i sub2api-fresh-deepseek-20260519_115244-postgres-1 psql -U sub2api -d sub2api"*)
CMD="$cmd" LOG_DIR="$log_dir" python3 - <<'PY'
import base64, os, re, pathlib, sys
import base64, os, re, sys
cmd = os.environ['CMD']
log_dir = pathlib.Path(os.environ['LOG_DIR'])
match = re.search(r"printf '%s' '([^']+)' \| base64 -d", cmd)
if not match:
raise SystemExit(f'failed to extract base64 payload from: {cmd}')
@@ -453,13 +464,10 @@ if "select id from users where email like 'relay-sub-%@sub2api.local' and not ex
elif "select k.key from users u join api_keys k on k.user_id=u.id" in sql and "not exists" in sql:
print('')
elif "UPDATE users" in sql and "INSERT INTO user_subscriptions" in sql:
log_dir.joinpath('prep.sql').write_text(sql, encoding='utf-8')
print('')
elif "INSERT INTO users" in sql and "INSERT INTO api_keys" in sql:
log_dir.joinpath('create-user.sql').write_text(sql, encoding='utf-8')
print('84\tuser-key-fresh')
elif "SELECT json_build_object(" in sql:
log_dir.joinpath('group-state.sql').write_text(sql, encoding='utf-8')
print('{"group_id":7,"subscription":{"status":"active"},"key":{"group_id":7}}')
else:
print('')
@@ -493,25 +501,38 @@ EOF
SKIP_ROLLBACK=1 \
bash "$ROOT_DIR/scripts/import_remote43_provider.sh" deepseek gpt-4 UPSTREAM_KEY >/dev/null
[[ -f "$psql_sql" ]] || fail "prep sql was not captured"
local prep_sql
prep_sql="$(cat "$psql_sql")"
assert_contains "$prep_sql" "UPDATE users"
assert_contains "$prep_sql" "UPDATE api_keys"
assert_contains "$prep_sql" "INSERT INTO user_subscriptions"
assert_contains "$prep_sql" "group_id = 7"
local runtime_context invalidation_log
[[ -f "$summary_file" ]] || fail "prep summary was not captured"
local prep_summary
prep_summary="$(cat "$summary_file")"
assert_contains "$prep_summary" '"subscription_group_id": 7'
assert_contains "$prep_summary" '"min_balance": 10'
assert_contains "$prep_summary" '"subscription_days": 30'
assert_not_contains "$prep_summary" '"prefix": "user-key'
local runtime_context invalidation_log subscription_state models_body chat_body upstream_models upstream_chat summary_json local_key_source
runtime_context="$(cat "$artifact_dir/run/01-runtime-context.json")"
assert_contains "$runtime_context" '"crm_host_base": "http://127.0.0.1:18093"'
assert_contains "$runtime_context" '"remote_host_base": "http://127.0.0.1:18093"'
invalidation_log="$(cat "$artifact_dir/run/07-redis-targeted-invalidation.txt")"
assert_contains "$invalidation_log" "auth_cache_key=apikey:auth:"
assert_contains "$invalidation_log" "balance_cache_key=billing:balance:84"
assert_contains "$invalidation_log" "subscription_cache_key=billing:sub:84:7"
local subscription_state models_body chat_body upstream_models upstream_chat summary_json
assert_contains "$runtime_context" '"subscription_user_id_hash"'
assert_not_contains "$runtime_context" '"subscription_user_id":'
assert_not_contains "$runtime_context" '"managed_user_email":'
local_key_source="$(cat "$artifact_dir/run/00-local-key-source.json")"
assert_contains "$local_key_source" '"fingerprint"'
assert_not_contains "$local_key_source" '"upstream_key":'
invalidation_log="$(cat "$artifact_dir/run/07-redis-targeted-invalidation.json")"
assert_contains "$invalidation_log" '"auth_cache_invalidated": true'
assert_contains "$invalidation_log" '"balance_cache_invalidated": true'
assert_contains "$invalidation_log" '"subscription_cache_invalidated": true'
assert_not_contains "$invalidation_log" 'apikey:auth:'
subscription_state="$(cat "$artifact_dir/run/08-subscription-group-state.json")"
assert_contains "$subscription_state" '"group_id":7'
assert_contains "$subscription_state" '"status":"active"'
assert_contains "$subscription_state" '"group_id": 7'
assert_contains "$subscription_state" '"status": "active"'
assert_contains "$subscription_state" '"redacted"'
assert_not_contains "$subscription_state" '"key": "'
models_body="$(cat "$artifact_dir/run/10-models.body.json")"
chat_body="$(cat "$artifact_dir/run/12-chat.body.json")"
upstream_models="$(cat "$artifact_dir/run/18-upstream-models.body.json")"
@@ -531,11 +552,100 @@ EOF
assert_contains "$ssh_contents" "http://127.0.0.1:18093/v1/chat/completions"
assert_not_contains "$ssh_contents" "http://127.0.0.1:18087/v1/models"
assert_not_contains "$ssh_contents" "http://127.0.0.1:18087/v1/chat/completions"
assert_not_contains "$ssh_contents" "user-key"
}
run_test_migrate_historical_artifacts() {
local tmpdir src_root sensitive_root target_dir
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' RETURN
src_root="$tmpdir/artifacts/real-host-acceptance"
sensitive_root="$tmpdir/artifacts/real-host-acceptance-sensitive"
target_dir="$src_root/20260522_foo"
mkdir -p "$target_dir"
cat > "$target_dir/00-local-key-source.json" <<'EOF'
{"source":"env:UPSTREAM_KEY","provider_id":"deepseek","upstream_key_prefix":"sk-live-secret","upstream_key_suffix":"cret42"}
EOF
cat > "$target_dir/01-runtime-context.json" <<'EOF'
{"subscription_user_id":"42","subscription_user_key_prefix":"user-key-secr","managed_user_email":"relay-sub-abc@sub2api.local","managed_probe_key_prefix":"sk-relay-secret-123456","crm_host_base":"http://127.0.0.1:18093","remote_host_base":"http://127.0.0.1:18093"}
EOF
cat > "$target_dir/05-subscription-access-prep.sql" <<'EOF'
BEGIN;
UPDATE api_keys SET group_id = 7 WHERE key = 'user-key-secret';
COMMIT;
EOF
cat > "$target_dir/07-redis-targeted-invalidation.txt" <<'EOF'
auth_cache_key=apikey:auth:abcd
balance_cache_key=billing:balance:42
subscription_cache_key=billing:sub:42:7
3
EOF
cat > "$target_dir/08-subscription-group-state.json" <<'EOF'
{"group_id":7,"subscription":{"user_id":42,"status":"active"},"key":{"id":9,"group_id":7,"status":"active","key":"user-key-secret"}}
EOF
cat > "$target_dir/09-models.headers.txt" <<'EOF'
HTTP/1.1 200 OK
Authorization: Bearer managed-secret
Content-Type: application/json
EOF
cat > "$target_dir/00-managed-key.txt" <<'EOF'
sk-managed-secret
EOF
cat > "$target_dir/00-managed-key-corrected.txt" <<'EOF'
sk-managed-secret-corrected
EOF
cat > "$target_dir/00-raw-user-key.txt" <<'EOF'
sk-user-secret
EOF
cat > "$target_dir/summary.json" <<'EOF'
{"provider_id":"deepseek","subscription_user_id":"24","gateway_key_prefix":"sk-deepseek-","host_account":{"data":{"credentials":{"api_key":"sk-live-123456"}}}}
EOF
cat > "$target_dir/99-semantic-summary.json" <<'EOF'
{"raw_user_id":"2","raw_key":"sk-raw-probe-20260523b","requested_probe_api_key":"sk-raw-probe-20260523b"}
EOF
cat > "$target_dir/05a-batch-detail-pre-access.json" <<'EOF'
{"access_closures":[{"DetailsJSON":"{\"requested_probe_api_key\":\"sk-raw-probe-20260523b\",\"subscription_users\":[\"crm-user\"]}"}]}
EOF
python3 "$ROOT_DIR/scripts/migrate_historical_artifacts.py" "$src_root" >/dev/null
local migrated_runtime migrated_key_source migrated_invalidation migrated_group_state headers_text summary_json semantic_json details_json
migrated_runtime="$(cat "$target_dir/01-runtime-context.json")"
migrated_key_source="$(cat "$target_dir/00-local-key-source.json")"
migrated_invalidation="$(cat "$target_dir/07-redis-targeted-invalidation.json")"
migrated_group_state="$(cat "$target_dir/08-subscription-group-state.json")"
headers_text="$(cat "$target_dir/09-models.headers.txt")"
summary_json="$(cat "$target_dir/summary.json")"
semantic_json="$(cat "$target_dir/99-semantic-summary.json")"
details_json="$(cat "$target_dir/05a-batch-detail-pre-access.json")"
assert_contains "$migrated_runtime" '"subscription_user_id_hash"'
assert_not_contains "$migrated_runtime" '"subscription_user_id":'
assert_not_contains "$migrated_runtime" '"managed_user_email":'
assert_contains "$migrated_key_source" '"redacted"'
assert_not_contains "$migrated_key_source" 'upstream_key_prefix'
assert_contains "$migrated_invalidation" '"auth_cache_invalidated": true'
assert_not_contains "$migrated_invalidation" 'apikey:auth:'
assert_contains "$migrated_group_state" '"redacted"'
assert_not_contains "$migrated_group_state" 'user-key-secret'
assert_not_contains "$headers_text" 'Authorization:'
assert_contains "$summary_json" '"api_key": {'
assert_not_contains "$summary_json" 'sk-live-123456'
assert_contains "$semantic_json" '"raw_key": {'
assert_not_contains "$semantic_json" 'sk-raw-probe-20260523b'
assert_contains "$details_json" '\"requested_probe_api_key\": {'
assert_not_contains "$details_json" 'sk-raw-probe-20260523b'
[[ -f "$target_dir/05-subscription-access-prep.summary.json" ]] || fail "sql summary was not created"
[[ -f "$sensitive_root/20260522_foo/00-managed-key.txt" ]] || fail "managed key was not moved to sensitive mirror"
[[ -f "$sensitive_root/20260522_foo/00-managed-key-corrected.txt" ]] || fail "managed key corrected file was not moved to sensitive mirror"
[[ -f "$sensitive_root/20260522_foo/05-subscription-access-prep.sql" ]] || fail "sql file was not moved to sensitive mirror"
}
run_test_build_subscription_access_prep_sql
run_test_real_host_acceptance_after_import_hook
run_test_check_deepseek_completion_split
run_test_import_remote43_provider_subscription_prep
run_test_migrate_historical_artifacts
echo "PASS: real host script regression checks"