| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- """Check the agent's own research and encrypted business entries; never save business records."""
- import argparse
- import json
- import os
- from pathlib import Path
- import re
- import subprocess
- import sys
- import tempfile
- import uuid
- sys.dont_write_bytecode = True
- from bootstrap import HERE, Stopped, atomic_create, encode, need, plain, private_json, sha, verify
- import voc
- def activate_research(data_dir):
- """Persist one non-secret variable, preserving all other .env bytes and a private backup."""
- file = plain(data_dir / '.env')
- before = file.read_bytes() if file.exists() else None
- expected = str(data_dir / 'ksf-library-channel/channel.json')
- lines = (before or b'').decode('utf-8-sig').splitlines()
- matches = [re.fullmatch(r'\s*(?:export\s+)?KSF_LIBRARY_CHANNEL\s*=\s*(.*?)\s*', x) for x in lines]
- values = [m.group(1).strip('\"\'') for m in matches if m]
- need(len(values) <= 1 and (not values or values[0] == expected), 'EXISTING_RESEARCH_BINDING_DIFFERS')
- if values:
- return False
- newline = b'\r\n' if b'\r\n' in (before or b'') else b'\n'
- raw = before or b''
- if raw and not raw.endswith(b'\n'):
- raw += newline
- raw += ('KSF_LIBRARY_CHANNEL=' + expected).encode() + newline
- if before is not None:
- backup = data_dir / 'ksf-enterprise-workshop' / ('env-before-' + uuid.uuid4().hex)
- atomic_create(backup, before)
- temp = file.with_name('.env.ksf-' + uuid.uuid4().hex)
- try:
- atomic_create(temp, raw)
- need((file.read_bytes() if file.exists() else None) == before, 'ENV_CONCURRENT_CHANGE')
- os.replace(temp, file)
- finally:
- if temp.exists():
- temp.unlink()
- return True
- def run_json(argv, env, runner=subprocess.run):
- result = runner(argv, env=env, capture_output=True, timeout=180)
- try:
- value = json.loads(result.stdout if result.returncode == 0 else result.stderr)
- except (ValueError, UnicodeError):
- raise Stopped('ENTRY_RESPONSE_INVALID') from None
- if result.returncode != 0 or value.get('ok') is not True:
- code = value.get('error', {}).get('code', '')
- raise Stopped(code if re.fullmatch('[A-Z][A-Z0-9_]{1,90}', str(code)) else 'ENTRY_FAILED')
- return value
- def check(data_dir, output, activate=False, runner=subprocess.run):
- result = verify(HERE, data_dir)
- need(sys.platform == 'linux', 'TARGET_LINUX_RUNTIME_REQUIRED')
- voc_result = voc.verify(HERE, data_dir, runner)
- env = dict(os.environ)
- env['KSF_LIBRARY_CHANNEL'] = str(data_dir / 'ksf-library-channel/channel.json')
- env['PYTHONDONTWRITEBYTECODE'] = '1'
- channel = private_json(Path(env['KSF_LIBRARY_CHANNEL']))
- need(channel.get('schema') == 'ksf.library-channel.v1', 'INVALID_CHANNEL_CONFIG')
- # The installed library enforces key/known_hosts ownership and pinned host-key checking.
- library = run_json([sys.executable, '-B', str(data_dir / 'skills/ksf-voc-library/scripts/query_voc.py'),
- 'contract'], env, runner)
- binding = library.get('publicationBinding', {})
- generation = library.get('generation')
- need(binding.get('mode') == 'ssh-channel' and binding.get('backend') == 'parse-postgresql'
- and re.fullmatch('[a-f0-9]{64}', str(generation)) is not None
- and binding.get('currentGeneration') == generation and library.get('readOnly') is True
- and library.get('databaseWrites') == 0, 'RESEARCH_CONTRACT_MISMATCH')
- need(channel.get('host') and channel.get('user'), 'INVALID_CHANNEL_CONFIG')
- request_file = output / ('contract-input-' + uuid.uuid4().hex + '.json')
- atomic_create(request_file, b'{}\n')
- workshop = run_json(['node', str(data_dir / 'skills/ksf-workshop-runtime/scripts/ksf-secure.mjs'),
- 'workshop-contract', '--input', str(request_file), '--request-id',
- 'enterprise-contract-' + uuid.uuid4().hex], env, runner)
- inner = workshop.get('entryResult', {})
- need(workshop.get('credentialLoadedForChild') is True
- and workshop.get('credentialWrittenToDisk') is False
- and inner.get('readOnly') is True and inner.get('result', {}).get('workshop', {}).get('version')
- == 'ksf.workshop.v1', 'WORKSHOP_CONTRACT_MISMATCH')
- changed = activate_research(data_dir) if activate else False
- return {**result, 'researchAuthorized': True, 'businessAuthorized': True,
- 'voc': voc_result, 'vocCredentialAvailable': voc_result['runtime']['credentialAvailable'],
- 'research': {'mode': binding['mode'], 'backend': binding['backend'], 'generation': generation,
- 'readOnly': True, 'databaseWrites': 0},
- 'workshop': {'version': 'ksf.workshop.v1', 'readOnly': True},
- 'defaultResearchEnvironmentUpdated': changed, 'hostEnvironmentReloadVerified': False,
- 'realSaveReadbackVerified': False, 'dashboardAttributionVerified': False}
- def main():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument('--data-dir', type=Path, required=True)
- parser.add_argument('--out', type=Path, required=True)
- parser.add_argument('--activate-research', action='store_true')
- args = parser.parse_args()
- need(args.data_dir.is_absolute() and args.out.is_absolute(), 'ABSOLUTE_PATH_REQUIRED')
- data_dir, output = plain(args.data_dir), plain(args.out)
- need(output not in data_dir.parents and output != data_dir
- and data_dir / 'skills' not in output.parents, 'UNSAFE_RESULT_DIRECTORY')
- output.mkdir(parents=True, exist_ok=True, mode=0o700)
- result = check(data_dir, output, args.activate_research)
- atomic_create(output / ('readiness-' + uuid.uuid4().hex + '.json'), encode(result))
- print(json.dumps(result, ensure_ascii=False, indent=2))
- if __name__ == '__main__':
- try:
- main()
- except (Stopped, OSError, ValueError, KeyError, subprocess.TimeoutExpired) as error:
- print(json.dumps({'ok': False, 'error': {'code': str(error) if isinstance(error, Stopped)
- else 'READINESS_STOPPED'}, 'businessWrites': 0}), file=sys.stderr)
- sys.exit(1)
|