fix: {project}-ops repo — separate operations from code (#757) (#767)

Fixes #757

## Changes
Separate operations from code into {project}-ops repo pattern. Added OPS_REPO_ROOT infrastructure (env.sh, load-project.sh, formula-session.sh with ensure_ops_repo helper). Updated all 8 agent scripts and 7 formulas to read/write vault items, journals, evidence, prerequisites, RESOURCES.md, and knowledge from the ops repo. Added setup_ops_repo() to disinto init for automatic ops repo creation and seeding. Removed migrated data from code repo (vault data dirs, planner journal/memory/prerequisites, supervisor journal/best-practices, evidence, RESOURCES.md). Updated all documentation. 55 files changed, ShellCheck clean, all 38 phase tests pass.

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/disinto/pulls/767
Reviewed-by: Disinto_bot <disinto_bot@noreply.codeberg.org>
This commit is contained in:
johba 2026-03-26 19:55:12 +01:00
parent a899fd0733
commit 71fe89cdd0
55 changed files with 421 additions and 932 deletions

View file

@ -10,11 +10,11 @@ to a human by writing `PHASE:escalate` to a phase file — using the same
unified escalation path as dev/action agents.
**Pipeline B — Procurement (*.md)**: The planner files resource requests as
markdown files in `vault/pending/`. `vault-poll.sh` notifies the human via
markdown files in `$OPS_REPO_ROOT/vault/pending/`. `vault-poll.sh` notifies the human via
vault/forge. The human fulfills the request (creates accounts, provisions infra,
adds secrets to `.env`) and moves the file to `vault/approved/`.
adds secrets to `.env`) and moves the file to `$OPS_REPO_ROOT/vault/approved/`.
`vault-fire.sh` then extracts the proposed entry and appends it to
`RESOURCES.md`.
`$OPS_REPO_ROOT/RESOURCES.md`.
**Pipeline C — Rent-a-Human (outreach drafts)**: Any agent can dispatch the
`run-rent-a-human` formula (via an `action` issue) when a task requires a human
@ -30,15 +30,15 @@ needed — the human reviews and publishes directly.
- `vault/vault-agent.sh` — Classifies and routes pending JSON actions via `claude -p`: auto-approve, auto-reject, or escalate to human
- `vault/vault-env.sh` — Shared env setup for vault sub-scripts: sources `lib/env.sh`, overrides `FORGE_TOKEN` with `FORGE_VAULT_TOKEN`, sets `VAULT_TOKEN` for vault-runner container
- `vault/PROMPT.md` — System prompt for the vault agent's Claude invocation
- `vault/vault-fire.sh` — Executes an approved action (JSON) in an **ephemeral Docker container** with vault-only secrets injected (GITHUB_TOKEN, CLAWHUB_TOKEN — never exposed to agents). For deployment actions, calls `lib/ci-helpers.sh:ci_promote()` to gate production promotes via Woodpecker environments. Writes RESOURCES.md entry for procurement MD approvals.
- `vault/vault-fire.sh` — Executes an approved action (JSON) in an **ephemeral Docker container** with vault-only secrets injected (GITHUB_TOKEN, CLAWHUB_TOKEN — never exposed to agents). For deployment actions, calls `lib/ci-helpers.sh:ci_promote()` to gate production promotes via Woodpecker environments. Writes `$OPS_REPO_ROOT/RESOURCES.md` entry for procurement MD approvals.
- `vault/vault-reject.sh` — Marks a JSON action as rejected
- `formulas/run-rent-a-human.toml` — Formula for human-action drafts: Claude researches target platform norms, drafts copy-paste content, writes to `vault/outreach/{platform}/drafts/`, notifies human via vault/forge
**Procurement flow**:
1. Planner drops `vault/pending/<name>.md` with what/why/proposed RESOURCES.md entry
**Procurement flow** (all vault items live in `$OPS_REPO_ROOT/vault/`):
1. Planner drops `$OPS_REPO_ROOT/vault/pending/<name>.md` with what/why/proposed RESOURCES.md entry
2. `vault-poll.sh` notifies human via vault/forge
3. Human fulfills: creates account, adds secrets to `.env`, moves file to `vault/approved/`
4. `vault-fire.sh` extracts proposed entry, appends to RESOURCES.md, moves to `vault/fired/`
3. Human fulfills: creates account, adds secrets to `.env`, moves file to `approved/`
4. `vault-fire.sh` extracts proposed entry, appends to `$OPS_REPO_ROOT/RESOURCES.md`, moves to `fired/`
5. Next planner run reads RESOURCES.md → new capability available → unblocks prerequisite tree
**Environment variables consumed**:

View file

@ -1,7 +1,7 @@
# Vault Agent
You are the vault agent for `$FORGE_REPO`. You were called by
`vault-poll.sh` because one or more actions in `vault/pending/` need
`vault-poll.sh` because one or more actions in `$OPS_REPO_ROOT/vault/pending/` need
classification and routing.
## Two Pipelines
@ -16,7 +16,7 @@ You classify and route these: auto-approve, escalate, or reject.
Resource requests from the planner. These always escalate to the human —
you do NOT auto-approve or reject procurement requests. The human fulfills
the request (creates accounts, provisions infra, adds secrets to .env)
and moves the file from `vault/pending/` to `vault/approved/`.
and moves the file from `$OPS_REPO_ROOT/vault/pending/` to `$OPS_REPO_ROOT/vault/approved/`.
`vault-fire.sh` then writes the RESOURCES.md entry.
## Your Job (Action Gating only)
@ -116,7 +116,7 @@ ROUTE: <action-id> → <auto-approve|escalate|reject> — <reason>
- Process ALL pending JSON actions in the batch. Never skip silently.
- For auto-approved actions, fire them immediately via `vault-fire.sh`.
- For escalated actions, move to `vault/approved/` only AFTER human approval.
- For escalated actions, move to `$OPS_REPO_ROOT/vault/approved/` only AFTER human approval.
- Read the action JSON carefully. Check the payload, not just the metadata.
- Ignore `.md` files in pending/ — those are procurement requests handled
separately by vault-poll.sh and the human.

View file

View file

View file

@ -13,9 +13,10 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "${SCRIPT_DIR}/vault-env.sh"
VAULT_DIR="${FACTORY_ROOT}/vault"
PROMPT_FILE="${VAULT_DIR}/PROMPT.md"
LOGFILE="${VAULT_DIR}/vault.log"
VAULT_SCRIPT_DIR="${FACTORY_ROOT}/vault"
OPS_VAULT_DIR="${OPS_REPO_ROOT}/vault"
PROMPT_FILE="${VAULT_SCRIPT_DIR}/PROMPT.md"
LOGFILE="${VAULT_SCRIPT_DIR}/vault.log"
CLAUDE_TIMEOUT="${CLAUDE_TIMEOUT:-3600}"
log() {
@ -26,7 +27,7 @@ log() {
ACTIONS_BATCH=""
ACTION_COUNT=0
for action_file in "${VAULT_DIR}/pending/"*.json; do
for action_file in "${OPS_VAULT_DIR}/pending/"*.json; do
[ -f "$action_file" ] || continue
ACTION_STATUS=$(jq -r '.status // ""' < "$action_file" 2>/dev/null)
@ -36,7 +37,7 @@ for action_file in "${VAULT_DIR}/pending/"*.json; do
if ! jq empty < "$action_file" 2>/dev/null; then
ACTION_ID=$(basename "$action_file" .json)
log "malformed JSON: $action_file — rejecting"
bash "${VAULT_DIR}/vault-reject.sh" "$ACTION_ID" "malformed JSON" 2>/dev/null || true
bash "${VAULT_SCRIPT_DIR}/vault-reject.sh" "$ACTION_ID" "malformed JSON" 2>/dev/null || true
continue
fi
@ -66,9 +67,10 @@ ${ACTIONS_BATCH}
## Environment
- FACTORY_ROOT=${FACTORY_ROOT}
- Vault directory: ${VAULT_DIR}
- vault-fire.sh: bash ${VAULT_DIR}/vault-fire.sh <action-id>
- vault-reject.sh: bash ${VAULT_DIR}/vault-reject.sh <action-id> \"<reason>\"
- OPS_REPO_ROOT=${OPS_REPO_ROOT}
- Vault data: ${OPS_VAULT_DIR}
- vault-fire.sh: bash ${VAULT_SCRIPT_DIR}/vault-fire.sh <action-id>
- vault-reject.sh: bash ${VAULT_SCRIPT_DIR}/vault-reject.sh <action-id> \"<reason>\"
Process each action now. For auto-approve, fire immediately. For reject, call vault-reject.sh.

View file

@ -17,10 +17,10 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "${SCRIPT_DIR}/vault-env.sh"
VAULT_DIR="${FACTORY_ROOT}/vault"
LOCKS_DIR="${VAULT_DIR}/.locks"
LOGFILE="${VAULT_DIR}/vault.log"
RESOURCES_FILE="${PROJECT_REPO_ROOT:-${FACTORY_ROOT}}/RESOURCES.md"
OPS_VAULT_DIR="${OPS_REPO_ROOT}/vault"
LOCKS_DIR="${FACTORY_ROOT}/vault/.locks"
LOGFILE="${FACTORY_ROOT}/vault/vault.log"
RESOURCES_FILE="${OPS_REPO_ROOT}/RESOURCES.md"
log() {
printf '[%s] vault-fire: %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*" >> "$LOGFILE"
@ -34,19 +34,19 @@ ACTION_ID="${1:?Usage: vault-fire.sh <item-id>}"
IS_PROCUREMENT=false
ACTION_FILE=""
if [ -f "${VAULT_DIR}/approved/${ACTION_ID}.md" ]; then
if [ -f "${OPS_VAULT_DIR}/approved/${ACTION_ID}.md" ]; then
IS_PROCUREMENT=true
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.md"
elif [ -f "${VAULT_DIR}/pending/${ACTION_ID}.md" ]; then
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.md"
elif [ -f "${OPS_VAULT_DIR}/pending/${ACTION_ID}.md" ]; then
IS_PROCUREMENT=true
mv "${VAULT_DIR}/pending/${ACTION_ID}.md" "${VAULT_DIR}/approved/${ACTION_ID}.md"
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.md"
mv "${OPS_VAULT_DIR}/pending/${ACTION_ID}.md" "${OPS_VAULT_DIR}/approved/${ACTION_ID}.md"
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.md"
log "$ACTION_ID: pending → approved (procurement)"
elif [ -f "${VAULT_DIR}/approved/${ACTION_ID}.json" ]; then
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.json"
elif [ -f "${VAULT_DIR}/pending/${ACTION_ID}.json" ]; then
mv "${VAULT_DIR}/pending/${ACTION_ID}.json" "${VAULT_DIR}/approved/${ACTION_ID}.json"
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.json"
elif [ -f "${OPS_VAULT_DIR}/approved/${ACTION_ID}.json" ]; then
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
elif [ -f "${OPS_VAULT_DIR}/pending/${ACTION_ID}.json" ]; then
mv "${OPS_VAULT_DIR}/pending/${ACTION_ID}.json" "${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
TMP=$(mktemp)
jq '.status = "approved"' "$ACTION_FILE" > "$TMP" && mv "$TMP" "$ACTION_FILE"
log "$ACTION_ID: pending → approved"
@ -93,7 +93,7 @@ if [ "$IS_PROCUREMENT" = true ]; then
log "$ACTION_ID: wrote RESOURCES.md entry"
# Move to fired/
mv "$ACTION_FILE" "${VAULT_DIR}/fired/${ACTION_ID}.md"
mv "$ACTION_FILE" "${OPS_VAULT_DIR}/fired/${ACTION_ID}.md"
rm -f "${LOCKS_DIR}/${ACTION_ID}.notified"
log "$ACTION_ID: approved → fired (procurement)"
exit 0
@ -122,7 +122,7 @@ if [ -f "${FACTORY_ROOT}/.env.vault.enc" ] && [ -f "${FACTORY_ROOT}/docker-compo
else
# Fallback for bare-metal or pre-migration setups: run action handler directly
log "$ACTION_ID: no .env.vault.enc or docker-compose.yml — running action directly"
bash "${VAULT_DIR}/vault-run-action.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1 || FIRE_EXIT=$?
bash "${SCRIPT_DIR}/vault-run-action.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1 || FIRE_EXIT=$?
fi
# =============================================================================
@ -132,7 +132,7 @@ if [ "$FIRE_EXIT" -eq 0 ]; then
# Update with fired timestamp and move to fired/
TMP=$(mktemp)
jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '.status = "fired" | .fired_at = $ts' "$ACTION_FILE" > "$TMP" \
&& mv "$TMP" "${VAULT_DIR}/fired/${ACTION_ID}.json"
&& mv "$TMP" "${OPS_VAULT_DIR}/fired/${ACTION_ID}.json"
rm -f "$ACTION_FILE"
log "$ACTION_ID: approved → fired"
else

View file

@ -26,8 +26,9 @@ FORGE_TOKEN="${FORGE_VAULT_TOKEN:-${FORGE_TOKEN}}"
LOGFILE="${FACTORY_ROOT}/vault/vault.log"
STATUSFILE="/tmp/vault-status"
LOCKFILE="/tmp/vault-poll.lock"
VAULT_DIR="${FACTORY_ROOT}/vault"
LOCKS_DIR="${VAULT_DIR}/.locks"
VAULT_SCRIPT_DIR="${FACTORY_ROOT}/vault"
OPS_VAULT_DIR="${OPS_REPO_ROOT}/vault"
LOCKS_DIR="${VAULT_SCRIPT_DIR}/.locks"
TIMEOUT_HOURS=48
@ -78,7 +79,7 @@ unlock_action() {
# =============================================================================
status "phase 1: retrying approved items"
for action_file in "${VAULT_DIR}/approved/"*.json; do
for action_file in "${OPS_VAULT_DIR}/approved/"*.json; do
[ -f "$action_file" ] || continue
ACTION_ID=$(jq -r '.id // ""' < "$action_file" 2>/dev/null)
[ -z "$ACTION_ID" ] && continue
@ -89,7 +90,7 @@ for action_file in "${VAULT_DIR}/approved/"*.json; do
fi
log "retrying approved action: $ACTION_ID"
if bash "${VAULT_DIR}/vault-fire.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1; then
if bash "${VAULT_SCRIPT_DIR}/vault-fire.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1; then
log "fired $ACTION_ID (retry)"
else
log "ERROR: fire failed for $ACTION_ID (retry)"
@ -99,7 +100,7 @@ for action_file in "${VAULT_DIR}/approved/"*.json; do
done
# Retry approved procurement requests (.md)
for req_file in "${VAULT_DIR}/approved/"*.md; do
for req_file in "${OPS_VAULT_DIR}/approved/"*.md; do
[ -f "$req_file" ] || continue
REQ_ID=$(basename "$req_file" .md)
@ -109,7 +110,7 @@ for req_file in "${VAULT_DIR}/approved/"*.md; do
fi
log "retrying approved procurement: $REQ_ID"
if bash "${VAULT_DIR}/vault-fire.sh" "$REQ_ID" >> "$LOGFILE" 2>&1; then
if bash "${VAULT_SCRIPT_DIR}/vault-fire.sh" "$REQ_ID" >> "$LOGFILE" 2>&1; then
log "fired procurement $REQ_ID (retry)"
else
log "ERROR: fire failed for procurement $REQ_ID (retry)"
@ -126,7 +127,7 @@ status "phase 2: checking escalation timeouts"
NOW_EPOCH=$(date +%s)
TIMEOUT_SECS=$((TIMEOUT_HOURS * 3600))
for action_file in "${VAULT_DIR}/pending/"*.json; do
for action_file in "${OPS_VAULT_DIR}/pending/"*.json; do
[ -f "$action_file" ] || continue
ACTION_STATUS=$(jq -r '.status // ""' < "$action_file" 2>/dev/null)
@ -142,7 +143,7 @@ for action_file in "${VAULT_DIR}/pending/"*.json; do
if [ "$AGE_SECS" -gt "$TIMEOUT_SECS" ]; then
AGE_HOURS=$((AGE_SECS / 3600))
log "timeout: $ACTION_ID escalated ${AGE_HOURS}h ago with no reply — auto-rejecting"
bash "${VAULT_DIR}/vault-reject.sh" "$ACTION_ID" "timeout (${AGE_HOURS}h, no human reply)" >> "$LOGFILE" 2>&1 || true
bash "${VAULT_SCRIPT_DIR}/vault-reject.sh" "$ACTION_ID" "timeout (${AGE_HOURS}h, no human reply)" >> "$LOGFILE" 2>&1 || true
fi
done
@ -154,7 +155,7 @@ status "phase 3: processing pending actions"
PENDING_COUNT=0
PENDING_SUMMARY=""
for action_file in "${VAULT_DIR}/pending/"*.json; do
for action_file in "${OPS_VAULT_DIR}/pending/"*.json; do
[ -f "$action_file" ] || continue
ACTION_STATUS=$(jq -r '.status // ""' < "$action_file" 2>/dev/null)
@ -181,7 +182,7 @@ if [ "$PENDING_COUNT" -gt 0 ]; then
log "found $PENDING_COUNT pending action(s), invoking vault-agent"
status "invoking vault-agent for $PENDING_COUNT action(s)"
bash "${VAULT_DIR}/vault-agent.sh" >> "$LOGFILE" 2>&1 || {
bash "${VAULT_SCRIPT_DIR}/vault-agent.sh" >> "$LOGFILE" 2>&1 || {
log "ERROR: vault-agent failed"
}
fi
@ -193,12 +194,12 @@ status "phase 4: processing pending procurement requests"
PROCURE_COUNT=0
for req_file in "${VAULT_DIR}/pending/"*.md; do
for req_file in "${OPS_VAULT_DIR}/pending/"*.md; do
[ -f "$req_file" ] || continue
REQ_ID=$(basename "$req_file" .md)
# Check if already notified (marker file)
if [ -f "${VAULT_DIR}/.locks/${REQ_ID}.notified" ]; then
if [ -f "${LOCKS_DIR}/${REQ_ID}.notified" ]; then
continue
fi
@ -215,8 +216,8 @@ for req_file in "${VAULT_DIR}/pending/"*.md; do
log "new procurement request: $REQ_ID$REQ_TITLE"
# Mark as notified so we don't re-send
mkdir -p "${VAULT_DIR}/.locks"
touch "${VAULT_DIR}/.locks/${REQ_ID}.notified"
mkdir -p "${LOCKS_DIR}"
touch "${LOCKS_DIR}/${REQ_ID}.notified"
unlock_action "$REQ_ID"
done
@ -239,7 +240,7 @@ if [ -n "${FORGE_REPO:-}" ] && [ -n "${FORGE_TOKEN:-}" ]; then
ISSUE_NUM=$(printf '%s' "$ACTION_ISSUES" | jq -r ".[$idx].number")
# Skip if already processed
if [ -f "${VAULT_DIR}/.locks/issue-${ISSUE_NUM}.vault-fired" ]; then
if [ -f "${LOCKS_DIR}/issue-${ISSUE_NUM}.vault-fired" ]; then
continue
fi
@ -272,21 +273,21 @@ if [ -n "${FORGE_REPO:-}" ] && [ -n "${FORGE_TOKEN:-}" ]; then
fi
# Skip if this action already exists in any stage
if [ -f "${VAULT_DIR}/approved/${ACTION_ID}.json" ] || \
[ -f "${VAULT_DIR}/fired/${ACTION_ID}.json" ] || \
[ -f "${VAULT_DIR}/rejected/${ACTION_ID}.json" ]; then
if [ -f "${OPS_VAULT_DIR}/approved/${ACTION_ID}.json" ] || \
[ -f "${OPS_VAULT_DIR}/fired/${ACTION_ID}.json" ] || \
[ -f "${OPS_VAULT_DIR}/rejected/${ACTION_ID}.json" ]; then
continue
fi
log "vault-bot authorized action on issue #${ISSUE_NUM}: ${ACTION_ID}"
printf '%s' "$ACTION_JSON" | jq '.status = "approved"' > "${VAULT_DIR}/approved/${ACTION_ID}.json"
printf '%s' "$ACTION_JSON" | jq '.status = "approved"' > "${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
COMMENT_COUNT=$((COMMENT_COUNT + 1))
# Fire the action
if bash "${VAULT_DIR}/vault-fire.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1; then
if bash "${VAULT_SCRIPT_DIR}/vault-fire.sh" "$ACTION_ID" >> "$LOGFILE" 2>&1; then
log "fired ${ACTION_ID} from issue #${ISSUE_NUM}"
# Mark issue as processed
touch "${VAULT_DIR}/.locks/issue-${ISSUE_NUM}.vault-fired"
touch "${LOCKS_DIR}/issue-${ISSUE_NUM}.vault-fired"
else
log "ERROR: fire failed for ${ACTION_ID} from issue #${ISSUE_NUM}"
fi

View file

@ -8,8 +8,9 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "${SCRIPT_DIR}/vault-env.sh"
VAULT_DIR="${FACTORY_ROOT}/vault"
LOGFILE="${VAULT_DIR}/vault.log"
OPS_VAULT_DIR="${OPS_REPO_ROOT}/vault"
LOGFILE="${FACTORY_ROOT}/vault/vault.log"
LOCKS_DIR="${FACTORY_ROOT}/vault/.locks"
log() {
printf '[%s] vault-reject: %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*" >> "$LOGFILE"
@ -20,10 +21,10 @@ REASON="${2:-unspecified}"
# Find the action file
ACTION_FILE=""
if [ -f "${VAULT_DIR}/pending/${ACTION_ID}.json" ]; then
ACTION_FILE="${VAULT_DIR}/pending/${ACTION_ID}.json"
elif [ -f "${VAULT_DIR}/approved/${ACTION_ID}.json" ]; then
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.json"
if [ -f "${OPS_VAULT_DIR}/pending/${ACTION_ID}.json" ]; then
ACTION_FILE="${OPS_VAULT_DIR}/pending/${ACTION_ID}.json"
elif [ -f "${OPS_VAULT_DIR}/approved/${ACTION_ID}.json" ]; then
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
else
log "ERROR: action $ACTION_ID not found in pending/ or approved/"
exit 1
@ -33,10 +34,10 @@ fi
TMP=$(mktemp)
jq --arg reason "$REASON" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.status = "rejected" | .rejected_at = $ts | .reject_reason = $reason' \
"$ACTION_FILE" > "$TMP" && mv "$TMP" "${VAULT_DIR}/rejected/${ACTION_ID}.json"
"$ACTION_FILE" > "$TMP" && mv "$TMP" "${OPS_VAULT_DIR}/rejected/${ACTION_ID}.json"
rm -f "$ACTION_FILE"
# Clean up lock if present
rm -f "${VAULT_DIR}/.locks/${ACTION_ID}.lock"
rm -f "${LOCKS_DIR}/${ACTION_ID}.lock"
log "$ACTION_ID: rejected — $REASON"

View file

@ -12,8 +12,9 @@
set -euo pipefail
VAULT_DIR="${DISINTO_VAULT_DIR:-/home/agent/disinto/vault}"
LOGFILE="${VAULT_DIR}/vault.log"
VAULT_SCRIPT_DIR="${DISINTO_VAULT_DIR:-/home/agent/disinto/vault}"
OPS_VAULT_DIR="${DISINTO_OPS_VAULT_DIR:-${VAULT_SCRIPT_DIR}}"
LOGFILE="${VAULT_SCRIPT_DIR}/vault.log"
ACTION_ID="${1:?Usage: vault-run-action.sh <action-id>}"
log() {
@ -22,7 +23,7 @@ log() {
}
# Find action file in approved/
ACTION_FILE="${VAULT_DIR}/approved/${ACTION_ID}.json"
ACTION_FILE="${OPS_VAULT_DIR}/approved/${ACTION_ID}.json"
if [ ! -f "$ACTION_FILE" ]; then
log "ERROR: action file not found: ${ACTION_FILE}"
echo "ERROR: action file not found: ${ACTION_FILE}" >&2
@ -118,7 +119,7 @@ case "$ACTION_TYPE" in
;;
blog-post|social-post|email-blast|pricing-change|dns-change|stripe-charge)
HANDLER="${VAULT_DIR}/handlers/${ACTION_TYPE}.sh"
HANDLER="${VAULT_SCRIPT_DIR}/handlers/${ACTION_TYPE}.sh"
if [ -x "$HANDLER" ]; then
bash "$HANDLER" "$ACTION_ID" "$PAYLOAD" 2>&1 || FIRE_EXIT=$?
else