67 lines
2.2 KiB
Python
Executable File
67 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Officer platform: mask a secret in `chat_session_events`.
|
|
|
|
SPECIFIC TO THIS MACHINE. Officer's sidecar commits every turn — assistant text,
|
|
tool inputs and tool outputs — to Postgres, so the web chat can replay a session
|
|
after a restart. That makes it a second readable copy of the conversation, and
|
|
the one a browser shows. Rows age out after 7 days (`api/chat/retention.ts`);
|
|
this masks them now rather than waiting.
|
|
|
|
Contract: secret on stdin line 1, mask on line 2. Print one line. Exit non-zero
|
|
only if the store exists but could not be updated.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
DB = os.environ.get("OFFICER_PGDB", "officer_dev")
|
|
HOST = os.environ.get("OFFICER_PGHOST", "127.0.0.1")
|
|
USER = os.environ.get("OFFICER_PGUSER", "postgres")
|
|
PASSWORD = os.environ.get("OFFICER_PGPASSWORD", "postgres")
|
|
|
|
|
|
def main() -> int:
|
|
lines = sys.stdin.read().splitlines()
|
|
if len(lines) < 2:
|
|
print("bad input: expected secret then mask")
|
|
return 2
|
|
secret, mask = lines[0], lines[1]
|
|
|
|
quote = lambda v: "'" + v.replace("'", "''") + "'"
|
|
stmt = (
|
|
"update chat_session_events "
|
|
f"set event = replace(event::text, {quote(secret)}, {quote(mask)})::jsonb "
|
|
f"where event::text like {quote('%' + secret + '%')};"
|
|
)
|
|
|
|
try:
|
|
out = subprocess.run(
|
|
["psql", "-h", HOST, "-U", USER, "-d", DB, "-tAc", stmt],
|
|
capture_output=True, text=True, timeout=30,
|
|
env={**os.environ, "PGPASSWORD": PASSWORD},
|
|
)
|
|
except FileNotFoundError:
|
|
print("skipped: psql not installed")
|
|
return 0
|
|
except subprocess.TimeoutExpired:
|
|
print("skipped: psql timed out")
|
|
return 0
|
|
|
|
if out.returncode != 0:
|
|
err = out.stderr.strip().splitlines()
|
|
# Not this machine, or the platform is not installed here. Not a failure.
|
|
if any("does not exist" in e for e in err):
|
|
print("skipped: no officer database here")
|
|
return 0
|
|
print(f"FAILED: {err[0][:100] if err else 'unknown error'}")
|
|
return 1
|
|
|
|
count = out.stdout.strip().split()[-1] if out.stdout.strip() else "0"
|
|
print(f"chat_session_events: {count} row(s) masked")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|