#!/usr/bin/env python3 """Owner-held verified KeyCape CLI files -> inherited pipe; never normal output. No login, secret retrieval, network, executor launch or authenticated admission. Decoded claims below are shape/lifetime checks, not signature verification. """ import argparse import base64 import contextlib import fcntl import json import math import os from pathlib import Path import signal import stat import threading import time MAX_FILE = 32768 MAX_TOKEN = 16384 class Refused(Exception): pass def need(condition, code): if not condition: raise Refused(code) def unique(pairs): out = {} for key, value in pairs: need(key not in out, 'duplicate_json_key') out[key] = value return out def decode(raw): try: return json.loads(raw, object_pairs_hook=unique, parse_constant=lambda _: (_ for _ in ()).throw(Refused('nonfinite_json'))) except Refused: raise except Exception: raise Refused('invalid_json') from None @contextlib.contextmanager def deadline(seconds): need(type(seconds) in (int, float) and math.isfinite(seconds) and 0 < seconds <= 5, 'invalid_delivery_budget') need(threading.current_thread() is threading.main_thread(), 'main_thread_required') need(signal.getitimer(signal.ITIMER_REAL) == (0.0, 0.0), 'existing_timer_refused') previous = signal.getsignal(signal.SIGALRM) def expired(*_): raise Refused('delivery_timeout') try: signal.signal(signal.SIGALRM, expired) signal.setitimer(signal.ITIMER_REAL, seconds) yield finally: signal.setitimer(signal.ITIMER_REAL, 0) signal.signal(signal.SIGALRM, previous) READY_SCHEMA = 'key39-private-input-ready/v1' READY_KEYS = {'schema','session_nonce','proposal_id','target','executor_sha256', 'envelope_sha256','bao_health_identity_sha256','valid_until_epoch', 'receive_budget_seconds'} def finite(value): try: return type(value) in (int,float) and math.isfinite(value) except (OverflowError,ValueError): return False def endpoint(fd, writable): need(type(fd) is int and fd >= 3, 'private_pipe_fd_required') try: identity = os.fstat(fd) mode = fcntl.fcntl(fd,fcntl.F_GETFL) & os.O_ACCMODE need(stat.S_ISFIFO(identity.st_mode) and mode == (os.O_WRONLY if writable else os.O_RDONLY), 'private_pipe_fd_required') for standard in (0,1,2): try: current = os.fstat(standard) except OSError: continue need((identity.st_dev,identity.st_ino) != (current.st_dev,current.st_ino), 'stdio_pipe_alias_refused') return identity.st_dev,identity.st_ino except OSError: raise Refused('private_pipe_fd_required') from None def wait_ready(fd, expected): need(isinstance(expected,dict) and set(expected) == READY_KEYS - {'schema','receive_budget_seconds'}, 'expected_child_pins_required') need(finite(expected['valid_until_epoch']) and expected['valid_until_epoch'] > time.time(), 'ready_window_expired') raw = b'' while len(raw) < 4096: chunk = os.read(fd,1) need(chunk, 'child_ready_missing') if chunk == b'\n': break raw += chunk else: raise Refused('child_ready_oversized') marker = decode(raw) need(isinstance(marker,dict) and set(marker) == READY_KEYS and marker.get('schema') == READY_SCHEMA, 'child_ready_invalid') need(all(marker.get(key) == value for key,value in expected.items()), 'child_ready_mismatch') need(finite(marker['valid_until_epoch']) and finite(marker['receive_budget_seconds']) and 0 < marker['receive_budget_seconds'] <= 15 and marker['valid_until_epoch'] > time.time(), 'ready_window_expired') return marker def claims(token, kind, now): need(isinstance(token, str) and 0 < len(token) <= MAX_TOKEN, 'invalid_token_shape') parts = token.split('.') need(len(parts) == 3 and all(parts), 'invalid_token_shape') try: obj = decode(base64.urlsafe_b64decode(parts[1] + '=' * (-len(parts[1]) % 4))) need(isinstance(obj, dict), 'invalid_token_shape') exp, iat = obj.get('exp'), obj.get('iat') need(type(exp) in (int,float) and type(iat) in (int,float) and math.isfinite(exp) and math.isfinite(iat) and iat <= now + 30 and iat < exp and exp >= now + 300, 'token_window_invalid') need(obj.get('iss') == 'https://kc.coulomb.social', 'token_source_invalid') if kind == 'human': need(obj.get('principal_type') == 'human' and obj.get('aud') == 'netkingdom-bootstrap-console' and isinstance(obj.get('sub'), str) and obj['sub'], 'human_shape_invalid') assurance = obj.get('assurance', {}) need(isinstance(assurance,dict) and assurance.get('level') == 'aal2' and assurance.get('mfa') is True, 'human_mfa_shape_invalid') else: need(obj.get('principal_type') == 'service' and obj.get('aud') == 'codex-railiance-platform' and obj.get('sub') == 'service:codex:railiance-platform' and obj.get('tenant') == 'tenant:platform' and obj.get('roles') == ['coding-agent'] and obj.get('scope') == 'openbao:login', 'coding_agent_shape_invalid') except Refused: raise except Exception: raise Refused('invalid_token_shape') from None return token def load(path, kind, now): p = Path(path) need(p.is_absolute() and p.parent.resolve() == p.parent, 'private_path_required') need(not any((ancestor / '.git').is_file() or (ancestor / '.git' / 'HEAD').exists() for ancestor in p.parents), 'git_path_refused') directory = os.open(p.parent, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW) try: ds = os.fstat(directory) need(ds.st_uid == os.getuid() and stat.S_IMODE(ds.st_mode) == 0o700, 'private_directory_required') fd = os.open(p.name, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=directory) try: original = os.fstat(fd) need(stat.S_ISREG(original.st_mode) and original.st_uid == os.getuid() and stat.S_IMODE(original.st_mode) == 0o600 and original.st_nlink == 1 and 0 < original.st_size <= MAX_FILE, 'private_file_required') raw = b'' while len(raw) <= MAX_FILE: chunk = os.read(fd, MAX_FILE + 1 - len(raw)) if not chunk: break raw += chunk need(len(raw) <= MAX_FILE, 'private_file_oversized') after = os.fstat(fd) need((original.st_size,original.st_mtime_ns,original.st_ctime_ns) == (after.st_size,after.st_mtime_ns,after.st_ctime_ns), 'private_file_changed') obj = decode(raw) need(isinstance(obj,dict) and obj.get('token_type','').lower() == 'bearer', 'invalid_cli_token_file') token = claims(obj.get('access_token'), kind, now) return token, directory, p.name, original finally: os.close(fd) except BaseException: os.close(directory) raise def consume(item): # Comparison is not atomic inode-conditioned unlink. Continuous exclusive # same-UID directory custody is mandatory; concurrent writers are outside scope. _, directory, name, original = item current = os.stat(name, dir_fd=directory, follow_symlinks=False) need((current.st_dev,current.st_ino,current.st_uid,current.st_nlink,current.st_size, current.st_mtime_ns,current.st_ctime_ns) == (original.st_dev,original.st_ino,original.st_uid,original.st_nlink,original.st_size, original.st_mtime_ns,original.st_ctime_ns), 'private_file_changed') os.unlink(name, dir_fd=directory) def deliver(human_path, agent_path, fd, *, ready_fd=None, expected=None, consume_owner_files=False, budget=5): receipt = {'adapter_performs_native_backend_actions': False, 'native_accepted': False, 'private_input_delivery_confirmed': False, 'caller_path_removal_completed': False, 'exclusive_same_uid_custody_required': True, 'atomic_inode_delete_guaranteed': False, 'child_ready_matched': False, 'credential_files_remain_possible': True, 'credential_copy_cleanup_verified': False, 'private_input_delivery_unknown': False} items = [] writing = False try: need(consume_owner_files is True, 'explicit_owner_file_consumption_required') data_identity = endpoint(fd,True) control_identity = endpoint(ready_fd,False) need(data_identity != control_identity, 'data_control_pipe_alias_refused') need(isinstance(expected,dict) and finite(expected.get('valid_until_epoch')), 'expected_child_pins_required') budget = min(budget, expected['valid_until_epoch'] - time.time()) with deadline(budget): marker = wait_ready(ready_fd,expected) receipt['child_ready_matched'] = True remaining_alarm = signal.getitimer(signal.ITIMER_REAL)[0] remaining = min(remaining_alarm, marker['receive_budget_seconds'], expected['valid_until_epoch'] - time.time()) need(remaining > 0, 'ready_window_expired') # Clip the existing timer; never restart or extend its original budget. signal.setitimer(signal.ITIMER_REAL, remaining) delivery_deadline = time.monotonic() + remaining now = time.time() items.append(load(human_path, 'human', now)) items.append(load(agent_path, 'coding-agent', now)) need((items[0][3].st_dev,items[0][3].st_ino) != (items[1][3].st_dev,items[1][3].st_ino), 'distinct_files_required') payload = json.dumps({'human_token':items[0][0], 'coding_agent_token':items[1][0]}, separators=(',', ':')).encode() + b'\n' # Unlink inspected caller-owned inodes; Python memory is not a zeroization guarantee. need(time.time() < expected['valid_until_epoch'] and time.monotonic() < delivery_deadline, 'ready_window_expired') for item in items: consume(item) receipt.update(caller_path_removal_completed=True) writing = True offset = 0 while offset < len(payload): need(time.time() < expected['valid_until_epoch'] and time.monotonic() < delivery_deadline, 'ready_window_expired') written = os.write(fd, payload[offset:]) need(written > 0, 'private_delivery_failed') offset += written need(time.time() < expected['valid_until_epoch'] and time.monotonic() < delivery_deadline, 'ready_window_expired') receipt['private_input_delivery_confirmed'] = True except Refused as error: receipt['failure_code'] = str(error) except Exception: receipt['failure_code'] = 'private_delivery_failed' finally: if writing and not receipt['private_input_delivery_confirmed']: receipt['private_input_delivery_unknown'] = True for item in items: os.close(item[1]) # Launcher owns these endpoints: EOF even after partial delivery. for owned in {fd,ready_fd}: if type(owned) is int and owned >= 3: try: os.close(owned) except OSError: pass return receipt # Deliberately no standalone ready-file/ready-boolean CLI. Only the reviewed # source launcher supplies its own captured child-control endpoint and exact pins.