#!/usr/bin/env bash # orca-drift-notify.sh — peer-side drift event recorder (P10b, REQ-106). # # Invoked by systemd Path units (orca-drift-.service) when a # critical path changes. Receives the changed path as $1 (from systemd # %f). Computes sha256sum of the file (or "DELETED" if absent), reads # the latest applied txn from /etc/orca/state/latest-applied-txn, and # writes an event JSON to /etc/orca/state/drift-events/.json. # Uses flock for serialization. R-001-clean: pure bash + sha256sum. # # Usage: orca-drift-notify.sh # # Exit codes: 0 = event recorded; 1 = bad args / write failure. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=lib/orca-log.sh . "$SCRIPT_DIR/lib/orca-log.sh" ORCA_LOG_ACTOR="spiffe://orca/cli/drift-notify" STATE_DIR="${ORCA_STATE_DIR:-/etc/orca/state}" EVENTS_DIR="$STATE_DIR/drift-events" LATEST_TXN_FILE="$STATE_DIR/latest-applied-txn" LOCK_FILE="$STATE_DIR/drift-events.lock" if [ "$#" -lt 1 ]; then orca_log_error "drift-notify" "-" "failed" "missing path argument" echo "usage: orca-drift-notify.sh " >&2 exit 1 fi PATH_ARG="$1" mkdir -p "$EVENTS_DIR" compute_sha() { local p="$1" if [ ! -e "$p" ]; then echo "DELETED" return fi sha256sum "$p" 2>/dev/null | awk '{print $1}' || echo "ERROR" } read_latest_txn() { if [ -f "$LATEST_TXN_FILE" ]; then cat "$LATEST_TXN_FILE" 2>/dev/null || true fi } gen_event_id() { local ts_us random_suffix ts_us="$(date -u +%Y%m%d%H%M%S%6N)" random_suffix="$(head -c 4 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n' || echo "0000")" echo "EVT-${ts_us}-${random_suffix}" } NEW_SHA="$(compute_sha "$PATH_ARG")" LATEST_TXN="$(read_latest_txn || true)" EVENT_ID="$(gen_event_id)" TS="$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)" HOST="$(hostname 2>/dev/null || echo unknown)" if [ "$NEW_SHA" = "DELETED" ]; then STATUS="deleted" elif [ ! -f "$PATH_ARG" ]; then STATUS="created" else STATUS="modified" fi escape_json() { local s="$1" s="${s//\\/\\\\}" s="${s//\"/\\\"}" printf '%s' "$s" } PATH_ESC="$(escape_json "$PATH_ARG")" HOST_ESC="$(escape_json "$HOST")" EVENT_JSON=$(cat <"$EVENT_FILE.tmp" mv "$EVENT_FILE.tmp" "$EVENT_FILE" ) 9>"$LOCK_FILE" orca_log_info "drift-notify" "$PATH_ARG" "ok" "event=$EVENT_ID status=$STATUS sha=$NEW_SHA" echo "event=$EVENT_ID" exit 0