feat: oc-scope-watchdog — auto-restores operator scopes after gateway restart
This commit is contained in:
parent
5aa0fff5fe
commit
78c72f4905
|
|
@ -5,8 +5,9 @@ Run after every gateway start to work around OC stripping scopes on restart.
|
|||
"""
|
||||
import json, glob, sys, os, time
|
||||
|
||||
# Give gateway a moment to write its files
|
||||
time.sleep(2)
|
||||
# Wait for gateway to fully initialize and write its files
|
||||
# (Gateway writes device-auth.json during startup, overwriting scopes)
|
||||
time.sleep(10)
|
||||
|
||||
BASE = os.path.expanduser('~/.openclaw')
|
||||
SCOPES = ['operator.write', 'operator.read']
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Watches OpenClaw device-auth.json and restores operator scopes when stripped.
|
||||
Runs as a persistent systemd service alongside openclaw-gateway.
|
||||
"""
|
||||
import json, glob, os, time, subprocess, sys
|
||||
|
||||
BASE = os.path.expanduser('~/.openclaw')
|
||||
DEVICE_AUTH = f'{BASE}/identity/device-auth.json'
|
||||
SCOPES = ['operator.write', 'operator.read']
|
||||
CHECK_INTERVAL = 30 # seconds
|
||||
|
||||
def get_scopes():
|
||||
try:
|
||||
with open(DEVICE_AUTH) as f:
|
||||
return json.load(f).get('scopes') or []
|
||||
except:
|
||||
return None
|
||||
|
||||
def restore_scopes():
|
||||
fixed = []
|
||||
# Fix device-auth.json
|
||||
try:
|
||||
with open(DEVICE_AUTH) as f:
|
||||
d = json.load(f)
|
||||
if d.get('scopes') != SCOPES:
|
||||
d['scopes'] = SCOPES
|
||||
with open(DEVICE_AUTH, 'w') as f:
|
||||
json.dump(d, f, indent=2)
|
||||
fixed.append('device-auth.json')
|
||||
except Exception as e:
|
||||
print(f'[scope-watchdog] device-auth error: {e}', file=sys.stderr)
|
||||
|
||||
# Fix devices/*.json
|
||||
for p in glob.glob(f'{BASE}/devices/*.json'):
|
||||
try:
|
||||
with open(p) as f:
|
||||
data = json.load(f)
|
||||
changed = False
|
||||
items = data if isinstance(data, list) else [data]
|
||||
for item in items:
|
||||
if isinstance(item, dict) and item.get('scopes') != SCOPES:
|
||||
item['scopes'] = SCOPES
|
||||
changed = True
|
||||
if changed:
|
||||
with open(p, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
fixed.append(os.path.basename(p))
|
||||
except:
|
||||
pass
|
||||
|
||||
return fixed
|
||||
|
||||
print('[scope-watchdog] Starting. Checking every 30s.', flush=True)
|
||||
|
||||
# Initial delay to let gateway fully start
|
||||
time.sleep(15)
|
||||
|
||||
while True:
|
||||
scopes = get_scopes()
|
||||
if scopes is None:
|
||||
print('[scope-watchdog] device-auth.json not found, waiting...', flush=True)
|
||||
elif scopes != SCOPES:
|
||||
print(f'[scope-watchdog] Scopes stripped ({scopes}), restoring...', flush=True)
|
||||
fixed = restore_scopes()
|
||||
if fixed:
|
||||
print(f'[scope-watchdog] Restored scopes in: {fixed}', flush=True)
|
||||
time.sleep(CHECK_INTERVAL)
|
||||
Loading…
Reference in New Issue