Protocol / SDK / Sign-In Flow
shippedLayer 1 · Protocol

Sign-In Flow

The SDK sequence that turns a wallet signature into a working session with a scoped capability set, without exposing the owner key to the app.

Sign-In Flow

The sign-in flow is the SDK sequence that turns one wallet signature into a working session with a scoped capability set — so the app acts with a delegated session key and never touches the owner key.

Actors

Owner DID (wallet) · ephemeral session did:key · the host node · the app manifest.

Sequence

  1. Resolve address/chain and hosts; create a session key (WASM TCWSessionManager, tinycloud-sdk-wasm/src/session.rs).
  2. resolveSignInCapabilities → the capabilities the manifest needs.
  3. prepareSession builds the SIWE-ReCap message.
  4. Wallet signs prepared.siwe → a CACAO.
  5. completeSessionSetup mints the session UCAN (delegationHeader/CID) delegating from owner → session key.
  6. checkNodeInfoafterSignIn hooksensureSpaceExists (space-hosting via host-SIWE if the space is absent).

Thereafter the session key signs invocations with no further wallet prompts. The platform entry is NodeUserAuthorization.signIn (packages/node-sdk/...); prepareSessionForSigning/signInWithPreparedSession support external signers.

Crypto

One wallet signature (step 4) authorizes the whole composed capability set; the node validates the resulting chain via cacao-chain-validation. Replay is bounded by the SIWE nonce + time.

Example

The tinyboilerplate frontend wires the whole flow with its client helpers: connect an OpenKey passkey, compose the app manifest with the backend policy, then sign in — one wallet prompt covers the composed capability set.

import {
  connectWallet,
  loadAppManifest,
  composeManifestWithBackend,
  createAndSignIn,
} from "@tinyboilerplate/client";

const { address, web3Provider } = await connectWallet({
  appName: "My App",
  host: "https://openkey.so",
});

const manifest = await loadAppManifest(`${BACKEND_URL}/api/manifest`);
const serverInfo = await (await fetch(`${BACKEND_URL}/api/server-info`)).json();
const capabilityRequest = composeManifestWithBackend(manifest, serverInfo);

const { tcw, session } = await createAndSignIn(web3Provider, {
  address,
  autoCreateSpace: true,
  capabilityRequest,
});
// tcw.did is the owner DID; `session.siwe` + `session.signature` verify the backend session.

Under @tinyboilerplate/client this is @tinycloud/web-sdk's TinyCloudWeb.signIn(); the capabilityRequest is the composed union so the single signature also pre-authorizes the backend delegation. See getting-started for the full run.

Relationships

Produces the session + root delegation that capabilities derive from; consumes the app manifest (and capability-composition for app+backend); driven from the browser as in getting-started; hosts the space via space-hosting; the node-side counterpart is cacao-chain-validation.

Status & drift

Shipped. The exact prepareSession/completeSessionSetup implementations live in the WASM crate (sdk-rs/tinycloud-sdk-wasm), surfaced through sdk-core/src/userAuthorization.ts.

Sources

  • js-sdk: packages/node-sdk/src/authorization/NodeUserAuthorization.ts, packages/sdk-core/src/userAuthorization.ts
  • tinycloud-node: tinycloud-sdk-wasm/src/session.rs