Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion docs/STORAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,19 @@ Before `configure-storage`:
policy, website endpoint, CDN behavior, or public hostname to the inbox.
3. Configure a public HTTPS URL for the published bucket. Disable caching, or
use a deliberately short TTL, for mutable `state/*`. Cache immutable
`blob/*` indefinitely.
`blob/*` indefinitely. The stale-pointer failure mode is why `state/*` must
never be cached: `state/<id>/<phase>/head.json` is a mutable pointer at a
fixed key, and a CDN that serves a stale copy leaves participants seeing
"not your turn" and witnesses missing the closure window while nothing
reports an error. Verify freshness once per origin before a ceremony:
write a probe object under `state/`, read it through the public URL,
overwrite it, and confirm the very next read returns the new bytes. As
measured on 2026-08-20, both guided setups are already safe by
construction — CloudFront provisioned with the `CachingDisabled` managed
policy and Cloudflare's `r2.dev` origin do not cache at all — which also
means neither offloads `blob/*`; enabling `blob/*` caching is a pure
optimization, and any change to caching requires re-running the probe
check for `state/*`.
4. Create a coordinator runtime credential that can read, write, and delete in
the published bucket and list, read, write, and delete in the inbox. Deletes
are needed only for disposable preflight probes.
Expand Down Expand Up @@ -144,6 +156,18 @@ For production, map an ordinary HTTPS hostname controlled by the coordinator,
such as `https://ceremony.example.org`, to the published bucket. Cloudflare's
generated `r2.dev` URL is rate-limited and intended for development.

The custom domain is an availability and longevity requirement, not an
integrity one: every published artifact is content-addressed and verified
against proof-tool signatures, so no URL can forge anything — it can only
fail to serve. What the coordinator-controlled hostname buys is immunity to
`r2.dev` rate limits during timed windows (each participant pulls the full
prefix and each auditor pulls the whole transcript), and a stable public
location for the transcript that survives bucket or provider moves for as
long as audits reference it. A rehearsal on `r2.dev` is fine. Note that a
custom domain routes through the zone's cache configuration while `r2.dev`
does not cache at all, so switching to one requires re-running the `state/*`
freshness check from the common prerequisites.

For a rehearsal, `configure-storage` refreshes the Wrangler OAuth token only
for its one-time inbox privacy check; later grants and uploads do not require
Wrangler. Its value is never written to the Machine 1 `.env`. For production
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ trap clear_r2_parent_token EXIT
--storage "$STORAGE_CONFIG" \
--role participant \
--identity "$participant_id" \
--credential-ttl 1h \
--minimum-upload-window 15m \
--credential-ttl "${PARTICIPANT_GRANT_TTL:-1h}" \
--minimum-upload-window "${PARTICIPANT_GRANT_MIN_UPLOAD_WINDOW:-15m}" \
--out "$out"

chmod 0600 "$out"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ trap clear_r2_parent_token EXIT
--storage "$STORAGE_CONFIG" \
--role "$role" \
--identity "$identity" \
--credential-ttl 1h \
--minimum-upload-window 15m \
--credential-ttl "${EVIDENCE_GRANT_TTL:-1h}" \
--minimum-upload-window "${EVIDENCE_GRANT_MIN_UPLOAD_WINDOW:-15m}" \
--enrollment "$enrollment" \
--enrollment-signature "$enrollment_signature" \
--out "$out"
Expand Down
11 changes: 11 additions & 0 deletions scripts/three-machine-rehearsal/machine-1/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ COORDINATOR_PROFILE=relay-ceremony
# Machines 2 and 3 to observe the closure before the beacon exists.
REHEARSAL_WITNESS_BUFFER_SECONDS=120

# Grant lifetimes. The tiny rehearsal completes each turn in seconds, so the
# defaults are deliberately short-lived. A production-sized (K=21) turn can
# spend the better part of an hour on the contribution alone before its
# upload starts: raise these accordingly (for example 4h / 30m) when driving
# a production-sized ceremony with these scripts. R2 grants must stay within
# the 168h provider limit.
PARTICIPANT_GRANT_TTL=1h
PARTICIPANT_GRANT_MIN_UPLOAD_WINDOW=15m
EVIDENCE_GRANT_TTL=1h
EVIDENCE_GRANT_MIN_UPLOAD_WINDOW=15m

# AWS-only values. The wrapper reads the region and account ID through AWS CLI
# and constructs GRANT_ROLE_ARN from GRANT_ROLE_NAME.
# Recommended: set AWS_REGION explicitly to the region the buckets live in.
Expand Down