- 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
192 lines
7.6 KiB
Python
192 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
"""RPF-WP-0035-T03: attended, silent move of fluid-telegram custody to tenant coulomb.
|
|
|
|
Founder ruling 2026-10-09 (ops-mason message b72ff77d): the hall-of-helix entries
|
|
found under the undocumented infotech prefix move to the approved coulomb prefix
|
|
that CCR-2026-0039 grants. For each of bot-token, operator-app, operator-session
|
|
and redaction-salt this process reads the current version at
|
|
``platform/workloads/infotech/fluid-telegram/hall-of-helix/<entry>``, writes it to
|
|
``platform/workloads/coulomb/fluid-telegram/hall-of-helix/<entry>`` with CAS 0
|
|
and verifies the readback. Only after all four are verified, and no source
|
|
changed during the run, are the infotech entries metadata-deleted. Values only
|
|
travel through this process's memory and the ``bao`` child's stdin.
|
|
|
|
Run from a railiance-platform checkout at the reviewed commit:
|
|
|
|
BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 \\
|
|
warden access openbao-platform-admin-login --exec -- \\
|
|
python3 scripts/fluid_telegram_custody_move.py \\
|
|
--confirm 'MOVE fluid-telegram hall-of-helix to coulomb' \\
|
|
--receipt "$HOME/ft-custody-move-receipt.json"
|
|
|
|
``--dry-run`` touches only KV metadata. ``--keep-source`` copies and verifies
|
|
but does not delete. A rerun after a completed move reports ``already_moved``.
|
|
|
|
The process prints nothing (stdout/stderr go to /dev/null). The optional
|
|
receipt (mode 0600, refused if it exists) holds versions, booleans and an
|
|
outcome code only.
|
|
|
|
Exit codes:
|
|
0 moved (or already moved / already identical); dry-run: a move would run
|
|
1 unexpected internal error (contained)
|
|
2 precondition refused before any write (confirmation, envelope, identity,
|
|
an entry absent at both prefixes, absence not provable, receipt exists)
|
|
3 a coulomb entry exists and differs, or a current version is not live;
|
|
never overwritten
|
|
4 write or delete failed
|
|
5 verify failed: readback differs, or a source changed during the run
|
|
6 dry-run only: some coulomb entries already exist
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
from tenant_engine_audit_core_sender_seed import Exit, bao, live_version, read_json # noqa: E402
|
|
|
|
SOURCE = 'workloads/infotech/fluid-telegram/hall-of-helix'
|
|
TARGET = 'workloads/coulomb/fluid-telegram/hall-of-helix'
|
|
ENTRIES = ('bot-token', 'operator-app', 'operator-session', 'redaction-salt')
|
|
CONFIRM = 'MOVE fluid-telegram hall-of-helix to coulomb'
|
|
SCHEMA = 'platform.fluid-telegram-custody-move.v1'
|
|
|
|
|
|
def meta(prefix, entry):
|
|
return read_json(f'platform/metadata/{prefix}/{entry}', absent_ok=True)
|
|
|
|
|
|
def data(prefix, entry, code=2):
|
|
raw = read_json(f'platform/data/{prefix}/{entry}', absent_ok=False, code=code)
|
|
try:
|
|
return raw['data'], raw['metadata']['version']
|
|
except (KeyError, TypeError):
|
|
raise Exit(code, 'unparseable_read') from None
|
|
|
|
|
|
def run(args, receipt):
|
|
if args.confirm != CONFIRM:
|
|
raise Exit(2, 'exact_confirmation_required')
|
|
if (Path.home().parent.name != '.warden-attended-login'
|
|
or os.environ.get('BAO_TOKEN') or os.environ.get('VAULT_TOKEN')):
|
|
raise Exit(2, 'attended_warden_envelope_required')
|
|
ident = read_json('auth/token/lookup-self', absent_ok=False)
|
|
policies = ident.get('policies') or []
|
|
if 'platform-admin' not in policies or 'root' in policies:
|
|
raise Exit(2, 'attended_platform_admin_required')
|
|
|
|
rows = receipt['entries']
|
|
plan = []
|
|
for entry in ENTRIES:
|
|
src, dst = meta(SOURCE, entry), meta(TARGET, entry)
|
|
row = rows[entry] = {'source_present': src is not None, 'target_present': dst is not None}
|
|
if src is None and dst is None:
|
|
raise Exit(2, 'entry_absent_at_both_prefixes')
|
|
if src is not None:
|
|
if live_version(src) is None:
|
|
raise Exit(3, 'source_current_version_not_live')
|
|
row['source_version'] = src['current_version']
|
|
if dst is not None:
|
|
if live_version(dst) is None:
|
|
raise Exit(3, 'target_current_version_not_live')
|
|
row['target_version'] = dst['current_version']
|
|
plan.append((entry, src, dst))
|
|
|
|
if args.dry_run:
|
|
receipt['value_reads'] = 0
|
|
if any(dst is not None for _, src, dst in plan if src is not None):
|
|
raise Exit(6, 'dry_run_target_present')
|
|
return 'dry_run_would_move' if any(src for _, src, _ in plan) else 'dry_run_already_moved'
|
|
|
|
if all(src is None for _, src, _ in plan):
|
|
return 'already_moved'
|
|
|
|
# Phase 1: copy and verify every entry before anything is deleted.
|
|
for entry, src, dst in plan:
|
|
if src is None:
|
|
continue
|
|
value, version = data(SOURCE, entry)
|
|
if version != src['current_version']:
|
|
raise Exit(5, 'source_changed_during_run')
|
|
row = rows[entry]
|
|
if dst is not None:
|
|
current, _ = data(TARGET, entry, code=3)
|
|
if current != value:
|
|
raise Exit(3, 'target_differs')
|
|
row['outcome'] = 'already_identical'
|
|
continue
|
|
result = bao(['write', '-format=json', f'platform/data/{TARGET}/{entry}', '-'],
|
|
payload={'options': {'cas': 0}, 'data': value})
|
|
if result.returncode != 0:
|
|
raise Exit(4, 'write_failed')
|
|
back, back_version = data(TARGET, entry, code=5)
|
|
if back != value or back_version != 1:
|
|
raise Exit(5, 'readback_mismatch')
|
|
row['target_version'] = 1
|
|
row['outcome'] = 'copied'
|
|
|
|
for entry, src, _ in plan:
|
|
if src is None:
|
|
continue
|
|
again = meta(SOURCE, entry)
|
|
if again is None or again.get('current_version') != src['current_version']:
|
|
raise Exit(5, 'source_changed_during_run')
|
|
|
|
if args.keep_source:
|
|
return 'copied_source_kept'
|
|
|
|
# Phase 2: remove the undocumented infotech entries (all versions).
|
|
for entry, src, _ in plan:
|
|
if src is None:
|
|
continue
|
|
if bao(['delete', f'platform/metadata/{SOURCE}/{entry}']).returncode != 0:
|
|
raise Exit(4, 'source_delete_failed')
|
|
if meta(SOURCE, entry) is not None:
|
|
raise Exit(5, 'source_still_present')
|
|
rows[entry]['source_deleted'] = True
|
|
return 'moved'
|
|
|
|
|
|
def main(argv=None):
|
|
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
os.dup2(devnull, 1)
|
|
os.dup2(devnull, 2)
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--confirm', default='')
|
|
parser.add_argument('--receipt', type=Path)
|
|
parser.add_argument('--dry-run', action='store_true')
|
|
parser.add_argument('--keep-source', action='store_true')
|
|
try:
|
|
args = parser.parse_args(argv)
|
|
except SystemExit:
|
|
return 2
|
|
receipt = {'schema': SCHEMA, 'mode': 'dry-run' if args.dry_run else 'move',
|
|
'source': 'platform/' + SOURCE, 'target': 'platform/' + TARGET,
|
|
'entries': {}, 'credential_values_emitted': False}
|
|
fd = None
|
|
if args.receipt is not None:
|
|
try:
|
|
fd = os.open(args.receipt, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
|
|
except OSError:
|
|
return 2
|
|
try:
|
|
receipt['outcome'] = run(args, receipt)
|
|
code = 0
|
|
except Exit as exc:
|
|
receipt['outcome'] = exc.reason
|
|
code = exc.code
|
|
except Exception:
|
|
receipt['outcome'] = 'contained_internal_error'
|
|
code = 1
|
|
receipt['exit_code'] = code
|
|
if fd is not None:
|
|
os.write(fd, (json.dumps(receipt, indent=2, sort_keys=True) + '\n').encode())
|
|
os.close(fd)
|
|
return code
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|