Skip to content

feat(rn-sdk): keychain-backed default DocumentsStore - #2263

Open
seshanthS wants to merge 1 commit into
feat/rn-sdk-enterprise-sessionfrom
feat/documents-bridge-domain
Open

feat(rn-sdk): keychain-backed default DocumentsStore#2263
seshanthS wants to merge 1 commit into
feat/rn-sdk-enterprise-sessionfrom
feat/documents-bridge-domain

Conversation

@seshanthS

Copy link
Copy Markdown
Collaborator

Stacked on #2262 (which stacks on #2245). PR 1 of 2 for the documents-domain swap — spec: specs/projects/sdk/workstreams/webview-in-app/plans/WIA-documents-bridge-domain.md.

Problem

DocumentsHandler's default store is in-memory, so any host that doesn't inject a documents store — the example app and any partner app using @selfxyz/rn-sdk out of the box — silently loses every captured document on app restart. This becomes load-bearing when webview-app switches its document I/O to the documents bridge domain (PR 2).

Change

  • New createKeychainDocumentsStore() (packages/rn-sdk/src/handlers/KeychainDocumentsStore.ts): DocumentsStore backed by react-native-keychain (already an optional peer dep), values as JSON strings in generic-password entries, corrupted/missing entries load as null, idempotent delete. Returns null when the module is absent.
  • DocumentsHandler default chain: injected store → keychain store → one-time-warn in-memory fallback (pure-JS tests, shells without keychain). Hosts passing documents (the WIA host) are unaffected.
  • Keychain services self_docs_catalog / self_docs_doc_<id>: outside KeychainHandler's collidable self_sdk_${key} namespace, disjoint from the Self app's own documentCatalog/document-<hash> services, and the doc_ infix keeps a document id (even the literal catalog) from colliding with the catalog service. Names are pinned by tests — renaming loses user data.
  • No new capability field: capabilities.secureStorage already signals keychain availability (same module).

Risks

  • Release coupling with PR 2: the rn-sdk npm release whose embedded webview bundle routes documents over this domain must include this store, or partner defaults regress to non-persistent.
  • Android keychain item size for real passport payloads (~50 KB) — to be verified on-device with a real chip read + relaunch before release.

Validation

  • packages/rn-sdk: 207/207 tests (7 new: service-name pins, round-trips, corrupt-JSON, collision guard, module-absent fallback), pnpm types green.

🤖 Generated with Claude Code

DocumentsHandler's default store was in-memory, so hosts that don't inject
a documents store (example app, partner apps) lost every captured document
on restart. The default is now keychain-backed via react-native-keychain
(already an optional peer dep), with a one-time-warn in-memory fallback
when the module is absent (pure-JS tests, shells without keychain).

Services are self_docs_catalog / self_docs_doc_<id> — deliberately outside
KeychainHandler's collidable self_sdk_${key} namespace and disjoint from
the Self app's own documentCatalog / document-<hash> services; the doc_
infix keeps a document id from colliding with the catalog service. Service
names are pinned by tests (renames lose user data).

First half of the documents-domain swap; spec:
specs/projects/sdk/workstreams/webview-in-app/plans/WIA-documents-bridge-domain.md

Validation: rn-sdk 207 tests + types green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
self-webview-app Ignored Ignored Aug 12, 2026 6:56am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • main
  • dev
  • staging

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 90de61fb-09a8-4972-a126-6ba4e2ebb485

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d51094bbf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

export type { NavigationCallbacks } from './NavigationHandler';
export { DocumentsHandler } from './DocumentsHandler';
export type { DocumentsStore } from './DocumentsHandler';
export { createKeychainDocumentsStore } from './KeychainDocumentsStore';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-export the store factory from the package root

Consumers of the published package cannot import this new factory: package.json exposes only the . entry point, while src/index.ts explicitly re-exports selected names from this internal barrel and omits createKeychainDocumentsStore. As a result, the export added here is unreachable through @selfxyz/rn-sdk; add it to the root export list if this factory is intended to be part of the announced API.

Useful? React with 👍 / 👎.

@@ -0,0 +1,69 @@
# WIA — Documents via the `documents` bridge domain

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Give the plan a backlog-ID filename

This new PR plan is named WIA-documents-bridge-domain.md, but repository instructions require plan filenames to use plans/<BACKLOG-ID>-<slug>.md; WIA is only the workstream prefix rather than an individual backlog ID such as the neighboring WIA-09 or WIA-17. Assign the plan a concrete backlog ID and update references to the filename.

AGENTS.md reference: AGENTS.md:L81-L87

Useful? React with 👍 / 👎.

}

async function write(service: string, username: string, value: unknown): Promise<void> {
await module!.setGenericPassword(username, JSON.stringify(value ?? null), { service });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject false keychain write results

When setGenericPassword resolves to false—a result explicitly permitted by KeychainModule—this helper still resolves successfully, so DocumentsHandler acknowledges the save to the WebView even though the document or catalog was not persisted. The UI can then proceed as if capture succeeded and the data disappears after relaunch; check the boolean and throw on false so persistence failures fail closed.

AGENTS.md reference: AGENTS.md:L34-L36

Useful? React with 👍 / 👎.

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.

1 participant