direxio-deployer 0.1.0 → 0.1.1
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.md +3 -1
- package/README_zh.md +3 -1
- package/SKILL.md +2 -2
- package/bin/direxio-deployer.mjs +1 -2
- package/package.json +2 -3
- package/references/deployment-lessons.md +5 -7
- package/references/deployment-workflow.md +1 -1
- package/references/tooling.md +11 -12
- package/references/user-journey.md +2 -2
- package/references/voip-turn-runbook.md +2 -2
- package/references/windows-deployment-notes.md +2 -1
- package/scripts/destroy.sh +24 -43
- package/scripts/json.mjs +841 -0
- package/scripts/lib/aws.sh +5 -1
- package/scripts/lib/json.sh +114 -0
- package/scripts/lib/operation_report.sh +8 -195
- package/scripts/lib/ops.sh +8 -21
- package/scripts/lib/state.sh +18 -44
- package/scripts/mcp-tools-list.mjs +21 -4
- package/scripts/orchestrate.sh +147 -249
- package/scripts/phases/s3_provision.sh +5 -10
- package/scripts/phases/s5_init_tokens.sh +7 -17
- package/scripts/phases/s6_wire_local.sh +9 -35
- package/scripts/phases/s7_verify_e2e.sh +5 -5
- package/scripts/pricing-estimate.sh +36 -80
- package/tests/aws_credentials_test.sh +0 -139
- package/tests/connect_daemon_runtime_check_test.sh +0 -120
- package/tests/default_paths_test.sh +0 -58
- package/tests/destroy_local_bridge_test.sh +0 -154
- package/tests/destroy_root_identity_test.sh +0 -91
- package/tests/destroy_route53_zone_test.sh +0 -80
- package/tests/domain_authoritative_dns_test.sh +0 -49
- package/tests/mcp_doctor_runtime_check_test.sh +0 -86
- package/tests/mcp_smoke_runtime_check_test.sh +0 -121
- package/tests/mcp_tools_runtime_check_test.sh +0 -123
- package/tests/npm_skill_distribution_test.sh +0 -95
- package/tests/operation_report_test.sh +0 -258
- package/tests/orchestrate_status_recovery_test.sh +0 -91
- package/tests/phase_timeout_test.sh +0 -88
- package/tests/pricing_estimate_test.sh +0 -159
- package/tests/render_userdata_remote_nodes_test.sh +0 -40
- package/tests/root_volume_tracking_test.sh +0 -41
- package/tests/route53_overwrite_guard_test.sh +0 -86
- package/tests/route53_zone_auto_create_test.sh +0 -66
- package/tests/runtime_summary_check_test.sh +0 -203
- package/tests/s6_wire_local_test.sh +0 -405
- package/tests/skill_structure_test.sh +0 -298
- package/tests/update_reset_ops_test.sh +0 -230
- package/tests/user_confirmation_gates_test.sh +0 -152
package/scripts/orchestrate.sh
CHANGED
|
@@ -23,9 +23,7 @@ set -uo pipefail
|
|
|
23
23
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
|
24
24
|
P2P_INSTALL_SCRIPTS_DIR="$HERE"
|
|
25
25
|
|
|
26
|
-
# Prefer workspace-local tools when present.
|
|
27
|
-
# into .tools/bin/jq.exe by the operator/system and is discoverable from
|
|
28
|
-
# Git Bash/MSYS only when this path is prepended.
|
|
26
|
+
# Prefer workspace-local tools when present.
|
|
29
27
|
REPO_ROOT=$(cd "$HERE/.." && pwd)
|
|
30
28
|
if [ -d "$REPO_ROOT/.tools/bin" ]; then
|
|
31
29
|
PATH="$REPO_ROOT/.tools/bin:$PATH"
|
|
@@ -58,17 +56,12 @@ phase_file() {
|
|
|
58
56
|
# Dependency check.
|
|
59
57
|
check_deps() {
|
|
60
58
|
local b missing=""
|
|
61
|
-
for b in aws
|
|
59
|
+
for b in aws ssh scp curl; do
|
|
62
60
|
command -v "$b" >/dev/null 2>&1 || missing="$missing $b"
|
|
63
61
|
done
|
|
64
62
|
[ -z "$missing" ] && return 0
|
|
65
63
|
|
|
66
64
|
warn "Missing dependencies:$missing"
|
|
67
|
-
case " $missing " in
|
|
68
|
-
*" jq "*)
|
|
69
|
-
warn "jq is required for state.json. If this workspace has .tools/bin/jq.exe, run from a POSIX shell that can see that path."
|
|
70
|
-
;;
|
|
71
|
-
esac
|
|
72
65
|
case " $missing " in
|
|
73
66
|
*" aws "*)
|
|
74
67
|
warn "Install AWS CLI v2 and configure credentials first:"
|
|
@@ -108,9 +101,9 @@ cmd_status_inventory() {
|
|
|
108
101
|
[ -f "$state" ] || continue
|
|
109
102
|
found=1
|
|
110
103
|
service_dir=${state%/state.json}
|
|
111
|
-
domain=$(
|
|
112
|
-
phase=$(
|
|
113
|
-
instance=$(
|
|
104
|
+
domain=$(json_get "$state" domain)
|
|
105
|
+
phase=$(json_get "$state" phase)
|
|
106
|
+
instance=$(json_get "$state" resources.instance_id)
|
|
114
107
|
if STATE_JSON="$state" first_unfinished_phase >/dev/null 2>&1; then
|
|
115
108
|
current=$(STATE_JSON="$state" first_unfinished_phase)
|
|
116
109
|
else
|
|
@@ -287,7 +280,7 @@ cmd_status() {
|
|
|
287
280
|
printf " %-20s %s\n" "$p" "$(phase_status "$p")"
|
|
288
281
|
done
|
|
289
282
|
echo "-- resources --"
|
|
290
|
-
|
|
283
|
+
json_entries "$STATE_JSON" resources | sed 's/^/ /'
|
|
291
284
|
print_recovery_summary "$current"
|
|
292
285
|
}
|
|
293
286
|
|
|
@@ -320,10 +313,10 @@ print_delivery() {
|
|
|
320
313
|
install_mode=$(state_get agent_install_mode)
|
|
321
314
|
install_status=$(state_get agent_install_status)
|
|
322
315
|
install_command=$(state_get agent_install_command)
|
|
323
|
-
runtime_summary=$(
|
|
324
|
-
app_gate=$(
|
|
325
|
-
real_chat_gate=$(
|
|
326
|
-
agent_runtime_gate=$(
|
|
316
|
+
runtime_summary=$(json_get "$STATE_JSON" runtime_checks.summary.status "not_run")
|
|
317
|
+
app_gate=$(json_get "$STATE_JSON" user_confirmations.app_initialization.status "pending_user_confirmation")
|
|
318
|
+
real_chat_gate=$(json_get "$STATE_JSON" user_confirmations.real_chat.status "pending_user_confirmation")
|
|
319
|
+
agent_runtime_gate=$(json_get "$STATE_JSON" user_confirmations.agent_mcp_runtime.status "pending_runtime_confirmation")
|
|
327
320
|
echo
|
|
328
321
|
echo -e "\033[32m========== Automated Deployment Gates Passed ==========\033[0m"
|
|
329
322
|
echo " App domain : $domain"
|
|
@@ -391,10 +384,10 @@ ensure_cost_estimate() {
|
|
|
391
384
|
fi
|
|
392
385
|
|
|
393
386
|
if output=$(bash "$HERE/pricing-estimate.sh" "${args[@]}" 2>/dev/null); then
|
|
394
|
-
status=$(printf '%s\n' "$output" |
|
|
395
|
-
total=$(printf '%s\n' "$output" |
|
|
396
|
-
region=$(printf '%s\n' "$output" |
|
|
397
|
-
instance_type=$(printf '%s\n' "$output" |
|
|
387
|
+
status=$(printf '%s\n' "$output" | json_stdin_get pricing_status "unknown" 2>/dev/null)
|
|
388
|
+
total=$(printf '%s\n' "$output" | json_stdin_get total_monthly_usd "unknown" 2>/dev/null)
|
|
389
|
+
region=$(printf '%s\n' "$output" | json_stdin_get region "unknown" 2>/dev/null)
|
|
390
|
+
instance_type=$(printf '%s\n' "$output" | json_stdin_get components.ec2_instance.instance_type "unknown" 2>/dev/null)
|
|
398
391
|
log "Cost estimate recorded (status=${status:-unknown}, region=${region:-unknown}, instance=${instance_type:-unknown}, monthly_usd≈${total:-unknown})."
|
|
399
392
|
if [ "$status" = "fallback" ]; then
|
|
400
393
|
warn "AWS Pricing API was unavailable or incomplete; cost_estimate uses conservative fallback values."
|
|
@@ -439,7 +432,7 @@ ensure_production_domain_selected() {
|
|
|
439
432
|
state_domain=$(domain_normalize "$state_domain")
|
|
440
433
|
state_mode=$(state_get domain_mode)
|
|
441
434
|
env_domain=$(domain_normalize "${DOMAIN:-}")
|
|
442
|
-
confirmed=$(
|
|
435
|
+
confirmed=$(json_get "$STATE_JSON" domain_confirmed_irreversible false)
|
|
443
436
|
|
|
444
437
|
if [ -n "$env_domain" ] && [ -n "$state_domain" ] && [ "$env_domain" != "$state_domain" ]; then
|
|
445
438
|
warn "Deployment blocked: current state is bound to DOMAIN=$state_domain, but this run passed DOMAIN=${env_domain}."
|
|
@@ -484,22 +477,22 @@ ensure_production_domain_selected() {
|
|
|
484
477
|
guard_existing_state() {
|
|
485
478
|
[ -f "$STATE_JSON" ] || return 0
|
|
486
479
|
local resources_count confirmed action
|
|
487
|
-
resources_count=$(
|
|
480
|
+
resources_count=$(json_length "$STATE_JSON" resources)
|
|
488
481
|
[ "$resources_count" -eq 0 ] && return 0
|
|
489
|
-
if [ "$(
|
|
482
|
+
if [ "$(json_get "$STATE_JSON" domain_mode)" = "ec2" ]; then
|
|
490
483
|
warn "Found legacy temporary-domain deployment state (domain_mode=ec2). Production deployment no longer supports resuming this mode."
|
|
491
484
|
warn "Destroy and rebuild, or use a new service directory:"
|
|
492
485
|
warn " P2P_EXISTING_STATE_ACTION=destroy bash $0"
|
|
493
486
|
warn " DOMAIN=__DOMAIN__ DOMAIN_MODE=user CONFIRM_DOMAIN_BINDING=1 bash $0"
|
|
494
487
|
return 2
|
|
495
488
|
fi
|
|
496
|
-
confirmed=$(
|
|
489
|
+
confirmed=$(json_get "$STATE_JSON" existing_state_confirmed false)
|
|
497
490
|
[ "$confirmed" = "true" ] && return 0
|
|
498
491
|
|
|
499
492
|
action=${P2P_EXISTING_STATE_ACTION:-}
|
|
500
493
|
if [ -z "$action" ] && [ -t 0 ]; then
|
|
501
494
|
warn "Found existing deployment state with recorded AWS resources:"
|
|
502
|
-
|
|
495
|
+
json_entries "$STATE_JSON" resources | sed 's/^/ /' >&2
|
|
503
496
|
warn "Choose: continue=resume / destroy=destroy and rebuild / abort=stop now"
|
|
504
497
|
printf "Action [abort]: " >&2
|
|
505
498
|
read -r action
|
|
@@ -601,7 +594,7 @@ cmd_confirm() {
|
|
|
601
594
|
warn "DIREXIO_CONFIRM_EVIDENCE is too short; provide a concrete user/runtime evidence note."
|
|
602
595
|
return 1
|
|
603
596
|
fi
|
|
604
|
-
runtime_summary_status=$(
|
|
597
|
+
runtime_summary_status=$(json_get "$STATE_JSON" runtime_checks.summary.status "not_run")
|
|
605
598
|
runtime_probe_confirmed=false
|
|
606
599
|
if [ "$gate" = "agent_mcp_runtime" ]; then
|
|
607
600
|
if [ "$runtime_summary_status" != "passed" ]; then
|
|
@@ -614,21 +607,19 @@ cmd_confirm() {
|
|
|
614
607
|
fi
|
|
615
608
|
runtime_probe_confirmed=true
|
|
616
609
|
fi
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
status
|
|
620
|
-
ts
|
|
621
|
-
evidence
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
--arg runtime_summary_status "$runtime_summary_status" \
|
|
631
|
-
--arg runtime_probe_confirmed "$runtime_probe_confirmed"
|
|
610
|
+
if [ "$gate" = "agent_mcp_runtime" ]; then
|
|
611
|
+
state_set_object "user_confirmations.$gate" \
|
|
612
|
+
status=confirmed \
|
|
613
|
+
"ts=$(_now)" \
|
|
614
|
+
"evidence=$evidence" \
|
|
615
|
+
"runtime_summary_status=$runtime_summary_status" \
|
|
616
|
+
"runtime_probe_confirmed=$runtime_probe_confirmed"
|
|
617
|
+
else
|
|
618
|
+
state_set_object "user_confirmations.$gate" \
|
|
619
|
+
status=confirmed \
|
|
620
|
+
"ts=$(_now)" \
|
|
621
|
+
"evidence=$evidence"
|
|
622
|
+
fi
|
|
632
623
|
echo "confirmed gate: $gate"
|
|
633
624
|
}
|
|
634
625
|
|
|
@@ -638,10 +629,11 @@ cmd_verify_mcp_doctor() {
|
|
|
638
629
|
return 1
|
|
639
630
|
}
|
|
640
631
|
|
|
641
|
-
local credentials mcp_cmd node_id out err report token_status
|
|
642
|
-
credentials=$(
|
|
643
|
-
|
|
644
|
-
|
|
632
|
+
local credentials mcp_cmd node_id out err report token_status report_domain report_room
|
|
633
|
+
credentials=$(json_get "$STATE_JSON" agent_credentials_file)
|
|
634
|
+
[ -n "$credentials" ] || credentials=$(json_get "$STATE_JSON" mcp_credentials_file)
|
|
635
|
+
mcp_cmd=$(json_get "$STATE_JSON" mcp_command "direxio-mcp")
|
|
636
|
+
node_id=$(json_get "$STATE_JSON" agent_node_id)
|
|
645
637
|
[ -n "$credentials" ] || {
|
|
646
638
|
warn "mcp doctor check requires agent_credentials_file or mcp_credentials_file in state.json"
|
|
647
639
|
return 1
|
|
@@ -651,45 +643,34 @@ cmd_verify_mcp_doctor() {
|
|
|
651
643
|
out=$(mktemp)
|
|
652
644
|
err=$(mktemp)
|
|
653
645
|
if ! DIREXIO_CREDENTIALS_FILE="$credentials" DIREXIO_AGENT_NODE_ID="$node_id" bash -c "$mcp_cmd doctor --json" > "$out" 2> "$err"; then
|
|
654
|
-
|
|
655
|
-
.runtime_checks.mcp_doctor = {
|
|
656
|
-
status: "failed",
|
|
657
|
-
ts: $ts,
|
|
658
|
-
evidence: "direxio-mcp doctor failed"
|
|
659
|
-
}
|
|
660
|
-
' --arg ts "$(_now)"
|
|
646
|
+
state_set_object runtime_checks.mcp_doctor status=failed "ts=$(_now)" "evidence=direxio-mcp doctor failed"
|
|
661
647
|
cat "$err" >&2
|
|
662
648
|
rm -f "$out" "$err"
|
|
663
649
|
return 1
|
|
664
650
|
fi
|
|
665
|
-
if !
|
|
666
|
-
|
|
667
|
-
.runtime_checks.mcp_doctor = {
|
|
668
|
-
status: "failed",
|
|
669
|
-
ts: $ts,
|
|
670
|
-
evidence: "direxio-mcp doctor returned non-json output"
|
|
671
|
-
}
|
|
672
|
-
' --arg ts "$(_now)"
|
|
651
|
+
if ! json_valid "$out" >/dev/null 2>&1; then
|
|
652
|
+
state_set_object runtime_checks.mcp_doctor status=failed "ts=$(_now)" "evidence=direxio-mcp doctor returned non-json output"
|
|
673
653
|
rm -f "$out" "$err"
|
|
674
654
|
return 1
|
|
675
655
|
fi
|
|
676
656
|
report=$(cat "$out")
|
|
677
|
-
token_status=$(printf '%s\n' "$report" |
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
657
|
+
token_status=$(printf '%s\n' "$report" | json_stdin_get token)
|
|
658
|
+
if [ "$token_status" = "redacted" ]; then
|
|
659
|
+
token_status=redacted
|
|
660
|
+
elif [ -n "$token_status" ]; then
|
|
661
|
+
token_status=present_redacted
|
|
662
|
+
else
|
|
663
|
+
token_status=missing
|
|
664
|
+
fi
|
|
665
|
+
report_domain=$(json_get "$out" domain)
|
|
666
|
+
report_room=$(json_get "$out" agent_room_id)
|
|
667
|
+
state_set_object runtime_checks.mcp_doctor \
|
|
668
|
+
status=passed \
|
|
669
|
+
"ts=$(_now)" \
|
|
670
|
+
"evidence=direxio-mcp doctor --json succeeded" \
|
|
671
|
+
"domain=$report_domain" \
|
|
672
|
+
"agent_room_id=$report_room" \
|
|
673
|
+
"token=$token_status"
|
|
693
674
|
rm -f "$out" "$err"
|
|
694
675
|
echo "verified runtime check: mcp_doctor"
|
|
695
676
|
}
|
|
@@ -700,56 +681,49 @@ cmd_verify_mcp_smoke() {
|
|
|
700
681
|
return 1
|
|
701
682
|
}
|
|
702
683
|
|
|
703
|
-
local service_url token room_id body code payload
|
|
704
|
-
service_url=$(
|
|
684
|
+
local service_url token room_id body code payload url response_room_id response_messages_type
|
|
685
|
+
service_url=$(json_get "$STATE_JSON" as_url)
|
|
705
686
|
if [ -z "$service_url" ]; then
|
|
706
687
|
local domain
|
|
707
|
-
domain=$(
|
|
688
|
+
domain=$(json_get "$STATE_JSON" domain)
|
|
708
689
|
[ -n "$domain" ] && service_url="https://$domain"
|
|
709
690
|
fi
|
|
710
|
-
token=$(
|
|
711
|
-
room_id=$(
|
|
691
|
+
token=$(json_get "$STATE_JSON" agent_token)
|
|
692
|
+
room_id=$(json_get "$STATE_JSON" agent_room_id)
|
|
712
693
|
if [ -z "$service_url" ] || [ -z "$token" ] || [ -z "$room_id" ]; then
|
|
713
694
|
warn "mcp smoke check requires as_url/domain, agent_token, and agent_room_id in state.json"
|
|
714
695
|
return 1
|
|
715
696
|
fi
|
|
716
697
|
|
|
717
698
|
body=$(mktemp)
|
|
718
|
-
payload=$(
|
|
699
|
+
payload=$(json_build mcp-messages-list "$room_id")
|
|
719
700
|
url="${service_url%/}/_p2p/query"
|
|
720
701
|
code=$(curl -sk -o "$body" -w '%{http_code}' \
|
|
721
702
|
-X POST "$url" \
|
|
722
703
|
-H 'Content-Type: application/json' \
|
|
723
704
|
-H "Authorization: Bearer $token" \
|
|
724
705
|
-d "$payload" 2>/dev/null)
|
|
725
|
-
if [ "$code" != "200" ] || !
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
evidence: $evidence
|
|
732
|
-
}
|
|
733
|
-
' --arg ts "$(_now)" --arg evidence "mcp.messages.list returned HTTP $code or invalid response"
|
|
706
|
+
if [ "$code" != "200" ] || ! json_assert "$body" messages-response >/dev/null 2>&1; then
|
|
707
|
+
state_set_object runtime_checks.mcp_smoke \
|
|
708
|
+
status=failed \
|
|
709
|
+
"ts=$(_now)" \
|
|
710
|
+
action=mcp.messages.list \
|
|
711
|
+
"evidence=mcp.messages.list returned HTTP $code or invalid response"
|
|
734
712
|
rm -f "$body"
|
|
735
713
|
return 1
|
|
736
714
|
fi
|
|
737
715
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
evidence: "read-only backend smoke check succeeded"
|
|
750
|
-
}' > "$tmp"
|
|
751
|
-
_state_write '.runtime_checks.mcp_smoke = $check[0]' --slurpfile check "$tmp"
|
|
752
|
-
rm -f "$body" "$tmp"
|
|
716
|
+
response_room_id=$(json_get "$body" room_id)
|
|
717
|
+
response_messages_type=$(json_type "$body" messages)
|
|
718
|
+
state_set_object runtime_checks.mcp_smoke \
|
|
719
|
+
status=passed \
|
|
720
|
+
"ts=$(_now)" \
|
|
721
|
+
action=mcp.messages.list \
|
|
722
|
+
"room_id=$room_id" \
|
|
723
|
+
"response_room_id=$response_room_id" \
|
|
724
|
+
"response_messages_type=$response_messages_type" \
|
|
725
|
+
"evidence=read-only backend smoke check succeeded"
|
|
726
|
+
rm -f "$body"
|
|
753
727
|
echo "verified runtime check: mcp_smoke"
|
|
754
728
|
}
|
|
755
729
|
|
|
@@ -760,9 +734,10 @@ cmd_verify_mcp_tools() {
|
|
|
760
734
|
}
|
|
761
735
|
|
|
762
736
|
local credentials mcp_cmd node_id node_cmd node_script out err report
|
|
763
|
-
credentials=$(
|
|
764
|
-
|
|
765
|
-
|
|
737
|
+
credentials=$(json_get "$STATE_JSON" agent_credentials_file)
|
|
738
|
+
[ -n "$credentials" ] || credentials=$(json_get "$STATE_JSON" mcp_credentials_file)
|
|
739
|
+
mcp_cmd=$(json_get "$STATE_JSON" mcp_command "direxio-mcp")
|
|
740
|
+
node_id=$(json_get "$STATE_JSON" agent_node_id)
|
|
766
741
|
[ -n "$credentials" ] || {
|
|
767
742
|
warn "mcp tools check requires agent_credentials_file or mcp_credentials_file in state.json"
|
|
768
743
|
return 1
|
|
@@ -778,52 +753,29 @@ cmd_verify_mcp_tools() {
|
|
|
778
753
|
out=$(mktemp)
|
|
779
754
|
err=$(mktemp)
|
|
780
755
|
if ! DIREXIO_CREDENTIALS_FILE="$credentials" DIREXIO_AGENT_NODE_ID="$node_id" "$node_cmd" "$node_script" "$mcp_cmd" > "$out" 2> "$err"; then
|
|
781
|
-
|
|
782
|
-
.runtime_checks.mcp_tools = {
|
|
783
|
-
status: "failed",
|
|
784
|
-
ts: $ts,
|
|
785
|
-
evidence: "MCP tools/list failed"
|
|
786
|
-
}
|
|
787
|
-
' --arg ts "$(_now)"
|
|
756
|
+
state_set_object runtime_checks.mcp_tools status=failed "ts=$(_now)" "evidence=MCP tools/list failed"
|
|
788
757
|
cat "$err" >&2
|
|
789
758
|
rm -f "$out" "$err"
|
|
790
759
|
return 1
|
|
791
760
|
fi
|
|
792
|
-
if !
|
|
793
|
-
|
|
794
|
-
.runtime_checks.mcp_tools = {
|
|
795
|
-
status: "failed",
|
|
796
|
-
ts: $ts,
|
|
797
|
-
evidence: "MCP tools/list returned invalid output"
|
|
798
|
-
}
|
|
799
|
-
' --arg ts "$(_now)"
|
|
761
|
+
if ! json_assert "$out" tools-list >/dev/null 2>&1; then
|
|
762
|
+
state_set_object runtime_checks.mcp_tools status=failed "ts=$(_now)" "evidence=MCP tools/list returned invalid output"
|
|
800
763
|
rm -f "$out" "$err"
|
|
801
764
|
return 1
|
|
802
765
|
fi
|
|
803
766
|
report=$(cat "$out")
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
tools: ($report.tools // [])
|
|
811
|
-
}
|
|
812
|
-
' --arg ts "$(_now)" --argjson report "$report"
|
|
767
|
+
state_set_object runtime_checks.mcp_tools \
|
|
768
|
+
status=passed \
|
|
769
|
+
"ts=$(_now)" \
|
|
770
|
+
"evidence=MCP tools/list succeeded" \
|
|
771
|
+
"tool_count=$(json_get "$out" tool_count 0)" \
|
|
772
|
+
"tools=$(json_get "$out" tools "[]")"
|
|
813
773
|
rm -f "$out" "$err"
|
|
814
774
|
echo "verified runtime check: mcp_tools"
|
|
815
775
|
}
|
|
816
776
|
|
|
817
777
|
_node_command() {
|
|
818
|
-
|
|
819
|
-
command -v node
|
|
820
|
-
return 0
|
|
821
|
-
fi
|
|
822
|
-
if command -v node.exe >/dev/null 2>&1; then
|
|
823
|
-
command -v node.exe
|
|
824
|
-
return 0
|
|
825
|
-
fi
|
|
826
|
-
return 1
|
|
778
|
+
json_node
|
|
827
779
|
}
|
|
828
780
|
|
|
829
781
|
_node_script_path() {
|
|
@@ -907,11 +859,12 @@ cmd_verify_connect_daemon() {
|
|
|
907
859
|
}
|
|
908
860
|
|
|
909
861
|
local service_name service_dir config runtime_dir binary target_work_dir status_out daemon_status work_dir evidence agent_error
|
|
910
|
-
service_name=$(
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
862
|
+
service_name=$(json_get "$STATE_JSON" agent_service_id)
|
|
863
|
+
[ -n "$service_name" ] || service_name=$(json_get "$STATE_JSON" domain)
|
|
864
|
+
service_dir=$(json_get "$STATE_JSON" agent_service_dir)
|
|
865
|
+
config=$(json_get "$STATE_JSON" cc_connect_config)
|
|
866
|
+
runtime_dir=$(json_get "$STATE_JSON" cc_connect_runtime_dir)
|
|
867
|
+
binary=$(json_get "$STATE_JSON" cc_connect_binary "direxio-connect")
|
|
915
868
|
[ -n "$service_name" ] || service_name=cc-connect
|
|
916
869
|
[ -n "$binary" ] || binary=direxio-connect
|
|
917
870
|
|
|
@@ -930,13 +883,7 @@ cmd_verify_connect_daemon() {
|
|
|
930
883
|
*/*|[A-Za-z]:/*|[A-Za-z]:\\*) ;;
|
|
931
884
|
*)
|
|
932
885
|
command -v "$binary" >/dev/null 2>&1 || {
|
|
933
|
-
|
|
934
|
-
.runtime_checks.connect_daemon = {
|
|
935
|
-
status: "failed",
|
|
936
|
-
ts: $ts,
|
|
937
|
-
evidence: "direxio-connect binary not found"
|
|
938
|
-
}
|
|
939
|
-
' --arg ts "$(_now)"
|
|
886
|
+
state_set_object runtime_checks.connect_daemon status=failed "ts=$(_now)" "evidence=direxio-connect binary not found"
|
|
940
887
|
warn "connect daemon check could not find binary: $binary"
|
|
941
888
|
return 1
|
|
942
889
|
}
|
|
@@ -944,14 +891,7 @@ cmd_verify_connect_daemon() {
|
|
|
944
891
|
esac
|
|
945
892
|
|
|
946
893
|
status_out=$("$binary" daemon status --service-name "$service_name" 2>/dev/null) || {
|
|
947
|
-
|
|
948
|
-
.runtime_checks.connect_daemon = {
|
|
949
|
-
status: "failed",
|
|
950
|
-
ts: $ts,
|
|
951
|
-
service_name: $service_name,
|
|
952
|
-
evidence: "direxio-connect daemon status failed"
|
|
953
|
-
}
|
|
954
|
-
' --arg ts "$(_now)" --arg service_name "$service_name"
|
|
894
|
+
state_set_object runtime_checks.connect_daemon status=failed "ts=$(_now)" "service_name=$service_name" "evidence=direxio-connect daemon status failed"
|
|
955
895
|
return 1
|
|
956
896
|
}
|
|
957
897
|
daemon_status=$(printf '%s\n' "$status_out" | sed -nE 's/^[[:space:]]*Status:[[:space:]]*//p' | head -n 1)
|
|
@@ -966,68 +906,45 @@ cmd_verify_connect_daemon() {
|
|
|
966
906
|
else
|
|
967
907
|
agent_error=$(connect_daemon_agent_error_from_logs "$binary" "$service_name")
|
|
968
908
|
if [ -n "$agent_error" ]; then
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
agent_error: $agent_error
|
|
979
|
-
}
|
|
980
|
-
' --arg ts "$(_now)" \
|
|
981
|
-
--arg service_name "$service_name" \
|
|
982
|
-
--arg daemon_status "$daemon_status" \
|
|
983
|
-
--arg work_dir "$(normalize_check_path "$work_dir")" \
|
|
984
|
-
--arg target_work_dir "$(normalize_check_path "$target_work_dir")" \
|
|
985
|
-
--arg agent_error "$agent_error"
|
|
909
|
+
state_set_object runtime_checks.connect_daemon \
|
|
910
|
+
status=failed \
|
|
911
|
+
"ts=$(_now)" \
|
|
912
|
+
"evidence=direxio-connect daemon logs report ACP session initialization failure" \
|
|
913
|
+
"service_name=$service_name" \
|
|
914
|
+
"daemon_status=$daemon_status" \
|
|
915
|
+
"work_dir=$(normalize_check_path "$work_dir")" \
|
|
916
|
+
"expected_work_dir=$(normalize_check_path "$target_work_dir")" \
|
|
917
|
+
"agent_error=$agent_error"
|
|
986
918
|
warn "direxio-connect daemon logs report ACP session initialization failure"
|
|
987
919
|
return 1
|
|
988
920
|
fi
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
expected_work_dir: $target_work_dir
|
|
998
|
-
}
|
|
999
|
-
' --arg ts "$(_now)" \
|
|
1000
|
-
--arg service_name "$service_name" \
|
|
1001
|
-
--arg daemon_status "$daemon_status" \
|
|
1002
|
-
--arg work_dir "$(normalize_check_path "$work_dir")" \
|
|
1003
|
-
--arg target_work_dir "$(normalize_check_path "$target_work_dir")"
|
|
921
|
+
state_set_object runtime_checks.connect_daemon \
|
|
922
|
+
status=passed \
|
|
923
|
+
"ts=$(_now)" \
|
|
924
|
+
"evidence=direxio-connect daemon is running for this service" \
|
|
925
|
+
"service_name=$service_name" \
|
|
926
|
+
"daemon_status=$daemon_status" \
|
|
927
|
+
"work_dir=$(normalize_check_path "$work_dir")" \
|
|
928
|
+
"expected_work_dir=$(normalize_check_path "$target_work_dir")"
|
|
1004
929
|
echo "verified runtime check: connect_daemon"
|
|
1005
930
|
return 0
|
|
1006
931
|
fi
|
|
1007
932
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
expected_work_dir: $target_work_dir
|
|
1017
|
-
}
|
|
1018
|
-
' --arg ts "$(_now)" \
|
|
1019
|
-
--arg evidence "$evidence" \
|
|
1020
|
-
--arg service_name "$service_name" \
|
|
1021
|
-
--arg daemon_status "$daemon_status" \
|
|
1022
|
-
--arg work_dir "$(normalize_check_path "$work_dir")" \
|
|
1023
|
-
--arg target_work_dir "$(normalize_check_path "$target_work_dir")"
|
|
933
|
+
state_set_object runtime_checks.connect_daemon \
|
|
934
|
+
status=failed \
|
|
935
|
+
"ts=$(_now)" \
|
|
936
|
+
"evidence=$evidence" \
|
|
937
|
+
"service_name=$service_name" \
|
|
938
|
+
"daemon_status=$daemon_status" \
|
|
939
|
+
"work_dir=$(normalize_check_path "$work_dir")" \
|
|
940
|
+
"expected_work_dir=$(normalize_check_path "$target_work_dir")"
|
|
1024
941
|
warn "$evidence"
|
|
1025
942
|
return 1
|
|
1026
943
|
}
|
|
1027
944
|
|
|
1028
945
|
runtime_check_status() {
|
|
1029
946
|
local check=$1
|
|
1030
|
-
|
|
947
|
+
json_get "$STATE_JSON" "runtime_checks.$check.status" "not_run"
|
|
1031
948
|
}
|
|
1032
949
|
|
|
1033
950
|
cmd_verify_runtime() {
|
|
@@ -1053,47 +970,28 @@ cmd_verify_runtime() {
|
|
|
1053
970
|
done
|
|
1054
971
|
|
|
1055
972
|
if [ "$failed_count" -eq 0 ]; then
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
mcp_tools: $tools_status,
|
|
1066
|
-
mcp_smoke: $smoke_status
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
' --arg ts "$(_now)" \
|
|
1070
|
-
--arg connect_status "$connect_status" \
|
|
1071
|
-
--arg doctor_status "$doctor_status" \
|
|
1072
|
-
--arg tools_status "$tools_status" \
|
|
1073
|
-
--arg smoke_status "$smoke_status"
|
|
973
|
+
state_set_object runtime_checks.summary \
|
|
974
|
+
status=passed \
|
|
975
|
+
"ts=$(_now)" \
|
|
976
|
+
failed_count=0 \
|
|
977
|
+
"evidence=all runtime checks passed" \
|
|
978
|
+
"checks.connect_daemon=$connect_status" \
|
|
979
|
+
"checks.mcp_doctor=$doctor_status" \
|
|
980
|
+
"checks.mcp_tools=$tools_status" \
|
|
981
|
+
"checks.mcp_smoke=$smoke_status"
|
|
1074
982
|
echo "verified runtime checks: passed"
|
|
1075
983
|
return 0
|
|
1076
984
|
fi
|
|
1077
985
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
mcp_tools: $tools_status,
|
|
1088
|
-
mcp_smoke: $smoke_status
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
' --arg ts "$(_now)" \
|
|
1092
|
-
--arg failed_count "$failed_count" \
|
|
1093
|
-
--arg connect_status "$connect_status" \
|
|
1094
|
-
--arg doctor_status "$doctor_status" \
|
|
1095
|
-
--arg tools_status "$tools_status" \
|
|
1096
|
-
--arg smoke_status "$smoke_status"
|
|
986
|
+
state_set_object runtime_checks.summary \
|
|
987
|
+
status=failed \
|
|
988
|
+
"ts=$(_now)" \
|
|
989
|
+
"failed_count=$failed_count" \
|
|
990
|
+
"evidence=one or more runtime checks failed" \
|
|
991
|
+
"checks.connect_daemon=$connect_status" \
|
|
992
|
+
"checks.mcp_doctor=$doctor_status" \
|
|
993
|
+
"checks.mcp_tools=$tools_status" \
|
|
994
|
+
"checks.mcp_smoke=$smoke_status"
|
|
1097
995
|
warn "runtime checks failed: $failed_count"
|
|
1098
996
|
return "${rc:-1}"
|
|
1099
997
|
}
|
|
@@ -253,12 +253,7 @@ _route53_existing_a_value() {
|
|
|
253
253
|
local zone_id=$1 domain=$2 records name
|
|
254
254
|
name="${domain}."
|
|
255
255
|
records=$(aws route53 list-resource-record-sets --hosted-zone-id "$zone_id" --output json 2>/dev/null) || return 0
|
|
256
|
-
printf '%s\n' "$records" |
|
|
257
|
-
.ResourceRecordSets[]?
|
|
258
|
-
| select(.Name == $name and .Type == "A")
|
|
259
|
-
| [.ResourceRecords[]?.Value]
|
|
260
|
-
| join(",")
|
|
261
|
-
' | sed -n '1p'
|
|
256
|
+
printf '%s\n' "$records" | json_stdin_route53_a_values "$name" | sed -n '1p'
|
|
262
257
|
}
|
|
263
258
|
|
|
264
259
|
_guard_route53_a_overwrite() {
|
|
@@ -342,7 +337,7 @@ _find_route53_zone() {
|
|
|
342
337
|
fi
|
|
343
338
|
;;
|
|
344
339
|
esac
|
|
345
|
-
done < <(printf '%s\n' "$zones_json" |
|
|
340
|
+
done < <(printf '%s\n' "$zones_json" | json_stdin_tsv HostedZones Id Name)
|
|
346
341
|
[ -n "$best_id" ] || return 1
|
|
347
342
|
printf '%s\t%s\n' "$best_id" "$best_name"
|
|
348
343
|
}
|
|
@@ -355,9 +350,9 @@ _create_route53_zone() {
|
|
|
355
350
|
--name "$zone_name" \
|
|
356
351
|
--caller-reference "$caller" \
|
|
357
352
|
--output json) || return 1
|
|
358
|
-
zone_id=$(printf '%s\n' "$created" |
|
|
359
|
-
returned_name=$(printf '%s\n' "$created" |
|
|
360
|
-
name_servers=$(printf '%s\n' "$created" |
|
|
353
|
+
zone_id=$(printf '%s\n' "$created" | json_stdin_get HostedZone.Id | sed 's#^/hostedzone/##')
|
|
354
|
+
returned_name=$(printf '%s\n' "$created" | json_stdin_get HostedZone.Name)
|
|
355
|
+
name_servers=$(printf '%s\n' "$created" | json_stdin_join DelegationSet.NameServers ",")
|
|
361
356
|
[ -n "$zone_id" ] && [ -n "$returned_name" ] || return 1
|
|
362
357
|
|
|
363
358
|
_record_route53_zone "$zone_id" "${returned_name%.}" true "$name_servers"
|