#!/usr/bin/env python3 """run_action.py TAG APP — run actions.sh APP inside the guest; record its @ts lines as events. The password the action needs is the app's own generated admin password (from the `up` step's 0600 scratch file) or, for apps whose first user the action creates, a fresh one. It travels inside the piped script, never on a command line, and is never written to evidence. """ import json, os, re, secrets, sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import bench tag, app = sys.argv[1], sys.argv[2] gen = {} f = os.path.join(bench.SC, f".generated-{tag}.json") if os.path.exists(f): gen = json.load(open(f)).get(app, {}) pw = gen.get("PAPERLESS_ADMIN_PASSWORD") or gen.get("NEXTCLOUD_ADMIN_PASSWORD") or ("Sz-" + secrets.token_hex(12)) script = f"export PW='{pw}'\n" + open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "actions.sh")).read().replace( 'APP=${1:?app}', f'APP={app}') out = bench.guest(script, timeout=6 * 3600) assert pw not in out, "secret in output" d = os.path.join(bench.AUDIT, "evidence", tag); os.makedirs(d, exist_ok=True) open(os.path.join(d, f"action-{app}.txt"), "a").write(out) bench._load(tag) for m in re.finditer(r"^@(\d+) (\S+)(.*)$", out, re.M): bench.EVENTS.append(dict(ts=int(m.group(1)), kind=m.group(2), app=app, note=m.group(3).strip())) bench._save(tag) print(out)