80 lines
4.9 KiB
Python
80 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
from pathlib import Path
|
|
import json, time
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
CONFIG = ROOT / "config" / "extraction"
|
|
REPORTS = ROOT / "reports" / "extraction"
|
|
DOCS = ROOT / "docs" / "03-deployment"
|
|
VALIDATION = REPORTS / "source-to-cex-offchain-sink-validation-latest.json"
|
|
|
|
def load(p): return json.loads(p.read_text())
|
|
def write(p, data): p.parent.mkdir(parents=True, exist_ok=True); p.write_text(json.dumps(data, indent=2)+"\n")
|
|
def write_text(p, text): p.parent.mkdir(parents=True, exist_ok=True); p.write_text(text.rstrip()+"\n")
|
|
def now(): return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
policy = load(CONFIG / "source-to-cex-production-policy.json")
|
|
inv = load(CONFIG / "additional-wallet-inventory.json")
|
|
plan = load(REPORTS / "source-to-cex-execution-plan-latest.json")
|
|
strict = load(REPORTS / "strict-operator-public-liquidity-table-latest.json")
|
|
validation = load(VALIDATION) if VALIDATION.exists() else None
|
|
sinks = []
|
|
issues = []
|
|
included_sink_count = 0
|
|
for a in inv.get('offchain_accounts', []):
|
|
if not a.get('include_in_baseline'):
|
|
continue
|
|
included_sink_count += 1
|
|
row = {
|
|
'label': a.get('label'), 'platform': a.get('platform', 'unknown'), 'enabled_for_production_handoff': bool(a.get('enabled_for_production_handoff')),
|
|
'deposit_address_present': bool(str(a.get('deposit_address','')).strip()), 'operational_status': a.get('operational_status','unknown'),
|
|
'preferred_deposit_asset': a.get('preferred_deposit_asset')
|
|
}
|
|
sinks.append(row)
|
|
if not row['enabled_for_production_handoff']: issues.append(f"{row['label']}: production handoff not enabled")
|
|
if not row['deposit_address_present']: issues.append(f"{row['label']}: missing deposit address")
|
|
if row['operational_status'] != 'enabled': issues.append(f"{row['label']}: operational_status is not enabled")
|
|
if not row['preferred_deposit_asset']: issues.append(f"{row['label']}: missing preferred deposit asset")
|
|
if included_sink_count == 0:
|
|
issues.append('no real off-chain sink is currently included in baseline scope')
|
|
direct = {r['route_id']: r['current_verified_public_depth_usd'] for r in strict.get('entries', [])}
|
|
payload = {
|
|
'generated_at': now(),
|
|
'ready_for_immediate_live_production': bool(policy.get('production_enabled')) and not issues and bool(sinks),
|
|
'strategy_frame': plan['strategy_frame'],
|
|
'mainnet_funding_posture': plan.get('mainnet_funding_posture'),
|
|
'policy': {'path':'config/extraction/source-to-cex-production-policy.json','production_enabled': bool(policy.get('production_enabled')),'packetization_policy': policy.get('packetization_policy',{})},
|
|
'offchain_sink_validation': validation,
|
|
'offchain_sinks': sinks,
|
|
'tasks': [
|
|
{'task':'operator_model_locked','status':'ready'},
|
|
{'task':'baseline_refreshed','status':'ready'},
|
|
{'task':'mainnet_normalization_modeled','status':'ready','evidence':{'cwusdc_direct_depth_usd':direct.get('cwusdc-direct-usdc'),'cwusdt_direct_depth_usd':direct.get('cwusdt-direct-usdt')}},
|
|
{'task':'production_policy_present','status':'ready'},
|
|
{'task':'offchain_sink_defined','status':'blocked' if issues or not sinks else 'ready','blocking_issues':issues},
|
|
{'task':'live_production_enabled','status':'blocked' if (issues or not sinks or not policy.get('production_enabled')) else 'ready'}
|
|
],
|
|
'blocking_issues': issues + ([] if policy.get('production_enabled') else ['source-to-cex production policy remains disabled']),
|
|
'next_live_inputs_required': [
|
|
'at least one real off-chain sink row with include_in_baseline=true',
|
|
'enabled_for_production_handoff=true on the real sink',
|
|
'real deposit address and chain for the chosen sink',
|
|
'operational_status=enabled for the chosen sink',
|
|
'operator decision to set production_enabled=true after live canaries succeed'
|
|
]
|
|
}
|
|
write(REPORTS / 'source-to-cex-production-readiness-latest.json', payload)
|
|
lines = ['# Source To CEX Production Readiness','',f"- Generated: `{payload['generated_at']}`",f"- Ready for immediate live production: `{payload['ready_for_immediate_live_production']}`",f"- Policy production enabled: `{payload['policy']['production_enabled']}`"]
|
|
if payload.get('mainnet_funding_posture'):
|
|
lines.append(f"- Mainnet funding posture: `{payload['mainnet_funding_posture']['mode']}` via `{', '.join(payload['mainnet_funding_posture']['required_deployer_assets'])}`")
|
|
lines += ['','## Blocking Issues','']
|
|
for issue in payload['blocking_issues'] or ['none']:
|
|
lines.append(f"- {issue}")
|
|
if validation:
|
|
lines += ['','## Off-Chain Sink Validation','',f"- Validation ready: `{validation['ready']}`",f"- Included sink count: `{validation['included_sink_count']}`"]
|
|
for warning in validation.get('warnings', []):
|
|
lines.append(f"- Warning: {warning}")
|
|
lines += ['','## Next Live Inputs Required','']
|
|
for item in payload['next_live_inputs_required']:
|
|
lines.append(f'- {item}')
|
|
write_text(DOCS / 'SOURCE_TO_CEX_PRODUCTION_READINESS.md', '\n'.join(lines))
|
|
print(REPORTS / 'source-to-cex-production-readiness-latest.json')
|