feat(web): storage wizard and browser uploads to your own storage - #37
Merged
Merged
Conversation
Adds /settings/storage (ux-dx-spec 3.1): provider tiles for R2, B2, AWS S3, MinIO, IPFS kubo, an IPFS pinning service and Dash Platform; per-provider forms with where-to-find hints; a live browser test (signed PUT, signed GET, anonymous public GET, CORS for Range reads and for PUT, delete probe) with copy-paste CORS fixes per provider; replication choice; the cost card. Credentials are sealed in the vault next to the limited key (AES-GCM under an HKDF of the vault data key), never in localStorage. The upload path (lib/storage) signs S3 requests with SigV4 on WebCrypto, pinned to the forge-core test vectors, adds to kubo with the CID re-derived locally, pins remotely, verifies every copy by re-read, and only then writes the packManifest (lib/repo/push.ts), matching forge-core field for field. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Shared byte and error helpers, one StoreOptions type, a status-hint switch, and fewer duplicated failure paths; no behavior change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Only public https addresses are recorded on chain or fetched by readers (lib/net.ts): profiles refuse a loopback or private public URL for uploads, fitManifestUris refuses non-https URIs, externalFetchUrls skips them, and the CSP opens loopback http only in devnet and dev builds. A copy counts only after an anonymous head-and-tail read through its public URL. Every Platform write asks first with its price, and the policy error says whether chunks were written. Requests use a 15 s connect and 120 s idle deadline instead of a 60 s total cap. The kubo fix creates a token limited to add, pin and id and merges this origin into the allowed list; the form explains the admin-API trust. Test results are tied to the exact values tested. Also: the reserved platform name, renames kept in policies, the record and settings written in one transaction with a discard option, secrets never put back into the page, header-unsafe secrets refused without echoing them, redirect vs CORS vs down told apart, live regions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Amber and green status text in the storage wizard now pairs the -700 shade on light surfaces with the base on dark, matching the Verification card. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A local kubo or MinIO works in every build: the CSP allows loopback http again (readers fetch only public https URLs themselves), and only the local API and endpoint may be loopback, never a published address. The kubo fix script works on a fresh node (the origin merge no longer relies on a failing config read) and creates a full-access owner token first, since any API.Authorizations entry locks the RPC API for the CLI and WebUI. Also: the chunks-written flag only after a chunk is written, request deadlines cleared when the body is not read, the test fingerprint hashed, AWS's bare wrong-region 301 told apart from CORS, and the renewal notice cleared once shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 13 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (40)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This is the web half of P0 #4 in
docs/design/ux-dx-spec.md§11: bring your own storage from the browser. It adds a storage wizard at/settings/storageand the upload path that browser writes pushing packs will use: merges (#13), fork follow-ups and release assets. Nothing here is hosted by Forge. Credentials stay encrypted in this browser, bytes go to the user's bucket or IPFS node, and Platform stores only the signedpackManifest.Storage wizard (§3.1)
Content-Rangevisible) → CORS preflight for PUT (browser pushes) → delete probe.put-bucket-cors,b2 bucket update,mc,ipfs config), prefilled with the bucket and this app's origin, plus Re-test. Reads are allowed from any origin; writes only from this app's origin.Credentials: in the vault, never localStorage
The #24 vault now holds a second AES-256-GCM blob next to the limited-key record:
CryptoKeyis in memory, and it is dropped on lock.autocomplete="off".Upload path (
lib/storage,lib/repo/push.ts)sigv4.ts) is pinned to the same vectors as forge-corebackends/sigv4.rs: the AWS test suite and the S3 reference examples. The signed host and path are exactly whatfetchsends (redirect: 'error',credentials: 'omit').cid.ts, which matchesipfs add --only-hash, multi-chunk DAG roots included) and a pin check. The Pinning Service API pin is reused when one already exists.lib/net.ts). Loopback, private and plain-http URLs are refused, and the storage test fails a public URL like127.0.0.1with the reason.http://127.0.0.1:*andhttp://localhost:*so the storage settings can reach the user's own local kubo or MinIO.writePackManifestmatches forge-corewrite_pack_manifestfield for field and is idempotent on the signer's(repoId, $ownerId, packHash)slot. It is written only after at leastreplicascopies are verified.platform://URIs come first, then https, then the rest;s3://is dropped first when the list is over budget (parity withReplication::uris/manifest_uris).pack::split.API.Authorizationsentry locks the RPC API for the CLI and WebUI;Reviews
f1a5da4. The reviewer verified that commit, and its follow-ups are fixed in3b8d715.56b9d58.dangertext failed WCAG AA on both themes, sodanger-400anddanger-700were added and applied to the danger button.lib/design/contrast.test.tspins the ratios.Testing
pnpm typecheck,pnpm lintandpnpm testpass (923 passed). Both builds pass (testnet, and devnetmoutai). New unit suites:sigv4.test.ts: the AWS suite and the S3 examples.cid.test.ts: the kubo-derived CIDs.storage.test.ts(49 tests): profile rules, published-URL rules, reader URL filtering, policies and renames, vault sealing, renewal and discard, chunk split, URI order and budget, the CORS blocks, and the replication engine against fake S3 and kubo (public re-read, re-upload, the policy failing, Platform asking first).lib/storage/upload.live.test.ts):packManifeston moutai (0.00067 DASH) → the manifest read back from Platform → the bytes fetched and hashed through the web reader.e2e/storage-wizard.spec.ts), 4/4 pass:Screenshots: empty, MinIO tested, profile saved, CORS fix, repo policy, mobile.
Not in this PR
storeAndRecordPackfrom the UI yet. Its callers come in the browser merge, fork and release PRs; the live test exercises the whole path.packManifestandchunkdocuments are estimates until measured from the browser (the live manifest cost 0.00067 DASH against a 0.0006 estimate).🤖 Generated with Claude Code