From 0472fa56dd00a8d29766a44e2377c1a74582282c Mon Sep 17 00:00:00 2001 From: homelab-runtime-publisher Date: Tue, 15 Sep 2026 12:36:14 +0000 Subject: [PATCH] runtime: publish SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1 --- ...2-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.json | 38 +++ ...12-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.txt | 80 +++++++ runtime/latest.json | 39 ++- runtime/latest.txt | 226 ++++++------------ 4 files changed, 228 insertions(+), 155 deletions(-) create mode 100644 runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.json create mode 100644 runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.txt diff --git a/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.json b/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.json new file mode 100644 index 00000000..c6954d6c --- /dev/null +++ b/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.json @@ -0,0 +1,38 @@ +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1", + "status": "OK", + "rc": 0, + "host": "pve01", + "mode": "read-only", + "component": "infra-dr-backupv2-ct112-cloud-seal-contract-preflight", + "started_at_utc": "2026-09-15T12:36:13Z", + "finished_at_utc": "2026-09-15T12:36:14Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "c92db35b051b231f28f75dee8513620581c9e13c76afce192d2ec6fee0e4f079", + "duplicate_failed_command_blocked": false, + "block_reason": null, + "execution_started": true, + "change_declared": false, + "result_contract_valid": true, + "result_contract_status": null, + "result_contract_error": null, + "command_rc": 0, + "changes_made": false, + "rollback_started": false, + "rollback_restored": null, + "mutation_outcome": "NO_MUTATION", + "sanitized": true, + "secrets_included": false, + "private_addresses_included": false, + "raw_evidence_retained_locally": true, + "raw_evidence_sha256": "c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3", + "sanitized_output_sha256": "c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1\nMODE=READ_ONLY_CT112_CLOUD_SEAL_CONTRACT_PREFLIGHT\nNO_BACKUP_EXECUTION=YES\nNO_VZDUMP_EXECUTION=YES\nNO_CLOUD_ACCESS=YES\nNO_RCLONE_EXECUTION=YES\nNO_CLOUD_DELETION=YES\nNO_SYSTEMD_MUTATION=YES\nNO_FILE_MUTATION=YES\nPRODUCTION_AND_CANDIDATE_IDENTITY=PASS\nSOURCE_SET_IDENTITY=PASS\nG426_IMMUTABLE_COMMIT=8e261f22b35fe49616ab7c2e23f5cac3a5b66376\nG426_STAGE_BINDING=PASS\nG426_GENERATION=G426-20260915T115318Z-d9bb39ace5781d2e\nG426_PAYLOAD_BYTES=223855196\nG426_PAYLOAD_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12\nG426_PAYLOAD_MODE=0400\nCLOUD_ENGINE_OWNER_GRAPH=PASS\nGUEST266_RUN_FLOW_CONTRACT={\"direct_calls\":[\"Path\",\"all\",\"callable\",\"check_result\",\"clock\",\"compression_check\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.valid_name\",\"core.validate_inventory\",\"guard\",\"int\",\"job.get\",\"large.cleanup\",\"large.discover\",\"large.restore\",\"large.upload\",\"len\",\"produce\",\"producer.validate_job\",\"say\",\"state_guard\",\"t.create\",\"t.make_dir\",\"t.need\",\"time.time\"],\"signature\":\"(job, work, entries, cloud, reader, produce, state_guard, guard, compression_check, generation, say, clock= at 0x76417f8f07c0>)\",\"source\":\"def run_flow(job,work,entries,cloud,reader,produce,state_guard,guard,compression_check,generation,say,clock=lambda:int(time.time())):\\n \\\"\\\"\\\"Caller provides real fresh PVE guards; simulation callbacks live in tests only.\\\"\\\"\\\"\\n producer.validate_job(job,clock());core.validate_inventory(entries)\\n t.need(job['type']=='lxc' and job.get('compression_dependent') is False,'FIRST_GUEST_POLICY')\\n t.need(core.valid_name(generation),'GENERATION_ID')\\n t.need(all(callable(f) for f in (produce,state_guard,guard,compression_check,say,clock)),'CALLBACKS_REQUIRED')\\n work=Path(work);state_guard();guard()\\n for sub in ('producer','upload','restore'):t.make_dir(work/sub,exclusive=True)\\n say('PHASE','REAL_SINGLE_GUEST_SNAPSHOT')\\n produced=produce(job,work/'producer')\\n source=check_result(produced,job,work/'producer');state_guard();guard()\\n t.create(work/'PRODUCER.json',core.canonical_bytes(produced))\\n say('PRODUCER_RC',0);say('PAYLOAD_BYTES',produced['size']);say('ARCHIVE_SHA256',produced['sha256'])\\n logical='guest-%s-%s-%d'%(job['node'],job['type'],job['vmid'])\\n say('PHASE','TWO_REPLICA_UPLOAD_AND_READBACK')\\n up=large.upload(source,work/'upload',entries,cloud,generation,logical,RESERVE_BYTES,guard,clock=clock)\\n t.need(up['manifest']['payload_bytes']==produced['size'] and up['manifest']['payload_sha256']==produced['sha256'],'MANIFEST_PRODUCER_MISMATCH')\\n say('SEALED_QUORUM_VERIFIED','YES');mh=core.manifest_hash(up['manifest']);say('MANIFEST_SHA256',mh)\\n say('PHASE','CLOUD_DISCOVERY_AND_ARCHIVE_RECONSTRUCTION')\\n found=large.discover(reader,entries,logical,mh)\\n restored=large.restore(work/'restore',reader,found)\\n t.need(compression_check(work/'restore/restored.bin') is True,'RECONSTRUCTED_COMPRESSION_FAILED')\\n state_guard();guard();say('PHASE','GUARDED_LOCAL_PAYLOAD_CLEANUP')\\n count=large.cleanup(up,restored,reader,guard)\\n return {'state':'SINGLE_GUEST_ARCHIVE_SEALED_AND_CLOUD_RECONSTRUCTED','vmid':job['vmid'],'type':job['type'],'node':job['node'],\\n 'generation':generation,'logical_id':logical,'manifest_sha256':mh,'payload_bytes':produced['size'],'payload_sha256':produced['sha256'],\\n 'replicas':up['manifest']['replicas'],'parts_count':len(up['manifest']['parts']),'archive_cloud_restore_verified':True,\\n 'guest_restore_verified':False,'application_consistency_verified':False,'whole_node_backup':False,'local_payload_files_remaining':0,\\n 'files_deleted':count,'accounts_scanned':found['accounts_scanned'],'config_sha256':job['config_sha256']}\\n\",\"source_sha256\":\"789140b440fc756f99c8979b543c60a44ada096b5acece83e7173791f23bb55c\"}\nLARGE264_UPLOAD_CONTRACT={\"direct_calls\":[\"Path\",\"clock\",\"cloud.absent\",\"cloud.bind\",\"cloud.get\",\"cloud.put\",\"cloud.quota\",\"cloud.read_stream\",\"core.allocate\",\"core.canonical_bytes\",\"core.make_manifest\",\"core.manifest_hash\",\"core.quota_reason\",\"core.valid_name\",\"core.validate_inventory\",\"core.verify_receipts\",\"guard\",\"hashlib.sha256\",\"int\",\"len\",\"r.validate_seal\",\"receipt\",\"receipts.append\",\"s.split_file\",\"s.verify_parts\",\"str\",\"t.create\",\"t.make_dir\",\"t.need\",\"t.sha\",\"time.time\"],\"signature\":\"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)\",\"source\":\"def upload(source,work,entries,cloud,generation,logical_id,reserve,guard,clock=lambda:int(time.time())):\\n \\\"\\\"\\\"Upload and seal; retain all source bytes here. Cleanup is a later gated operation.\\\"\\\"\\\"\\n work=Path(work);source=Path(source);guard();core.validate_inventory(entries)\\n t.need(core.valid_name(generation) and core.valid_name(logical_id),'GENERATION_ID')\\n partdir=work/'parts';t.make_dir(partdir,exclusive=True)\\n record=s.split_file(source,partdir)\\n t.create(work/'parts-record.json',core.canonical_bytes(record))\\n quotas={e['account_id']:cloud.quota(e['crypt_remote']) for e in entries}\\n allocation=core.allocate(entries,quotas,record['payload_bytes'],reserve,clock())\\n m=core.make_manifest(generation,logical_id,record['payload_bytes'],record['payload_sha256'],record['parts'],allocation)\\n mb=core.canonical_bytes(m);mh=core.manifest_hash(m);cloud.bind(m)\\n t.create(work/'allocation.json',core.canonical_bytes(allocation));t.create(work/'manifest.json',mb)\\n for rep in m['replicas']:\\n guard();cloud.absent(rep['crypt_remote'])\\n receipts=[]\\n for rep in m['replicas']:\\n guard();remote=rep['crypt_remote'];q=cloud.quota(remote)\\n t.need(core.quota_reason(q,clock()) is None and q['free']>=allocation['required_free_bytes'],'SELECTED_ACCOUNT_CAPACITY_CHANGED')\\n s.verify_parts(partdir,record)\\n for part in m['parts']:cloud.put(remote,part['name'],partdir/part['name'])\\n cloud.put(remote,'manifest.json',work/'manifest.json')\\n t.need(cloud.get(remote,'manifest.json',len(mb)+1)==mb,'MANIFEST_READBACK_MISMATCH')\\n whole=hashlib.sha256();count=0\\n for part in m['parts']:\\n observed=cloud.read_stream(remote,part['name'],part['size'],part['sha256'],whole.update)\\n t.need(observed=={'size':part['size'],'sha256':part['sha256']},'PART_READBACK_MISMATCH');count+=observed['size']\\n receipts.append(receipt(rep,m,whole,count));t.create(work/('receipt-%d.json'%len(receipts)),core.canonical_bytes(receipts[-1]))\\n core.verify_receipts(m,receipts)\\n seal={'schema_version':2,'state':'SEALED','generation':generation,'logical_id':logical_id,\\n 'manifest_sha256':mh,'replicas':m['replicas'],'receipts':receipts,\\n 'acceptance':'IDENTICAL_SEAL_REQUIRED_ON_BOTH_NAMED_ACCOUNTS'}\\n sb=core.canonical_bytes(seal);t.need(len(sb)<=core.SEAL_MAX_BYTES,'SEAL_BOUND')\\n r.validate_seal(sb,entries,generation,logical_id);t.create(work/'SEALED.json',sb)\\n for rep in m['replicas']:\\n guard();cloud.put(rep['crypt_remote'],'SEALED.json',work/'SEALED.json')\\n for rep in m['replicas']:\\n t.need(cloud.get(rep['crypt_remote'],'SEALED.json',len(sb)+1)==sb,'SEALED_QUORUM_REQUIRED')\\n guard();s.verify_parts(partdir,record)\\n t.create(work/'QUORUM_VERIFIED.json',core.canonical_bytes({'manifest_sha256':mh,'seal_sha256':t.sha(sb)}))\\n return {'sealed':True,'manifest':m,'seal_bytes':sb,'parts_record':record,'source':str(source),'work':str(work)}\\n\",\"source_sha256\":\"3fc04eea643b977e58713bea8a7b9bcfd485e60251a4393874dfe1a428014bbe\"}\nLARGE264_RESTORE_CONTRACT={\"direct_calls\":[\"Path\",\"cloud.read_stream\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.validate_manifest\",\"core.verify_receipts\",\"download_part\",\"enumerate\",\"fresh_seals\",\"hashlib.sha256\",\"receipt\",\"receipts.append\",\"s.reassemble\",\"str\",\"t.create\",\"t.make_dir\",\"t.need\"],\"signature\":\"(work, cloud, discovery)\",\"source\":\"def restore(work,cloud,discovery):\\n \\\"\\\"\\\"Reconstruct one replica on disk; hash every byte of the other independently.\\\"\\\"\\\"\\n work=Path(work);m=discovery['manifest'];core.validate_manifest(m)\\n partdir=work/'parts';t.make_dir(partdir,exclusive=True);owned={};receipts=[]\\n for i,rep in enumerate(m['replicas']):\\n whole=hashlib.sha256();count=0\\n for part in m['parts']:\\n if i==0:owned[part['name']]=download_part(cloud,rep,m,part,partdir/part['name'],whole)\\n else:\\n got=cloud.read_stream(rep['crypt_remote'],m['generation'],part['name'],part['size'],part['sha256'],whole.update)\\n t.need(got=={'size':part['size'],'sha256':part['sha256']},'PART_DOWNLOAD_MISMATCH')\\n count+=part['size']\\n receipts.append(receipt(rep,m,whole,count))\\n core.verify_receipts(m,receipts);fresh_seals(cloud,discovery)\\n rec={'schema_version':1,'payload_bytes':m['payload_bytes'],'payload_sha256':m['payload_sha256'],\\n 'part_bytes':core.PART_BYTES,'parts':m['parts'],'owned':owned,'source_identity':[0]*8}\\n result=s.reassemble(partdir,rec,work/'restored.bin')\\n fresh_seals(cloud,discovery)\\n t.create(work/'RESTORE_VERIFIED.json',core.canonical_bytes({'manifest_sha256':core.manifest_hash(m),'verified_replicas':2,\\n 'accounts_scanned':discovery['accounts_scanned'],'payload_bytes':result['size'],'payload_sha256':result['sha256']}))\\n return {'verified_replicas':2,'manifest_sha256':core.manifest_hash(m),'discovery':discovery,\\n 'parts_record':rec,'reassembled':result,'work':str(work)}\\n\",\"source_sha256\":\"0a73a874d1354b5a63645f4848a9bae933e463e444c3db177ab07c01ecd1f614\"}\nLARGE264_DISCOVER_CONTRACT={\"direct_calls\":[\"all\",\"blobs.append\",\"candidates.append\",\"cloud.get\",\"cloud.list_generations\",\"core.canonical_bytes\",\"core.valid_hash\",\"core.valid_name\",\"core.validate_inventory\",\"core.validate_manifest\",\"core.verify_receipts\",\"generations.update\",\"iter\",\"len\",\"next\",\"r.strict_json\",\"r.validate_seal\",\"seen.values\",\"set\",\"sorted\",\"t.need\",\"t.sha\",\"type\"],\"signature\":\"(cloud, entries, logical_id, expected_hash)\",\"source\":\"def discover(cloud,entries,logical_id,expected_hash):\\n \\\"\\\"\\\"Find placement from all cloud catalogs, using only an external manifest digest.\\\"\\\"\\\"\\n core.validate_inventory(entries)\\n t.need(core.valid_name(logical_id) and core.valid_hash(expected_hash),'DISCOVERY_INPUT')\\n listed={};generations=set()\\n for e in entries:\\n gs=cloud.list_generations(e['crypt_remote'])\\n t.need(type(gs) is list and len(gs)<=r.MAX_GENERATIONS and all(core.valid_name(g) for g in gs),'GENERATION_LIST_INVALID')\\n t.need(len(gs)==len(set(gs)),'GENERATION_LIST_DUPLICATE');listed[e['crypt_remote']]=set(gs);generations.update(gs)\\n t.need(len(generations)<=r.MAX_GENERATIONS,'TOTAL_GENERATIONS_BOUND')\\n candidates=[]\\n for gen in sorted(generations):\\n seen={}\\n for e in entries:\\n remote=e['crypt_remote']\\n if gen not in listed[remote]:continue\\n b=cloud.get(remote,gen,'SEALED.json',core.SEAL_MAX_BYTES+1,missing_ok=True)\\n if b is None:continue\\n seal=r.validate_seal(b,entries,gen,logical_id)\\n t.need(remote in {x['crypt_remote'] for x in seal['replicas']},'UNNAMED_SEAL_LOCATION');seen[remote]=(b,seal)\\n if not seen:continue\\n sb,seal=next(iter(seen.values()))\\n if seal['manifest_sha256']!=expected_hash:continue\\n named={x['crypt_remote'] for x in seal['replicas']}\\n t.need(set(seen)==named and all(b==sb for b,_ in seen.values()),'IDENTICAL_TWO_SEALS_REQUIRED')\\n blobs=[]\\n for rep in seal['replicas']:\\n b=cloud.get(rep['crypt_remote'],gen,'manifest.json',core.MANIFEST_MAX_BYTES+1)\\n t.need(type(b) is bytes and t.sha(b)==expected_hash,'MANIFEST_DIGEST_MISMATCH')\\n m=r.strict_json(b,core.MANIFEST_MAX_BYTES);core.validate_manifest(m)\\n t.need(m['generation']==gen and m['logical_id']==logical_id and m['replicas']==seal['replicas'],'MANIFEST_PLACEMENT')\\n t.need(core.canonical_bytes(m)==b,'MANIFEST_CANONICAL_BYTES');core.verify_receipts(m,seal['receipts']);blobs.append(b)\\n t.need(len(blobs)==2 and blobs[0]==blobs[1],'TWO_MANIFEST_COPIES_REQUIRED')\\n candidates.append({'manifest':m,'seal_bytes':sb,'accounts_scanned':len(listed)})\\n t.need(len(candidates)==1,'EXACTLY_ONE_ACCEPTED_GENERATION_REQUIRED')\\n return candidates[0]\\n\",\"source_sha256\":\"0f9d514dfa0985bfa0ee6446aa85a78377346003039896395cb39e0bf3643702\"}\nLARGE264_CLEANUP_CONTRACT={\"direct_calls\":[\"Path\",\"any\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.validate_manifest\",\"core.verify_receipts\",\"fresh_seals\",\"guard\",\"items.append\",\"len\",\"os.close\",\"os.fsync\",\"os.stat\",\"os.unlink\",\"p.exists\",\"p.is_symlink\",\"r.strict_json\",\"restore_result.get\",\"s.hash_file\",\"s.validate_record\",\"s.verify_parts\",\"str\",\"t.ident\",\"t.need\",\"t.open_dir\",\"tuple\",\"type\",\"upload_result.get\"],\"signature\":\"(upload_result, restore_result, cloud, guard)\",\"source\":\"def cleanup(upload_result,restore_result,cloud,guard):\\n \\\"\\\"\\\"No unlink until every expected file and both remote seals have passed verification.\\\"\\\"\\\"\\n t.need(type(upload_result) is dict and upload_result.get('sealed') is True,'UPLOAD_QUORUM_REQUIRED')\\n t.need(type(restore_result) is dict and restore_result.get('verified_replicas')==2,'RESTORE_REQUIRED')\\n m=upload_result['manifest'];core.validate_manifest(m);mh=core.manifest_hash(m)\\n t.need(restore_result['manifest_sha256']==mh,'RESTORE_GENERATION_MISMATCH')\\n t.need(core.canonical_bytes(restore_result['discovery']['manifest'])==core.canonical_bytes(m) and\\n restore_result['discovery']['seal_bytes']==upload_result['seal_bytes'],'RESTORE_QUORUM_MISMATCH')\\n core.verify_receipts(m,r.strict_json(upload_result['seal_bytes'],core.SEAL_MAX_BYTES)['receipts'])\\n guard();fresh_seals(cloud,restore_result['discovery'])\\n items=[]\\n for record,base in ((upload_result['parts_record'],Path(upload_result['work'])/'parts'),\\n (restore_result['parts_record'],Path(restore_result['work'])/'parts')):\\n s.validate_record(record);s.verify_parts(base,record)\\n for part in record['parts']:items.append((base/part['name'],tuple(record['owned'][part['name']]),part['size'],part['sha256']))\\n items.append((Path(upload_result['source']),tuple(upload_result['parts_record']['source_identity']),m['payload_bytes'],m['payload_sha256']))\\n items.append((Path(restore_result['work'])/'restored.bin',tuple(restore_result['reassembled']['identity']),m['payload_bytes'],m['payload_sha256']))\\n t.need(len({str(p) for p,_,_,_ in items})==len(items),'CLEANUP_DUPLICATE_PATH')\\n for p,identity,size,h in items:\\n n,d,seen=s.hash_file(p,size);t.need(seen==identity and n==size and d==h,'CLEANUP_IDENTITY_OR_HASH')\\n guard();fresh_seals(cloud,restore_result['discovery'])\\n for p,identity,size,h in items:\\n parent=t.open_dir(p.parent)\\n try:\\n t.need(t.ident(os.stat(p.name,dir_fd=parent,follow_symlinks=False))==identity,'CLEANUP_FILE_CHANGED')\\n os.unlink(p.name,dir_fd=parent);os.fsync(parent)\\n finally:os.close(parent)\\n t.need(not any(p.exists() or p.is_symlink() for p,_,_,_ in items),'LOCAL_CLEANUP_INCOMPLETE')\\n return len(items)\\n\",\"source_sha256\":\"2cbbf3325b84192705686a2c6d3a02f58a75f51145f68204786e08194013cd3b\"}\nLARGE264_FUNCTION_INDEX={\"cleanup\":\"(upload_result, restore_result, cloud, guard)\",\"discover\":\"(cloud, entries, logical_id, expected_hash)\",\"download_part\":\"(cloud, rep, m, part, path, whole)\",\"flags\":\"(executable, snapshot, work, args)\",\"fresh_seals\":\"(cloud, discovery)\",\"process_stream\":\"(argv, env, size, digest, consume, seconds)\",\"random_source\":\"(path, size=536870929)\",\"receipt\":\"(rep, m, whole, count)\",\"restore\":\"(work, cloud, discovery)\",\"upload\":\"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)\"}\nTEST_GUEST266_STORE_SOURCE={\"source\":\"class Store:\\n def __init__(self,mode='ok'):self.objects={};self.m=None;self.mode=mode\\n def quota(self,remote):return {'ok':True,'observed_at':NOW,'total':1000*G,'used':0,'free':1000*G-int(remote[1:])*1000}\\n def bind(self,m):self.m=m\\n def absent(self,remote):\\n if self.mode=='collision':raise t.Stop('COLLISION')\\n def put(self,remote,name,path):\\n if remote==self.m['replicas'][1]['crypt_remote'] and (self.mode=='second' or self.mode=='second_seal' and name=='SEALED.json'):raise t.Stop('TEST_FAILURE')\\n key=(remote,self.m['generation'],name)\\n if key in self.objects:raise t.Stop('COLLISION')\\n self.objects[key]=Path(path).read_bytes()\\n def get(self,remote,name,limit):return self.objects[(remote,self.m['generation'],name)][:limit]\\n def read_stream(self,remote,name,size,h,consume):\\n b=self.get(remote,name,size+1);sink=s.DigestSink(size,h)\\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\\n return sink.finish()\\n\",\"source_sha256\":\"e45ff3e4e95d841661711a92f70d6f927351f9e6d60a3325fece9de4669b0664\"}\nTEST_GUEST266_READER_SOURCE={\"source\":\"class Reader:\\n def __init__(self,store,mode='ok'):self.store=store;self.mode=mode;self.listed=[]\\n def list_generations(self,remote):\\n self.listed.append(remote)\\n return sorted({gen for r,gen,n in self.store.objects if r==remote})\\n def get(self,remote,gen,name,limit,missing_ok=False):\\n v=self.store.objects.get((remote,gen,name))\\n if v is None and missing_ok:return None\\n if v is None:raise t.Stop('MISSING')\\n return v[:limit]\\n def read_stream(self,remote,gen,name,size,h,consume):\\n b=self.get(remote,gen,name,size+1)\\n if self.mode=='corrupt' and remote==self.store.m['replicas'][1]['crypt_remote']:b=b'!'+b[1:]\\n sink=s.DigestSink(size,h)\\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\\n return sink.finish()\\n\",\"source_sha256\":\"dd76a1f73d7b66ecb837c2b80514a45f5ffd265d819aec6bda3d92d8113d1fcb\"}\nTEST_GUEST266_INVENTORY_CONTRACT={\"direct_calls\":[\"('acct%d' % i).encode\",\"range\",\"t.sha\"],\"signature\":\"()\",\"source\":\"def inventory():return [{'account_id':t.sha(('acct%d'%i).encode()),'crypt_remote':'c%d'%i,'mail_remote':'m%d'%i,'wrapped_path':'bucket'} for i in range(13)]\\n\",\"source_sha256\":\"4f0238dd193df9eb06953459c1e6dbe8eef7f7d3cdd3712be7d3c27b9abd6559\"}\nTEST_PRODUCER282_E2E_SOURCE={\"source\":\" def test_fresh_archive_flows_through_existing_two_replica_engine(self):\\n import guest266 as guest\\n import test_guest266 as support\\n job,tools=self.fixture();work=self.root/'generation';work.mkdir(mode=0o700)\\n store=support.Store();now=int(time.time())\\n def quota(remote):return {'ok':True,'observed_at':now,'total':1000*1024**3,'used':0,'free':1000*1024**3-int(remote[1:])*1000}\\n store.quota=quota\\n def prod(j,p):return f.produce(j,p,tools,lambda:None,mapping=MAP,expected_config=job['config_sha256'],emit=lambda k,v:self.events.append((k,v)))\\n def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0\\n result=guest.run_flow(job,work,support.inventory(),store,support.Reader(store),prod,lambda:None,lambda:None,crc,'G268-fixture',lambda k,v:None,clock=lambda:now)\\n self.assertEqual(result['local_payload_files_remaining'],0);self.assertTrue(result['archive_cloud_restore_verified']);self.assertFalse(result['guest_restore_verified'])\\n self.assertTrue((work/'producer/producer.stderr.log').exists());self.assertFalse((work/'producer/guest-112.tar.zst').exists())\\n\",\"source_sha256\":\"a6de003495ee86836bb1bffb2a22a124331a4323726f5715c2a934d445d6b24f\"}\nCANDIDATE_CLOUD_ADAPTER_REFERENCES=[{\"file\":\"large264.py\",\"line\":56,\"line_sha256\":\"4ab4edc665f49c291b4ca5abb42b2e27a74403237f18eeabafab26dfb6dbbfd5\",\"tokens\":[\"class\",\"CloudLarge\",\"t\",\"RcloneIO\"]},{\"file\":\"large264.py\",\"line\":59,\"line_sha256\":\"d9107b9e748f739f75a51ce83c5708419ce820ae1090723ab8026949927e02c4\",\"tokens\":[\"t\",\"need\",\"type\",\"args\",\"is\",\"list\",\"and\",\"args\",\"and\",\"args\",\"in\",\"about\",\"lsjson\",\"copyto\",\"cat\",\"RCLONE_VERB_FORBIDDEN\"]},{\"file\":\"large264.py\",\"line\":61,\"line_sha256\":\"64b38e98ebced99e31c8f94c752a2767cae4b427e23d07bd1e3064ef4a2e2c45\",\"tokens\":[\"self\",\"check\",\"seconds\",\"min\",\"if\",\"args\",\"copyto\",\"else\",\"self\",\"deadline\",\"time\",\"monotonic\"]},{\"file\":\"large264.py\",\"line\":63,\"line_sha256\":\"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575\",\"tokens\":[\"if\",\"args\",\"copyto\",\"self\",\"writes_attempted\"]},{\"file\":\"large264.py\",\"line\":74,\"line_sha256\":\"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"dest\",\"stat\"]},{\"file\":\"large264.py\",\"line\":78,\"line_sha256\":\"ff1b43c434f93c38e81d2b9bd559e31baef49dcf3ed4bde121b02f72b38f607f\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"copyto\",\"str\",\"path\",\"dest\",\"immutable\",\"no\",\"update\",\"modtime\"]},{\"file\":\"large264.py\",\"line\":132,\"line_sha256\":\"6cad508b04c1979421f1df76e719cf88139404497f82f198f9aeb30afe55c6b3\",\"tokens\":[\"quotas\",\"e\",\"account_id\",\"cloud\",\"quota\",\"e\",\"crypt_remote\",\"for\",\"e\",\"in\",\"entries\"]},{\"file\":\"large264.py\",\"line\":141,\"line_sha256\":\"501fc63af37bd9126f146bbc6562c1d135cfca1f67db3ef1f53a9b949fdc61e7\",\"tokens\":[\"guard\",\"remote\",\"rep\",\"crypt_remote\",\"q\",\"cloud\",\"quota\",\"remote\"]},{\"file\":\"restore262.py\",\"line\":3,\"line_sha256\":\"bbd85fe87a59f8247a0a1a5cc42ed497bbafdfbc87e03590612447d705256d9e\",\"tokens\":[\"Cloud\",\"access\",\"is\",\"strictly\",\"lsjson\",\"cat\",\"No\",\"source\",\"local\",\"workspace\",\"manifest\",\"receipt\"]},{\"file\":\"restore262.py\",\"line\":50,\"line_sha256\":\"e442d31b20e2eff9207d7fc0b651516ba35d205677719c9a2add3f1e0f5090ce\",\"tokens\":[\"t\",\"need\",\"t\",\"sha\",\"t\",\"read_secure\",\"self\",\"executable\",\"self\",\"exe_sha\",\"RCLONE_BINARY_CHANGED\"]},{\"file\":\"restore262.py\",\"line\":62,\"line_sha256\":\"a1c27af31b577ebbce3ccfffad12e19986dc4af9437cf454480c2dd49dda9c94\",\"tokens\":[\"t\",\"need\",\"type\",\"args\",\"is\",\"list\",\"and\",\"args\",\"and\",\"args\",\"in\",\"lsjson\",\"cat\",\"READ_ONLY_CLOUD_VERB_REQUIRED\"]},{\"file\":\"restore262.py\",\"line\":69,\"line_sha256\":\"93cbda6a3396bc2369974f589ad0a1494e7561a293ebadfe361c38d64f8acf87\",\"tokens\":[\"rc\",\"out\",\"self\",\"call\",\"lsjson\",\"self\",\"address\",\"remote\",\"dirs\",\"only\",\"max\",\"depth\"]},{\"file\":\"stream263.py\",\"line\":3,\"line_sha256\":\"14c9c361fa8ac5652d5ee51d2f3f18721d40d02442fb2e0e3da2c5cbe47cc99a\",\"tokens\":[\"No\",\"executable\",\"entry\",\"point\",\"network\",\"rclone\",\"backup\",\"execution\",\"sealing\",\"or\",\"deletion\"]},{\"file\":\"test_guest266.py\",\"line\":25,\"line_sha256\":\"23b4bb50f445dce73aec7ebd298f7d6ecb1063c6049601af0dae6061f7f9636d\",\"tokens\":[\"def\",\"quota\",\"self\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"NOW\",\"total\",\"G\",\"used\",\"free\",\"G\",\"int\",\"remote\"]},{\"file\":\"test_producer282.py\",\"line\":190,\"line_sha256\":\"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f\",\"tokens\":[\"def\",\"quota\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"now\",\"total\",\"used\",\"free\",\"int\",\"remote\"]},{\"file\":\"test_pve270.py\",\"line\":189,\"line_sha256\":\"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f\",\"tokens\":[\"def\",\"quota\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"now\",\"total\",\"used\",\"free\",\"int\",\"remote\"]},{\"file\":\"transport261.py\",\"line\":3,\"line_sha256\":\"44ce8b584aa0bd838288d3f181dd94c706cb7198cd5d7265305d1432647338c0\",\"tokens\":[\"Only\",\"about\",\"lsjson\",\"copyto\",\"and\",\"cat\",\"are\",\"permitted\",\"A\",\"completed\",\"canary\",\"is\",\"a\",\"small\"]},{\"file\":\"transport261.py\",\"line\":171,\"line_sha256\":\"7bd06d43b3c7c43e92988bc7f5bc79c61ff5a4cdeb0dbc2c719bc09d6d5296bd\",\"tokens\":[\"class\",\"RcloneIO\"]},{\"file\":\"transport261.py\",\"line\":185,\"line_sha256\":\"0a241b5e17035863793b414ac6576aa655e63cae48232001b88b38d46c593b7f\",\"tokens\":[\"need\",\"sha\",\"read_secure\",\"self\",\"executable\",\"self\",\"exe_sha\",\"RCLONE_BINARY_CHANGED\"]},{\"file\":\"transport261.py\",\"line\":187,\"line_sha256\":\"e4da1a906be5d6978f3a47abcd8d524463a8c41ec17dae4a813aec34f6d2349d\",\"tokens\":[\"need\",\"args\",\"in\",\"about\",\"lsjson\",\"copyto\",\"cat\",\"RCLONE_VERB_FORBIDDEN\"]},{\"file\":\"transport261.py\",\"line\":193,\"line_sha256\":\"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575\",\"tokens\":[\"if\",\"args\",\"copyto\",\"self\",\"writes_attempted\"]},{\"file\":\"transport261.py\",\"line\":197,\"line_sha256\":\"a887c54bf0d144f2fb71086d385dd1eecd5f3c4ed54c8d46fd3775be00275e3e\",\"tokens\":[\"def\",\"quota\",\"self\",\"remote\"]},{\"file\":\"transport261.py\",\"line\":219,\"line_sha256\":\"b8f85d8b53248a1a6741103aa8ec42a948488b1daca961287026505b0754bafb\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"self\",\"address\",\"remote\",\"max\",\"depth\"]},{\"file\":\"transport261.py\",\"line\":224,\"line_sha256\":\"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"dest\",\"stat\"]},{\"file\":\"transport261.py\",\"line\":227,\"line_sha256\":\"ec6a68482d4a09142676ac25a5010d18bdcf8b21d9f60067e857f5818c3e1311\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"copyto\",\"str\",\"path\",\"dest\",\"immutable\",\"no\",\"update\",\"modtime\"]},{\"file\":\"transport261.py\",\"line\":248,\"line_sha256\":\"12f619354bdfdb6783b881c113091a83637a533c3de9b7e185e8ed9e8bd35f60\",\"tokens\":[\"for\",\"e\",\"in\",\"entries\",\"quotas\",\"e\",\"account_id\",\"cloud\",\"quota\",\"e\",\"crypt_remote\"]},{\"file\":\"transport261.py\",\"line\":255,\"line_sha256\":\"3ecbce0f455e711bb54ae15ac845dc3de4e46d8ba23713ec58ec4d7f8eea8815\",\"tokens\":[\"q\",\"cloud\",\"quota\",\"e\",\"crypt_remote\"]},{\"file\":\"v2core.py\",\"line\":110,\"line_sha256\":\"1a51f0e9266b714dd0ebfaf2043d97756197268e3676b2897d53e570528ee2fc\",\"tokens\":[\"rclone\",\"crypt\",\"byte\",\"header\",\"plus\",\"per\",\"nonempty\",\"KiB\",\"block\"]}]\nG426_PAYLOAD_POST_INSPECTION_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12\nPRODUCTION_POST_PREFLIGHT_UNCHANGED=PASS\nCANDIDATE_POST_PREFLIGHT_UNCHANGED=PASS\nCLOUD_SEAL_CONTRACT_PREFLIGHT=PASS\nSTATUS=OK\nPHASE=COMPLETE\nREASON=NONE\nNEXT_GATE=CT112_REAL_BACKUP_1_TWO_REPLICA_SEAL_IMPLEMENTATION\nCHANGES_MADE=false\nMUTATION_OUTCOME=NO_MUTATION\nBACKUP_EXECUTIONS=0\nVZDUMP_EXECUTIONS=0\nCLOUD_WRITES=0\nCLOUD_DELETIONS=0\nSYSTEMD_MUTATIONS=0\nSCHEDULER_CUTOVER=NO\nLEGACY_BACKUP_DISABLES=0\nLOCAL_G426_PAYLOAD_PRESERVED=YES\nHOMELAB_RESULT_CONTRACT={\"changes_made\":false,\"command_id\":\"SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1\",\"rollback_restored\":null,\"rollback_started\":false,\"status\":\"OK\",\"version\":1}\n" +} diff --git a/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.txt b/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.txt new file mode 100644 index 00000000..fa2cc0ce --- /dev/null +++ b/runtime/history/SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1.txt @@ -0,0 +1,80 @@ +CHAT_OUTPUT_BEGIN +COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1 +STATUS=OK +RC=0 +HOST=pve01 +MODE=read-only +COMPONENT=infra-dr-backupv2-ct112-cloud-seal-contract-preflight +REFERENCE_REGISTER_CHECK=OK +REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 +ERROR_REGISTER_CHECK=OK +ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 +COMMAND_SHA256=c92db35b051b231f28f75dee8513620581c9e13c76afce192d2ec6fee0e4f079 +DUPLICATE_FAILED_COMMAND_BLOCKED=false +EXECUTION_STARTED=true +CHANGE_DECLARED=false +RESULT_CONTRACT_VALID=true +RESULT_CONTRACT_STATUS=NOT_APPLICABLE +RESULT_CONTRACT_ERROR=NONE +COMMAND_RC=0 +CHANGES_MADE=false +ROLLBACK_STARTED=false +ROLLBACK_RESTORED=null +MUTATION_OUTCOME=NO_MUTATION +SANITIZED=yes +SECRETS_INCLUDED=no +PRIVATE_ADDRESSES_INCLUDED=no +RAW_EVIDENCE_SHA256=c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3 +SANITIZED_OUTPUT_SHA256=c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3 +OUTPUT_BEGIN +COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1 +MODE=READ_ONLY_CT112_CLOUD_SEAL_CONTRACT_PREFLIGHT +NO_BACKUP_EXECUTION=YES +NO_VZDUMP_EXECUTION=YES +NO_CLOUD_ACCESS=YES +NO_RCLONE_EXECUTION=YES +NO_CLOUD_DELETION=YES +NO_SYSTEMD_MUTATION=YES +NO_FILE_MUTATION=YES +PRODUCTION_AND_CANDIDATE_IDENTITY=PASS +SOURCE_SET_IDENTITY=PASS +G426_IMMUTABLE_COMMIT=8e261f22b35fe49616ab7c2e23f5cac3a5b66376 +G426_STAGE_BINDING=PASS +G426_GENERATION=G426-20260915T115318Z-d9bb39ace5781d2e +G426_PAYLOAD_BYTES=223855196 +G426_PAYLOAD_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12 +G426_PAYLOAD_MODE=0400 +CLOUD_ENGINE_OWNER_GRAPH=PASS +GUEST266_RUN_FLOW_CONTRACT={"direct_calls":["Path","all","callable","check_result","clock","compression_check","core.canonical_bytes","core.manifest_hash","core.valid_name","core.validate_inventory","guard","int","job.get","large.cleanup","large.discover","large.restore","large.upload","len","produce","producer.validate_job","say","state_guard","t.create","t.make_dir","t.need","time.time"],"signature":"(job, work, entries, cloud, reader, produce, state_guard, guard, compression_check, generation, say, clock= at 0x76417f8f07c0>)","source":"def run_flow(job,work,entries,cloud,reader,produce,state_guard,guard,compression_check,generation,say,clock=lambda:int(time.time())):\n \"\"\"Caller provides real fresh PVE guards; simulation callbacks live in tests only.\"\"\"\n producer.validate_job(job,clock());core.validate_inventory(entries)\n t.need(job['type']=='lxc' and job.get('compression_dependent') is False,'FIRST_GUEST_POLICY')\n t.need(core.valid_name(generation),'GENERATION_ID')\n t.need(all(callable(f) for f in (produce,state_guard,guard,compression_check,say,clock)),'CALLBACKS_REQUIRED')\n work=Path(work);state_guard();guard()\n for sub in ('producer','upload','restore'):t.make_dir(work/sub,exclusive=True)\n say('PHASE','REAL_SINGLE_GUEST_SNAPSHOT')\n produced=produce(job,work/'producer')\n source=check_result(produced,job,work/'producer');state_guard();guard()\n t.create(work/'PRODUCER.json',core.canonical_bytes(produced))\n say('PRODUCER_RC',0);say('PAYLOAD_BYTES',produced['size']);say('ARCHIVE_SHA256',produced['sha256'])\n logical='guest-%s-%s-%d'%(job['node'],job['type'],job['vmid'])\n say('PHASE','TWO_REPLICA_UPLOAD_AND_READBACK')\n up=large.upload(source,work/'upload',entries,cloud,generation,logical,RESERVE_BYTES,guard,clock=clock)\n t.need(up['manifest']['payload_bytes']==produced['size'] and up['manifest']['payload_sha256']==produced['sha256'],'MANIFEST_PRODUCER_MISMATCH')\n say('SEALED_QUORUM_VERIFIED','YES');mh=core.manifest_hash(up['manifest']);say('MANIFEST_SHA256',mh)\n say('PHASE','CLOUD_DISCOVERY_AND_ARCHIVE_RECONSTRUCTION')\n found=large.discover(reader,entries,logical,mh)\n restored=large.restore(work/'restore',reader,found)\n t.need(compression_check(work/'restore/restored.bin') is True,'RECONSTRUCTED_COMPRESSION_FAILED')\n state_guard();guard();say('PHASE','GUARDED_LOCAL_PAYLOAD_CLEANUP')\n count=large.cleanup(up,restored,reader,guard)\n return {'state':'SINGLE_GUEST_ARCHIVE_SEALED_AND_CLOUD_RECONSTRUCTED','vmid':job['vmid'],'type':job['type'],'node':job['node'],\n 'generation':generation,'logical_id':logical,'manifest_sha256':mh,'payload_bytes':produced['size'],'payload_sha256':produced['sha256'],\n 'replicas':up['manifest']['replicas'],'parts_count':len(up['manifest']['parts']),'archive_cloud_restore_verified':True,\n 'guest_restore_verified':False,'application_consistency_verified':False,'whole_node_backup':False,'local_payload_files_remaining':0,\n 'files_deleted':count,'accounts_scanned':found['accounts_scanned'],'config_sha256':job['config_sha256']}\n","source_sha256":"789140b440fc756f99c8979b543c60a44ada096b5acece83e7173791f23bb55c"} +LARGE264_UPLOAD_CONTRACT={"direct_calls":["Path","clock","cloud.absent","cloud.bind","cloud.get","cloud.put","cloud.quota","cloud.read_stream","core.allocate","core.canonical_bytes","core.make_manifest","core.manifest_hash","core.quota_reason","core.valid_name","core.validate_inventory","core.verify_receipts","guard","hashlib.sha256","int","len","r.validate_seal","receipt","receipts.append","s.split_file","s.verify_parts","str","t.create","t.make_dir","t.need","t.sha","time.time"],"signature":"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)","source":"def upload(source,work,entries,cloud,generation,logical_id,reserve,guard,clock=lambda:int(time.time())):\n \"\"\"Upload and seal; retain all source bytes here. Cleanup is a later gated operation.\"\"\"\n work=Path(work);source=Path(source);guard();core.validate_inventory(entries)\n t.need(core.valid_name(generation) and core.valid_name(logical_id),'GENERATION_ID')\n partdir=work/'parts';t.make_dir(partdir,exclusive=True)\n record=s.split_file(source,partdir)\n t.create(work/'parts-record.json',core.canonical_bytes(record))\n quotas={e['account_id']:cloud.quota(e['crypt_remote']) for e in entries}\n allocation=core.allocate(entries,quotas,record['payload_bytes'],reserve,clock())\n m=core.make_manifest(generation,logical_id,record['payload_bytes'],record['payload_sha256'],record['parts'],allocation)\n mb=core.canonical_bytes(m);mh=core.manifest_hash(m);cloud.bind(m)\n t.create(work/'allocation.json',core.canonical_bytes(allocation));t.create(work/'manifest.json',mb)\n for rep in m['replicas']:\n guard();cloud.absent(rep['crypt_remote'])\n receipts=[]\n for rep in m['replicas']:\n guard();remote=rep['crypt_remote'];q=cloud.quota(remote)\n t.need(core.quota_reason(q,clock()) is None and q['free']>=allocation['required_free_bytes'],'SELECTED_ACCOUNT_CAPACITY_CHANGED')\n s.verify_parts(partdir,record)\n for part in m['parts']:cloud.put(remote,part['name'],partdir/part['name'])\n cloud.put(remote,'manifest.json',work/'manifest.json')\n t.need(cloud.get(remote,'manifest.json',len(mb)+1)==mb,'MANIFEST_READBACK_MISMATCH')\n whole=hashlib.sha256();count=0\n for part in m['parts']:\n observed=cloud.read_stream(remote,part['name'],part['size'],part['sha256'],whole.update)\n t.need(observed=={'size':part['size'],'sha256':part['sha256']},'PART_READBACK_MISMATCH');count+=observed['size']\n receipts.append(receipt(rep,m,whole,count));t.create(work/('receipt-%d.json'%len(receipts)),core.canonical_bytes(receipts[-1]))\n core.verify_receipts(m,receipts)\n seal={'schema_version':2,'state':'SEALED','generation':generation,'logical_id':logical_id,\n 'manifest_sha256':mh,'replicas':m['replicas'],'receipts':receipts,\n 'acceptance':'IDENTICAL_SEAL_REQUIRED_ON_BOTH_NAMED_ACCOUNTS'}\n sb=core.canonical_bytes(seal);t.need(len(sb)<=core.SEAL_MAX_BYTES,'SEAL_BOUND')\n r.validate_seal(sb,entries,generation,logical_id);t.create(work/'SEALED.json',sb)\n for rep in m['replicas']:\n guard();cloud.put(rep['crypt_remote'],'SEALED.json',work/'SEALED.json')\n for rep in m['replicas']:\n t.need(cloud.get(rep['crypt_remote'],'SEALED.json',len(sb)+1)==sb,'SEALED_QUORUM_REQUIRED')\n guard();s.verify_parts(partdir,record)\n t.create(work/'QUORUM_VERIFIED.json',core.canonical_bytes({'manifest_sha256':mh,'seal_sha256':t.sha(sb)}))\n return {'sealed':True,'manifest':m,'seal_bytes':sb,'parts_record':record,'source':str(source),'work':str(work)}\n","source_sha256":"3fc04eea643b977e58713bea8a7b9bcfd485e60251a4393874dfe1a428014bbe"} +LARGE264_RESTORE_CONTRACT={"direct_calls":["Path","cloud.read_stream","core.canonical_bytes","core.manifest_hash","core.validate_manifest","core.verify_receipts","download_part","enumerate","fresh_seals","hashlib.sha256","receipt","receipts.append","s.reassemble","str","t.create","t.make_dir","t.need"],"signature":"(work, cloud, discovery)","source":"def restore(work,cloud,discovery):\n \"\"\"Reconstruct one replica on disk; hash every byte of the other independently.\"\"\"\n work=Path(work);m=discovery['manifest'];core.validate_manifest(m)\n partdir=work/'parts';t.make_dir(partdir,exclusive=True);owned={};receipts=[]\n for i,rep in enumerate(m['replicas']):\n whole=hashlib.sha256();count=0\n for part in m['parts']:\n if i==0:owned[part['name']]=download_part(cloud,rep,m,part,partdir/part['name'],whole)\n else:\n got=cloud.read_stream(rep['crypt_remote'],m['generation'],part['name'],part['size'],part['sha256'],whole.update)\n t.need(got=={'size':part['size'],'sha256':part['sha256']},'PART_DOWNLOAD_MISMATCH')\n count+=part['size']\n receipts.append(receipt(rep,m,whole,count))\n core.verify_receipts(m,receipts);fresh_seals(cloud,discovery)\n rec={'schema_version':1,'payload_bytes':m['payload_bytes'],'payload_sha256':m['payload_sha256'],\n 'part_bytes':core.PART_BYTES,'parts':m['parts'],'owned':owned,'source_identity':[0]*8}\n result=s.reassemble(partdir,rec,work/'restored.bin')\n fresh_seals(cloud,discovery)\n t.create(work/'RESTORE_VERIFIED.json',core.canonical_bytes({'manifest_sha256':core.manifest_hash(m),'verified_replicas':2,\n 'accounts_scanned':discovery['accounts_scanned'],'payload_bytes':result['size'],'payload_sha256':result['sha256']}))\n return {'verified_replicas':2,'manifest_sha256':core.manifest_hash(m),'discovery':discovery,\n 'parts_record':rec,'reassembled':result,'work':str(work)}\n","source_sha256":"0a73a874d1354b5a63645f4848a9bae933e463e444c3db177ab07c01ecd1f614"} +LARGE264_DISCOVER_CONTRACT={"direct_calls":["all","blobs.append","candidates.append","cloud.get","cloud.list_generations","core.canonical_bytes","core.valid_hash","core.valid_name","core.validate_inventory","core.validate_manifest","core.verify_receipts","generations.update","iter","len","next","r.strict_json","r.validate_seal","seen.values","set","sorted","t.need","t.sha","type"],"signature":"(cloud, entries, logical_id, expected_hash)","source":"def discover(cloud,entries,logical_id,expected_hash):\n \"\"\"Find placement from all cloud catalogs, using only an external manifest digest.\"\"\"\n core.validate_inventory(entries)\n t.need(core.valid_name(logical_id) and core.valid_hash(expected_hash),'DISCOVERY_INPUT')\n listed={};generations=set()\n for e in entries:\n gs=cloud.list_generations(e['crypt_remote'])\n t.need(type(gs) is list and len(gs)<=r.MAX_GENERATIONS and all(core.valid_name(g) for g in gs),'GENERATION_LIST_INVALID')\n t.need(len(gs)==len(set(gs)),'GENERATION_LIST_DUPLICATE');listed[e['crypt_remote']]=set(gs);generations.update(gs)\n t.need(len(generations)<=r.MAX_GENERATIONS,'TOTAL_GENERATIONS_BOUND')\n candidates=[]\n for gen in sorted(generations):\n seen={}\n for e in entries:\n remote=e['crypt_remote']\n if gen not in listed[remote]:continue\n b=cloud.get(remote,gen,'SEALED.json',core.SEAL_MAX_BYTES+1,missing_ok=True)\n if b is None:continue\n seal=r.validate_seal(b,entries,gen,logical_id)\n t.need(remote in {x['crypt_remote'] for x in seal['replicas']},'UNNAMED_SEAL_LOCATION');seen[remote]=(b,seal)\n if not seen:continue\n sb,seal=next(iter(seen.values()))\n if seal['manifest_sha256']!=expected_hash:continue\n named={x['crypt_remote'] for x in seal['replicas']}\n t.need(set(seen)==named and all(b==sb for b,_ in seen.values()),'IDENTICAL_TWO_SEALS_REQUIRED')\n blobs=[]\n for rep in seal['replicas']:\n b=cloud.get(rep['crypt_remote'],gen,'manifest.json',core.MANIFEST_MAX_BYTES+1)\n t.need(type(b) is bytes and t.sha(b)==expected_hash,'MANIFEST_DIGEST_MISMATCH')\n m=r.strict_json(b,core.MANIFEST_MAX_BYTES);core.validate_manifest(m)\n t.need(m['generation']==gen and m['logical_id']==logical_id and m['replicas']==seal['replicas'],'MANIFEST_PLACEMENT')\n t.need(core.canonical_bytes(m)==b,'MANIFEST_CANONICAL_BYTES');core.verify_receipts(m,seal['receipts']);blobs.append(b)\n t.need(len(blobs)==2 and blobs[0]==blobs[1],'TWO_MANIFEST_COPIES_REQUIRED')\n candidates.append({'manifest':m,'seal_bytes':sb,'accounts_scanned':len(listed)})\n t.need(len(candidates)==1,'EXACTLY_ONE_ACCEPTED_GENERATION_REQUIRED')\n return candidates[0]\n","source_sha256":"0f9d514dfa0985bfa0ee6446aa85a78377346003039896395cb39e0bf3643702"} +LARGE264_CLEANUP_CONTRACT={"direct_calls":["Path","any","core.canonical_bytes","core.manifest_hash","core.validate_manifest","core.verify_receipts","fresh_seals","guard","items.append","len","os.close","os.fsync","os.stat","os.unlink","p.exists","p.is_symlink","r.strict_json","restore_result.get","s.hash_file","s.validate_record","s.verify_parts","str","t.ident","t.need","t.open_dir","tuple","type","upload_result.get"],"signature":"(upload_result, restore_result, cloud, guard)","source":"def cleanup(upload_result,restore_result,cloud,guard):\n \"\"\"No unlink until every expected file and both remote seals have passed verification.\"\"\"\n t.need(type(upload_result) is dict and upload_result.get('sealed') is True,'UPLOAD_QUORUM_REQUIRED')\n t.need(type(restore_result) is dict and restore_result.get('verified_replicas')==2,'RESTORE_REQUIRED')\n m=upload_result['manifest'];core.validate_manifest(m);mh=core.manifest_hash(m)\n t.need(restore_result['manifest_sha256']==mh,'RESTORE_GENERATION_MISMATCH')\n t.need(core.canonical_bytes(restore_result['discovery']['manifest'])==core.canonical_bytes(m) and\n restore_result['discovery']['seal_bytes']==upload_result['seal_bytes'],'RESTORE_QUORUM_MISMATCH')\n core.verify_receipts(m,r.strict_json(upload_result['seal_bytes'],core.SEAL_MAX_BYTES)['receipts'])\n guard();fresh_seals(cloud,restore_result['discovery'])\n items=[]\n for record,base in ((upload_result['parts_record'],Path(upload_result['work'])/'parts'),\n (restore_result['parts_record'],Path(restore_result['work'])/'parts')):\n s.validate_record(record);s.verify_parts(base,record)\n for part in record['parts']:items.append((base/part['name'],tuple(record['owned'][part['name']]),part['size'],part['sha256']))\n items.append((Path(upload_result['source']),tuple(upload_result['parts_record']['source_identity']),m['payload_bytes'],m['payload_sha256']))\n items.append((Path(restore_result['work'])/'restored.bin',tuple(restore_result['reassembled']['identity']),m['payload_bytes'],m['payload_sha256']))\n t.need(len({str(p) for p,_,_,_ in items})==len(items),'CLEANUP_DUPLICATE_PATH')\n for p,identity,size,h in items:\n n,d,seen=s.hash_file(p,size);t.need(seen==identity and n==size and d==h,'CLEANUP_IDENTITY_OR_HASH')\n guard();fresh_seals(cloud,restore_result['discovery'])\n for p,identity,size,h in items:\n parent=t.open_dir(p.parent)\n try:\n t.need(t.ident(os.stat(p.name,dir_fd=parent,follow_symlinks=False))==identity,'CLEANUP_FILE_CHANGED')\n os.unlink(p.name,dir_fd=parent);os.fsync(parent)\n finally:os.close(parent)\n t.need(not any(p.exists() or p.is_symlink() for p,_,_,_ in items),'LOCAL_CLEANUP_INCOMPLETE')\n return len(items)\n","source_sha256":"2cbbf3325b84192705686a2c6d3a02f58a75f51145f68204786e08194013cd3b"} +LARGE264_FUNCTION_INDEX={"cleanup":"(upload_result, restore_result, cloud, guard)","discover":"(cloud, entries, logical_id, expected_hash)","download_part":"(cloud, rep, m, part, path, whole)","flags":"(executable, snapshot, work, args)","fresh_seals":"(cloud, discovery)","process_stream":"(argv, env, size, digest, consume, seconds)","random_source":"(path, size=536870929)","receipt":"(rep, m, whole, count)","restore":"(work, cloud, discovery)","upload":"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)"} +TEST_GUEST266_STORE_SOURCE={"source":"class Store:\n def __init__(self,mode='ok'):self.objects={};self.m=None;self.mode=mode\n def quota(self,remote):return {'ok':True,'observed_at':NOW,'total':1000*G,'used':0,'free':1000*G-int(remote[1:])*1000}\n def bind(self,m):self.m=m\n def absent(self,remote):\n if self.mode=='collision':raise t.Stop('COLLISION')\n def put(self,remote,name,path):\n if remote==self.m['replicas'][1]['crypt_remote'] and (self.mode=='second' or self.mode=='second_seal' and name=='SEALED.json'):raise t.Stop('TEST_FAILURE')\n key=(remote,self.m['generation'],name)\n if key in self.objects:raise t.Stop('COLLISION')\n self.objects[key]=Path(path).read_bytes()\n def get(self,remote,name,limit):return self.objects[(remote,self.m['generation'],name)][:limit]\n def read_stream(self,remote,name,size,h,consume):\n b=self.get(remote,name,size+1);sink=s.DigestSink(size,h)\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\n return sink.finish()\n","source_sha256":"e45ff3e4e95d841661711a92f70d6f927351f9e6d60a3325fece9de4669b0664"} +TEST_GUEST266_READER_SOURCE={"source":"class Reader:\n def __init__(self,store,mode='ok'):self.store=store;self.mode=mode;self.listed=[]\n def list_generations(self,remote):\n self.listed.append(remote)\n return sorted({gen for r,gen,n in self.store.objects if r==remote})\n def get(self,remote,gen,name,limit,missing_ok=False):\n v=self.store.objects.get((remote,gen,name))\n if v is None and missing_ok:return None\n if v is None:raise t.Stop('MISSING')\n return v[:limit]\n def read_stream(self,remote,gen,name,size,h,consume):\n b=self.get(remote,gen,name,size+1)\n if self.mode=='corrupt' and remote==self.store.m['replicas'][1]['crypt_remote']:b=b'!'+b[1:]\n sink=s.DigestSink(size,h)\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\n return sink.finish()\n","source_sha256":"dd76a1f73d7b66ecb837c2b80514a45f5ffd265d819aec6bda3d92d8113d1fcb"} +TEST_GUEST266_INVENTORY_CONTRACT={"direct_calls":["('acct%d' % i).encode","range","t.sha"],"signature":"()","source":"def inventory():return [{'account_id':t.sha(('acct%d'%i).encode()),'crypt_remote':'c%d'%i,'mail_remote':'m%d'%i,'wrapped_path':'bucket'} for i in range(13)]\n","source_sha256":"4f0238dd193df9eb06953459c1e6dbe8eef7f7d3cdd3712be7d3c27b9abd6559"} +TEST_PRODUCER282_E2E_SOURCE={"source":" def test_fresh_archive_flows_through_existing_two_replica_engine(self):\n import guest266 as guest\n import test_guest266 as support\n job,tools=self.fixture();work=self.root/'generation';work.mkdir(mode=0o700)\n store=support.Store();now=int(time.time())\n def quota(remote):return {'ok':True,'observed_at':now,'total':1000*1024**3,'used':0,'free':1000*1024**3-int(remote[1:])*1000}\n store.quota=quota\n def prod(j,p):return f.produce(j,p,tools,lambda:None,mapping=MAP,expected_config=job['config_sha256'],emit=lambda k,v:self.events.append((k,v)))\n def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0\n result=guest.run_flow(job,work,support.inventory(),store,support.Reader(store),prod,lambda:None,lambda:None,crc,'G268-fixture',lambda k,v:None,clock=lambda:now)\n self.assertEqual(result['local_payload_files_remaining'],0);self.assertTrue(result['archive_cloud_restore_verified']);self.assertFalse(result['guest_restore_verified'])\n self.assertTrue((work/'producer/producer.stderr.log').exists());self.assertFalse((work/'producer/guest-112.tar.zst').exists())\n","source_sha256":"a6de003495ee86836bb1bffb2a22a124331a4323726f5715c2a934d445d6b24f"} +CANDIDATE_CLOUD_ADAPTER_REFERENCES=[{"file":"large264.py","line":56,"line_sha256":"4ab4edc665f49c291b4ca5abb42b2e27a74403237f18eeabafab26dfb6dbbfd5","tokens":["class","CloudLarge","t","RcloneIO"]},{"file":"large264.py","line":59,"line_sha256":"d9107b9e748f739f75a51ce83c5708419ce820ae1090723ab8026949927e02c4","tokens":["t","need","type","args","is","list","and","args","and","args","in","about","lsjson","copyto","cat","RCLONE_VERB_FORBIDDEN"]},{"file":"large264.py","line":61,"line_sha256":"64b38e98ebced99e31c8f94c752a2767cae4b427e23d07bd1e3064ef4a2e2c45","tokens":["self","check","seconds","min","if","args","copyto","else","self","deadline","time","monotonic"]},{"file":"large264.py","line":63,"line_sha256":"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575","tokens":["if","args","copyto","self","writes_attempted"]},{"file":"large264.py","line":74,"line_sha256":"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec","tokens":["rc","_","self","call","lsjson","dest","stat"]},{"file":"large264.py","line":78,"line_sha256":"ff1b43c434f93c38e81d2b9bd559e31baef49dcf3ed4bde121b02f72b38f607f","tokens":["rc","_","self","call","copyto","str","path","dest","immutable","no","update","modtime"]},{"file":"large264.py","line":132,"line_sha256":"6cad508b04c1979421f1df76e719cf88139404497f82f198f9aeb30afe55c6b3","tokens":["quotas","e","account_id","cloud","quota","e","crypt_remote","for","e","in","entries"]},{"file":"large264.py","line":141,"line_sha256":"501fc63af37bd9126f146bbc6562c1d135cfca1f67db3ef1f53a9b949fdc61e7","tokens":["guard","remote","rep","crypt_remote","q","cloud","quota","remote"]},{"file":"restore262.py","line":3,"line_sha256":"bbd85fe87a59f8247a0a1a5cc42ed497bbafdfbc87e03590612447d705256d9e","tokens":["Cloud","access","is","strictly","lsjson","cat","No","source","local","workspace","manifest","receipt"]},{"file":"restore262.py","line":50,"line_sha256":"e442d31b20e2eff9207d7fc0b651516ba35d205677719c9a2add3f1e0f5090ce","tokens":["t","need","t","sha","t","read_secure","self","executable","self","exe_sha","RCLONE_BINARY_CHANGED"]},{"file":"restore262.py","line":62,"line_sha256":"a1c27af31b577ebbce3ccfffad12e19986dc4af9437cf454480c2dd49dda9c94","tokens":["t","need","type","args","is","list","and","args","and","args","in","lsjson","cat","READ_ONLY_CLOUD_VERB_REQUIRED"]},{"file":"restore262.py","line":69,"line_sha256":"93cbda6a3396bc2369974f589ad0a1494e7561a293ebadfe361c38d64f8acf87","tokens":["rc","out","self","call","lsjson","self","address","remote","dirs","only","max","depth"]},{"file":"stream263.py","line":3,"line_sha256":"14c9c361fa8ac5652d5ee51d2f3f18721d40d02442fb2e0e3da2c5cbe47cc99a","tokens":["No","executable","entry","point","network","rclone","backup","execution","sealing","or","deletion"]},{"file":"test_guest266.py","line":25,"line_sha256":"23b4bb50f445dce73aec7ebd298f7d6ecb1063c6049601af0dae6061f7f9636d","tokens":["def","quota","self","remote","return","ok","True","observed_at","NOW","total","G","used","free","G","int","remote"]},{"file":"test_producer282.py","line":190,"line_sha256":"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f","tokens":["def","quota","remote","return","ok","True","observed_at","now","total","used","free","int","remote"]},{"file":"test_pve270.py","line":189,"line_sha256":"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f","tokens":["def","quota","remote","return","ok","True","observed_at","now","total","used","free","int","remote"]},{"file":"transport261.py","line":3,"line_sha256":"44ce8b584aa0bd838288d3f181dd94c706cb7198cd5d7265305d1432647338c0","tokens":["Only","about","lsjson","copyto","and","cat","are","permitted","A","completed","canary","is","a","small"]},{"file":"transport261.py","line":171,"line_sha256":"7bd06d43b3c7c43e92988bc7f5bc79c61ff5a4cdeb0dbc2c719bc09d6d5296bd","tokens":["class","RcloneIO"]},{"file":"transport261.py","line":185,"line_sha256":"0a241b5e17035863793b414ac6576aa655e63cae48232001b88b38d46c593b7f","tokens":["need","sha","read_secure","self","executable","self","exe_sha","RCLONE_BINARY_CHANGED"]},{"file":"transport261.py","line":187,"line_sha256":"e4da1a906be5d6978f3a47abcd8d524463a8c41ec17dae4a813aec34f6d2349d","tokens":["need","args","in","about","lsjson","copyto","cat","RCLONE_VERB_FORBIDDEN"]},{"file":"transport261.py","line":193,"line_sha256":"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575","tokens":["if","args","copyto","self","writes_attempted"]},{"file":"transport261.py","line":197,"line_sha256":"a887c54bf0d144f2fb71086d385dd1eecd5f3c4ed54c8d46fd3775be00275e3e","tokens":["def","quota","self","remote"]},{"file":"transport261.py","line":219,"line_sha256":"b8f85d8b53248a1a6741103aa8ec42a948488b1daca961287026505b0754bafb","tokens":["rc","_","self","call","lsjson","self","address","remote","max","depth"]},{"file":"transport261.py","line":224,"line_sha256":"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec","tokens":["rc","_","self","call","lsjson","dest","stat"]},{"file":"transport261.py","line":227,"line_sha256":"ec6a68482d4a09142676ac25a5010d18bdcf8b21d9f60067e857f5818c3e1311","tokens":["rc","_","self","call","copyto","str","path","dest","immutable","no","update","modtime"]},{"file":"transport261.py","line":248,"line_sha256":"12f619354bdfdb6783b881c113091a83637a533c3de9b7e185e8ed9e8bd35f60","tokens":["for","e","in","entries","quotas","e","account_id","cloud","quota","e","crypt_remote"]},{"file":"transport261.py","line":255,"line_sha256":"3ecbce0f455e711bb54ae15ac845dc3de4e46d8ba23713ec58ec4d7f8eea8815","tokens":["q","cloud","quota","e","crypt_remote"]},{"file":"v2core.py","line":110,"line_sha256":"1a51f0e9266b714dd0ebfaf2043d97756197268e3676b2897d53e570528ee2fc","tokens":["rclone","crypt","byte","header","plus","per","nonempty","KiB","block"]}] +G426_PAYLOAD_POST_INSPECTION_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12 +PRODUCTION_POST_PREFLIGHT_UNCHANGED=PASS +CANDIDATE_POST_PREFLIGHT_UNCHANGED=PASS +CLOUD_SEAL_CONTRACT_PREFLIGHT=PASS +STATUS=OK +PHASE=COMPLETE +REASON=NONE +NEXT_GATE=CT112_REAL_BACKUP_1_TWO_REPLICA_SEAL_IMPLEMENTATION +CHANGES_MADE=false +MUTATION_OUTCOME=NO_MUTATION +BACKUP_EXECUTIONS=0 +VZDUMP_EXECUTIONS=0 +CLOUD_WRITES=0 +CLOUD_DELETIONS=0 +SYSTEMD_MUTATIONS=0 +SCHEDULER_CUTOVER=NO +LEGACY_BACKUP_DISABLES=0 +LOCAL_G426_PAYLOAD_PRESERVED=YES +HOMELAB_RESULT_CONTRACT={"changes_made":false,"command_id":"SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1","rollback_restored":null,"rollback_started":false,"status":"OK","version":1} + +OUTPUT_END +CHAT_OUTPUT_END diff --git a/runtime/latest.json b/runtime/latest.json index dddb8d89..c6954d6c 100644 --- a/runtime/latest.json +++ b/runtime/latest.json @@ -1 +1,38 @@ -{"schema_version":1,"channel":"homelab-runtime","command_id":"CONTEXT-AUTO-20260915T121701Z","status":"OK","rc":0,"host":"pve01","mode":"read-only","component":"cluster-context","started_at_utc":"2026-09-15T12:17:01Z","finished_at_utc":"2026-09-15T12:17:02Z","reference_register_checked":true,"reference_sha256":"5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66","error_register_checked":true,"error_register_sha256":"3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0","changes_made":false,"sanitized":true,"secrets_included":false,"private_addresses_included":false,"output":"AUTOMATIC_CLUSTER_CONTEXT_REFRESH=OK"} +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1", + "status": "OK", + "rc": 0, + "host": "pve01", + "mode": "read-only", + "component": "infra-dr-backupv2-ct112-cloud-seal-contract-preflight", + "started_at_utc": "2026-09-15T12:36:13Z", + "finished_at_utc": "2026-09-15T12:36:14Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "c92db35b051b231f28f75dee8513620581c9e13c76afce192d2ec6fee0e4f079", + "duplicate_failed_command_blocked": false, + "block_reason": null, + "execution_started": true, + "change_declared": false, + "result_contract_valid": true, + "result_contract_status": null, + "result_contract_error": null, + "command_rc": 0, + "changes_made": false, + "rollback_started": false, + "rollback_restored": null, + "mutation_outcome": "NO_MUTATION", + "sanitized": true, + "secrets_included": false, + "private_addresses_included": false, + "raw_evidence_retained_locally": true, + "raw_evidence_sha256": "c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3", + "sanitized_output_sha256": "c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1\nMODE=READ_ONLY_CT112_CLOUD_SEAL_CONTRACT_PREFLIGHT\nNO_BACKUP_EXECUTION=YES\nNO_VZDUMP_EXECUTION=YES\nNO_CLOUD_ACCESS=YES\nNO_RCLONE_EXECUTION=YES\nNO_CLOUD_DELETION=YES\nNO_SYSTEMD_MUTATION=YES\nNO_FILE_MUTATION=YES\nPRODUCTION_AND_CANDIDATE_IDENTITY=PASS\nSOURCE_SET_IDENTITY=PASS\nG426_IMMUTABLE_COMMIT=8e261f22b35fe49616ab7c2e23f5cac3a5b66376\nG426_STAGE_BINDING=PASS\nG426_GENERATION=G426-20260915T115318Z-d9bb39ace5781d2e\nG426_PAYLOAD_BYTES=223855196\nG426_PAYLOAD_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12\nG426_PAYLOAD_MODE=0400\nCLOUD_ENGINE_OWNER_GRAPH=PASS\nGUEST266_RUN_FLOW_CONTRACT={\"direct_calls\":[\"Path\",\"all\",\"callable\",\"check_result\",\"clock\",\"compression_check\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.valid_name\",\"core.validate_inventory\",\"guard\",\"int\",\"job.get\",\"large.cleanup\",\"large.discover\",\"large.restore\",\"large.upload\",\"len\",\"produce\",\"producer.validate_job\",\"say\",\"state_guard\",\"t.create\",\"t.make_dir\",\"t.need\",\"time.time\"],\"signature\":\"(job, work, entries, cloud, reader, produce, state_guard, guard, compression_check, generation, say, clock= at 0x76417f8f07c0>)\",\"source\":\"def run_flow(job,work,entries,cloud,reader,produce,state_guard,guard,compression_check,generation,say,clock=lambda:int(time.time())):\\n \\\"\\\"\\\"Caller provides real fresh PVE guards; simulation callbacks live in tests only.\\\"\\\"\\\"\\n producer.validate_job(job,clock());core.validate_inventory(entries)\\n t.need(job['type']=='lxc' and job.get('compression_dependent') is False,'FIRST_GUEST_POLICY')\\n t.need(core.valid_name(generation),'GENERATION_ID')\\n t.need(all(callable(f) for f in (produce,state_guard,guard,compression_check,say,clock)),'CALLBACKS_REQUIRED')\\n work=Path(work);state_guard();guard()\\n for sub in ('producer','upload','restore'):t.make_dir(work/sub,exclusive=True)\\n say('PHASE','REAL_SINGLE_GUEST_SNAPSHOT')\\n produced=produce(job,work/'producer')\\n source=check_result(produced,job,work/'producer');state_guard();guard()\\n t.create(work/'PRODUCER.json',core.canonical_bytes(produced))\\n say('PRODUCER_RC',0);say('PAYLOAD_BYTES',produced['size']);say('ARCHIVE_SHA256',produced['sha256'])\\n logical='guest-%s-%s-%d'%(job['node'],job['type'],job['vmid'])\\n say('PHASE','TWO_REPLICA_UPLOAD_AND_READBACK')\\n up=large.upload(source,work/'upload',entries,cloud,generation,logical,RESERVE_BYTES,guard,clock=clock)\\n t.need(up['manifest']['payload_bytes']==produced['size'] and up['manifest']['payload_sha256']==produced['sha256'],'MANIFEST_PRODUCER_MISMATCH')\\n say('SEALED_QUORUM_VERIFIED','YES');mh=core.manifest_hash(up['manifest']);say('MANIFEST_SHA256',mh)\\n say('PHASE','CLOUD_DISCOVERY_AND_ARCHIVE_RECONSTRUCTION')\\n found=large.discover(reader,entries,logical,mh)\\n restored=large.restore(work/'restore',reader,found)\\n t.need(compression_check(work/'restore/restored.bin') is True,'RECONSTRUCTED_COMPRESSION_FAILED')\\n state_guard();guard();say('PHASE','GUARDED_LOCAL_PAYLOAD_CLEANUP')\\n count=large.cleanup(up,restored,reader,guard)\\n return {'state':'SINGLE_GUEST_ARCHIVE_SEALED_AND_CLOUD_RECONSTRUCTED','vmid':job['vmid'],'type':job['type'],'node':job['node'],\\n 'generation':generation,'logical_id':logical,'manifest_sha256':mh,'payload_bytes':produced['size'],'payload_sha256':produced['sha256'],\\n 'replicas':up['manifest']['replicas'],'parts_count':len(up['manifest']['parts']),'archive_cloud_restore_verified':True,\\n 'guest_restore_verified':False,'application_consistency_verified':False,'whole_node_backup':False,'local_payload_files_remaining':0,\\n 'files_deleted':count,'accounts_scanned':found['accounts_scanned'],'config_sha256':job['config_sha256']}\\n\",\"source_sha256\":\"789140b440fc756f99c8979b543c60a44ada096b5acece83e7173791f23bb55c\"}\nLARGE264_UPLOAD_CONTRACT={\"direct_calls\":[\"Path\",\"clock\",\"cloud.absent\",\"cloud.bind\",\"cloud.get\",\"cloud.put\",\"cloud.quota\",\"cloud.read_stream\",\"core.allocate\",\"core.canonical_bytes\",\"core.make_manifest\",\"core.manifest_hash\",\"core.quota_reason\",\"core.valid_name\",\"core.validate_inventory\",\"core.verify_receipts\",\"guard\",\"hashlib.sha256\",\"int\",\"len\",\"r.validate_seal\",\"receipt\",\"receipts.append\",\"s.split_file\",\"s.verify_parts\",\"str\",\"t.create\",\"t.make_dir\",\"t.need\",\"t.sha\",\"time.time\"],\"signature\":\"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)\",\"source\":\"def upload(source,work,entries,cloud,generation,logical_id,reserve,guard,clock=lambda:int(time.time())):\\n \\\"\\\"\\\"Upload and seal; retain all source bytes here. Cleanup is a later gated operation.\\\"\\\"\\\"\\n work=Path(work);source=Path(source);guard();core.validate_inventory(entries)\\n t.need(core.valid_name(generation) and core.valid_name(logical_id),'GENERATION_ID')\\n partdir=work/'parts';t.make_dir(partdir,exclusive=True)\\n record=s.split_file(source,partdir)\\n t.create(work/'parts-record.json',core.canonical_bytes(record))\\n quotas={e['account_id']:cloud.quota(e['crypt_remote']) for e in entries}\\n allocation=core.allocate(entries,quotas,record['payload_bytes'],reserve,clock())\\n m=core.make_manifest(generation,logical_id,record['payload_bytes'],record['payload_sha256'],record['parts'],allocation)\\n mb=core.canonical_bytes(m);mh=core.manifest_hash(m);cloud.bind(m)\\n t.create(work/'allocation.json',core.canonical_bytes(allocation));t.create(work/'manifest.json',mb)\\n for rep in m['replicas']:\\n guard();cloud.absent(rep['crypt_remote'])\\n receipts=[]\\n for rep in m['replicas']:\\n guard();remote=rep['crypt_remote'];q=cloud.quota(remote)\\n t.need(core.quota_reason(q,clock()) is None and q['free']>=allocation['required_free_bytes'],'SELECTED_ACCOUNT_CAPACITY_CHANGED')\\n s.verify_parts(partdir,record)\\n for part in m['parts']:cloud.put(remote,part['name'],partdir/part['name'])\\n cloud.put(remote,'manifest.json',work/'manifest.json')\\n t.need(cloud.get(remote,'manifest.json',len(mb)+1)==mb,'MANIFEST_READBACK_MISMATCH')\\n whole=hashlib.sha256();count=0\\n for part in m['parts']:\\n observed=cloud.read_stream(remote,part['name'],part['size'],part['sha256'],whole.update)\\n t.need(observed=={'size':part['size'],'sha256':part['sha256']},'PART_READBACK_MISMATCH');count+=observed['size']\\n receipts.append(receipt(rep,m,whole,count));t.create(work/('receipt-%d.json'%len(receipts)),core.canonical_bytes(receipts[-1]))\\n core.verify_receipts(m,receipts)\\n seal={'schema_version':2,'state':'SEALED','generation':generation,'logical_id':logical_id,\\n 'manifest_sha256':mh,'replicas':m['replicas'],'receipts':receipts,\\n 'acceptance':'IDENTICAL_SEAL_REQUIRED_ON_BOTH_NAMED_ACCOUNTS'}\\n sb=core.canonical_bytes(seal);t.need(len(sb)<=core.SEAL_MAX_BYTES,'SEAL_BOUND')\\n r.validate_seal(sb,entries,generation,logical_id);t.create(work/'SEALED.json',sb)\\n for rep in m['replicas']:\\n guard();cloud.put(rep['crypt_remote'],'SEALED.json',work/'SEALED.json')\\n for rep in m['replicas']:\\n t.need(cloud.get(rep['crypt_remote'],'SEALED.json',len(sb)+1)==sb,'SEALED_QUORUM_REQUIRED')\\n guard();s.verify_parts(partdir,record)\\n t.create(work/'QUORUM_VERIFIED.json',core.canonical_bytes({'manifest_sha256':mh,'seal_sha256':t.sha(sb)}))\\n return {'sealed':True,'manifest':m,'seal_bytes':sb,'parts_record':record,'source':str(source),'work':str(work)}\\n\",\"source_sha256\":\"3fc04eea643b977e58713bea8a7b9bcfd485e60251a4393874dfe1a428014bbe\"}\nLARGE264_RESTORE_CONTRACT={\"direct_calls\":[\"Path\",\"cloud.read_stream\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.validate_manifest\",\"core.verify_receipts\",\"download_part\",\"enumerate\",\"fresh_seals\",\"hashlib.sha256\",\"receipt\",\"receipts.append\",\"s.reassemble\",\"str\",\"t.create\",\"t.make_dir\",\"t.need\"],\"signature\":\"(work, cloud, discovery)\",\"source\":\"def restore(work,cloud,discovery):\\n \\\"\\\"\\\"Reconstruct one replica on disk; hash every byte of the other independently.\\\"\\\"\\\"\\n work=Path(work);m=discovery['manifest'];core.validate_manifest(m)\\n partdir=work/'parts';t.make_dir(partdir,exclusive=True);owned={};receipts=[]\\n for i,rep in enumerate(m['replicas']):\\n whole=hashlib.sha256();count=0\\n for part in m['parts']:\\n if i==0:owned[part['name']]=download_part(cloud,rep,m,part,partdir/part['name'],whole)\\n else:\\n got=cloud.read_stream(rep['crypt_remote'],m['generation'],part['name'],part['size'],part['sha256'],whole.update)\\n t.need(got=={'size':part['size'],'sha256':part['sha256']},'PART_DOWNLOAD_MISMATCH')\\n count+=part['size']\\n receipts.append(receipt(rep,m,whole,count))\\n core.verify_receipts(m,receipts);fresh_seals(cloud,discovery)\\n rec={'schema_version':1,'payload_bytes':m['payload_bytes'],'payload_sha256':m['payload_sha256'],\\n 'part_bytes':core.PART_BYTES,'parts':m['parts'],'owned':owned,'source_identity':[0]*8}\\n result=s.reassemble(partdir,rec,work/'restored.bin')\\n fresh_seals(cloud,discovery)\\n t.create(work/'RESTORE_VERIFIED.json',core.canonical_bytes({'manifest_sha256':core.manifest_hash(m),'verified_replicas':2,\\n 'accounts_scanned':discovery['accounts_scanned'],'payload_bytes':result['size'],'payload_sha256':result['sha256']}))\\n return {'verified_replicas':2,'manifest_sha256':core.manifest_hash(m),'discovery':discovery,\\n 'parts_record':rec,'reassembled':result,'work':str(work)}\\n\",\"source_sha256\":\"0a73a874d1354b5a63645f4848a9bae933e463e444c3db177ab07c01ecd1f614\"}\nLARGE264_DISCOVER_CONTRACT={\"direct_calls\":[\"all\",\"blobs.append\",\"candidates.append\",\"cloud.get\",\"cloud.list_generations\",\"core.canonical_bytes\",\"core.valid_hash\",\"core.valid_name\",\"core.validate_inventory\",\"core.validate_manifest\",\"core.verify_receipts\",\"generations.update\",\"iter\",\"len\",\"next\",\"r.strict_json\",\"r.validate_seal\",\"seen.values\",\"set\",\"sorted\",\"t.need\",\"t.sha\",\"type\"],\"signature\":\"(cloud, entries, logical_id, expected_hash)\",\"source\":\"def discover(cloud,entries,logical_id,expected_hash):\\n \\\"\\\"\\\"Find placement from all cloud catalogs, using only an external manifest digest.\\\"\\\"\\\"\\n core.validate_inventory(entries)\\n t.need(core.valid_name(logical_id) and core.valid_hash(expected_hash),'DISCOVERY_INPUT')\\n listed={};generations=set()\\n for e in entries:\\n gs=cloud.list_generations(e['crypt_remote'])\\n t.need(type(gs) is list and len(gs)<=r.MAX_GENERATIONS and all(core.valid_name(g) for g in gs),'GENERATION_LIST_INVALID')\\n t.need(len(gs)==len(set(gs)),'GENERATION_LIST_DUPLICATE');listed[e['crypt_remote']]=set(gs);generations.update(gs)\\n t.need(len(generations)<=r.MAX_GENERATIONS,'TOTAL_GENERATIONS_BOUND')\\n candidates=[]\\n for gen in sorted(generations):\\n seen={}\\n for e in entries:\\n remote=e['crypt_remote']\\n if gen not in listed[remote]:continue\\n b=cloud.get(remote,gen,'SEALED.json',core.SEAL_MAX_BYTES+1,missing_ok=True)\\n if b is None:continue\\n seal=r.validate_seal(b,entries,gen,logical_id)\\n t.need(remote in {x['crypt_remote'] for x in seal['replicas']},'UNNAMED_SEAL_LOCATION');seen[remote]=(b,seal)\\n if not seen:continue\\n sb,seal=next(iter(seen.values()))\\n if seal['manifest_sha256']!=expected_hash:continue\\n named={x['crypt_remote'] for x in seal['replicas']}\\n t.need(set(seen)==named and all(b==sb for b,_ in seen.values()),'IDENTICAL_TWO_SEALS_REQUIRED')\\n blobs=[]\\n for rep in seal['replicas']:\\n b=cloud.get(rep['crypt_remote'],gen,'manifest.json',core.MANIFEST_MAX_BYTES+1)\\n t.need(type(b) is bytes and t.sha(b)==expected_hash,'MANIFEST_DIGEST_MISMATCH')\\n m=r.strict_json(b,core.MANIFEST_MAX_BYTES);core.validate_manifest(m)\\n t.need(m['generation']==gen and m['logical_id']==logical_id and m['replicas']==seal['replicas'],'MANIFEST_PLACEMENT')\\n t.need(core.canonical_bytes(m)==b,'MANIFEST_CANONICAL_BYTES');core.verify_receipts(m,seal['receipts']);blobs.append(b)\\n t.need(len(blobs)==2 and blobs[0]==blobs[1],'TWO_MANIFEST_COPIES_REQUIRED')\\n candidates.append({'manifest':m,'seal_bytes':sb,'accounts_scanned':len(listed)})\\n t.need(len(candidates)==1,'EXACTLY_ONE_ACCEPTED_GENERATION_REQUIRED')\\n return candidates[0]\\n\",\"source_sha256\":\"0f9d514dfa0985bfa0ee6446aa85a78377346003039896395cb39e0bf3643702\"}\nLARGE264_CLEANUP_CONTRACT={\"direct_calls\":[\"Path\",\"any\",\"core.canonical_bytes\",\"core.manifest_hash\",\"core.validate_manifest\",\"core.verify_receipts\",\"fresh_seals\",\"guard\",\"items.append\",\"len\",\"os.close\",\"os.fsync\",\"os.stat\",\"os.unlink\",\"p.exists\",\"p.is_symlink\",\"r.strict_json\",\"restore_result.get\",\"s.hash_file\",\"s.validate_record\",\"s.verify_parts\",\"str\",\"t.ident\",\"t.need\",\"t.open_dir\",\"tuple\",\"type\",\"upload_result.get\"],\"signature\":\"(upload_result, restore_result, cloud, guard)\",\"source\":\"def cleanup(upload_result,restore_result,cloud,guard):\\n \\\"\\\"\\\"No unlink until every expected file and both remote seals have passed verification.\\\"\\\"\\\"\\n t.need(type(upload_result) is dict and upload_result.get('sealed') is True,'UPLOAD_QUORUM_REQUIRED')\\n t.need(type(restore_result) is dict and restore_result.get('verified_replicas')==2,'RESTORE_REQUIRED')\\n m=upload_result['manifest'];core.validate_manifest(m);mh=core.manifest_hash(m)\\n t.need(restore_result['manifest_sha256']==mh,'RESTORE_GENERATION_MISMATCH')\\n t.need(core.canonical_bytes(restore_result['discovery']['manifest'])==core.canonical_bytes(m) and\\n restore_result['discovery']['seal_bytes']==upload_result['seal_bytes'],'RESTORE_QUORUM_MISMATCH')\\n core.verify_receipts(m,r.strict_json(upload_result['seal_bytes'],core.SEAL_MAX_BYTES)['receipts'])\\n guard();fresh_seals(cloud,restore_result['discovery'])\\n items=[]\\n for record,base in ((upload_result['parts_record'],Path(upload_result['work'])/'parts'),\\n (restore_result['parts_record'],Path(restore_result['work'])/'parts')):\\n s.validate_record(record);s.verify_parts(base,record)\\n for part in record['parts']:items.append((base/part['name'],tuple(record['owned'][part['name']]),part['size'],part['sha256']))\\n items.append((Path(upload_result['source']),tuple(upload_result['parts_record']['source_identity']),m['payload_bytes'],m['payload_sha256']))\\n items.append((Path(restore_result['work'])/'restored.bin',tuple(restore_result['reassembled']['identity']),m['payload_bytes'],m['payload_sha256']))\\n t.need(len({str(p) for p,_,_,_ in items})==len(items),'CLEANUP_DUPLICATE_PATH')\\n for p,identity,size,h in items:\\n n,d,seen=s.hash_file(p,size);t.need(seen==identity and n==size and d==h,'CLEANUP_IDENTITY_OR_HASH')\\n guard();fresh_seals(cloud,restore_result['discovery'])\\n for p,identity,size,h in items:\\n parent=t.open_dir(p.parent)\\n try:\\n t.need(t.ident(os.stat(p.name,dir_fd=parent,follow_symlinks=False))==identity,'CLEANUP_FILE_CHANGED')\\n os.unlink(p.name,dir_fd=parent);os.fsync(parent)\\n finally:os.close(parent)\\n t.need(not any(p.exists() or p.is_symlink() for p,_,_,_ in items),'LOCAL_CLEANUP_INCOMPLETE')\\n return len(items)\\n\",\"source_sha256\":\"2cbbf3325b84192705686a2c6d3a02f58a75f51145f68204786e08194013cd3b\"}\nLARGE264_FUNCTION_INDEX={\"cleanup\":\"(upload_result, restore_result, cloud, guard)\",\"discover\":\"(cloud, entries, logical_id, expected_hash)\",\"download_part\":\"(cloud, rep, m, part, path, whole)\",\"flags\":\"(executable, snapshot, work, args)\",\"fresh_seals\":\"(cloud, discovery)\",\"process_stream\":\"(argv, env, size, digest, consume, seconds)\",\"random_source\":\"(path, size=536870929)\",\"receipt\":\"(rep, m, whole, count)\",\"restore\":\"(work, cloud, discovery)\",\"upload\":\"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)\"}\nTEST_GUEST266_STORE_SOURCE={\"source\":\"class Store:\\n def __init__(self,mode='ok'):self.objects={};self.m=None;self.mode=mode\\n def quota(self,remote):return {'ok':True,'observed_at':NOW,'total':1000*G,'used':0,'free':1000*G-int(remote[1:])*1000}\\n def bind(self,m):self.m=m\\n def absent(self,remote):\\n if self.mode=='collision':raise t.Stop('COLLISION')\\n def put(self,remote,name,path):\\n if remote==self.m['replicas'][1]['crypt_remote'] and (self.mode=='second' or self.mode=='second_seal' and name=='SEALED.json'):raise t.Stop('TEST_FAILURE')\\n key=(remote,self.m['generation'],name)\\n if key in self.objects:raise t.Stop('COLLISION')\\n self.objects[key]=Path(path).read_bytes()\\n def get(self,remote,name,limit):return self.objects[(remote,self.m['generation'],name)][:limit]\\n def read_stream(self,remote,name,size,h,consume):\\n b=self.get(remote,name,size+1);sink=s.DigestSink(size,h)\\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\\n return sink.finish()\\n\",\"source_sha256\":\"e45ff3e4e95d841661711a92f70d6f927351f9e6d60a3325fece9de4669b0664\"}\nTEST_GUEST266_READER_SOURCE={\"source\":\"class Reader:\\n def __init__(self,store,mode='ok'):self.store=store;self.mode=mode;self.listed=[]\\n def list_generations(self,remote):\\n self.listed.append(remote)\\n return sorted({gen for r,gen,n in self.store.objects if r==remote})\\n def get(self,remote,gen,name,limit,missing_ok=False):\\n v=self.store.objects.get((remote,gen,name))\\n if v is None and missing_ok:return None\\n if v is None:raise t.Stop('MISSING')\\n return v[:limit]\\n def read_stream(self,remote,gen,name,size,h,consume):\\n b=self.get(remote,gen,name,size+1)\\n if self.mode=='corrupt' and remote==self.store.m['replicas'][1]['crypt_remote']:b=b'!'+b[1:]\\n sink=s.DigestSink(size,h)\\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\\n return sink.finish()\\n\",\"source_sha256\":\"dd76a1f73d7b66ecb837c2b80514a45f5ffd265d819aec6bda3d92d8113d1fcb\"}\nTEST_GUEST266_INVENTORY_CONTRACT={\"direct_calls\":[\"('acct%d' % i).encode\",\"range\",\"t.sha\"],\"signature\":\"()\",\"source\":\"def inventory():return [{'account_id':t.sha(('acct%d'%i).encode()),'crypt_remote':'c%d'%i,'mail_remote':'m%d'%i,'wrapped_path':'bucket'} for i in range(13)]\\n\",\"source_sha256\":\"4f0238dd193df9eb06953459c1e6dbe8eef7f7d3cdd3712be7d3c27b9abd6559\"}\nTEST_PRODUCER282_E2E_SOURCE={\"source\":\" def test_fresh_archive_flows_through_existing_two_replica_engine(self):\\n import guest266 as guest\\n import test_guest266 as support\\n job,tools=self.fixture();work=self.root/'generation';work.mkdir(mode=0o700)\\n store=support.Store();now=int(time.time())\\n def quota(remote):return {'ok':True,'observed_at':now,'total':1000*1024**3,'used':0,'free':1000*1024**3-int(remote[1:])*1000}\\n store.quota=quota\\n def prod(j,p):return f.produce(j,p,tools,lambda:None,mapping=MAP,expected_config=job['config_sha256'],emit=lambda k,v:self.events.append((k,v)))\\n def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0\\n result=guest.run_flow(job,work,support.inventory(),store,support.Reader(store),prod,lambda:None,lambda:None,crc,'G268-fixture',lambda k,v:None,clock=lambda:now)\\n self.assertEqual(result['local_payload_files_remaining'],0);self.assertTrue(result['archive_cloud_restore_verified']);self.assertFalse(result['guest_restore_verified'])\\n self.assertTrue((work/'producer/producer.stderr.log').exists());self.assertFalse((work/'producer/guest-112.tar.zst').exists())\\n\",\"source_sha256\":\"a6de003495ee86836bb1bffb2a22a124331a4323726f5715c2a934d445d6b24f\"}\nCANDIDATE_CLOUD_ADAPTER_REFERENCES=[{\"file\":\"large264.py\",\"line\":56,\"line_sha256\":\"4ab4edc665f49c291b4ca5abb42b2e27a74403237f18eeabafab26dfb6dbbfd5\",\"tokens\":[\"class\",\"CloudLarge\",\"t\",\"RcloneIO\"]},{\"file\":\"large264.py\",\"line\":59,\"line_sha256\":\"d9107b9e748f739f75a51ce83c5708419ce820ae1090723ab8026949927e02c4\",\"tokens\":[\"t\",\"need\",\"type\",\"args\",\"is\",\"list\",\"and\",\"args\",\"and\",\"args\",\"in\",\"about\",\"lsjson\",\"copyto\",\"cat\",\"RCLONE_VERB_FORBIDDEN\"]},{\"file\":\"large264.py\",\"line\":61,\"line_sha256\":\"64b38e98ebced99e31c8f94c752a2767cae4b427e23d07bd1e3064ef4a2e2c45\",\"tokens\":[\"self\",\"check\",\"seconds\",\"min\",\"if\",\"args\",\"copyto\",\"else\",\"self\",\"deadline\",\"time\",\"monotonic\"]},{\"file\":\"large264.py\",\"line\":63,\"line_sha256\":\"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575\",\"tokens\":[\"if\",\"args\",\"copyto\",\"self\",\"writes_attempted\"]},{\"file\":\"large264.py\",\"line\":74,\"line_sha256\":\"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"dest\",\"stat\"]},{\"file\":\"large264.py\",\"line\":78,\"line_sha256\":\"ff1b43c434f93c38e81d2b9bd559e31baef49dcf3ed4bde121b02f72b38f607f\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"copyto\",\"str\",\"path\",\"dest\",\"immutable\",\"no\",\"update\",\"modtime\"]},{\"file\":\"large264.py\",\"line\":132,\"line_sha256\":\"6cad508b04c1979421f1df76e719cf88139404497f82f198f9aeb30afe55c6b3\",\"tokens\":[\"quotas\",\"e\",\"account_id\",\"cloud\",\"quota\",\"e\",\"crypt_remote\",\"for\",\"e\",\"in\",\"entries\"]},{\"file\":\"large264.py\",\"line\":141,\"line_sha256\":\"501fc63af37bd9126f146bbc6562c1d135cfca1f67db3ef1f53a9b949fdc61e7\",\"tokens\":[\"guard\",\"remote\",\"rep\",\"crypt_remote\",\"q\",\"cloud\",\"quota\",\"remote\"]},{\"file\":\"restore262.py\",\"line\":3,\"line_sha256\":\"bbd85fe87a59f8247a0a1a5cc42ed497bbafdfbc87e03590612447d705256d9e\",\"tokens\":[\"Cloud\",\"access\",\"is\",\"strictly\",\"lsjson\",\"cat\",\"No\",\"source\",\"local\",\"workspace\",\"manifest\",\"receipt\"]},{\"file\":\"restore262.py\",\"line\":50,\"line_sha256\":\"e442d31b20e2eff9207d7fc0b651516ba35d205677719c9a2add3f1e0f5090ce\",\"tokens\":[\"t\",\"need\",\"t\",\"sha\",\"t\",\"read_secure\",\"self\",\"executable\",\"self\",\"exe_sha\",\"RCLONE_BINARY_CHANGED\"]},{\"file\":\"restore262.py\",\"line\":62,\"line_sha256\":\"a1c27af31b577ebbce3ccfffad12e19986dc4af9437cf454480c2dd49dda9c94\",\"tokens\":[\"t\",\"need\",\"type\",\"args\",\"is\",\"list\",\"and\",\"args\",\"and\",\"args\",\"in\",\"lsjson\",\"cat\",\"READ_ONLY_CLOUD_VERB_REQUIRED\"]},{\"file\":\"restore262.py\",\"line\":69,\"line_sha256\":\"93cbda6a3396bc2369974f589ad0a1494e7561a293ebadfe361c38d64f8acf87\",\"tokens\":[\"rc\",\"out\",\"self\",\"call\",\"lsjson\",\"self\",\"address\",\"remote\",\"dirs\",\"only\",\"max\",\"depth\"]},{\"file\":\"stream263.py\",\"line\":3,\"line_sha256\":\"14c9c361fa8ac5652d5ee51d2f3f18721d40d02442fb2e0e3da2c5cbe47cc99a\",\"tokens\":[\"No\",\"executable\",\"entry\",\"point\",\"network\",\"rclone\",\"backup\",\"execution\",\"sealing\",\"or\",\"deletion\"]},{\"file\":\"test_guest266.py\",\"line\":25,\"line_sha256\":\"23b4bb50f445dce73aec7ebd298f7d6ecb1063c6049601af0dae6061f7f9636d\",\"tokens\":[\"def\",\"quota\",\"self\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"NOW\",\"total\",\"G\",\"used\",\"free\",\"G\",\"int\",\"remote\"]},{\"file\":\"test_producer282.py\",\"line\":190,\"line_sha256\":\"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f\",\"tokens\":[\"def\",\"quota\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"now\",\"total\",\"used\",\"free\",\"int\",\"remote\"]},{\"file\":\"test_pve270.py\",\"line\":189,\"line_sha256\":\"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f\",\"tokens\":[\"def\",\"quota\",\"remote\",\"return\",\"ok\",\"True\",\"observed_at\",\"now\",\"total\",\"used\",\"free\",\"int\",\"remote\"]},{\"file\":\"transport261.py\",\"line\":3,\"line_sha256\":\"44ce8b584aa0bd838288d3f181dd94c706cb7198cd5d7265305d1432647338c0\",\"tokens\":[\"Only\",\"about\",\"lsjson\",\"copyto\",\"and\",\"cat\",\"are\",\"permitted\",\"A\",\"completed\",\"canary\",\"is\",\"a\",\"small\"]},{\"file\":\"transport261.py\",\"line\":171,\"line_sha256\":\"7bd06d43b3c7c43e92988bc7f5bc79c61ff5a4cdeb0dbc2c719bc09d6d5296bd\",\"tokens\":[\"class\",\"RcloneIO\"]},{\"file\":\"transport261.py\",\"line\":185,\"line_sha256\":\"0a241b5e17035863793b414ac6576aa655e63cae48232001b88b38d46c593b7f\",\"tokens\":[\"need\",\"sha\",\"read_secure\",\"self\",\"executable\",\"self\",\"exe_sha\",\"RCLONE_BINARY_CHANGED\"]},{\"file\":\"transport261.py\",\"line\":187,\"line_sha256\":\"e4da1a906be5d6978f3a47abcd8d524463a8c41ec17dae4a813aec34f6d2349d\",\"tokens\":[\"need\",\"args\",\"in\",\"about\",\"lsjson\",\"copyto\",\"cat\",\"RCLONE_VERB_FORBIDDEN\"]},{\"file\":\"transport261.py\",\"line\":193,\"line_sha256\":\"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575\",\"tokens\":[\"if\",\"args\",\"copyto\",\"self\",\"writes_attempted\"]},{\"file\":\"transport261.py\",\"line\":197,\"line_sha256\":\"a887c54bf0d144f2fb71086d385dd1eecd5f3c4ed54c8d46fd3775be00275e3e\",\"tokens\":[\"def\",\"quota\",\"self\",\"remote\"]},{\"file\":\"transport261.py\",\"line\":219,\"line_sha256\":\"b8f85d8b53248a1a6741103aa8ec42a948488b1daca961287026505b0754bafb\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"self\",\"address\",\"remote\",\"max\",\"depth\"]},{\"file\":\"transport261.py\",\"line\":224,\"line_sha256\":\"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"lsjson\",\"dest\",\"stat\"]},{\"file\":\"transport261.py\",\"line\":227,\"line_sha256\":\"ec6a68482d4a09142676ac25a5010d18bdcf8b21d9f60067e857f5818c3e1311\",\"tokens\":[\"rc\",\"_\",\"self\",\"call\",\"copyto\",\"str\",\"path\",\"dest\",\"immutable\",\"no\",\"update\",\"modtime\"]},{\"file\":\"transport261.py\",\"line\":248,\"line_sha256\":\"12f619354bdfdb6783b881c113091a83637a533c3de9b7e185e8ed9e8bd35f60\",\"tokens\":[\"for\",\"e\",\"in\",\"entries\",\"quotas\",\"e\",\"account_id\",\"cloud\",\"quota\",\"e\",\"crypt_remote\"]},{\"file\":\"transport261.py\",\"line\":255,\"line_sha256\":\"3ecbce0f455e711bb54ae15ac845dc3de4e46d8ba23713ec58ec4d7f8eea8815\",\"tokens\":[\"q\",\"cloud\",\"quota\",\"e\",\"crypt_remote\"]},{\"file\":\"v2core.py\",\"line\":110,\"line_sha256\":\"1a51f0e9266b714dd0ebfaf2043d97756197268e3676b2897d53e570528ee2fc\",\"tokens\":[\"rclone\",\"crypt\",\"byte\",\"header\",\"plus\",\"per\",\"nonempty\",\"KiB\",\"block\"]}]\nG426_PAYLOAD_POST_INSPECTION_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12\nPRODUCTION_POST_PREFLIGHT_UNCHANGED=PASS\nCANDIDATE_POST_PREFLIGHT_UNCHANGED=PASS\nCLOUD_SEAL_CONTRACT_PREFLIGHT=PASS\nSTATUS=OK\nPHASE=COMPLETE\nREASON=NONE\nNEXT_GATE=CT112_REAL_BACKUP_1_TWO_REPLICA_SEAL_IMPLEMENTATION\nCHANGES_MADE=false\nMUTATION_OUTCOME=NO_MUTATION\nBACKUP_EXECUTIONS=0\nVZDUMP_EXECUTIONS=0\nCLOUD_WRITES=0\nCLOUD_DELETIONS=0\nSYSTEMD_MUTATIONS=0\nSCHEDULER_CUTOVER=NO\nLEGACY_BACKUP_DISABLES=0\nLOCAL_G426_PAYLOAD_PRESERVED=YES\nHOMELAB_RESULT_CONTRACT={\"changes_made\":false,\"command_id\":\"SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1\",\"rollback_restored\":null,\"rollback_started\":false,\"status\":\"OK\",\"version\":1}\n" +} diff --git a/runtime/latest.txt b/runtime/latest.txt index 09c68279..fa2cc0ce 100644 --- a/runtime/latest.txt +++ b/runtime/latest.txt @@ -1,162 +1,80 @@ CHAT_OUTPUT_BEGIN -COMMAND_ID=CONTEXT-AUTO-[PRIVATE_IP]701Z +COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1 STATUS=OK RC=0 HOST=pve01 -COMPONENT=cluster-context -REFERENCE_SHA[PRIVATE_IP]e5154c41cb[PRIVATE_IP]aca68090be[PRIVATE_IP]bf[PRIVATE_IP]df[PRIVATE_IP] -ERROR_REGISTER_SHA[PRIVATE_IP]ec0f527ed3afeed[PRIVATE_IP]ee[PRIVATE_IP]bbfb[PRIVATE_IP]af4ba7ba0 +MODE=read-only +COMPONENT=infra-dr-backupv2-ct112-cloud-seal-contract-preflight +REFERENCE_REGISTER_CHECK=OK +REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 +ERROR_REGISTER_CHECK=OK +ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 +COMMAND_SHA256=c92db35b051b231f28f75dee8513620581c9e13c76afce192d2ec6fee0e4f079 +DUPLICATE_FAILED_COMMAND_BLOCKED=false +EXECUTION_STARTED=true +CHANGE_DECLARED=false +RESULT_CONTRACT_VALID=true +RESULT_CONTRACT_STATUS=NOT_APPLICABLE +RESULT_CONTRACT_ERROR=NONE +COMMAND_RC=0 +CHANGES_MADE=false +ROLLBACK_STARTED=false +ROLLBACK_RESTORED=null +MUTATION_OUTCOME=NO_MUTATION +SANITIZED=yes +SECRETS_INCLUDED=no +PRIVATE_ADDRESSES_INCLUDED=no +RAW_EVIDENCE_SHA256=c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3 +SANITIZED_OUTPUT_SHA256=c1d3cbae7498e09aa4e54da7ebb0dccf3852f02ee425b59732aff80cbe2d72d3 OUTPUT_BEGIN -GENERATED_AT_UTC=[PRIVATE_IP]T12:17:01Z -Cluster information -------------------- -Name: homelab -Config Version: 3 -Transport: knet -Secure auth: on +COMMAND_ID=SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1 +MODE=READ_ONLY_CT112_CLOUD_SEAL_CONTRACT_PREFLIGHT +NO_BACKUP_EXECUTION=YES +NO_VZDUMP_EXECUTION=YES +NO_CLOUD_ACCESS=YES +NO_RCLONE_EXECUTION=YES +NO_CLOUD_DELETION=YES +NO_SYSTEMD_MUTATION=YES +NO_FILE_MUTATION=YES +PRODUCTION_AND_CANDIDATE_IDENTITY=PASS +SOURCE_SET_IDENTITY=PASS +G426_IMMUTABLE_COMMIT=8e261f22b35fe49616ab7c2e23f5cac3a5b66376 +G426_STAGE_BINDING=PASS +G426_GENERATION=G426-20260915T115318Z-d9bb39ace5781d2e +G426_PAYLOAD_BYTES=223855196 +G426_PAYLOAD_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12 +G426_PAYLOAD_MODE=0400 +CLOUD_ENGINE_OWNER_GRAPH=PASS +GUEST266_RUN_FLOW_CONTRACT={"direct_calls":["Path","all","callable","check_result","clock","compression_check","core.canonical_bytes","core.manifest_hash","core.valid_name","core.validate_inventory","guard","int","job.get","large.cleanup","large.discover","large.restore","large.upload","len","produce","producer.validate_job","say","state_guard","t.create","t.make_dir","t.need","time.time"],"signature":"(job, work, entries, cloud, reader, produce, state_guard, guard, compression_check, generation, say, clock= at 0x76417f8f07c0>)","source":"def run_flow(job,work,entries,cloud,reader,produce,state_guard,guard,compression_check,generation,say,clock=lambda:int(time.time())):\n \"\"\"Caller provides real fresh PVE guards; simulation callbacks live in tests only.\"\"\"\n producer.validate_job(job,clock());core.validate_inventory(entries)\n t.need(job['type']=='lxc' and job.get('compression_dependent') is False,'FIRST_GUEST_POLICY')\n t.need(core.valid_name(generation),'GENERATION_ID')\n t.need(all(callable(f) for f in (produce,state_guard,guard,compression_check,say,clock)),'CALLBACKS_REQUIRED')\n work=Path(work);state_guard();guard()\n for sub in ('producer','upload','restore'):t.make_dir(work/sub,exclusive=True)\n say('PHASE','REAL_SINGLE_GUEST_SNAPSHOT')\n produced=produce(job,work/'producer')\n source=check_result(produced,job,work/'producer');state_guard();guard()\n t.create(work/'PRODUCER.json',core.canonical_bytes(produced))\n say('PRODUCER_RC',0);say('PAYLOAD_BYTES',produced['size']);say('ARCHIVE_SHA256',produced['sha256'])\n logical='guest-%s-%s-%d'%(job['node'],job['type'],job['vmid'])\n say('PHASE','TWO_REPLICA_UPLOAD_AND_READBACK')\n up=large.upload(source,work/'upload',entries,cloud,generation,logical,RESERVE_BYTES,guard,clock=clock)\n t.need(up['manifest']['payload_bytes']==produced['size'] and up['manifest']['payload_sha256']==produced['sha256'],'MANIFEST_PRODUCER_MISMATCH')\n say('SEALED_QUORUM_VERIFIED','YES');mh=core.manifest_hash(up['manifest']);say('MANIFEST_SHA256',mh)\n say('PHASE','CLOUD_DISCOVERY_AND_ARCHIVE_RECONSTRUCTION')\n found=large.discover(reader,entries,logical,mh)\n restored=large.restore(work/'restore',reader,found)\n t.need(compression_check(work/'restore/restored.bin') is True,'RECONSTRUCTED_COMPRESSION_FAILED')\n state_guard();guard();say('PHASE','GUARDED_LOCAL_PAYLOAD_CLEANUP')\n count=large.cleanup(up,restored,reader,guard)\n return {'state':'SINGLE_GUEST_ARCHIVE_SEALED_AND_CLOUD_RECONSTRUCTED','vmid':job['vmid'],'type':job['type'],'node':job['node'],\n 'generation':generation,'logical_id':logical,'manifest_sha256':mh,'payload_bytes':produced['size'],'payload_sha256':produced['sha256'],\n 'replicas':up['manifest']['replicas'],'parts_count':len(up['manifest']['parts']),'archive_cloud_restore_verified':True,\n 'guest_restore_verified':False,'application_consistency_verified':False,'whole_node_backup':False,'local_payload_files_remaining':0,\n 'files_deleted':count,'accounts_scanned':found['accounts_scanned'],'config_sha256':job['config_sha256']}\n","source_sha256":"789140b440fc756f99c8979b543c60a44ada096b5acece83e7173791f23bb55c"} +LARGE264_UPLOAD_CONTRACT={"direct_calls":["Path","clock","cloud.absent","cloud.bind","cloud.get","cloud.put","cloud.quota","cloud.read_stream","core.allocate","core.canonical_bytes","core.make_manifest","core.manifest_hash","core.quota_reason","core.valid_name","core.validate_inventory","core.verify_receipts","guard","hashlib.sha256","int","len","r.validate_seal","receipt","receipts.append","s.split_file","s.verify_parts","str","t.create","t.make_dir","t.need","t.sha","time.time"],"signature":"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)","source":"def upload(source,work,entries,cloud,generation,logical_id,reserve,guard,clock=lambda:int(time.time())):\n \"\"\"Upload and seal; retain all source bytes here. Cleanup is a later gated operation.\"\"\"\n work=Path(work);source=Path(source);guard();core.validate_inventory(entries)\n t.need(core.valid_name(generation) and core.valid_name(logical_id),'GENERATION_ID')\n partdir=work/'parts';t.make_dir(partdir,exclusive=True)\n record=s.split_file(source,partdir)\n t.create(work/'parts-record.json',core.canonical_bytes(record))\n quotas={e['account_id']:cloud.quota(e['crypt_remote']) for e in entries}\n allocation=core.allocate(entries,quotas,record['payload_bytes'],reserve,clock())\n m=core.make_manifest(generation,logical_id,record['payload_bytes'],record['payload_sha256'],record['parts'],allocation)\n mb=core.canonical_bytes(m);mh=core.manifest_hash(m);cloud.bind(m)\n t.create(work/'allocation.json',core.canonical_bytes(allocation));t.create(work/'manifest.json',mb)\n for rep in m['replicas']:\n guard();cloud.absent(rep['crypt_remote'])\n receipts=[]\n for rep in m['replicas']:\n guard();remote=rep['crypt_remote'];q=cloud.quota(remote)\n t.need(core.quota_reason(q,clock()) is None and q['free']>=allocation['required_free_bytes'],'SELECTED_ACCOUNT_CAPACITY_CHANGED')\n s.verify_parts(partdir,record)\n for part in m['parts']:cloud.put(remote,part['name'],partdir/part['name'])\n cloud.put(remote,'manifest.json',work/'manifest.json')\n t.need(cloud.get(remote,'manifest.json',len(mb)+1)==mb,'MANIFEST_READBACK_MISMATCH')\n whole=hashlib.sha256();count=0\n for part in m['parts']:\n observed=cloud.read_stream(remote,part['name'],part['size'],part['sha256'],whole.update)\n t.need(observed=={'size':part['size'],'sha256':part['sha256']},'PART_READBACK_MISMATCH');count+=observed['size']\n receipts.append(receipt(rep,m,whole,count));t.create(work/('receipt-%d.json'%len(receipts)),core.canonical_bytes(receipts[-1]))\n core.verify_receipts(m,receipts)\n seal={'schema_version':2,'state':'SEALED','generation':generation,'logical_id':logical_id,\n 'manifest_sha256':mh,'replicas':m['replicas'],'receipts':receipts,\n 'acceptance':'IDENTICAL_SEAL_REQUIRED_ON_BOTH_NAMED_ACCOUNTS'}\n sb=core.canonical_bytes(seal);t.need(len(sb)<=core.SEAL_MAX_BYTES,'SEAL_BOUND')\n r.validate_seal(sb,entries,generation,logical_id);t.create(work/'SEALED.json',sb)\n for rep in m['replicas']:\n guard();cloud.put(rep['crypt_remote'],'SEALED.json',work/'SEALED.json')\n for rep in m['replicas']:\n t.need(cloud.get(rep['crypt_remote'],'SEALED.json',len(sb)+1)==sb,'SEALED_QUORUM_REQUIRED')\n guard();s.verify_parts(partdir,record)\n t.create(work/'QUORUM_VERIFIED.json',core.canonical_bytes({'manifest_sha256':mh,'seal_sha256':t.sha(sb)}))\n return {'sealed':True,'manifest':m,'seal_bytes':sb,'parts_record':record,'source':str(source),'work':str(work)}\n","source_sha256":"3fc04eea643b977e58713bea8a7b9bcfd485e60251a4393874dfe1a428014bbe"} +LARGE264_RESTORE_CONTRACT={"direct_calls":["Path","cloud.read_stream","core.canonical_bytes","core.manifest_hash","core.validate_manifest","core.verify_receipts","download_part","enumerate","fresh_seals","hashlib.sha256","receipt","receipts.append","s.reassemble","str","t.create","t.make_dir","t.need"],"signature":"(work, cloud, discovery)","source":"def restore(work,cloud,discovery):\n \"\"\"Reconstruct one replica on disk; hash every byte of the other independently.\"\"\"\n work=Path(work);m=discovery['manifest'];core.validate_manifest(m)\n partdir=work/'parts';t.make_dir(partdir,exclusive=True);owned={};receipts=[]\n for i,rep in enumerate(m['replicas']):\n whole=hashlib.sha256();count=0\n for part in m['parts']:\n if i==0:owned[part['name']]=download_part(cloud,rep,m,part,partdir/part['name'],whole)\n else:\n got=cloud.read_stream(rep['crypt_remote'],m['generation'],part['name'],part['size'],part['sha256'],whole.update)\n t.need(got=={'size':part['size'],'sha256':part['sha256']},'PART_DOWNLOAD_MISMATCH')\n count+=part['size']\n receipts.append(receipt(rep,m,whole,count))\n core.verify_receipts(m,receipts);fresh_seals(cloud,discovery)\n rec={'schema_version':1,'payload_bytes':m['payload_bytes'],'payload_sha256':m['payload_sha256'],\n 'part_bytes':core.PART_BYTES,'parts':m['parts'],'owned':owned,'source_identity':[0]*8}\n result=s.reassemble(partdir,rec,work/'restored.bin')\n fresh_seals(cloud,discovery)\n t.create(work/'RESTORE_VERIFIED.json',core.canonical_bytes({'manifest_sha256':core.manifest_hash(m),'verified_replicas':2,\n 'accounts_scanned':discovery['accounts_scanned'],'payload_bytes':result['size'],'payload_sha256':result['sha256']}))\n return {'verified_replicas':2,'manifest_sha256':core.manifest_hash(m),'discovery':discovery,\n 'parts_record':rec,'reassembled':result,'work':str(work)}\n","source_sha256":"0a73a874d1354b5a63645f4848a9bae933e463e444c3db177ab07c01ecd1f614"} +LARGE264_DISCOVER_CONTRACT={"direct_calls":["all","blobs.append","candidates.append","cloud.get","cloud.list_generations","core.canonical_bytes","core.valid_hash","core.valid_name","core.validate_inventory","core.validate_manifest","core.verify_receipts","generations.update","iter","len","next","r.strict_json","r.validate_seal","seen.values","set","sorted","t.need","t.sha","type"],"signature":"(cloud, entries, logical_id, expected_hash)","source":"def discover(cloud,entries,logical_id,expected_hash):\n \"\"\"Find placement from all cloud catalogs, using only an external manifest digest.\"\"\"\n core.validate_inventory(entries)\n t.need(core.valid_name(logical_id) and core.valid_hash(expected_hash),'DISCOVERY_INPUT')\n listed={};generations=set()\n for e in entries:\n gs=cloud.list_generations(e['crypt_remote'])\n t.need(type(gs) is list and len(gs)<=r.MAX_GENERATIONS and all(core.valid_name(g) for g in gs),'GENERATION_LIST_INVALID')\n t.need(len(gs)==len(set(gs)),'GENERATION_LIST_DUPLICATE');listed[e['crypt_remote']]=set(gs);generations.update(gs)\n t.need(len(generations)<=r.MAX_GENERATIONS,'TOTAL_GENERATIONS_BOUND')\n candidates=[]\n for gen in sorted(generations):\n seen={}\n for e in entries:\n remote=e['crypt_remote']\n if gen not in listed[remote]:continue\n b=cloud.get(remote,gen,'SEALED.json',core.SEAL_MAX_BYTES+1,missing_ok=True)\n if b is None:continue\n seal=r.validate_seal(b,entries,gen,logical_id)\n t.need(remote in {x['crypt_remote'] for x in seal['replicas']},'UNNAMED_SEAL_LOCATION');seen[remote]=(b,seal)\n if not seen:continue\n sb,seal=next(iter(seen.values()))\n if seal['manifest_sha256']!=expected_hash:continue\n named={x['crypt_remote'] for x in seal['replicas']}\n t.need(set(seen)==named and all(b==sb for b,_ in seen.values()),'IDENTICAL_TWO_SEALS_REQUIRED')\n blobs=[]\n for rep in seal['replicas']:\n b=cloud.get(rep['crypt_remote'],gen,'manifest.json',core.MANIFEST_MAX_BYTES+1)\n t.need(type(b) is bytes and t.sha(b)==expected_hash,'MANIFEST_DIGEST_MISMATCH')\n m=r.strict_json(b,core.MANIFEST_MAX_BYTES);core.validate_manifest(m)\n t.need(m['generation']==gen and m['logical_id']==logical_id and m['replicas']==seal['replicas'],'MANIFEST_PLACEMENT')\n t.need(core.canonical_bytes(m)==b,'MANIFEST_CANONICAL_BYTES');core.verify_receipts(m,seal['receipts']);blobs.append(b)\n t.need(len(blobs)==2 and blobs[0]==blobs[1],'TWO_MANIFEST_COPIES_REQUIRED')\n candidates.append({'manifest':m,'seal_bytes':sb,'accounts_scanned':len(listed)})\n t.need(len(candidates)==1,'EXACTLY_ONE_ACCEPTED_GENERATION_REQUIRED')\n return candidates[0]\n","source_sha256":"0f9d514dfa0985bfa0ee6446aa85a78377346003039896395cb39e0bf3643702"} +LARGE264_CLEANUP_CONTRACT={"direct_calls":["Path","any","core.canonical_bytes","core.manifest_hash","core.validate_manifest","core.verify_receipts","fresh_seals","guard","items.append","len","os.close","os.fsync","os.stat","os.unlink","p.exists","p.is_symlink","r.strict_json","restore_result.get","s.hash_file","s.validate_record","s.verify_parts","str","t.ident","t.need","t.open_dir","tuple","type","upload_result.get"],"signature":"(upload_result, restore_result, cloud, guard)","source":"def cleanup(upload_result,restore_result,cloud,guard):\n \"\"\"No unlink until every expected file and both remote seals have passed verification.\"\"\"\n t.need(type(upload_result) is dict and upload_result.get('sealed') is True,'UPLOAD_QUORUM_REQUIRED')\n t.need(type(restore_result) is dict and restore_result.get('verified_replicas')==2,'RESTORE_REQUIRED')\n m=upload_result['manifest'];core.validate_manifest(m);mh=core.manifest_hash(m)\n t.need(restore_result['manifest_sha256']==mh,'RESTORE_GENERATION_MISMATCH')\n t.need(core.canonical_bytes(restore_result['discovery']['manifest'])==core.canonical_bytes(m) and\n restore_result['discovery']['seal_bytes']==upload_result['seal_bytes'],'RESTORE_QUORUM_MISMATCH')\n core.verify_receipts(m,r.strict_json(upload_result['seal_bytes'],core.SEAL_MAX_BYTES)['receipts'])\n guard();fresh_seals(cloud,restore_result['discovery'])\n items=[]\n for record,base in ((upload_result['parts_record'],Path(upload_result['work'])/'parts'),\n (restore_result['parts_record'],Path(restore_result['work'])/'parts')):\n s.validate_record(record);s.verify_parts(base,record)\n for part in record['parts']:items.append((base/part['name'],tuple(record['owned'][part['name']]),part['size'],part['sha256']))\n items.append((Path(upload_result['source']),tuple(upload_result['parts_record']['source_identity']),m['payload_bytes'],m['payload_sha256']))\n items.append((Path(restore_result['work'])/'restored.bin',tuple(restore_result['reassembled']['identity']),m['payload_bytes'],m['payload_sha256']))\n t.need(len({str(p) for p,_,_,_ in items})==len(items),'CLEANUP_DUPLICATE_PATH')\n for p,identity,size,h in items:\n n,d,seen=s.hash_file(p,size);t.need(seen==identity and n==size and d==h,'CLEANUP_IDENTITY_OR_HASH')\n guard();fresh_seals(cloud,restore_result['discovery'])\n for p,identity,size,h in items:\n parent=t.open_dir(p.parent)\n try:\n t.need(t.ident(os.stat(p.name,dir_fd=parent,follow_symlinks=False))==identity,'CLEANUP_FILE_CHANGED')\n os.unlink(p.name,dir_fd=parent);os.fsync(parent)\n finally:os.close(parent)\n t.need(not any(p.exists() or p.is_symlink() for p,_,_,_ in items),'LOCAL_CLEANUP_INCOMPLETE')\n return len(items)\n","source_sha256":"2cbbf3325b84192705686a2c6d3a02f58a75f51145f68204786e08194013cd3b"} +LARGE264_FUNCTION_INDEX={"cleanup":"(upload_result, restore_result, cloud, guard)","discover":"(cloud, entries, logical_id, expected_hash)","download_part":"(cloud, rep, m, part, path, whole)","flags":"(executable, snapshot, work, args)","fresh_seals":"(cloud, discovery)","process_stream":"(argv, env, size, digest, consume, seconds)","random_source":"(path, size=536870929)","receipt":"(rep, m, whole, count)","restore":"(work, cloud, discovery)","upload":"(source, work, entries, cloud, generation, logical_id, reserve, guard, clock= at 0x76417facc180>)"} +TEST_GUEST266_STORE_SOURCE={"source":"class Store:\n def __init__(self,mode='ok'):self.objects={};self.m=None;self.mode=mode\n def quota(self,remote):return {'ok':True,'observed_at':NOW,'total':1000*G,'used':0,'free':1000*G-int(remote[1:])*1000}\n def bind(self,m):self.m=m\n def absent(self,remote):\n if self.mode=='collision':raise t.Stop('COLLISION')\n def put(self,remote,name,path):\n if remote==self.m['replicas'][1]['crypt_remote'] and (self.mode=='second' or self.mode=='second_seal' and name=='SEALED.json'):raise t.Stop('TEST_FAILURE')\n key=(remote,self.m['generation'],name)\n if key in self.objects:raise t.Stop('COLLISION')\n self.objects[key]=Path(path).read_bytes()\n def get(self,remote,name,limit):return self.objects[(remote,self.m['generation'],name)][:limit]\n def read_stream(self,remote,name,size,h,consume):\n b=self.get(remote,name,size+1);sink=s.DigestSink(size,h)\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\n return sink.finish()\n","source_sha256":"e45ff3e4e95d841661711a92f70d6f927351f9e6d60a3325fece9de4669b0664"} +TEST_GUEST266_READER_SOURCE={"source":"class Reader:\n def __init__(self,store,mode='ok'):self.store=store;self.mode=mode;self.listed=[]\n def list_generations(self,remote):\n self.listed.append(remote)\n return sorted({gen for r,gen,n in self.store.objects if r==remote})\n def get(self,remote,gen,name,limit,missing_ok=False):\n v=self.store.objects.get((remote,gen,name))\n if v is None and missing_ok:return None\n if v is None:raise t.Stop('MISSING')\n return v[:limit]\n def read_stream(self,remote,gen,name,size,h,consume):\n b=self.get(remote,gen,name,size+1)\n if self.mode=='corrupt' and remote==self.store.m['replicas'][1]['crypt_remote']:b=b'!'+b[1:]\n sink=s.DigestSink(size,h)\n for i in range(0,len(b),257):sink.feed(b[i:i+257]);consume(b[i:i+257])\n return sink.finish()\n","source_sha256":"dd76a1f73d7b66ecb837c2b80514a45f5ffd265d819aec6bda3d92d8113d1fcb"} +TEST_GUEST266_INVENTORY_CONTRACT={"direct_calls":["('acct%d' % i).encode","range","t.sha"],"signature":"()","source":"def inventory():return [{'account_id':t.sha(('acct%d'%i).encode()),'crypt_remote':'c%d'%i,'mail_remote':'m%d'%i,'wrapped_path':'bucket'} for i in range(13)]\n","source_sha256":"4f0238dd193df9eb06953459c1e6dbe8eef7f7d3cdd3712be7d3c27b9abd6559"} +TEST_PRODUCER282_E2E_SOURCE={"source":" def test_fresh_archive_flows_through_existing_two_replica_engine(self):\n import guest266 as guest\n import test_guest266 as support\n job,tools=self.fixture();work=self.root/'generation';work.mkdir(mode=0o700)\n store=support.Store();now=int(time.time())\n def quota(remote):return {'ok':True,'observed_at':now,'total':1000*1024**3,'used':0,'free':1000*1024**3-int(remote[1:])*1000}\n store.quota=quota\n def prod(j,p):return f.produce(j,p,tools,lambda:None,mapping=MAP,expected_config=job['config_sha256'],emit=lambda k,v:self.events.append((k,v)))\n def crc(p):return subprocess.run(['/usr/bin/zstd','--test','--quiet',str(p)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0\n result=guest.run_flow(job,work,support.inventory(),store,support.Reader(store),prod,lambda:None,lambda:None,crc,'G268-fixture',lambda k,v:None,clock=lambda:now)\n self.assertEqual(result['local_payload_files_remaining'],0);self.assertTrue(result['archive_cloud_restore_verified']);self.assertFalse(result['guest_restore_verified'])\n self.assertTrue((work/'producer/producer.stderr.log').exists());self.assertFalse((work/'producer/guest-112.tar.zst').exists())\n","source_sha256":"a6de003495ee86836bb1bffb2a22a124331a4323726f5715c2a934d445d6b24f"} +CANDIDATE_CLOUD_ADAPTER_REFERENCES=[{"file":"large264.py","line":56,"line_sha256":"4ab4edc665f49c291b4ca5abb42b2e27a74403237f18eeabafab26dfb6dbbfd5","tokens":["class","CloudLarge","t","RcloneIO"]},{"file":"large264.py","line":59,"line_sha256":"d9107b9e748f739f75a51ce83c5708419ce820ae1090723ab8026949927e02c4","tokens":["t","need","type","args","is","list","and","args","and","args","in","about","lsjson","copyto","cat","RCLONE_VERB_FORBIDDEN"]},{"file":"large264.py","line":61,"line_sha256":"64b38e98ebced99e31c8f94c752a2767cae4b427e23d07bd1e3064ef4a2e2c45","tokens":["self","check","seconds","min","if","args","copyto","else","self","deadline","time","monotonic"]},{"file":"large264.py","line":63,"line_sha256":"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575","tokens":["if","args","copyto","self","writes_attempted"]},{"file":"large264.py","line":74,"line_sha256":"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec","tokens":["rc","_","self","call","lsjson","dest","stat"]},{"file":"large264.py","line":78,"line_sha256":"ff1b43c434f93c38e81d2b9bd559e31baef49dcf3ed4bde121b02f72b38f607f","tokens":["rc","_","self","call","copyto","str","path","dest","immutable","no","update","modtime"]},{"file":"large264.py","line":132,"line_sha256":"6cad508b04c1979421f1df76e719cf88139404497f82f198f9aeb30afe55c6b3","tokens":["quotas","e","account_id","cloud","quota","e","crypt_remote","for","e","in","entries"]},{"file":"large264.py","line":141,"line_sha256":"501fc63af37bd9126f146bbc6562c1d135cfca1f67db3ef1f53a9b949fdc61e7","tokens":["guard","remote","rep","crypt_remote","q","cloud","quota","remote"]},{"file":"restore262.py","line":3,"line_sha256":"bbd85fe87a59f8247a0a1a5cc42ed497bbafdfbc87e03590612447d705256d9e","tokens":["Cloud","access","is","strictly","lsjson","cat","No","source","local","workspace","manifest","receipt"]},{"file":"restore262.py","line":50,"line_sha256":"e442d31b20e2eff9207d7fc0b651516ba35d205677719c9a2add3f1e0f5090ce","tokens":["t","need","t","sha","t","read_secure","self","executable","self","exe_sha","RCLONE_BINARY_CHANGED"]},{"file":"restore262.py","line":62,"line_sha256":"a1c27af31b577ebbce3ccfffad12e19986dc4af9437cf454480c2dd49dda9c94","tokens":["t","need","type","args","is","list","and","args","and","args","in","lsjson","cat","READ_ONLY_CLOUD_VERB_REQUIRED"]},{"file":"restore262.py","line":69,"line_sha256":"93cbda6a3396bc2369974f589ad0a1494e7561a293ebadfe361c38d64f8acf87","tokens":["rc","out","self","call","lsjson","self","address","remote","dirs","only","max","depth"]},{"file":"stream263.py","line":3,"line_sha256":"14c9c361fa8ac5652d5ee51d2f3f18721d40d02442fb2e0e3da2c5cbe47cc99a","tokens":["No","executable","entry","point","network","rclone","backup","execution","sealing","or","deletion"]},{"file":"test_guest266.py","line":25,"line_sha256":"23b4bb50f445dce73aec7ebd298f7d6ecb1063c6049601af0dae6061f7f9636d","tokens":["def","quota","self","remote","return","ok","True","observed_at","NOW","total","G","used","free","G","int","remote"]},{"file":"test_producer282.py","line":190,"line_sha256":"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f","tokens":["def","quota","remote","return","ok","True","observed_at","now","total","used","free","int","remote"]},{"file":"test_pve270.py","line":189,"line_sha256":"b54584f63e7cb14df8cb2c66db5cbd015113fca4052614c02df0996f2a6b8f7f","tokens":["def","quota","remote","return","ok","True","observed_at","now","total","used","free","int","remote"]},{"file":"transport261.py","line":3,"line_sha256":"44ce8b584aa0bd838288d3f181dd94c706cb7198cd5d7265305d1432647338c0","tokens":["Only","about","lsjson","copyto","and","cat","are","permitted","A","completed","canary","is","a","small"]},{"file":"transport261.py","line":171,"line_sha256":"7bd06d43b3c7c43e92988bc7f5bc79c61ff5a4cdeb0dbc2c719bc09d6d5296bd","tokens":["class","RcloneIO"]},{"file":"transport261.py","line":185,"line_sha256":"0a241b5e17035863793b414ac6576aa655e63cae48232001b88b38d46c593b7f","tokens":["need","sha","read_secure","self","executable","self","exe_sha","RCLONE_BINARY_CHANGED"]},{"file":"transport261.py","line":187,"line_sha256":"e4da1a906be5d6978f3a47abcd8d524463a8c41ec17dae4a813aec34f6d2349d","tokens":["need","args","in","about","lsjson","copyto","cat","RCLONE_VERB_FORBIDDEN"]},{"file":"transport261.py","line":193,"line_sha256":"95e28cb4c920f1f05c3b36f067a836e937b488aacbd4b8464d96b9c41b3e7575","tokens":["if","args","copyto","self","writes_attempted"]},{"file":"transport261.py","line":197,"line_sha256":"a887c54bf0d144f2fb71086d385dd1eecd5f3c4ed54c8d46fd3775be00275e3e","tokens":["def","quota","self","remote"]},{"file":"transport261.py","line":219,"line_sha256":"b8f85d8b53248a1a6741103aa8ec42a948488b1daca961287026505b0754bafb","tokens":["rc","_","self","call","lsjson","self","address","remote","max","depth"]},{"file":"transport261.py","line":224,"line_sha256":"f69498f74dc185afaea74dad0cbe99178138f77cd288369e3cd6e9eba05ea4ec","tokens":["rc","_","self","call","lsjson","dest","stat"]},{"file":"transport261.py","line":227,"line_sha256":"ec6a68482d4a09142676ac25a5010d18bdcf8b21d9f60067e857f5818c3e1311","tokens":["rc","_","self","call","copyto","str","path","dest","immutable","no","update","modtime"]},{"file":"transport261.py","line":248,"line_sha256":"12f619354bdfdb6783b881c113091a83637a533c3de9b7e185e8ed9e8bd35f60","tokens":["for","e","in","entries","quotas","e","account_id","cloud","quota","e","crypt_remote"]},{"file":"transport261.py","line":255,"line_sha256":"3ecbce0f455e711bb54ae15ac845dc3de4e46d8ba23713ec58ec4d7f8eea8815","tokens":["q","cloud","quota","e","crypt_remote"]},{"file":"v2core.py","line":110,"line_sha256":"1a51f0e9266b714dd0ebfaf2043d97756197268e3676b2897d53e570528ee2fc","tokens":["rclone","crypt","byte","header","plus","per","nonempty","KiB","block"]}] +G426_PAYLOAD_POST_INSPECTION_SHA256=8b7ed12905966302695ab4d8a3de81c171ed516e1f072eb1f761aace05cecd12 +PRODUCTION_POST_PREFLIGHT_UNCHANGED=PASS +CANDIDATE_POST_PREFLIGHT_UNCHANGED=PASS +CLOUD_SEAL_CONTRACT_PREFLIGHT=PASS +STATUS=OK +PHASE=COMPLETE +REASON=NONE +NEXT_GATE=CT112_REAL_BACKUP_1_TWO_REPLICA_SEAL_IMPLEMENTATION +CHANGES_MADE=false +MUTATION_OUTCOME=NO_MUTATION +BACKUP_EXECUTIONS=0 +VZDUMP_EXECUTIONS=0 +CLOUD_WRITES=0 +CLOUD_DELETIONS=0 +SYSTEMD_MUTATIONS=0 +SCHEDULER_CUTOVER=NO +LEGACY_BACKUP_DISABLES=0 +LOCAL_G426_PAYLOAD_PRESERVED=YES +HOMELAB_RESULT_CONTRACT={"changes_made":false,"command_id":"SUPPORT-260915-INFRA-DR-BACKUPV2-CT112-CLOUD-SEAL-CONTRACT-PREFLIGHT-427R1","rollback_restored":null,"rollback_started":false,"status":"OK","version":1} -Quorum information ------------------- -Date: Tue Sep [PRIVATE_IP] 2026 -Quorum provider: corosync_votequorum -Nodes: 3 -Node ID: [PRIVATE_IP] -Ring ID: 1.130 -Quorate: Yes - -Votequorum information ----------------------- -Expected votes: 3 -Highest expected: 3 -Total votes: 3 -Quorum: 2 -Flags: Quorate - -Membership information ----------------------- - Nodeid Votes Name -[PRIVATE_IP] [PRIVATE_IP].11 (local) -[PRIVATE_IP] [PRIVATE_IP].13 -[PRIVATE_IP] [PRIVATE_IP].12 - -Membership information ----------------------- - Nodeid Votes Name - 1 1 pve01 (local) - 2 1 pve03 - 3 1 pve02 -[{"cpu":[PRIVATE_IP][PRIVATE_IP],"disk":[PRIVATE_IP],"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"lxc/110","maxcpu":1,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":0,"name":"dns1","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"lxc","uptime":[PRIVATE_IP],"vmid":110},{"cpu":[PRIVATE_IP][PRIVATE_IP],"disk":[PRIVATE_IP],"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"lxc/111","maxcpu":1,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":0,"name":"dns2","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve02","status":"running","template":0,"type":"lxc","uptime":[PRIVATE_IP],"vmid":111},{"cpu":0,"disk":[PRIVATE_IP],"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"lxc/112","maxcpu":1,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":0,"name":"unbound1","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"lxc","uptime":[PRIVATE_IP],"vmid":112},{"cpu":[PRIVATE_IP][PRIVATE_IP],"disk":[PRIVATE_IP],"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"lxc/113","maxcpu":1,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":0,"name":"unbound2","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve02","status":"running","template":0,"type":"lxc","uptime":[PRIVATE_IP],"vmid":113},{"cpu":[PRIVATE_IP]76666,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/130","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"edge-vm","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve03","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":130},{"cpu":[PRIVATE_IP]71836,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/150","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"snikket","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":150},{"cpu":[PRIVATE_IP]791523,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/160","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"forum-prod","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve02","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":160},{"cpu":[PRIVATE_IP]96,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/170","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"core-apps","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":170},{"cpu":[PRIVATE_IP]03387,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/171","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"monitoring","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":171},{"cpu":[PRIVATE_IP]05841,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/190","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"homelab-ops-worker","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve03","status":"running","template":0,"type":"qemu","uptime":[PRIVATE_IP],"vmid":190},{"cpu":[PRIVATE_IP]052406,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/210","maxcpu":2,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"newfi-prod","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve01","status":"running","template":0,"type":"qemu","uptime":739157,"vmid":210},{"cpu":[PRIVATE_IP]116819,"disk":0,"diskread":[PRIVATE_IP],"diskwrite":[PRIVATE_IP],"id":"qemu/211","maxcpu":2,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"memhost":[PRIVATE_IP],"name":"newfi-staging","netin":[PRIVATE_IP],"netout":[PRIVATE_IP],"node":"pve03","status":"running","template":0,"type":"qemu","uptime":935088,"vmid":211},{"cpu":0,"disk":0,"diskread":0,"diskwrite":0,"id":"qemu/9130","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":0,"memhost":0,"name":"edge-cold-standby","netin":0,"netout":0,"node":"pve02","status":"stopped","template":0,"type":"qemu","uptime":0,"vmid":9130},{"cgroup-mode":2,"cpu":[PRIVATE_IP]3004,"disk":[PRIVATE_IP],"id":"node/pve02","level":"","maxcpu":4,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"node":"pve02","status":"online","type":"node","uptime":[PRIVATE_IP]},{"cgroup-mode":2,"cpu":[PRIVATE_IP]51519,"disk":[PRIVATE_IP],"id":"node/pve01","level":"","maxcpu":24,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"node":"pve01","status":"online","type":"node","uptime":[PRIVATE_IP]},{"cgroup-mode":2,"cpu":[PRIVATE_IP]0527,"disk":[PRIVATE_IP],"id":"node/pve03","level":"","maxcpu":8,"maxdisk":[PRIVATE_IP],"maxmem":[PRIVATE_IP],"mem":[PRIVATE_IP],"node":"pve03","status":"online","type":"node","uptime":[PRIVATE_IP]},{"content":"backup,vztmpl,import,iso","disk":[PRIVATE_IP],"id":"storage/pve02/local","maxdisk":[PRIVATE_IP],"node":"pve02","plugintype":"dir","shared":0,"status":"available","storage":"local","type":"storage"},{"content":"backup,vztmpl,import,iso","disk":[PRIVATE_IP],"id":"storage/pve01/local","maxdisk":[PRIVATE_IP],"node":"pve01","plugintype":"dir","shared":0,"status":"available","storage":"local","type":"storage"},{"content":"backup,vztmpl,import,iso","disk":[PRIVATE_IP],"id":"storage/pve03/local","maxdisk":[PRIVATE_IP],"node":"pve03","plugintype":"dir","shared":0,"status":"available","storage":"local","type":"storage"},{"content":"rootdir,images","disk":[PRIVATE_IP],"id":"storage/pve02/local-lvm","maxdisk":[PRIVATE_IP],"node":"pve02","plugintype":"lvmthin","shared":0,"status":"available","storage":"local-lvm","type":"storage"},{"content":"rootdir,images","disk":[PRIVATE_IP],"id":"storage/pve01/local-lvm","maxdisk":[PRIVATE_IP],"node":"pve01","plugintype":"lvmthin","shared":0,"status":"available","storage":"local-lvm","type":"storage"},{"content":"rootdir,images","disk":[PRIVATE_IP],"id":"storage/pve03/local-lvm","maxdisk":[PRIVATE_IP],"node":"pve03","plugintype":"lvmthin","shared":0,"status":"available","storage":"local-lvm","type":"storage"},{"id":"network/pve02/zone/localnetwork","network":"localnetwork","network-type":"zone","node":"pve02","status":"ok","type":"network"},{"id":"network/pve01/zone/localnetwork","network":"localnetwork","network-type":"zone","node":"pve01","status":"ok","type":"network"},{"id":"network/pve03/zone/localnetwork","network":"localnetwork","network-type":"zone","node":"pve03","status":"ok","type":"network"}] -Name Type Status Total (KiB) Used (KiB) Available (KiB) % -local dir active [PRIVATE_IP] [PRIVATE_IP] [PRIVATE_IP] 21.05% -local-lvm lvmthin active [PRIVATE_IP] [PRIVATE_IP] [PRIVATE_IP] 11.07% - UNIT LOAD ACTIVE SUB DESCRIPTION -● homelab-backup-retention-gc.service loaded failed failed Homelab owner-aware cloud retention GC - -Legend: LOAD → Reflects whether the unit definition was properly loaded. - ACTIVE → The high-level unit activation state, i.e. generalization of SUB. - SUB → The low-level unit activation state, values depend on unit type. - -1 loaded units listed. -NEXT LEFT LAST PASSED UNIT ACTIVATES -Tue [PRIVATE_IP] 15:17:16 MSK 13s Tue [PRIVATE_IP] 15:07:16 MSK 9min ago skladchik-reports-monitor-supervisor.timer skladchik-reports-monitor-supervisor.service -Tue [PRIVATE_IP] 15:17:36 MSK 34s Tue [PRIVATE_IP] 15:16:32 MSK 30s ago homelab-router-watchdog.timer homelab-router-watchdog.service -Tue [PRIVATE_IP] 15:17:56 MSK 54s Tue [PRIVATE_IP] 15:16:56 MSK 5s ago homelab-private-vpn-hosts-health.timer homelab-private-vpn-hosts-health.service -Tue [PRIVATE_IP] 15:19:56 MSK 2min 54s Tue [PRIVATE_IP] 15:14:56 MSK 2min 5s ago homelab-smartctl-textfile.timer homelab-smartctl-textfile.service -Tue [PRIVATE_IP] 15:19:56 MSK 2min 54s Tue [PRIVATE_IP] 15:14:56 MSK 2min 5s ago netbird-peers-health.timer netbird-peers-health.service -Tue [PRIVATE_IP] 15:20:57 MSK 3min 55s Tue [PRIVATE_IP] 15:15:32 MSK 1min 30s ago homelab-health-metrics.timer homelab-health-metrics.service -Tue [PRIVATE_IP] 15:22:56 MSK 5min Tue [PRIVATE_IP] 15:07:56 MSK 9min ago prometheus-node-exporter-apt.timer prometheus-node-exporter-apt.service -Tue [PRIVATE_IP] 15:25:40 MSK 8min Tue [PRIVATE_IP] 15:10:40 MSK 6min ago homelab-disk-space-health.timer homelab-disk-space-health.service -Tue [PRIVATE_IP] 15:25:40 MSK 8min Tue [PRIVATE_IP] 15:10:40 MSK 6min ago prometheus-node-exporter-nvme.timer prometheus-node-exporter-nvme.service -Tue [PRIVATE_IP] 15:29:56 MSK 12min Tue [PRIVATE_IP] 15:14:56 MSK 2min 5s ago homelab-pve03-staging-capacity-health.timer homelab-pve03-staging-capacity-health.service -Tue [PRIVATE_IP] 15:30:00 MSK 12min Tue [PRIVATE_IP] 13:30:10 MSK 1h 46min ago homelab-app-cloud-quorum-queue.timer homelab-app-cloud-quorum-queue.service -Tue [PRIVATE_IP] 15:30:00 MSK 12min Tue [PRIVATE_IP] 15:15:00 MSK 2min 2s ago homelab-incident-journal.timer homelab-incident-journal.service -Tue [PRIVATE_IP] 15:30:08 MSK 13min Tue [PRIVATE_IP] 15:15:23 MSK 1min 38s ago homelab-external-probe-vps-health.timer homelab-external-probe-vps-health.service -Tue [PRIVATE_IP] 15:31:17 MSK 14min Tue [PRIVATE_IP] 15:15:22 MSK 1min 40s ago homelab-forum-snuffleupagus-health.timer homelab-forum-snuffleupagus-health.service -Tue [PRIVATE_IP] 15:31:29 MSK 14min Tue [PRIVATE_IP] 15:16:16 MSK 46s ago homelab-duty-admin-v2.timer homelab-duty-admin-v2.service -Tue [PRIVATE_IP] 15:32:27 MSK 15min Tue [PRIVATE_IP] 15:01:40 MSK 15min ago homelab-mkdocs-auto-refresh.timer homelab-mkdocs-auto-refresh.service -Tue [PRIVATE_IP] 15:35:42 MSK 18min Tue [PRIVATE_IP] 15:05:56 MSK 11min ago homelab-backup-audit.timer homelab-backup-audit.service -Tue [PRIVATE_IP] 15:43:46 MSK 26min Tue [PRIVATE_IP] 15:09:56 MSK 7min ago homelab-reference-refresh.timer homelab-reference-refresh.service -Tue [PRIVATE_IP] 16:06:51 MSK 49min Tue [PRIVATE_IP] 15:00:56 MSK 16min ago homelab-control-backup.timer homelab-control-backup.service -Tue [PRIVATE_IP] 16:32:47 MSK 1h 15min Tue [PRIVATE_IP] 12:34:51 MSK 2h 42min ago homelab-vm-cloud-quorum-queue.timer homelab-vm-cloud-quorum-queue.service -Tue [PRIVATE_IP] 16:35:56 MSK 1h 18min Tue [PRIVATE_IP] 10:35:56 MSK 4h 41min ago homelab-vps-identity-audit.timer homelab-vps-identity-audit.service -Tue [PRIVATE_IP] 16:47:56 MSK 1h 30min Mon [PRIVATE_IP] 16:47:56 MSK 22h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service -Tue [PRIVATE_IP] 20:00:25 MSK 4h 43min Tue [PRIVATE_IP] 13:53:32 MSK 1h 23min ago homelab-evidence-root.timer homelab-evidence-root.service -Tue [PRIVATE_IP] 20:42:13 MSK 5h 25min Tue [PRIVATE_IP] 14:33:56 MSK 43min ago homelab-mailru-trash-gc.timer homelab-mailru-trash-gc.service -Wed [PRIVATE_IP] 00:00:00 MSK 8h Tue [PRIVATE_IP] 00:00:00 MSK 15h ago dpkg-db-backup.timer dpkg-db-backup.service -Wed [PRIVATE_IP] 00:00:37 MSK 8h Tue [PRIVATE_IP] 00:03:58 MSK 15h ago homelab-storage-capacity.timer homelab-storage-capacity.service -Wed [PRIVATE_IP] 00:08:49 MSK 8h Tue [PRIVATE_IP] 00:13:32 MSK 15h ago homelab-evidence-catalog.timer homelab-evidence-catalog.service -Wed [PRIVATE_IP] 00:14:32 MSK 8h Tue [PRIVATE_IP] 00:05:16 MSK 15h ago homelab-docker-health.timer homelab-docker-health.service -Wed [PRIVATE_IP] 00:17:43 MSK 9h Tue [PRIVATE_IP] 00:14:42 MSK 15h ago homelab-quality-gate.timer homelab-quality-gate.service -Wed [PRIVATE_IP] 00:43:14 MSK 9h Tue [PRIVATE_IP] 00:27:55 MSK 14h ago logrotate.timer logrotate.service -Wed [PRIVATE_IP] 01:15:56 MSK 9h Tue [PRIVATE_IP] 11:20:42 MSK 3h 56min ago apt-daily.timer apt-daily.service -Wed [PRIVATE_IP] 02:07:23 MSK 10h Tue [PRIVATE_IP] 01:27:32 MSK 13h ago pve-daily-update.timer pve-daily-update.service -Wed [PRIVATE_IP] 03:25:26 MSK 12h Tue [PRIVATE_IP] 03:34:58 MSK 11h ago homelab-backup-retention-gc.timer homelab-backup-retention-gc.service -Wed [PRIVATE_IP] 06:11:52 MSK 14h Tue [PRIVATE_IP] 06:34:40 MSK 8h ago apt-daily-upgrade.timer apt-daily-upgrade.service -Wed [PRIVATE_IP] 07:16:18 MSK 15h Tue [PRIVATE_IP] 07:16:16 MSK 8h ago homelab-drift-check.timer homelab-drift-check.service -Wed [PRIVATE_IP] 07:33:00 MSK 16h Tue [PRIVATE_IP] 07:24:10 MSK 7h ago homelab-service-registry-check.timer homelab-service-registry-check.service -Wed [PRIVATE_IP] 07:40:23 MSK 16h Tue [PRIVATE_IP] 07:36:32 MSK 7h ago homelab-alerting-health.timer homelab-alerting-health.service -Wed [PRIVATE_IP] 07:49:14 MSK 16h Tue [PRIVATE_IP] 07:57:56 MSK 7h ago homelab-dependency-map-check.timer homelab-dependency-map-check.service -Wed [PRIVATE_IP] 07:53:55 MSK 16h Tue [PRIVATE_IP] 07:55:32 MSK 7h ago homelab-desired-state-sync.timer homelab-desired-state-sync.service -Wed [PRIVATE_IP] 07:55:30 MSK 16h Tue [PRIVATE_IP] 08:10:32 MSK 7h ago homelab-duty-admin-report.timer homelab-duty-admin-report.service -Wed [PRIVATE_IP] 07:57:32 MSK 16h Tue [PRIVATE_IP] 07:59:16 MSK 7h ago homelab-runbook-generate.timer homelab-runbook-generate.service -Wed [PRIVATE_IP] 08:05:53 MSK 16h Tue [PRIVATE_IP] 08:14:16 MSK 7h ago homelab-overall-health.timer homelab-overall-health.service -Wed [PRIVATE_IP] 08:10:55 MSK 16h Tue [PRIVATE_IP] 08:16:32 MSK 7h ago homelab-kuma-monitor-policy.timer homelab-kuma-monitor-policy.service -Wed [PRIVATE_IP] 08:16:13 MSK 16h Tue [PRIVATE_IP] 08:21:56 MSK 6h ago homelab-final-readiness-gate.timer homelab-final-readiness-gate.service -Wed [PRIVATE_IP] 08:30:52 MSK 17h Tue [PRIVATE_IP] 08:31:53 MSK 6h ago homelab-capacity-risk.timer homelab-capacity-risk.service -Wed [PRIVATE_IP] 08:32:24 MSK 17h Tue [PRIVATE_IP] 08:49:40 MSK 6h ago homelab-secret-exposure-guard.timer homelab-secret-exposure-guard.service -Wed [PRIVATE_IP] 08:37:59 MSK 17h Tue [PRIVATE_IP] 07:08:51 MSK 8h ago man-db.timer man-db.service -Wed [PRIVATE_IP] 08:44:27 MSK 17h Tue [PRIVATE_IP] 08:45:56 MSK 6h ago homelab-cluster-passport.timer homelab-cluster-passport.service -Wed [PRIVATE_IP] 08:49:46 MSK 17h Tue [PRIVATE_IP] 08:49:40 MSK 6h ago homelab-golden-state-index.timer homelab-golden-state-index.service -Wed [PRIVATE_IP] 10:15:00 MSK 18h Tue [PRIVATE_IP] 10:15:02 MSK 5h 2min ago skladchik-reports-monitor-monthly-selftest-watch.timer skladchik-reports-monitor-monthly-selftest-watch.service -Sun [PRIVATE_IP] 03:10:13 MSK 4 days Sun [PRIVATE_IP] 03:10:22 MSK 2 days ago e2scrub_all.timer e2scrub_all.service -Sun [PRIVATE_IP] 03:10:15 MSK 4 days Sun [PRIVATE_IP] 03:10:39 MSK 2 days ago xfs_scrub_all.timer xfs_scrub_all.service -Sun [PRIVATE_IP] 06:41:17 MSK 4 days Sun [PRIVATE_IP] 07:35:56 MSK 2 days ago homelab-rotating-boot-drill.timer homelab-rotating-boot-drill.service -Mon [PRIVATE_IP] 00:00:47 MSK 5 days Mon [PRIVATE_IP] 00:10:39 MSK 1 day 15h ago homelab-secret-sanity.timer homelab-secret-sanity.service -Mon [PRIVATE_IP] 00:46:24 MSK 5 days Mon [PRIVATE_IP] 00:30:56 MSK 1 day 14h ago fstrim.timer fstrim.service -- - - - prometheus-node-exporter-ipmitool-sensor.timer prometheus-node-exporter-ipmitool-sensor.service -- - - - prometheus-node-exporter-mellanox-hca-temp.timer prometheus-node-exporter-mellanox-hca-temp.service -- - - - prometheus-node-exporter-smartmon.timer prometheus-node-exporter-smartmon.service - -58 timers listed. -RUNTIME_MANIFEST_ID=df[PRIVATE_IP]ac9b5abd[PRIVATE_IP]b[PRIVATE_IP]d89496fb2bde[PRIVATE_IP] -EXPERIMENT_ID=5462ee[PRIVATE_IP]ebe[PRIVATE_IP]feb2ad[PRIVATE_IP]1ad87bbac0b8108 -COLLECTION_START_AT=[PRIVATE_IP]T[PRIVATE_IP]:00 -FIRST_COMPLETE_D1_CLOSE=[PRIVATE_IP]T[PRIVATE_IP]:00 -PRODUCTION_LAUNCH_ALLOWED=False -EXECUTION_AUTHORITY=False -RISK_AUTHORITY=False -STAGE_A_HEALTH=AWAITING_PRIMARY_FINALITY -FORENSIC_PREVIOUS_EPOCH_PRESERVED=YES - -## NEWFI_TASK6_AUTH_CHECKPOINT_V[PRIVATE_IP] -- Scope: historical accepted AUTH test, not a current SMTP connection test. -- Newfi approved SMTP account/sender: aleisaev@yandex.ru. -- Endpoint used by accepted test: smtp.yandex.ru:465 with certificate verification; single PLAIN initial response accepted with code 235. -- Evidence: incident ledger ### NEWFI_TASK6_YANDEX_AUTH_V2_OBSERVATION and ### NEWFI_TASK6_AUTH_PROOF_CLOSE_V1. -- No password file written, no application configuration changed, no mail sent by the accepted AUTH test. -- Persistent transport installation and application delivery are not proven by this checkpoint. Task6 is not complete. -- AUTH challenge and missing-file incidents closed; launch/session incident remains OPEN with original cause unproven. -- This update does not change VM211, VM160, routing, board state or Git. -- Other incidents and infrastructure health were not assessed. - - -## NEWFI_PRIVATE_STRUCTURE92_WRONG_MARKER_SCOPE_[PRIVATE_IP] CLOSURE -- Status: CLOSED -- RCA: NEWFI92 inspected the pve01 NEWFI90 attempt marker, which had not been finalized because the outer shell exited immediately after the guest returned RC3 following its successful rollback. The guest marker contained the true final rollback state. -- Correction: NEWFI93 required both the guest FINISHED/ROLLED_BACK record and a fresh exact demo-state readback before reconciling the outer NEWFI90 marker. NEWFI92 itself never reserved an attempt or mutated state. - - -## NEWFI_PRIVATE_NEWFI95_NESTED_TRIPLE_QUOTE_PARSE_[PRIVATE_IP] -- Status: OPEN -- Command: NEWFI95 -- Symptom: after the content-structure precheck passed, the pve03 Python wrapper failed to parse at the PHP line beginning with $root. No Portal discovery or application mutation was reached. -- RCA: an outer raw triple-single-quoted guest Python payload contained an inner raw triple-single-quoted PHP payload. The inner delimiter terminated the outer Python string, causing PHP source to be parsed as Python. -- Safety: NEWFI95 was read-only, created no attempt marker, and did not reach the intended nested guest execution. Do not replay NEWFI95. - - -## NEWFI_PRIVATE_NEWFI95_NESTED_TRIPLE_QUOTE_PARSE_[PRIVATE_IP] CLOSURE -- Status: CLOSED -- RCA: an inner triple-single-quoted PHP literal terminated the outer triple-single-quoted Python guest payload in NEWFI95. The wrapper therefore failed parsing before the intended Portal discovery executed. -- Correction: NEWFI96 removed the nested Python payload layer entirely and passed one Python program directly to VM211 through qm guest exec stdin. The read-only Portal contract completed with QGA exit 0 and the implementation worktree remained unchanged. OUTPUT_END CHAT_OUTPUT_END