Implement sharing phase 2+3: InboxKeeper, pending shares, grant fan-out
Introduces the full sharing lifecycle beyond the initial create-grant happy path:
- Error::RecipientNotReady distinguishes "valid DID, no Opake key" from NotFound
(typo'd handle). resolve_identity maps step-5 NotFound → RecipientNotReady.
retry_pending_shares now treats both NotFound and RecipientNotReady as
still_pending rather than failed (bug fix).
- Pending share queue: create_pending_share enqueues when recipient not ready;
retry_pending_shares completes or expires them. Unit tests cover TTL expiry,
still_pending paths, transient-failure non-caching, and empty queue.
- InboxKeeper: mirrors WorkspaceKeeper for incoming grants. Bootstrap via
listInbox, SSE-patched via grant:upsert / grant:delete. Appview now fetches
{owner_did, recipient_did} before deleting grant rows so the broadcaster can
fan out to both parties on delete.
- SDK: listInbox, watchInbox, resolveGrantMetadata, downloadFromGrant,
createPendingShare, listPendingShares, cancelPendingShare wired through WASM.
InboxGrant / ResolvedGrantMetadata types exported.
- @opake/react: useInbox, usePendingShares, useShareMutations, useShares hooks.
- Web: SharedWithMe page rewritten to use InboxKeeper watcher with batched
owner-handle resolution, retry button on metadata errors. Share button hidden
in workspace context (allowSharing prop on PanelContent). ShareDialog includes
TTL in the pending-share toast. Stale E2E snapshot and outdated copy updated.
This is a binary file and will not be displayed.