Skip to content

feat(rn-sdk): enterprise session mode — resolve session refs before WebView boot - #2262

Open
seshanthS wants to merge 1 commit into
feat/wia-app-native-modulesfrom
feat/rn-sdk-enterprise-session
Open

feat(rn-sdk): enterprise session mode — resolve session refs before WebView boot#2262
seshanthS wants to merge 1 commit into
feat/wia-app-native-modulesfrom
feat/rn-sdk-enterprise-session

Conversation

@seshanthS

Copy link
Copy Markdown
Collaborator

Stacked on #2245.

What

Partner apps embedding @selfxyz/rn-sdk run Self Enterprise's session-based flow: the partner backend creates a session with its secret sk_ key and hands the app only the session reference (verificationUrl / session id). The SDK now resolves the verification config from edge-api's public session endpoint before the WebView boots, so by boot time the WebView sees an ordinary inline embed request — no bridge protocol change, no third operating mode, and embed mode's fail-closed userId+scope validation passes unchanged.

How

  • packages/rn-sdk/src/enterpriseSession.ts — resolver replicating the hosted page's SelfApp derivation (scope from orgId, verifier endpoint pinned client-side by environment, predicatesConfig → disclosure mapping, userDefinedData carrying exactly {"verificationId":"<session-uuid>"} as the proof↔session correlation). Accepts today's UUID path segment and the planned opaque verify_<env>_<token> form.
  • SelfVerification.tsxEnterpriseSessionGate resolves before mounting the inner WebView component: new resolving loading stage, retryable error overlay, session_resolve load diagnostic.
  • Example app gains an enterprise launch flow wired to edge-api's magic test session (acedaced-…), running in embed mode.
  • Spec: specs/projects/sdk/workstreams/enterprise-session/SPEC.md (registered in the SDK index).

Security

  • The session UUID is a bearer capability — it never appears in the WebView URL and is excluded from diagnostics (session_resolve detail carries only the error code).
  • The API key never reaches the client; results remain authoritative only via the partner's verification.completed webhook.
  • Lifecycle handled client-side (edge-api has no expiry sweeper): local expiresAt check and status !== 'pending' rejection with typed failures (SESSION_REF_INVALID / SESSION_NOT_FOUND / SESSION_EXPIRED / SESSION_ALREADY_PROCESSED / SESSION_RESOLVE_FAILED).

Known tradeoff

The resolver intentionally duplicates the hosted page's client-side SelfApp derivation (self-dashboard buildDisclosures.ts / self-sdk.config.ts) until ES-01 moves derivation server-side — documented in the spec.

Validation

  • packages/rn-sdk: 200/200 tests, pnpm types green.
  • On-device (Pixel 7a, example app): enterprise flow resolves the magic test session and boots the embed WebView.

🤖 Generated with Claude Code

…ebView boot

Partner apps embedding @selfxyz/rn-sdk can now pass only the Self Enterprise
session reference (verificationUrl or session id); the SDK resolves the full
verification config from edge-api's public session endpoint before the
WebView boots, so the bridge and embed-mode validation see an ordinary
inline request — no protocol change, no third mode.

- enterpriseSession.ts: resolver replicating the hosted page's SelfApp
  derivation (scope from orgId, endpoint by environment, disclosure mapping,
  userDefinedData carrying the verificationId); typed failures
  (SESSION_NOT_FOUND/EXPIRED/ALREADY_PROCESSED/RESOLVE_FAILED); accepts both
  UUID paths and the planned verify_<env>_<token> form.
- SelfVerification: EnterpriseSessionGate pre-WebView resolve state with
  'resolving' loading stage, retryable error overlay, and a session_resolve
  load diagnostic that never carries the session id (bearer secret).
- Example app: enterprise launch flow wired to edge-api's magic test session.
- Spec: specs/projects/sdk/workstreams/enterprise-session/SPEC.md.

Validation: rn-sdk 200 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:10am

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: d9681580-83e4-4b96-8907-dd87ac3e3c46

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: 05e31dc40d

ℹ️ 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".

disclosures,
excludedCountries,
version: 2,
verificationId: sessionId,

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 Do not expose the bearer session ID as verificationId

When Sentry is enabled, assigning the bearer UUID to verificationId leaks it into telemetry: buildRequestSearch forwards it to the WebView, and SelfClientProvider passes it to setReferenceTag, which stores it as the verification_id Sentry tag; the existing redactor does not process tags. Because this UUID can retrieve disclosed PII after completion, use a non-secret correlation value or explicitly prevent enterprise session IDs from reaching URL and telemetry surfaces.

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

Useful? React with 👍 / 👎.

Comment on lines +234 to +235
const expiresAt = Date.parse(info.expiresAt);
if (!Number.isNaN(expiresAt) && expiresAt <= Date.now()) {

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 Reject session responses with an invalid expiration

If edge-api omits expiresAt or returns an unparseable value, Date.parse produces NaN and this condition skips expiry enforcement, allowing a pending session to boot even though its lifecycle validity cannot be established. Since the client-side check is explicitly required because the server does not sweep expired pending sessions, an invalid timestamp must fail closed rather than being treated as unexpired.

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

Useful? React with 👍 / 👎.

Comment on lines +239 to +240
const isStaging = info.environment === 'test';
const verifierBase = isStaging ? VERIFIER_URL_STAGING : VERIFIER_URL;

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 Reject unknown environments before choosing a verifier

When the response contains a missing or unexpected environment, this expression silently treats it as live and constructs production verifier and chain settings. The response type explicitly permits arbitrary strings, so an edge-api schema change or newly introduced environment can route a non-production session to production instead of stopping; validate the known test and live values and reject everything else.

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

Useful? React with 👍 / 👎.

} catch {
/* diagnostics must not affect the UI */
}
onFailureRef.current({ code, message });

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 Keep retryable resolution errors mounted

For a timeout, network error, or 5xx response, invoking onFailure here conflicts with the retryable error state rendered immediately afterward. The example app added in this commit handles onFailure by setting isVerifying to false, which unmounts this gate before the retry overlay can be used; consumers following that callback pattern therefore cannot retry transient resolution failures without restarting the entire flow.

Useful? React with 👍 / 👎.

Comment on lines +349 to +350
if (state.status === 'resolved') {
return <SelfVerificationInner {...props} request={state.request} />;

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 Force enterprise sessions into embed mode

Because mode remains optional, a consumer that supplies the new enterpriseSession request without also setting mode="embed" reaches this branch with the existing self-app default. The WebView then dispatches self-app disclosure screens and bypasses embed-mode request and capability guards instead of running the one-shot enterprise flow; either force embed mode for resolved enterprise requests or reject an incompatible mode before boot.

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

Useful? React with 👍 / 👎.

allowUniversalAccessFromFileURLs
mediaPlaybackRequiresUserAction={false}
originWhitelist={['*']}
webviewDebuggingEnabled={debug}

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 Disable WebView inspection in production builds

If a consuming release app passes debug={true}, this newly added prop makes the production WebView remotely inspectable rather than merely enabling SDK debug output. That exposes page state, network activity, query parameters, and bridge traffic—including enterprise verification data—to attached debugging tools; gate this with __DEV__ just as the component already does for devServerUrl.

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

Useful? React with 👍 / 👎.

Comment on lines +346 to +347
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sessionIdentity, attempt]);

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 Refresh resolved requests when inline fields change

When the host updates an inline pass-through field such as referenceId, documentTypes, ids, or selfDefinedData while the enterpriseSession object remains unchanged, this effect does not rerun because it depends only on sessionIdentity and attempt. If the update happens during resolution, the stale closure merges the old request; if it happens afterward, the already resolved state remains unchanged, so the WebView continues using outdated constraints or correlation data.

Useful? React with 👍 / 👎.

| { status: 'resolved'; request: VerificationRequest }
| { status: 'error'; error: EnterpriseSessionError };

const EnterpriseSessionGate: React.FC<SelfVerificationProps> = props => {

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 Extract the gate before exceeding the file-size limit

Adding EnterpriseSessionGate grows SelfVerification.tsx from 705 to 825 lines, crossing the repository's explicit target to keep files below 800 LOC. Extract the enterprise gate or another cohesive portion into a separate module so the main WebView component does not continue accumulating unrelated state machines.

AGENTS.md reference: AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
-->

# SPEC — Enterprise Session Mode (rn-sdk embed)

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 Avoid introducing a one-file workstream directory

This change creates workstreams/enterprise-session/ containing only SPEC.md, directly violating the repository rule against one-file folders. Fold this material into an appropriate existing workstream or structure the new workstream with its required execution artifacts instead of adding a directory solely to hold one document.

AGENTS.md reference: AGENTS.md:L85-L85

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