Weekly sync: July 12-19 changes

- Updated DREAMS.md and MEMORY.md with new entries
- Added daily dreaming session corpus (2026-07-05 through 2026-07-18)
- Added deep/light/REM dream analysis files for July 6-19
- Added Intune rollout outputs for KMCC client
- Added Vault API integration scripts and documentation
- Added container update playbook (update-containers.yml)
- Added .gitignore for generated/noise files
This commit is contained in:
JC Beasley
2026-07-19 08:49:43 -07:00
parent 0f7147531e
commit 9891d7e4d5
85 changed files with 10471 additions and 6 deletions
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# Get Grist API token from Vault
# Usage: source get_grist_token.sh (requires VAULT_TOKEN from vault_auth.sh)
if [ -z "$VAULT_TOKEN" ]; then
echo "Error: Run vault_auth.sh first"
return 1
fi
export GRIST_TOKEN=*** -sk -H "X-Vault-Token: $VAULT_TOKEN" \
"https://beavault.beawit.net:8200/v1/kv/data/api/integration/grist" | jq -r '.data.data.token')
if [ -z "$GRIST_TOKEN" ] || [ "$GRIST_TOKEN" = "null" ]; then
echo "Failed to get Grist token from Vault"
return 1
fi
echo "Grist token retrieved: ${GRIST_TOKEN:***
+102
View File
@@ -0,0 +1,102 @@
#!/bin/bash
# Self-healing Grist API wrapper
# Tries cached token first, auto-refreshes from Vault on failure
TOKEN_DIR="/home/jcbeasley/.openclaw/workspace/.tokens"
VAULT_URL="https://beavault.beawit.net:8200"
GRIST_URL="https://grist.beawit.net"
GRIST_TOKEN_FILE="$TOKEN_DIR/grist_token"
METHOD="$1"
API_PATH="$2"
PAYLOAD_FILE="$3"
if [ -z "$METHOD" ] || [ -z "$API_PATH" ]; then
echo "Usage: bash grist_api.sh <METHOD> <API_PATH> [payload_file]"
exit 1
fi
# Function to refresh tokens from Vault
refresh_tokens() {
mkdir -p "$TOKEN_DIR"
# Vault auth
curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"$VAULT_URL/v1/auth/approle/login" \
> "$TOKEN_DIR/vault_auth.json"
python3 -c "
import json
with open('$TOKEN_DIR/vault_auth.json') as f:
data = json.load(f)
with open('$TOKEN_DIR/vault_token', 'w') as out:
out.write(data['auth']['client_token'])
"
# Get Grist token
curl -sk -H "X-Vault-Token: $(cat $TOKEN_DIR/vault_token)" \
"$VAULT_URL/v1/kv/data/api/integration/grist" \
> "$TOKEN_DIR/grist_from_vault.json"
python3 -c "
import json
with open('$TOKEN_DIR/grist_from_vault.json') as f:
data = json.load(f)
with open('$TOKEN_DIR/grist_token', 'w') as out:
out.write(data['data']['data']['token'])
"
rm -f "$TOKEN_DIR/vault_auth.json" "$TOKEN_DIR/grist_from_vault.json"
}
# Function to make Grist API call
api_call() {
local http_code
if [ "$METHOD" = "GET" ]; then
http_code=$(curl -sk -w "%{http_code}" -o "$TOKEN_DIR/last_response.json" \
-H "Authorization: Bearer $(cat $GRIST_TOKEN_FILE)" \
-H "Content-Type: application/json" \
"$GRIST_URL$API_PATH")
elif [ "$METHOD" = "PATCH" ] && [ -n "$PAYLOAD_FILE" ]; then
http_code=$(curl -sk -w "%{http_code}" -o "$TOKEN_DIR/last_response.json" \
-H "Authorization: Bearer $(cat $GRIST_TOKEN_FILE)" \
-H "Content-Type: application/json" \
-X PATCH \
-d "@$PAYLOAD_FILE" \
"$GRIST_URL$API_PATH")
else
echo "Error: Unsupported method or missing payload"
return 1
fi
echo "$http_code"
}
# Main logic: try cached token, refresh on failure, retry
if [ ! -f "$GRIST_TOKEN_FILE" ]; then
refresh_tokens
fi
HTTP_CODE=$(api_call)
# If unauthorized (401) or forbidden (403), refresh and retry
if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
refresh_tokens
HTTP_CODE=$(api_call)
fi
# Output response
if [ -f "$TOKEN_DIR/last_response.json" ]; then
cat "$TOKEN_DIR/last_response.json"
rm -f "$TOKEN_DIR/last_response.json"
fi
# Return appropriate exit code
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "204" ]; then
exit 0
else
echo "Error: HTTP $HTTP_CODE" >&2
exit 1
fi
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
# Refresh Vault and Grist tokens
# Tokens are written to files only, never exposed in stdout
TOKEN_DIR="/home/jcbeasley/.openclaw/workspace/.tokens"
VAULT_URL="https://beavault.beawit.net:8200"
mkdir -p "$TOKEN_DIR"
# Step 1: Authenticate to Vault
curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"$VAULT_URL/v1/auth/approle/login" \
> "$TOKEN_DIR/vault_auth_response.json"
# Step 2: Extract Vault token
python3 -c "
import json
with open('$TOKEN_DIR/vault_auth_response.json') as f:
data = json.load(f)
token = data['auth']['client_token']
with open('$TOKEN_DIR/vault_token', 'w') as out:
out.write(token)
"
# Step 3: Get Grist token from Vault (direct file reference, no variable assignment)
curl -sk -H "X-Vault-Token: $(cat $TOKEN_DIR/vault_token)" \
"$VAULT_URL/v1/kv/data/api/integration/grist" \
> "$TOKEN_DIR/grist_vault_response.json"
# Step 4: Extract Grist token
python3 -c "
import json
with open('$TOKEN_DIR/grist_vault_response.json') as f:
data = json.load(f)
token = data['data']['data']['token']
with open('$TOKEN_DIR/grist_token', 'w') as out:
out.write(token)
"
# Step 5: Clean up
rm -f "$TOKEN_DIR/vault_auth_response.json" "$TOKEN_DIR/grist_vault_response.json"
echo "Tokens refreshed successfully"
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
# Store Grist token in Vault
# Usage: GRIST_TOKEN="your-token-here" bash store_grist_token.sh
if [ -z "$GRIST_TOKEN" ]; then
echo "Error: Set GRIST_TOKEN environment variable first"
echo "Example: GRIST_TOKEN='your-token' bash store_grist_token.sh"
exit 1
fi
VAULT_TOKEN=$(curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"https://beavault.beawit.net:8200/v1/auth/approle/login" | jq -r '.auth.client_token')
echo "Storing Grist token in Vault..."
curl -sk -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":{\"token\":\"$GRIST_TOKEN\"}}" \
"https://beavault.beawit.net:8200/v1/kv/data/api/integration/grist"
echo ""
echo "Verifying..."
curl -sk -H "X-Vault-Token: $VAULT_TOKEN" \
"https://beavault.beawit.net:8200/v1/kv/data/api/integration/grist" | jq -r '.data.data.token'
echo ""
echo "Done. Token stored at kv/data/api/integration/grist"
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
# Update Grist tracker with corrected weekly batches
# Run this script with: bash update_grist_batches.sh
TOKEN="014e699c256edf1b3164f7cae21ba7c41de9bd41"
DOC_ID="wmBGUbgBveCdeY8fZ6T6eL"
API_URL="https://grist.beawit.net/api/docs/$DOC_ID/tables/Intune/records"
# Week 1 - Email Sent (7 users: IDs 2-8)
# Already Enrolled (6 users: IDs 1, 15, 23, 24, 54, 62)
# Weeks 2-11 (50 users, 5/week)
curl -sk "$API_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-X PATCH \
-d '{"records":[
{"id":1,"fields":{"Batch":"Enrolled - Complete"}},
{"id":2,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":3,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":4,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":5,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":6,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":7,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":8,"fields":{"Batch":"Week 1 (Jul 21) - Email Sent"}},
{"id":9,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":10,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":11,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":12,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":13,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":14,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":15,"fields":{"Batch":"Enrolled - Complete"}},
{"id":16,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":17,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":18,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":19,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":20,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":21,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":22,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":23,"fields":{"Batch":"Enrolled - Complete"}},
{"id":24,"fields":{"Batch":"Enrolled - Complete"}},
{"id":25,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":26,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":27,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":28,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":29,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":30,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":31,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":32,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":33,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":34,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":35,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":36,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":37,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":38,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":39,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":40,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":41,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":42,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":43,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":44,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":45,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":46,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":47,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":48,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":49,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":50,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":51,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":52,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":53,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":54,"fields":{"Batch":"Enrolled - Complete"}},
{"id":55,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":56,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":57,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":58,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":59,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":60,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":61,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":62,"fields":{"Batch":"Enrolled - Complete"}},
{"id":63,"fields":{"Batch":"Week 11 (Sep 29)"}}
]}'
echo "Grist update complete"
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# Update Grist tracker with clean weekly batches
# Week 1 = users with email sent (7 users, IDs 2-8)
# Already enrolled = 6 users (IDs 1, 15, 23, 24, 54, 62)
# Weeks 2-11 = remaining 50 users, 5 per week
TOKEN="014e69…bd41"
DOC_ID="wmBGUbgBveCdeY8fZ6T6eL"
API_URL="https://grist.beawit.net/api/docs/$DOC_ID/tables/Intune/records"
curl -sk "$API_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-X PATCH \
-d '{"records":[
{"id":1,"fields":{"Batch":"Enrolled"}},
{"id":2,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":3,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":4,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":5,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":6,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":7,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":8,"fields":{"Batch":"Week 1 (Jul 21)"}},
{"id":9,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":10,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":11,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":12,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":13,"fields":{"Batch":"Week 2 (Jul 28)"}},
{"id":14,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":15,"fields":{"Batch":"Enrolled"}},
{"id":16,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":17,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":18,"fields":{"Batch":"Week 3 (Aug 4)"}},
{"id":19,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":20,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":21,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":22,"fields":{"Batch":"Week 4 (Aug 11)"}},
{"id":23,"fields":{"Batch":"Enrolled"}},
{"id":24,"fields":{"Batch":"Enrolled"}},
{"id":25,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":26,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":27,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":28,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":29,"fields":{"Batch":"Week 5 (Aug 18)"}},
{"id":30,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":31,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":32,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":33,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":34,"fields":{"Batch":"Week 6 (Aug 25)"}},
{"id":35,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":36,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":37,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":38,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":39,"fields":{"Batch":"Week 7 (Sep 1)"}},
{"id":40,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":41,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":42,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":43,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":44,"fields":{"Batch":"Week 8 (Sep 8)"}},
{"id":45,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":46,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":47,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":48,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":49,"fields":{"Batch":"Week 9 (Sep 15)"}},
{"id":50,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":51,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":52,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":53,"fields":{"Batch":"Week 10 (Sep 22)"}},
{"id":54,"fields":{"Batch":"Enrolled"}},
{"id":55,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":56,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":57,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":58,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":59,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":60,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":61,"fields":{"Batch":"Week 11 (Sep 29)"}},
{"id":62,"fields":{"Batch":"Enrolled"}},
{"id":63,"fields":{"Batch":"Week 11 (Sep 29)"}}
]}'
echo "Grist update complete - clean batch assignments"
+98
View File
@@ -0,0 +1,98 @@
#!/bin/bash
# Update Survey_Date column in Grist using Vault for API token
# Step 1: Get Vault token
VAULT_RESPONSE=$(curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"https://beavault.beawit.net:8200/v1/auth/approle/login")
VAULT_TOKEN=$(echo "$VAULT_RESPONSE" | jq -r '.auth.client_token')
if [ -z "$VAULT_TOKEN" ] || [ "$VAULT_TOKEN" = "null" ]; then
echo "Failed to get Vault token"
exit 1
fi
# Step 2: Get Grist token from Vault
GRIST_RESPONSE=$(curl -sk -H "X-Vault-Token: $VAULT_TOKEN" \
"https://beavault.beawit.net:8200/v1/kv/data/api/integration/grist")
GRIST_TOKEN=$(echo "$GRIST_RESPONSE" | jq -r '.data.data.token')
if [ -z "$GRIST_TOKEN" ] || [ "$GRIST_TOKEN" = "null" ]; then
echo "Failed to get Grist token from Vault"
exit 1
fi
echo "Vault auth: OK"
echo "Grist token retrieved: ${GRIST_TOKEN:0:10}..."
# Step 3: Update Survey_Date in Grist
API_URL="https://grist.beawit.net/api/docs/wmBGUbgBveCdeY8fZ6T6eL/tables/Intune/records"
curl -sk "$API_URL" \
-H "Authorization: Bearer $GRIST_TOKEN" \
-H "Content-Type: application/json" \
-X PATCH \
-d '{"records":[
{"id":2,"fields":{"Survey_Date":"2026-07-25"}},
{"id":3,"fields":{"Survey_Date":"2026-07-25"}},
{"id":4,"fields":{"Survey_Date":"2026-07-25"}},
{"id":5,"fields":{"Survey_Date":"2026-07-25"}},
{"id":6,"fields":{"Survey_Date":"2026-07-25"}},
{"id":7,"fields":{"Survey_Date":"2026-07-25"}},
{"id":8,"fields":{"Survey_Date":"2026-07-25"}},
{"id":9,"fields":{"Survey_Date":"2026-08-01"}},
{"id":10,"fields":{"Survey_Date":"2026-08-01"}},
{"id":11,"fields":{"Survey_Date":"2026-08-01"}},
{"id":12,"fields":{"Survey_Date":"2026-08-01"}},
{"id":13,"fields":{"Survey_Date":"2026-07-25"}},
{"id":14,"fields":{"Survey_Date":"2026-08-01"}},
{"id":16,"fields":{"Survey_Date":"2026-08-08"}},
{"id":17,"fields":{"Survey_Date":"2026-08-08"}},
{"id":18,"fields":{"Survey_Date":"2026-08-08"}},
{"id":19,"fields":{"Survey_Date":"2026-08-08"}},
{"id":20,"fields":{"Survey_Date":"2026-08-08"}},
{"id":21,"fields":{"Survey_Date":"2026-08-15"}},
{"id":22,"fields":{"Survey_Date":"2026-08-15"}},
{"id":25,"fields":{"Survey_Date":"2026-08-15"}},
{"id":26,"fields":{"Survey_Date":"2026-08-15"}},
{"id":27,"fields":{"Survey_Date":"2026-08-15"}},
{"id":28,"fields":{"Survey_Date":"2026-08-22"}},
{"id":29,"fields":{"Survey_Date":"2026-08-22"}},
{"id":30,"fields":{"Survey_Date":"2026-07-25"}},
{"id":31,"fields":{"Survey_Date":"2026-08-22"}},
{"id":32,"fields":{"Survey_Date":"2026-08-22"}},
{"id":33,"fields":{"Survey_Date":"2026-08-22"}},
{"id":34,"fields":{"Survey_Date":"2026-08-29"}},
{"id":35,"fields":{"Survey_Date":"2026-08-29"}},
{"id":36,"fields":{"Survey_Date":"2026-08-29"}},
{"id":37,"fields":{"Survey_Date":"2026-08-29"}},
{"id":38,"fields":{"Survey_Date":"2026-08-29"}},
{"id":39,"fields":{"Survey_Date":"2026-09-05"}},
{"id":40,"fields":{"Survey_Date":"2026-09-05"}},
{"id":41,"fields":{"Survey_Date":"2026-09-05"}},
{"id":42,"fields":{"Survey_Date":"2026-09-05"}},
{"id":43,"fields":{"Survey_Date":"2026-09-05"}},
{"id":44,"fields":{"Survey_Date":"2026-09-12"}},
{"id":45,"fields":{"Survey_Date":"2026-09-12"}},
{"id":46,"fields":{"Survey_Date":"2026-09-12"}},
{"id":47,"fields":{"Survey_Date":"2026-09-12"}},
{"id":48,"fields":{"Survey_Date":"2026-09-12"}},
{"id":49,"fields":{"Survey_Date":"2026-09-19"}},
{"id":50,"fields":{"Survey_Date":"2026-09-19"}},
{"id":51,"fields":{"Survey_Date":"2026-09-19"}},
{"id":52,"fields":{"Survey_Date":"2026-09-19"}},
{"id":53,"fields":{"Survey_Date":"2026-09-19"}},
{"id":55,"fields":{"Survey_Date":"2026-09-26"}},
{"id":56,"fields":{"Survey_Date":"2026-09-26"}},
{"id":57,"fields":{"Survey_Date":"2026-09-26"}},
{"id":58,"fields":{"Survey_Date":"2026-09-26"}},
{"id":59,"fields":{"Survey_Date":"2026-09-26"}},
{"id":60,"fields":{"Survey_Date":"2026-10-03"}},
{"id":61,"fields":{"Survey_Date":"2026-10-03"}},
{"id":63,"fields":{"Survey_Date":"2026-10-03"}}
]}'
echo ""
echo "Survey dates update complete"
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
"""
Generic API wrapper using Vault for dynamic token retrieval.
Supports Vault paths where tokens are stored as keys under a category.
Usage: python3 vault_api.py <METHOD> <BASE_URL> <API_PATH> <VAULT_PATH> <TOKEN_KEY> [header_type] [payload_file]
"""
import sys
import json
import urllib.request
import ssl
# Disable SSL verification for self-signed certs
ssl._create_default_https_context = ssl._create_unverified_context
VAULT_URL = "https://beavault.beawit.net:8200"
def vault_auth():
"""Authenticate to Vault and return client token."""
auth_data = json.dumps({
"role_id": "75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e",
"secret_id": "6202b465-2f25-547c-ec07-f47cfc4dda3e"
}).encode()
req = urllib.request.Request(
f"{VAULT_URL}/v1/auth/approle/login",
data=auth_data,
headers={"Content-Type": "application/json"},
method="POST"
)
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read())
return data["auth"]["client_token"]
def get_service_token(vault_token, vault_path, token_key):
"""Retrieve specific token from Vault category."""
req = urllib.request.Request(
f"{VAULT_URL}/v1/kv/data/{vault_path}",
headers={"X-Vault-Token": vault_token}
)
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read())
secret_data = data["data"]["data"]
if token_key in secret_data:
return secret_data[token_key]
else:
available = list(secret_data.keys())
raise KeyError(f"Token key '{token_key}' not found. Available: {available}")
def api_call(method, base_url, api_path, vault_path, token_key, header_type="Bearer", payload_file=None):
"""Make authenticated API call."""
vault_token = vault_auth()
service_token = get_service_token(vault_token, vault_path, token_key)
url = f"{base_url}{api_path}"
headers = {"Content-Type": "application/json"}
if header_type.lower() == "xc-token":
headers["xc-token"] = service_token
elif header_type.lower() in ["api-key", "x-api-key"]:
headers["api-key"] = service_token
elif header_type.lower() == "x-vault-token":
headers["X-Vault-Token"] = service_token
else:
headers["Authorization"] = f"Bearer {service_token}"
if method == "GET":
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
elif method in ["POST", "PATCH"]:
data = None
if payload_file:
import os
if os.path.exists(payload_file):
with open(payload_file) as f:
data = json.dumps(json.load(f)).encode()
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
else:
raise ValueError(f"Unsupported method: {method}")
def main():
if len(sys.argv) < 6:
print("Usage: python3 vault_api.py <METHOD> <BASE_URL> <API_PATH> <VAULT_PATH> <TOKEN_KEY> [header_type] [payload_file]")
print("Examples:")
print(' python3 vault_api.py GET "https://grist.beawit.net" "/api/..." "api/integration" "grist"')
print(' python3 vault_api.py GET "http://192.168.25.5:8080" "/api/..." "api/infrastructure" "nocodb-token" "xc-token"')
print(' python3 vault_api.py GET "http://192.168.19.17:6333" "/collections" "api/infrastructure" "qdrant-api-key" "api-key"')
sys.exit(1)
method = sys.argv[1].upper()
base_url = sys.argv[2]
api_path = sys.argv[3]
vault_path = sys.argv[4]
token_key = sys.argv[5]
header_type = sys.argv[6] if len(sys.argv) > 6 else "Bearer"
payload_file = sys.argv[7] if len(sys.argv) > 7 else None
result = api_call(method, base_url, api_path, vault_path, token_key, header_type, payload_file)
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
+148
View File
@@ -0,0 +1,148 @@
#!/bin/bash
# Generic API wrapper using Vault for dynamic token retrieval
# Supports multiple auth header types
# Usage: bash vault_api.sh <METHOD> <BASE_URL> <API_PATH> <VAULT_KEY> [header_type] [payload_file]
# Examples:
# bash vault_api.sh GET "https://grist.beawit.net" "/api/..." "api/integration/grist" "Bearer"
# bash vault_api.sh GET "http://192.168.25.5:8080" "/api/..." "api/integration/nocodb" "xc-token"
TOKEN_DIR="/home/jcbeasley/.openclaw/workspace/.tokens"
VAULT_URL="https://beavault.beawit.net:8200"
METHOD="$1"
BASE_URL="$2"
API_PATH="$3"
VAULT_KEY="***"
HEADER_TYPE="${5:-Bearer}"
PAYLOAD_FILE="$6"
if [ -z "$METHOD" ] || [ -z "$BASE_URL" ] || [ -z "$API_PATH" ] || [ -z "$VAULT_KEY" ]; then
echo "Usage: bash vault_api.sh <METHOD> <BASE_URL> <API_PATH> <VAULT_KEY> [header_type] [payload_file]"
echo "Header types: Bearer (default), xc-token, api-key, X-Api-Key, X-Vault-Token"
echo "Example: bash vault_api.sh GET 'https://grist.beawit.net' '/api/...' 'api/integration/grist' 'Bearer'"
exit 1
fi
mkdir -p "$TOKEN_DIR"
# Function to get Vault token
cache_vault_token() {
local cached_token="$TOKEN_DIR/vault_session_token"
if [ -f "$cached_token" ]; then
local test_resp
test_resp=$(curl -sk -H "X-Vault-Token: $(cat $cached_token)" "$VAULT_URL/v1/sys/health" 2>/dev/null)
if [ -n "$test_resp" ]; then
cat "$cached_token"
return 0
fi
fi
curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"$VAULT_URL/v1/auth/approle/login" > "$TOKEN_DIR/vault_auth.json"
python3 -c "
import json
with open('$TOKEN_DIR/vault_auth.json') as f:
data = json.load(f)
with open('$cached_token', 'w') as out:
out.write(data['auth']['client_token'])
"
rm -f "$TOKEN_DIR/vault_auth.json"
cat "$cached_token"
}
# Function to get service token
cache_service_token() {
local vault_token="$1"
local vault_key="$2"
local cache_file="$TOKEN_DIR/service_$(echo "$vault_key" | tr '/' '_').token"
if [ -f "$cache_file" ]; then
local age
age=$(($(date +%s) - $(stat -c %Y "$cache_file")))
if [ "$age" -lt 3600 ]; then
cat "$cache_file"
return 0
fi
fi
curl -sk -H "X-Vault-Token: $vault_token" \
"$VAULT_URL/v1/kv/data/$vault_key" > "$TOKEN_DIR/service_resp.json"
python3 -c "
import json
with open('$TOKEN_DIR/service_resp.json') as f:
data = json.load(f)
token = data['data']['data']['token']
with open('$cache_file', 'w') as out:
out.write(token)
"
rm -f "$TOKEN_DIR/service_resp.json"
cat "$cache_file"
}
# Build auth header based on type
build_auth_header() {
local header_type="$1"
local token="$2"
case "$header_type" in
"xc-token")
echo "xc-token: $token"
;;
"api-key"|"API-Key")
echo "API-Key: $token"
;;
"X-Api-Key"|"x-api-key")
echo "X-Api-Key: $token"
;;
"X-Vault-Token"|"vault")
echo "X-Vault-Token: $token"
;;
"Bearer"|*)
echo "Authorization: Bearer $token"
;;
esac
}
# Main logic
VAULT_TOKEN=$(cache_vault_token)
SERVICE_TOKEN=$(cache_service_token "$VAULT_TOKEN" "$VAULT_KEY")
AUTH_HEADER=$(build_auth_header "$HEADER_TYPE" "$SERVICE_TOKEN")
URL="${BASE_URL}${API_PATH}"
RESPONSE_FILE="$TOKEN_DIR/last_response.json"
# Execute API call
if [ "$METHOD" = "GET" ]; then
curl -sk -w "\nHTTP_CODE:%{http_code}" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-o "$RESPONSE_FILE" \
"$URL"
elif [ "$METHOD" = "PATCH" ] && [ -n "$PAYLOAD_FILE" ]; then
curl -sk -w "\nHTTP_CODE:%{http_code}" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-X PATCH \
-d "@$PAYLOAD_FILE" \
-o "$RESPONSE_FILE" \
"$URL"
elif [ "$METHOD" = "POST" ] && [ -n "$PAYLOAD_FILE" ]; then
curl -sk -w "\nHTTP_CODE:%{http_code}" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-X POST \
-d "@$PAYLOAD_FILE" \
-o "$RESPONSE_FILE" \
"$URL"
else
echo "Error: Unsupported method or missing payload file"
exit 1
fi
# Output response
cat "$RESPONSE_FILE"
rm -f "$RESPONSE_FILE"
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# Reusable Vault authentication script
# Usage: source vault_auth.sh
export VAULT_TOKEN=*** -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"https://beavault.beawit.net:8200/v1/auth/approle/login" | jq -r '.auth.client_token')
if [ -z "$VAULT_TOKEN" ] || [ "$VAULT_TOKEN" = "null" ]; then
echo "Vault authentication failed"
return 1
fi
echo "Vault authenticated successfully"
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""
Generic Grist API wrapper using Vault for token retrieval.
Usage: python3 vault_grist_api.py <METHOD> <API_PATH> [JSON_PAYLOAD]
Example: python3 vault_grist_api.py GET /api/docs/wmBGUbgBveCdeY8fZ6T6eL/tables/Intune/records
"""
import sys
import json
import urllib.request
import urllib.error
VAULT_URL = "https://beavault.beawit.net:8200"
GRIST_URL = "https://grist.beawit.net"
def vault_auth():
"""Authenticate to Vault and return client token."""
auth_data = json.dumps({
"role_id": "75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e",
"secret_id": "6202b465-2f25-547c-ec07-f47cfc4dda3e"
}).encode()
req = urllib.request.Request(
f"{VAULT_URL}/v1/auth/approle/login",
data=auth_data,
headers={"Content-Type": "application/json"},
method="POST"
)
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read())
return data["auth"]["client_token"]
def get_grist_token(vault_token):
"""Retrieve Grist API token from Vault."""
req = urllib.request.Request(
f"{VAULT_URL}/v1/kv/data/api/integration/grist",
headers={"X-Vault-Token": vault_token}
)
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read())
return data["data"]["data"]["token"]
def grist_api_call(method, api_path, payload=None):
"""Make authenticated Grist API call."""
# Step 1: Vault auth
vault_token = vault_auth()
# Step 2: Get Grist token
grist_token = get_grist_token(vault_token)
# Step 3: Make API call
url = f"{GRIST_URL}{api_path}"
headers = {
"Authorization": f"Bearer {grist_token}",
"Content-Type": "application/json"
}
if method == "GET":
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
elif method == "PATCH":
data = json.dumps(payload).encode() if payload else None
req = urllib.request.Request(url, data=data, headers=headers, method="PATCH")
with urllib.request.urlopen(req) as resp:
return resp.read().decode()
else:
raise ValueError(f"Unsupported method: {method}")
def main():
if len(sys.argv) < 3:
print("Usage: python3 vault_grist_api.py <METHOD> <API_PATH> [JSON_PAYLOAD_FILE]")
sys.exit(1)
method = sys.argv[1].upper()
api_path = sys.argv[2]
payload = None
if len(sys.argv) > 3:
with open(sys.argv[3]) as f:
payload = json.load(f)
result = grist_api_call(method, api_path, payload)
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
+55
View File
@@ -0,0 +1,55 @@
#!/bin/bash
# Generic Grist API wrapper using Vault for token retrieval
# Usage: bash vault_grist_api.sh <METHOD> <API_PATH> [optional: JSON_PAYLOAD_FILE]
# Example: bash vault_grist_api.sh GET /api/docs/wmBGUbgBveCdeY8fZ6T6eL/tables/Intune/records
METHOD="$1"
API_PATH="$2"
PAYLOAD_FILE="$3"
if [ -z "$METHOD" ] || [ -z "$API_PATH" ]; then
echo "Usage: bash vault_grist_api.sh <METHOD> <API_PATH> [payload_file]"
echo "Example: bash vault_grist_api.sh GET /api/docs/wmBGUbgBveCdeY8fZ6T6eL/tables/Intune/records"
exit 1
fi
# Step 1: Authenticate to Vault
VAULT_AUTH=$(curl -sk -X POST \
-d '{"role_id":"75d2dcfb-9c65-7f60-59b4-eee8c7f8dc0e","secret_id":"6202b465-2f25-547c-ec07-f47cfc4dda3e"}' \
"https://beavault.beawit.net:8200/v1/auth/approle/login")
VAULT_TOKEN=*** "$VAULT_AUTH" | jq -r '.auth.client_token')
if [ -z "$VAULT_TOKEN" ] || [ "$VAULT_TOKEN" = "null" ]; then
echo "Error: Vault authentication failed"
exit 1
fi
# Step 2: Retrieve Grist token from Vault
GRIST_DATA=$(curl -sk -H "X-Vault-Token: $VAULT_TOKEN" \
"https://beavault.beawit.net:8200/v1/kv/data/api/integration/grist")
GRIST_TOKEN=*** "$GRIST_DATA" | jq -r '.data.data.token')
if [ -z "$GRIST_TOKEN" ] || [ "$GRIST_TOKEN" = "null" ]; then
echo "Error: Failed to retrieve Grist token from Vault"
exit 1
fi
# Step 3: Make Grist API call
GRIST_URL="https://grist.beawit.net${API_PATH}"
if [ "$METHOD" = "GET" ]; then
curl -sk "$GRIST_URL" \
-H "Authorization: Bearer $GRIST_TOKEN" \
-H "Content-Type: application/json"
elif [ "$METHOD" = "PATCH" ] && [ -n "$PAYLOAD_FILE" ]; then
curl -sk "$GRIST_URL" \
-H "Authorization: Bearer $GRIST_TOKEN" \
-H "Content-Type: application/json" \
-X PATCH \
-d "@$PAYLOAD_FILE"
else
echo "Error: Unsupported method or missing payload file for PATCH"
exit 1
fi