WORM Storage Synchronization
Once a redaction pipeline seals a document and its audit manifest, those artifacts must land somewhere that neither an administrator, a rogue process, nor opposing counsel can quietly alter. Write-once-read-many (WORM) object storage provides that guarantee at the infrastructure layer, and synchronizing sealed artifacts into it is the durability backbone of the Immutable Audit Trails & Chain of Custody field guide. This page covers how to push redacted PDFs and their Cryptographic Audit Manifests into object-locked buckets so the chain of custody survives contact with production infrastructure.
Storage Modes & Lock Configuration Permalink to this section
WORM enforcement on AWS S3 comes in two retention modes. In governance mode, users holding the s3:BypassGovernanceRetention permission can shorten or delete a retained object; it protects against accidents, not against a determined insider. In compliance mode, no identity — not even the account root user — can overwrite or delete the object before its retain-until date elapses. Legal-hold is an independent boolean flag that freezes an object indefinitely regardless of any retention date, useful for litigation that outlives the scheduled retention window. The single non-negotiable prerequisite is that Object Lock must be enabled at bucket creation and cannot be added to an existing bucket; enabling it also permanently enables versioning, which the lock relies on to pin immutable object versions.
| Parameter | Type / values | Default | Notes |
|---|---|---|---|
ObjectLockMode |
GOVERNANCE | COMPLIANCE |
none | Compliance is irreversible before expiry |
RetainUntilDate |
RFC 3339 UTC datetime | none | Must be strictly in the future at PUT time |
LegalHold |
ON | OFF |
OFF |
Overrides expiry; freezes until explicitly released |
| Versioning | Enabled (forced) |
Enabled |
Auto-enabled with Object Lock; cannot be suspended |
| Default retention | mode + days/years | unset | Set once via PutObjectLockConfiguration |
The same primitives exist beyond AWS. MinIO implements the S3 Object Lock API for on-premises deployments, and Azure Blob Storage offers time-based retention and legal holds through immutable-blob policies, so the synchronization logic below ports with only endpoint and credential changes.
Verified Synchronization Implementation Permalink to this section
The following worker uploads a sealed artifact with a compliance-mode retain-until date computed from the statutory retention window. It hashes locally so the audit manifest can later prove the stored bytes are unaltered, and it never writes document content to logs.
import hashlib
from datetime import datetime, timedelta, timezone
import boto3
s3 = boto3.client("s3")
def sync_to_worm(bucket: str, key: str, path: str, retention_years: int = 6) -> str:
"""Upload a sealed artifact under a compliance-mode object lock.
Returns the SHA-256 of the stored bytes for the audit manifest."""
with open(path, "rb") as fh:
payload = fh.read()
digest = hashlib.sha256(payload).hexdigest() # log the hash, never the bytes
# Retain-until must be strictly in the future; anchor to UTC to avoid drift.
retain_until = datetime.now(timezone.utc) + timedelta(days=365 * retention_years)
s3.put_object(
Bucket=bucket,
Key=key,
Body=payload,
ObjectLockMode="COMPLIANCE",
ObjectLockRetainUntilDate=retain_until,
Metadata={"sha256": digest},
)
return digest
For artifacts above roughly 100 MB — common with high-resolution scanned discovery sets — replace the single put_object call with a multipart upload (create_multipart_upload carrying the same ObjectLockMode and ObjectLockRetainUntilDate) so a failed transfer resumes without re-hashing the whole file.
Compliance Alignment Permalink to this section
Object-locked WORM storage is the mechanism that satisfies the electronic-records rules examiners cite. SEC Rule 17a-4(f)(2)(ii)(A) requires that records be preserved “in a non-rewriteable, non-erasable format” — precisely the property compliance mode enforces — and FINRA Rule 4511 incorporates those same 17a-4 formats and retention periods for broker-dealer records. For the audit trail itself, NIST SP 800-53 Rev. 5 control AU-9 (Protection of Audit Information) requires that audit records be protected from unauthorized modification and deletion; a compliance-mode retain-until date is a direct technical control for AU-9. Persisting the SHA-256 digest alongside each object lets an examiner independently confirm integrity, which pairs with the tamper-evident linking described in Cryptographic Audit Manifests.
Performance & Scale Permalink to this section
Object Lock adds no measurable latency to a PUT — the retain-until date is stored as object metadata, not computed. Real throughput is bound by the upload itself. A single-threaded worker sustains roughly 60–90 MB/s per connection against an in-region S3 endpoint; sharding a nightly batch of sealed artifacts across eight concurrent workers clears well over 40,000 redacted PDFs per hour on 4 vCPUs, since the CPU cost is dominated by the local SHA-256 pass (about 1.5 GB/s) rather than the network. Feeding those uploads from the Async Batch Processing Pipelines already running the redaction stage keeps the sync stage from becoming a serial bottleneck.
Edge Cases & Failure Handling Permalink to this section
- Bucket created without versioning or Object Lock. Every
put_objectcarrying anObjectLockModefails withInvalidRequestbecause retention needs versioned objects to pin. There is no retrofit — recreate the bucket withObjectLockEnabledForBucket=Trueand re-sync. - Retain-until date in the past. A skewed worker clock or a naive
datetimecomputed in local time can produce a retain-until date at or before “now”, which S3 rejects. Always build the date in UTC and add a safety margin; monitor host clock drift so NTP failures surface before they corrupt a batch. - Sync lag leaving artifacts unlocked. If the redaction worker crashes between sealing a document and syncing it, the artifact sits on mutable local disk outside WORM protection. Drive synchronization from a durable queue with at-least-once delivery and reconcile the object store against the manifest ledger so any unsynced key is retried, not silently dropped.
Related Permalink to this section
Once artifacts are landing in WORM storage, walk through the concrete provisioning steps in Syncing Redaction Artifacts to S3 Object Lock, then set defaults and reconcile windows in Enforcing Retention Policies on WORM Buckets. The integrity digests referenced here originate in Cryptographic Audit Manifests, and the upload workers extend the Async Batch Processing Pipelines. Part of the Immutable Audit Trails & Chain of Custody field guide.