Skip to content

Harden R2 publication, corpus rebuild, progress, and error boundaries#14

Merged
adewale merged 10 commits into
mainfrom
claude/scalability-visualization-review-174hr7
Jul 11, 2026
Merged

Harden R2 publication, corpus rebuild, progress, and error boundaries#14
adewale merged 10 commits into
mainfrom
claude/scalability-visualization-review-174hr7

Conversation

@adewale

@adewale adewale commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

This PR is a release-hardening pass across R2 depot publication, corpus migration, progress/error contracts, and verification infrastructure. It is intentionally described as one correctness-by-construction change set: the CLI, storage protocols, smoke capabilities, and tests now enforce the same safety invariants end to end.

What changed

Depot and R2

  • Added validated opaque R2 identities/configuration, placeholder/conflict rejection before networking, setup actions, and actionable authorization classification.
  • Added bounded jittered conditional-write retries with typed contention errors.
  • Made latest publication carry an opaque expected-parent capability. Concurrent same-machine writers can no longer publish a stale prepared state over the winner.
  • Made unchanged pushes heal missing machine-index registration after interrupted first publication.
  • Reported actual blob creation separately from already-present and parent-carried blobs.
  • Bound the live smoke test to one source-pinned bucket/account/attestation nonce. Runtime target flags and target environment overrides are rejected/stripped.
  • Required an exact pre-existing remote attestation before any mutation; cleanup removes discovery registration before run namespaces and treats non-NotFound head failures as errors.

Corpus rebuild and lifecycle

  • Added backup-only aha corpus rebuild --backup; there is no unsafe no-backup operation.
  • Canonicalized symlink-resolved corpus identity before overlap checks, locking, staging, and swapping.
  • Added context-cancellable lifecycle lock acquisition and a visible rebuild_lock progress phase.
  • Validated the sibling staging tree, recursively synced its files/directories, synced the parent before and after promotion, then used atomic directory exchange on Darwin/Linux.
  • Explicitly rejects rebuild promotion on unsupported platforms rather than silently providing weaker semantics.

Public UX contracts

  • Added typed progress for capture/upload/publish/pull/ingest/verify/rebuild/smoke phases with serialized observer delivery and monotonic sequence numbers.
  • Preserved stdout JSON isolation; progress and terminal state stay on stderr (auto|off|plain|tty|json).
  • Centralized safe error presentation across CLI, doctor, MCP, and HTTP with stable aha.error.v1, one structured next action, and allowlisted verbose diagnostics.
  • Removed duplicate privacy remediation and made malformed-config doctor actions point to a valid sibling repair config rather than loop on the broken file.

Verification and documentation

  • Isolated CLI, MCP, smoke, build, and generated-doc tests from ambient user config and shared /tmp paths.
  • Added conformance-root attestation for Python/TypeScript/Go MCP clients.
  • Moved docs generation to explicit commands; ordinary tests are read-only.
  • Added Linux, Darwin, and Windows production cross-builds, including platform-specific no-follow file opening and export locks.
  • Corrected verification to run real depot fuzz targets and added a structural test preventing future stale fuzz command names.
  • Updated onboarding, lifecycle, trust, R2 settings, command schema, architecture, and correctness-by-construction documentation.

Key invariants

  1. A stale same-machine publication cannot replace a newer latest pointer.
  2. An unchanged retry repairs discoverability after a partial first push.
  3. The live smoke harness cannot select a production destination at runtime and cannot mutate before target attestation.
  4. A corpus rebuild cannot promote an unverified/unsynced tree, bypass a lock through a symlink alias, or omit its backup.
  5. Public output never renders raw SDK/SQL/path/credential-bearing causes and emits one next action.
  6. Progress callbacks are ordered; stderr progress cannot corrupt final stdout JSON.

Testing

  • make verify-full — pass
    • go test ./...
    • go vet ./...
    • go test -race ./...
    • bounded model/archive/adapter/depot fuzz targets
    • TypeScript runtime tests
    • Linux/Darwin/Windows production builds
    • isolated MCP conformance and Code Mode workflow
  • Targeted race suites for depot, corpus, user errors, and test-quality guards — pass.
  • Integration-tag attestation/credential-isolation tests — pass.
  • R2 attestation provisioner ran against the pinned bucket; a remote read was byte-compared with scripts/r2-smoketest-target.json — pass.
  • Final attestation-gated scripts/r2-smoketest.sh run against the source-pinned bucket — pass, including push/delta/reuse/pull/deep-verify and concurrent first-push coverage. The wrapper confirmed the test-only target/capability boundary before mutation and completed cleanup.

Risk and review plan

This is a large cross-cutting PR, not the narrow onboarding change in its original description. Splitting it now would separate mutually dependent protocol, CLI, safety, and conformance guarantees and make intermediate branches misleadingly unsafe, so the PR metadata is expanded instead.

Recommended review order:

  1. internal/depot/{push_v2,depot_v2,r2_integration_v2_test}.go
  2. internal/corpus/{rebuild,lifecycle_lock,path_identity,durability,swap_*}.go
  3. internal/usererror and CLI/MCP/HTTP boundaries
  4. internal/progress and progress call sites
  5. scripts/r2-smoketest*.sh, scripts/verify.sh, and test-quality guards
  6. documentation and generated surfaces

Residual platform note: atomic corpus rebuild promotion is intentionally supported only on Darwin/Linux; Windows returns an explicit unsupported error. Existing corpus operations still build on Windows.

claude and others added 10 commits June 12, 2026 08:22
…dd smoketest script

The recommended R2 token (Object Read & Write, scoped to one bucket)
cannot create buckets, but `depot init` auto-created missing buckets and
its 403 hint told users to re-check permissions that were already
correct. ensureBucket now surfaces non-NotFound HeadBucket errors as
themselves, names the bucket-creation step when CreateBucket is denied,
and the hint layer answers that case with "pre-create the bucket"
instead. Onboarding §8 is reordered into dependency order: bucket, then
bucket-scoped token, then init.

The production R2 client pins request/response checksums to
WhenRequired per Cloudflare's SDK guidance — R2 implements
x-amz-checksum-* only partially, the SDK default attaches checksums to
every PutObject, and the fake-S3 suite can never catch that mismatch.

scripts/r2-smoketest.sh preflights the R2 environment with per-variable
guidance and runs the live-bucket integration test (-count=1, so a
cached pass can't vouch for the live service).

Docs: bucket-lock guidance scoped to blobs/ (locking machines/ would
break the conditional pointer/index overwrites every push performs),
Account-vs-User token choice, temporary credentials for CI, location
hints, and a troubleshooting entry for the create-bucket denial.

https://claude.ai/code/session_01PtaKyYUoZtmThtvxFCskYA
@adewale adewale changed the title R2 onboarding: fix depot init's token trap, pin SDK checksums, add live smoketest script Harden R2 publication, corpus rebuild, progress, and error boundaries Jul 11, 2026
@adewale adewale merged commit d8f4446 into main Jul 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants