Repository navigation
feat: shared spaces for shared cars - #77
Merged
Merged
Conversation
Blind encrypted record spaces at /spaces/v1, one SharedSpace Durable Object per space, behind SPACES_ENABLED and KV spaces:enabled. Alert car.invite at once in Buddies.
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.
Summary
Adds Shared Spaces (
/spaces/v1): a blind, end-to-end encrypted record store shared by up to 10 members. The app's Shared Cars feature uses it, so a household can keep one car's mileage together. The decision is ADR 0037 in the app repo, and the wire contract is the app'sdocs/shared-cars-protocol.md.What the server holds. Each space is one
SharedSpaceDurable Object holding sealed records under opaque ids, with a per-spaceseq. The server keeps the version with the newest stamp; a deletion wins a tie, then the lower blob hash.memberIdthat commits to the member's X25519 key, and a hash of their token. Accounts are never recorded against a space; the bearer session only gates suspension and rate limits.Ops:
create,sync,put,invite/create,invite/delete,join,leave,member/remove,rekey,delete, plus a live WebSocket that sendshelloandchanged.Rules that keep a blind server honest about membership:
memberIdmatchesdhPuboncreateandjoin, and a freshjoinmust carry the current epoch.m.<memberId>is writable only by that member, andk.<x>(the key chain) only by the owner.rekey: stores its key chain link in the same transaction, replacing any planted copy.member/removecloses every open invite, so a removed member can't rejoin through someone else's invitation before the rekey.Limits:
spaces:maxMembers); 50,000 records and 256 MiB per space; 16 KB per record; 100 records per put.Kill switch:
spaces:enabled/SPACES_ENABLED. While it's off,leave,member/remove, anddeletestill work, so people can always get off a car.Buddies:
car.invitebecomes an immediate push kind.syncpaging moved to a shared chunked reader (src/durableObjectStorage.ts). It never leaves a SQLite cursor open; an open cursor madeDROP TABLEfail withSQLITE_LOCKEDin Spaces.deleteAllThenand a shared rolling-window helper replace duplicated code. Buddies' behavior is unchanged.Config: the
SHARED_SPACEbinding and migrationv10are added for both prod andenv.dev. Sentry dropsx-ww-space-auth,x-ww-space-token, and the internalx-ww-space-member-token.Verification
pnpm typecheckpasses, andpnpm testpasses 102 files, 1,676 tests.pnpm fuzz:buddies --runs 300passes.SQLITE_LOCKEDbug, now fixed with a regression e2e.rekeywith its link;wrangler.log.sharedCars.interop.test.tspasses 8 of 8 against this branch. It covers a car's whole life with three people, two rekeys, and another device opening the car with an empty keyring.The app's half, witness-work#1227, needs this on
mainfirst.