railiance-platform/tests/test_fluid_telegram_custody_move.py
codex bed91ceaf2
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
RPF-WP-0035-T03: fluid-telegram operator matrix lane and custody helpers
- New CCR request type workload-kv-operator-matrix (scripts/operator_matrix_lane.py):
  exact per-entry create/read/update, OIDC role on the existing netkingdom mount,
  and exact agent denies appended to the live agent-high-risk-boundary (live
  content preserved, partial presence refused). credential-change.py now
  dispatches lane request types through one module table.
- CCR-2026-0039 (proposed): hall-of-helix four-entry matrix at tenant coulomb
  per the founder ruling of 2026-10-09; policy, role and overlay sources.
- scripts/fluid_telegram_custody_move.py: silent CAS-0 move of the four
  undocumented infotech entries, deleting sources only after all verify.
- scripts/kv_duplicate_retire.py: silent retirement of
  activity-core/default/llm-connect-provider-secrets once no live non-admin
  policy grants it.
- Founder session commands recorded in the T03 note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 469992@bnt-lap001
Assistant-Session: e4b8e420-df0a-441d-83ae-7f19130594d9
2026-10-09 12:10:21 +02:00

144 lines
6.5 KiB
Python

"""Offline tests for the fluid-telegram custody move helper against a fake ``bao``.
Runs the helper as a real subprocess with a fake ``bao`` first on PATH, so the
silence contract (empty stdout and stderr) is tested end to end.
"""
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import textwrap
import unittest
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / 'scripts/fluid_telegram_custody_move.py'
CONFIRM = 'MOVE fluid-telegram hall-of-helix to coulomb'
SRC = 'workloads/infotech/fluid-telegram/hall-of-helix'
DST = 'workloads/coulomb/fluid-telegram/hall-of-helix'
VALUES = {
'bot-token': {'token': 'bt-' + 'Q1w2' * 10},
'operator-app': {'api_id': '1234567', 'api_hash': 'ah-' + 'E3r4' * 8},
'operator-session': {'session_b64': 'c2Vzc2lvbg' * 12},
'redaction-salt': {'salt': 'sa-' + 'T5y6' * 8},
}
FAKE_BAO = textwrap.dedent('''\
#!/usr/bin/env python3
import json, os, sys
sf = os.environ['FAKE_BAO_STATE']
st = json.load(open(sf))
st['calls'].append(sys.argv[1:])
def save(): json.dump(st, open(sf, 'w'))
def out(obj): save(); print(json.dumps(obj)); sys.exit(0)
def missing(): save(); sys.stderr.write('No value found at x\\n'); sys.exit(2)
a = sys.argv[1:]
print('Success! noise', file=sys.stderr)
if a[0] == 'read':
p = a[-1]
if p == 'auth/token/lookup-self':
out({'data': st['identity']})
mount, kind, rest = p.split('/', 2)
e = st['kv'].get(rest)
if not e: missing()
cv = len(e['versions'])
if kind == 'metadata':
out({'data': {'current_version': cv, 'versions': {str(i + 1): {} for i in range(cv)}}})
out({'data': {'data': e['versions'][-1], 'metadata': {'version': cv}}})
if a[0] == 'write':
p = a[-2].split('/', 2)[2]
body = json.loads(sys.stdin.read())
if st.get('fail_write'): save(); sys.exit(2)
e = st['kv'].setdefault(p, {'versions': []})
if body['options']['cas'] != len(e['versions']): save(); sys.exit(2)
e['versions'].append(body['data'])
out({'data': {'version': len(e['versions'])}})
if a[0] == 'delete':
st['kv'].pop(a[1].split('/', 2)[2], None)
save(); sys.exit(0)
save(); sys.exit(9)
''')
class CustodyMove(unittest.TestCase):
def setUp(self):
self.tmp = Path(tempfile.mkdtemp())
(self.tmp / 'bin').mkdir()
fake = self.tmp / 'bin/bao'
fake.write_text(FAKE_BAO)
fake.chmod(0o755)
self.home = self.tmp / '.warden-attended-login' / 'session'
self.home.mkdir(parents=True)
kv = {f'{SRC}/{k}': {'versions': [v]} for k, v in VALUES.items()}
kv[f'{SRC}/operator-session']['versions'] = [{'session_b64': 'old'}] * 3 + [VALUES['operator-session']]
self.state = {'calls': [], 'identity': {'policies': ['default', 'platform-admin']}, 'kv': kv}
def run_helper(self, *extra, confirm=CONFIRM):
(self.tmp / 'state.json').write_text(json.dumps(self.state))
receipt = self.tmp / f'receipt-{len(list(self.tmp.glob("receipt-*")))}.json'
env = {k: v for k, v in os.environ.items() if k not in ('BAO_TOKEN', 'VAULT_TOKEN')}
env.update(PATH=f'{self.tmp / "bin"}:{env["PATH"]}', HOME=str(self.home),
FAKE_BAO_STATE=str(self.tmp / 'state.json'))
proc = subprocess.run([sys.executable, str(SCRIPT), '--confirm', confirm,
'--receipt', str(receipt), *extra],
env=env, capture_output=True, text=True)
self.assertEqual((proc.stdout, proc.stderr), ('', ''))
self.state = json.loads((self.tmp / 'state.json').read_text())
text = receipt.read_text()
for value in VALUES.values():
for secret in value.values():
self.assertNotIn(secret, text)
return proc.returncode, json.loads(text)
def test_moves_all_four_then_deletes_sources(self):
code, receipt = self.run_helper()
self.assertEqual((code, receipt['outcome']), (0, 'moved'))
for entry, value in VALUES.items():
self.assertEqual(self.state['kv'][f'{DST}/{entry}']['versions'], [value])
self.assertNotIn(f'{SRC}/{entry}', self.state['kv'])
self.assertTrue(receipt['entries'][entry]['source_deleted'])
self.assertEqual(receipt['entries']['operator-session']['source_version'], 4)
self.assertFalse(receipt['credential_values_emitted'])
def test_rerun_after_move_is_already_moved(self):
self.run_helper()
code, receipt = self.run_helper()
self.assertEqual((code, receipt['outcome']), (0, 'already_moved'))
def test_dry_run_reads_no_values(self):
code, receipt = self.run_helper('--dry-run')
self.assertEqual((code, receipt['outcome']), (0, 'dry_run_would_move'))
self.assertFalse(any(c[0] == 'read' and '/data/' in c[-1] for c in self.state['calls']))
self.assertFalse(any(c[0] in ('write', 'delete') for c in self.state['calls']))
def test_keep_source_copies_without_deleting(self):
code, receipt = self.run_helper('--keep-source')
self.assertEqual((code, receipt['outcome']), (0, 'copied_source_kept'))
self.assertIn(f'{SRC}/bot-token', self.state['kv'])
self.assertIn(f'{DST}/bot-token', self.state['kv'])
def test_differing_target_refuses_and_deletes_nothing(self):
self.state['kv'][f'{DST}/redaction-salt'] = {'versions': [{'salt': 'other'}]}
code, receipt = self.run_helper()
self.assertEqual((code, receipt['outcome']), (3, 'target_differs'))
self.assertFalse(any(c[0] == 'delete' for c in self.state['calls']))
self.assertEqual(self.state['kv'][f'{DST}/redaction-salt']['versions'], [{'salt': 'other'}])
def test_write_failure_deletes_nothing(self):
self.state['fail_write'] = True
code, receipt = self.run_helper()
self.assertEqual((code, receipt['outcome']), (4, 'write_failed'))
self.assertFalse(any(c[0] == 'delete' for c in self.state['calls']))
def test_refuses_without_confirmation_identity_or_envelope(self):
code, receipt = self.run_helper(confirm='MOVE')
self.assertEqual((code, receipt['outcome']), (2, 'exact_confirmation_required'))
self.state['identity'] = {'policies': ['root', 'platform-admin']}
code, receipt = self.run_helper()
self.assertEqual((code, receipt['outcome']), (2, 'attended_platform_admin_required'))
self.assertFalse(any(c[0] in ('write', 'delete') for c in self.state['calls']))
if __name__ == '__main__':
unittest.main()