Retain verified recovery proof independently and bind the protected point
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a17f16-d99c-7ea3-95f0-8212897fba6b
This commit is contained in:
parent
e1918b3f88
commit
09f4fd33cb
7 changed files with 257 additions and 11 deletions
|
|
@ -49,8 +49,7 @@ def download(client, ref, output):
|
|||
return dict(ref, independently_retrieved_hash_verified=True, automatic_expiry=False)
|
||||
|
||||
|
||||
def publish(client, source):
|
||||
archive.regular_file(source)
|
||||
def require_protected_bucket(client):
|
||||
if client.get_bucket_versioning(Bucket=BUCKET).get("Status") != "Enabled":
|
||||
raise Refused("protected_bucket_versioning_required")
|
||||
try:
|
||||
|
|
@ -61,6 +60,40 @@ def publish(client, source):
|
|||
lifecycle = []
|
||||
if lifecycle:
|
||||
raise Refused("protected_bucket_must_have_no_lifecycle_expiry")
|
||||
|
||||
|
||||
def protect_receipt(writer, reader, receipt):
|
||||
"""Retain the recovery proof independently, without a self-hash cycle."""
|
||||
require_protected_bucket(writer)
|
||||
payload = json.dumps(receipt, sort_keys=True, separators=(",", ":")).encode()
|
||||
if len(payload) > 1024**2 or receipt.get("status") != "application_restored_verified":
|
||||
raise Refused("bounded_successful_recovery_proof_required")
|
||||
expected = hashlib.sha256(payload).hexdigest()
|
||||
key = "kits/receipts/" + expected + "/recovery-proof.json"
|
||||
try:
|
||||
head = writer.head_object(Bucket=BUCKET, Key=key)
|
||||
except Exception as error:
|
||||
if status(error) != 404:
|
||||
raise
|
||||
response = writer.put_object(Bucket=BUCKET, Key=key, Body=payload,
|
||||
IfNoneMatch="*", Metadata={"sha256": expected}, ContentType="application/json")
|
||||
version = archive.require_version(response.get("VersionId"))
|
||||
else:
|
||||
if head["ContentLength"] != len(payload) or head.get("Metadata", {}).get("sha256") != expected:
|
||||
raise Refused("existing_proof_binding_differs")
|
||||
version = archive.require_version(head.get("VersionId"))
|
||||
response = reader.get_object(Bucket=BUCKET, Key=key, VersionId=version)
|
||||
with response["Body"] as stream:
|
||||
if response.get("VersionId") != version or stream.read(len(payload) + 1) != payload:
|
||||
raise Refused("independent_proof_readback_differs")
|
||||
return {"project_id": PROJECT, "bucket": BUCKET, "object_key": key, "version_id": version,
|
||||
"sha256": expected, "bytes": len(payload), "independent_readback_verified": True,
|
||||
"automatic_expiry": False}
|
||||
|
||||
|
||||
def publish(client, source):
|
||||
archive.regular_file(source)
|
||||
require_protected_bucket(client)
|
||||
size = source.stat().st_size
|
||||
if not 0 < size <= MAX_BYTES:
|
||||
raise Refused("bounded_kit_required")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue