feat(store): a way to get the file out of the store - #24
Merged
Conversation
A deck made at slides.betamobility.ai could not be put on the person's own disk. `installStoreHost` polyfills the picker, so every kernel save purpose — Cmd-S, "Save a copy", every share export — resolves to a store object. That is right for all of them, and together they left no door: the only download on the store origin was the rollback copy an update leaves behind. That is the on-ramp the Drive workflow needs (docs/beta-drive-workflow.md), so "Save to your computer…" is added to Save as…, shown only on the store origin, where it is the mirror of "Save to Beta…" on a file. It does NOT adopt the handle. The kernel's saveFile adopts what a picker returns and writes Cmd-S through it afterwards, which would quietly move the deck off the store; `saveToDisk` writes the handle directly and leaves the Cmd-S target alone, the same reason writeUpdatedFileAs grew `keepHandle`. The file keeps its collab, so it is the same deck live-synced with the stored one, not a fork — "Duplicate as new deck…" is still the fork. `serializeAuto`, so a password-protected deck lands on disk encrypted. Without the File System Access API there is no folder to choose and it is a download, which is Safari's answer and still the file. Verified in a browser against the built shell served AT the store origin, so installStoreHost really ran: the picker is called with the deck's name, its own `bento-disk` id (the browser then remembers that folder) and the compound extension; 1,034,826 bytes reach the writable; NO /api/decks request is made during the save; and a Cmd-S immediately afterwards still PUTs to /api/decks/<id> and writes nothing to the picked file. Off the store origin the item is absent and no host is installed. Gates: tsc -b, kernel tsc, build:single, shell-gate, test-export-secrets 58/58, i18n coverage with all 8 core catalogues complete (the four new strings are in every one). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhNJ6no7FeLu15siczqD3C
CI caught what the local checks did not: packed.ts is generated, and test-i18n-coverage reads PACKED_LOCALES out of it, so it verified that the eight catalogues are complete without noticing the table was built before the strings existed. build-i18n.mjs --check is the one that knows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhNJ6no7FeLu15siczqD3C
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.
A deck made at
slides.betamobility.aicould not be saved to the person's own computer or Drive.The gap
installStoreHostpolyfillsshowSaveFilePicker, so every kernel save purpose resolves to a store object:bento-doc(⌘S) PUTs,bento-copyandbento-sharePOST new decks. Each of those is right on its own, and together they left no door out. The only download on the store origin wasbento-backup, the rollback copy an update leaves behind.That is exactly the on-ramp the Drive workflow needs (#23,
docs/beta-drive-workflow.md): decks belong beside a project's material, and there was no way to put one there.The change
Save as… → "Save to your computer…", shown only on the store origin, where it is the mirror of "Save to Beta…" on a file.
saveFileadopts what a picker returns and writes ⌘S through it from then on, which would quietly move the deck off the store.saveToDiskwrites the handle directly and leaves the ⌘S target alone — same reasoning aswriteUpdatedFileAs'skeepHandlefor share exports.collab, so it is the same deck, live-synced with the stored one. "Duplicate as new deck…" is still the fork.serializeAuto, neverserializeFile, so a password-protected deck lands on disk encrypted.bento-diskpicker id, so the browser remembers that folder rather than wherever an unrelated export last went.Verification
Run in a browser against the built shell served at the store origin, so
installStoreHostactually ran (Playwright route +addInitScriptso the host captures a stub picker the way real Chrome would):Beta_Slides.bento.html, idbento-disk, and the compound.bento.htmlextension/api/decksrequests during the savePUT /api/decks/<id>and wrote 0 further bytes to the picked file — the handle was not hijackedGates:
tsc -b, kerneltsc,build:single,shell-gate,test-export-secrets58/58, i18n coverage with all 8 core catalogues complete (the four new strings are in every one, not just English).Ships with
Needs a shell release to reach people; the worker change in #25 does not. Stacked on neither — both branch from
main.🤖 Generated with Claude Code
https://claude.ai/code/session_01KhNJ6no7FeLu15siczqD3C