#!/usr/bin/env python3 """Seal a measured essentials archive with an explicit recovery contract.""" from datetime import datetime, timezone import json import os from pathlib import PurePosixPath import shutil import stat import zipfile MANIFEST='backup-manifest.json' OMITTED=('data/packages/','data/repo-archive/','data/indexers/','data/actions_log/','log/') BUDGET=600*1024**2 def seal(path): temporary=path.with_name(path.name+'.sealing') fd=os.open(temporary,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600);os.close(fd) try: with zipfile.ZipFile(path) as source, zipfile.ZipFile(temporary,'w') as target: kept=0 for member in source.infolist(): name=PurePosixPath(member.filename) if name.is_absolute() or '..' in name.parts or stat.S_ISLNK(member.external_attr>>16): raise ValueError('unsafe_archive_member') if member.filename==MANIFEST: raise ValueError('archive_already_sealed') if member.filename.startswith(OMITTED): continue with source.open(member) as incoming, target.open(member,'w') as outgoing: shutil.copyfileobj(incoming,outgoing,1024*1024) kept+=1 target.writestr(MANIFEST,json.dumps({'schema':'platform.forgejo-backup-profile.v1', 'profile':'essentials','created_at':datetime.now(timezone.utc).isoformat(), 'complete_application_backup':False,'omitted_prefixes':list(OMITTED), 'kept_members':kept,'package_registry_available':False, 'recovery_contract':'Git and collaboration recovery; packages require full primary or an independent artifact source.', 'unique_data_policy':'Keep repositories, database, configuration, attachments, LFS and Actions artifacts when present.'},sort_keys=True),compress_type=zipfile.ZIP_DEFLATED) if temporary.stat().st_size>BUDGET: raise ValueError('essentials_budget_exceeded') os.replace(temporary,path) finally: temporary.unlink(missing_ok=True)