Add .bms-actions logging (partial): auth login/refresh, create, note, delete. Need: update, assign, resolve.

This commit is contained in:
OpenClaw Agent
2026-04-07 21:30:00 +00:00
parent ef2aca507f
commit 5e2f822ad7
3 changed files with 154 additions and 3 deletions

17
scripts/bms-auth.sh Executable file → Normal file
View File

@@ -4,6 +4,10 @@
set -euo pipefail
# Import logging
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/bms-logging.sh"
BMS_API_BASE="${BMS_API_BASE:-https://api.bms.kaseya.com}"
BMS_TOKEN_FILE="${BMS_TOKEN_FILE:-$HOME/.bms_token.json}"
@@ -76,6 +80,15 @@ cmd_auth_login() {
save_token "$response"
echo "Authenticated successfully. Token cached at $BMS_TOKEN_FILE" >&2
# Log successful login
local args_json
args_json=$(jq -n \
--arg tenant "${BMS_TENANT}" \
--arg username "${BMS_USERNAME}" \
'{"tenant": $tenant, "username": $username}')
local result_json='{"success": true}'
log_action "auth.login" "$args_json" "$result_json" "success"
}
cmd_auth_refresh() {
@@ -94,6 +107,10 @@ cmd_auth_refresh() {
save_token "$response"
echo "Token refreshed." >&2
# Log token refresh
local result_json='{"success": true}'
log_action "auth.refresh" "{}" "$result_json" "success"
}
cmd_auth_status() {

59
scripts/bms-logging.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# bms-logging.sh — Action logging for BMS skill
# Centralized logging of user-initiated actions for audit/review
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Log directory (can be overridden)
BMS_LOG_DIR="${BMS_LOG_DIR:-$HOME/.bms-actions}"
# Ensure log directory exists
mkdir -p "$BMS_LOG_DIR"
# Current log file (by date, UTC)
BMS_LOG_FILE="$BMS_LOG_DIR/$(date -u +%Y-%m-%d).jsonl"
# Sanitize arguments: strip any sensitive values from a JSON object
# Usage: sanitized=$(sanitize_args '{"password":"secret","token":"abc"}')
sanitize_args() {
local input="$1"
# Remove known sensitive keys; preserve structure
jq 'del(.["BMS_PASSWORD"], .["BMS_MFA_CODE"], .["BMS_CLIENT_SECRET"], .["access_token"], .["refresh_token"], .["token"], .["Authorization"])' 2>/dev/null <<<"$input" || echo "$input"
}
# Log an action
# Arguments: command, args_json, result_json, status (success|error)
log_action() {
local command="$1"
local args_json="${2:-{}}"
local result_json="${3:-{}}"
local status="${4:-success}"
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Sanitize args and result
local safe_args safe_result
safe_args=$(sanitize_args "$args_json")
safe_result=$(sanitize_args "$result_json")
# Build log entry as single JSON line
local entry
entry=$(jq -n \
--arg ts "$timestamp" \
--arg cmd "$command" \
--argjson args "$safe_args" \
--argjson result "$safe_result" \
--arg stat "$status" \
'{timestamp: $ts, command: $cmd, args: $args, result: $result, status: $stat}')
# Append atomically
echo "$entry" >> "$BMS_LOG_FILE"
}
# Get current log file path
get_log_path() {
echo "$BMS_LOG_FILE"
}

81
scripts/bms-tickets.sh Executable file → Normal file
View File

@@ -3,7 +3,10 @@
set -euo pipefail
# Import logging
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/bms-logging.sh"
BMS_API_BASE="${BMS_API_BASE:-https://api.bms.kaseya.com}"
# ─── Helpers ─────────────────────────────────────────────────────────────────
@@ -272,10 +275,43 @@ cmd_create() {
if [[ "$success" != "true" ]] || [[ -z "$ticket_id" ]] || [[ "$ticket_id" == "null" ]]; then
echo "Create ticket failed or returned ambiguous response:" >&2
echo "$response" | jq . >&2
# Log failure
local args_json result_json
args_json=$(jq -n \
--arg title "$title" \
--arg details "$details" \
--argjson account_id "$account_id" \
--argjson location_id "$location_id" \
--argjson status_id "$status_id" \
--argjson priority_id "$priority_id" \
--argjson type_id "$type_id" \
--argjson source_id "$source_id" \
--argjson queue_id "${queue_id:-null}" \
--argjson assignee_id "${assignee_id:-null}" \
'{title: $title, details: $details, account_id: $account_id, location_id: $location_id, status_id: $status_id, priority_id: $priority_id, type_id: $type_id, source_id: $source_id, queue_id: $queue_id, assignee_id: $assignee_id}')
result_json=$(jq -n '{error: "creation_failed", response: ("$response" | fromjson? // "$response")}')
log_action "tickets.create" "$args_json" "$result_json" "error"
exit 1
fi
echo "Created ticket ID: ${ticket_id}${ticket_number:-N/A}"
# Log success
local args_json result_json
args_json=$(jq -n \
--arg title "$title" \
--arg details "$details" \
--argjson account_id "$account_id" \
--argjson location_id "$location_id" \
--argjson status_id "$status_id" \
--argjson priority_id "$priority_id" \
--argjson type_id "$type_id" \
--argjson source_id "$source_id" \
--argjson queue_id "${queue_id:-null}" \
--argjson assignee_id "${assignee_id:-null}" \
'{title: $title, details: $details, account_id: $account_id, location_id: $location_id, status_id: $status_id, priority_id: $priority_id, type_id: $type_id, source_id: $source_id, queue_id: $queue_id, assignee_id: $assignee_id}')
result_json=$(jq -n --argjson tid "$ticket_id" --arg tn "${ticket_number:-}" '{ticket_id: $tid, ticket_number: $tn}')
log_action "tickets.create" "$args_json" "$result_json" "success"
}
cmd_update() {
@@ -362,7 +398,25 @@ cmd_note() {
local response
response=$(bms_curl POST "/v2/servicedesk/tickets/${ticket_id}/notes" -d "$body")
echo "$response" | jq -r '"Note added (ID: \(.Data.Id // .Id // "ok"))"'
local note_id
note_id=$(echo "$response" | jq -r '.Data.Id // .Id // empty')
if [[ -z "$note_id" || "$note_id" == "null" ]]; then
echo "Note add failed or returned ambiguous response:" >&2
echo "$response" | jq . >&2
# Log failure
local args_json result_json
args_json=$(jq -n --argjson ticket_id "$ticket_id" --arg message "$message" --argjson type_id "$type_id" '{ticket_id: $ticket_id, message: $message, type_id: $type_id}')
result_json=$(jq -n '{error: "note_add_failed", response: ("$response" | fromjson? // "$response")}')
log_action "tickets.note" "$args_json" "$result_json" "error"
exit 1
fi
echo "Note added (ID: ${note_id})"
# Log success
local args_json result_json
args_json=$(jq -n --argjson ticket_id "$ticket_id" --arg message "$message" --argjson type_id "$type_id" '{ticket_id: $ticket_id, message: $message, type_id: $type_id}')
result_json=$(jq -n --argjson note_id "$note_id" '{note_id: $note_id}')
log_action "tickets.note" "$args_json" "$result_json" "success"
}
cmd_assign() {
@@ -447,15 +501,36 @@ cmd_delete() {
local ids=("$@")
[[ ${#ids[@]} -gt 0 ]] || die "Usage: bms tickets delete <id> [id2 ...]"
local response=""
if [[ ${#ids[@]} -eq 1 ]]; then
bms_curl DELETE "/v2/servicedesk/tickets/${ids[0]}" >/dev/null
response=$(bms_curl DELETE "/v2/servicedesk/tickets/${ids[0]}")
echo "Deleted ticket ${ids[0]}"
else
local body
body=$(printf '%s\n' "${ids[@]}" | jq -Rs 'split("\n") | map(select(. != "")) | map(tonumber) | {Ids: .}')
bms_curl DELETE "/v2/servicedesk/tickets" -d "$body" >/dev/null
response=$(bms_curl DELETE "/v2/servicedesk/tickets" -d "$body")
echo "Deleted tickets: ${ids[*]}"
fi
# Check success (DELETE often returns { success: true } or empty)
local success
success=$(echo "$response" | jq -r '.success // .Success // ""')
if [[ "$success" != "true" ]] && [[ -n "$response" ]] && echo "$response" | jq -e . >/dev/null 2>&1; then
# If response is JSON but not success=true, treat as failure
echo "Delete operation may have failed:" >&2
echo "$response" | jq . >&2
local args_json result_json
args_json=$(jq -n --argjson ids "${ids}" '{ids: $ids}')
result_json=$(jq -n '{error: "delete_failed", response: ("$response" | fromjson? // "$response")}')
log_action "tickets.delete" "$args_json" "$result_json" "error"
exit 1
fi
# Log success
local args_json result_json
args_json=$(jq -n --argjson ids "${ids}" '{ids: $ids}')
result_json=$(jq -n --argjson deleted_ids "${ids}" '{deleted_ids: $deleted_ids}')
log_action "tickets.delete" "$args_json" "$result_json" "success"
}
# ─── Dispatch ────────────────────────────────────────────────────────────────