The flows are numbered (BF-1, BF-2, …) and referenced from code and other docs. Each section below covers purpose, what’s non-obvious, and where the iOS and Android implementations diverge — not a step-by-step script. The authoritative sequencing lives in the client code; this page exists to explain why a flow looks the way it does.
When. A user finishes onboarding and creates their first backup, picking one or two recovery methods.Non-obvious. The client generates a fresh at this moment, encrypts the , encrypts the keypair with the of each enrolled , and then discards the keypair’s secret. Only the public key is retained locally so subsequent sync operations can re-encrypt new s without authenticating a Main Factor. This is what makes background sync (BF-4) possible.A is also generated at creation and registered with the Backup Service in the same /v1/create call, so the device is immediately authorized to push updates.OIDC + Passkey one-tap enrollment. When the user enrolls both a Passkey and an OIDC factor (Google/Apple) at creation, the client takes advantage of a merged Turnkey passkey challenge: the Passkey signs both a Backup Service challenge and a Turnkey activity stamp in a single user gesture. This is also the pattern used in BF-3 when adding an OIDC factor to an existing Passkey-only account.Cross-platform. iOS and Android diverge only in the platform-specific factor enrollment (Passkey ceremony, OIDC sign-in SDK). The Bedrock-side sealing and backup-service interaction are identical.
When. A user signs into World App on a new device.Non-obvious. Retrieval (or previously “Recovery”) is the most architecturally distinct flow because the user has no local state. The client has to bootstrap from a single Main Factor.The client identifies the backup by presenting the Main Factor’s public identifier (passkey credential ID, OIDC sub, or Keychain public key) — the Backup Service has a reverse lookup table that maps these to a backup_id. Once the backup is located, the user authenticates the factor and the Backup Service returns the together with the metadata.After the backup is decrypted, the client generates a fresh for the new device and registers it via /v1/add-sync-factor. This call uses a short-lived sync_factor_token issued by /v1/retrieve/from-challenge, which lets the client add the new device authorization without re-prompting for a Main Factor.OIDC recovery quirk. For OIDC factors, decrypting the requires the held by Turnkey. The user authenticates to Turnkey via OIDC; Turnkey’s enclave verifies the OIDC token and the user’s identity before exporting the secret to the client. This is why OIDC recovery requires a network round-trip beyond the one to the Backup Service.
When. A user adds a second (or third) recovery method from Settings.Non-obvious. Adding a factor does not require re-encrypting the entire backup. The client only needs to encrypt the existing with the new and append the resulting to the metadata. This is the entire point of the keypair indirection layer (see Layered Encryption Model).To add an OIDC factor with a Passkey already enrolled, the merged Turnkey passkey challenge from BF-1 is reused — one passkey tap authorizes both /v1/add-factor on the Backup Service and the Turnkey activity that creates the OIDC provider.Currently disabled. Adding a Passkey when an OIDC factor exists is not supported today. Removing a Passkey while an OIDC factor exists is also not supported, because the Passkey is the fallback path for Turnkey when the Sync Factor’s Turnkey credentials are no longer valid (see Unauthorized Device).
When. The user takes an action that produces a new file (e.g., orb verification yields a new PCP) or modifies the credential vault.Non-obvious. Sync runs silently — it only uses the , not a . The client retains the public half of the from creation/recovery, which is enough to re-encrypt the new without unlocking any factor secret.The flow is gated by the manifest hash. If the local manifest is stale (the user updated their backup on another device), the sync attempt fails with manifest_hash_mismatch and the UI escalates to BF-5.
When. App launch, and on demand from sync failures.Non-obvious. This is the only flow that prompts re-authentication of a Main Factor outside of explicit user intent. Because background sync cannot fetch encrypted backup contents (the can’t decrypt), reconciling a remote update requires a Main Factor.The client simply fetches the remote manifest hash; if it doesn’t match the local hash, the UI presents a recovery-style prompt and the user re-authenticates a Main Factor to download the updated backup. After download, local sync resumes normally.
When. The user removes a recovery method from Settings.Non-obvious. Two systems need updating: the Backup Service (remove from ) and Turnkey (remove the corresponding OIDC provider, or delete the sub-organization if it’s the last OIDC factor). Both deletions happen using the , not a Main Factor — Turnkey policy explicitly authorizes the Sync Factor for these specific deletion activities (see Components & Parties — Turnkey). This avoids a passkey prompt on every Settings interaction.Failure handling. If the Sync Factor is no longer valid in Turnkey (PUBLIC_KEY_NOT_FOUND — see Unauthorized Device), the client falls back to the user’s Passkey to perform the Turnkey operation. This is one of the reasons a Passkey is currently required to manage other factors.Last factor. Deleting the last cascades into BF-8.
When. The user removes their last , or initiates full account deletion in World App.Non-obvious. Deletion clears state across three places — the Backup Service (metadata + sealed blob + factor lookup), Turnkey (entire sub-organization, if one exists), and local device (Sync Factor keypair, plus the iCloud Keychain factor on iOS). All three deletions are issued from the client with retries; failures are logged but do not block the user-visible “deleted” outcome, because the Backup Service’s deletion is authoritative.
When. The user has lost every and every but still controls the original device (and therefore the Root Key). This is the last-resort path; see Disaster Recovery via /v1/reset for the full rationale and preconditions.Non-obvious. This is a destructive wipe, not a recovery of backup contents. This process clears the backup so the user can re-enroll from scratch. It’s authorized by the the user reproduces locally, so nothing here depends on a Main or Sync Factor:
The Backup Service /v1/reset deletes the metadata, sealed blob, and factor-lookup entries. This deletion is authoritative.
The Turnkey sub-organization is torn down. The client submits a deleteSubOrganization activity stamped with the Backup Account Key acting as the break_glass_user.
When. After every login, and periodically thereafter. Not user-initiated.Non-obvious. This is housekeeping, not a user flow, but it is the only mechanism that can correct a Turnkey sub-organization created by an older client or that has unexpectedly drifted as nothing server-side has the authority to write to it. The client calls Bedrock’s TurnkeyManager.run_migrations with the and, when available, a .Migrations mostly require a to write, which the client does not have outside a login. So if a is required, the user is prompted to authenticate, similar to the Authorize Device flow. See Turnkey Migrations.
Last modified on August 10, 2026
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"TFH Docs","colors":{"primary":"#000000","light":"#fff","dark":"#000"},"logo":{"light":"https://mintcdn.com/tfh-docs/mf_bptVMfIjmPmfI/images/tfh-logo.svg?fit=max\u0026auto=format\u0026n=mf_bptVMfIjmPmfI\u0026q=85\u0026s=3b03e00cfb34cd8e527991e29403307c","dark":"https://mintcdn.com/tfh-docs/mf_bptVMfIjmPmfI/images/tfh-logo-dark.svg?fit=max\u0026auto=format\u0026n=mf_bptVMfIjmPmfI\u0026q=85\u0026s=800640c9ba942854ecd2f264a58a3071"},"favicon":{"light":"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon.svg","dark":"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon-dark.svg"},"navbar":{"primary":{"type":"button","label":"Developer Portal","href":"https://developer.worldcoin.org"}},"footer":{"socials":{"x":"https://x.com/tfh_technology","linkedin":"https://www.linkedin.com/company/tools-for-humanity-corp","github":"https://github.com/toolsforhumanity"}},"styling":{"eyebrows":"breadcrumbs","latex":false},"metadata":{"timestamp":true},"navigation":{"global":{"anchors":[{"anchor":"Mini Apps","icon":"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/mini-apps-card.svg","color":{"light":"#fff","dark":"#fff"},"href":"https://docs.world.org/mini-apps"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"tfh-docs","hasAudioNarration":false,"actualSubdomain":"tfh-docs","customDomains":["docs.toolsforhumanity.com"],"gitSource":{"type":"github","owner":"toolsforhumanity","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae3afec35fba98072d540dc","collectionId":"2b849e56-a0ce-49dd-8c8f-01f7f835f3dd","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae3afec35fba98072d540dc"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae3afec35fba98072d540dc","clientVersion":"0.0.4044","searchFilterCounts":[{"language":"default","tag":"World App","count":10},{"language":"default","tag":"Backup \u0026 Recovery","count":6},{"language":"default","tag":"Home","count":1},{"language":"default","tag":"Orb","count":1},{"language":"default","tag":"Advanced","count":1},{"language":"default","tag":"Wallet","count":1}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"@import url(/fonts/excalifont.woff2);@font-face{font-family:'Excalifont';src:url(/fonts/excalifont.woff2) format('woff2');font-weight:400;font-style:normal}"}],"page":{"pagePath":"world-app/backup/flows","slug":"/world-app/backup/flows","pageMetadata":{"title":"Backup Flows","sidebarTitle":"Flows","description":"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.","href":"/world-app/backup/flows"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];const BackupAccountKey=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`The secp256k1 keypair derived deterministically from the user's Root Key. Its public key is encoded into the Backup Account ID; it is the disaster-recovery key that authorizes /v1/reset and the deletion of the user's Turnkey sub-organization.`,children:`Backup Account Key`})};const EncryptedBackupEncryptionKeypair=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`An encrypted version of the Backup Encryption Keypair. It is encrypted with a Factor Secret.`,children:`Encrypted Backup Encryption Keypair`})};const BackupMetadata=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`The plain-text metadata that accompanies each backup. It is stored in the Backup Service.`,children:`Backup Metadata`})};const SealedBackup=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`The encrypted version of the Unsealed Backup. It is stored in the Backup Service. It is decrypted with the Backup Encryption Keypair.`,children:`Sealed Backup`})};const FactorSecret=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`A 32-byte secret derived from or held by a Main Factor. Used to encrypt the Backup Encryption Keypair.`,children:`Factor Secret`})};const BackupEncryptionKeypair=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`The single keypair used to encrypt the Unsealed Backup. It is randomly generated by World App and not persisted anywhere.`,children:`Backup Encryption Keypair`})};const SyncFactor=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`A Sync Factor (an Elliptic Curve Keypair) is a secondary authentication mechanism for a backup. It grants limited permissions and does not require a user interaction to be used. It is primarily used to sync the backup.`,children:`Sync Factor`})};const MainFactor=()=>{const{Tooltip}=_provideComponents()||{};if(!Tooltip)_missingMdxReference(`Tooltip`,true);return _jsx(Tooltip,{tip:`A Main Factor (e.g. a Passkey, OIDC account or Keypair in iCloud Keychain) is the primary authentication mechanism for a backup. It grants the broadest permissions and requires a user interaction to be used.`,children:`Main Factor`})};function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,ol:`ol`,p:`p`,strong:`strong`,..._provideComponents(),...props.components},{Heading,Mermaid,_MdxComponentBoundary}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Mermaid)_missingMdxReference(`Mermaid`,true);if(!_MdxComponentBoundary)_missingMdxReference(`_MdxComponentBoundary`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`1`,id:`conventions`,children:`Conventions`}),`\n`,_jsxs(_components.p,{children:[`The flows are numbered (BF-1, BF-2, …) and referenced from code and other docs. Each section below covers `,_jsx(_components.strong,{children:`purpose, what’s non-obvious, and where the iOS and Android implementations diverge`}),` — not a step-by-step script. The authoritative sequencing lives in the client code; this page exists to explain `,_jsx(_components.em,{children:`why`}),` a flow looks the way it does.`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-1-backup-creation`,children:`BF-1: Backup Creation`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` A user finishes onboarding and creates their first backup, picking one or two recovery methods.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` The client generates a `,_jsx(_components.em,{children:`fresh`}),` `,_jsx(_MdxComponentBoundary,{name:`BackupEncryptionKeypair`,children:_jsx(BackupEncryptionKeypair,{})}),` at this moment, encrypts the `,_jsx(_MdxComponentBoundary,{name:`SealedBackup`,children:_jsx(SealedBackup,{})}),`, encrypts the keypair with the `,_jsx(_MdxComponentBoundary,{name:`FactorSecret`,children:_jsx(FactorSecret,{})}),` of each enrolled `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),`, and then `,_jsx(_components.strong,{children:`discards the keypair’s secret`}),`. Only the public key is retained locally so subsequent sync operations can re-encrypt new `,_jsx(_MdxComponentBoundary,{name:`SealedBackup`,children:_jsx(SealedBackup,{})}),`s without authenticating a Main Factor. This is what makes background sync (BF-4) possible.`]}),`\n`,_jsxs(_components.p,{children:[`A `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),` is also generated at creation and registered with the Backup Service in the same `,_jsx(_components.code,{children:`/v1/create`}),` call, so the device is immediately authorized to push updates.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`OIDC + Passkey one-tap enrollment.`}),` When the user enrolls both a Passkey and an OIDC factor (Google/Apple) at creation, the client takes advantage of a `,_jsx(_components.em,{children:`merged Turnkey passkey challenge`}),`: the Passkey signs both a Backup Service challenge and a Turnkey activity stamp in a single user gesture. This is also the pattern used in BF-3 when adding an OIDC factor to an existing Passkey-only account.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Cross-platform.`}),` iOS and Android diverge only in the platform-specific factor enrollment (Passkey ceremony, OIDC sign-in SDK). The Bedrock-side sealing and backup-service interaction are identical.`]}),`\n`,_jsx(Mermaid,{chart:`flowchart LR\n User -->|enroll factor| Client\n Client -->|generate BackupEncryptionKeypair| Client\n Client -->|seal backup| Client\n Client -->|encrypt keypair with FactorSecret| Client\n Client -->|POST /v1/create| BackupService\n Client -->|register Sync Factor| BackupService\n Client -.->|if OIDC| Turnkey`}),`\n`,_jsx(Heading,{level:`1`,id:`bf-2-backup-retrieval`,children:`BF-2: Backup Retrieval`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` A user signs into World App on a new device.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` Retrieval (or previously “Recovery”) is the most architecturally distinct flow because the user has no local state. The client has to bootstrap from a single Main Factor.`]}),`\n`,_jsxs(_components.p,{children:[`The client identifies the backup by presenting the Main Factor’s `,_jsx(_components.em,{children:`public identifier`}),` (passkey credential ID, OIDC `,_jsx(_components.code,{children:`sub`}),`, or Keychain public key) — the Backup Service has a reverse lookup table that maps these to a `,_jsx(_components.code,{children:`backup_id`}),`. Once the backup is located, the user authenticates the factor and the Backup Service returns the `,_jsx(_MdxComponentBoundary,{name:`SealedBackup`,children:_jsx(SealedBackup,{})}),` together with the metadata.`]}),`\n`,_jsxs(_components.p,{children:[`After the backup is decrypted, the client generates a fresh `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),` for the new device and registers it via `,_jsx(_components.code,{children:`/v1/add-sync-factor`}),`. This call uses a short-lived `,_jsx(_components.code,{children:`sync_factor_token`}),` issued by `,_jsx(_components.code,{children:`/v1/retrieve/from-challenge`}),`, which lets the client add the new device authorization without re-prompting for a Main Factor.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`OIDC recovery quirk.`}),` For OIDC factors, decrypting the `,_jsx(_MdxComponentBoundary,{name:`BackupEncryptionKeypair`,children:_jsx(BackupEncryptionKeypair,{})}),` requires the `,_jsx(_MdxComponentBoundary,{name:`FactorSecret`,children:_jsx(FactorSecret,{})}),` held by Turnkey. The user authenticates to Turnkey via OIDC; Turnkey’s enclave verifies the OIDC token `,_jsx(_components.em,{children:`and the user’s identity`}),` before exporting the secret to the client. This is why OIDC recovery requires a network round-trip beyond the one to the Backup Service.`]}),`\n`,_jsx(Mermaid,{chart:`sequenceDiagram\n participant Client\n participant BackupService\n participant Turnkey\n Client->>BackupService: identify backup by factor public ID\n Client->>BackupService: /v1/retrieve/challenge/* + auth Main Factor\n BackupService->>Client: Sealed Backup + Metadata + sync_factor_token\n opt OIDC factor\n Client->>Turnkey: authenticate (OIDC)\n Turnkey->>Client: factor secret\n end\n Client->>Client: decrypt EncryptedBackupKeypair → decrypt SealedBackup\n Client->>BackupService: /v1/add-sync-factor (with token)\n Client->>Turnkey: Add sync factor`}),`\n`,_jsx(Heading,{level:`1`,id:`bf-3-adding-a-main-factor`,children:`BF-3: Adding a Main Factor`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` A user adds a second (or third) recovery method from Settings.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` Adding a factor `,_jsx(_components.em,{children:`does not`}),` require re-encrypting the entire backup. The client only needs to encrypt the existing `,_jsx(_MdxComponentBoundary,{name:`BackupEncryptionKeypair`,children:_jsx(BackupEncryptionKeypair,{})}),` with the new `,_jsx(_MdxComponentBoundary,{name:`FactorSecret`,children:_jsx(FactorSecret,{})}),` and append the resulting `,_jsx(_MdxComponentBoundary,{name:`EncryptedBackupEncryptionKeypair`,children:_jsx(EncryptedBackupEncryptionKeypair,{})}),` to the metadata. This is the entire point of the keypair indirection layer (see `,_jsx(_components.a,{href:`/world-app/backup/index#layered-encryption-model`,children:`Layered Encryption Model`}),`).`]}),`\n`,_jsxs(_components.p,{children:[`To add an OIDC factor with a Passkey already enrolled, the merged Turnkey passkey challenge from BF-1 is reused — one passkey tap authorizes both `,_jsx(_components.code,{children:`/v1/add-factor`}),` on the Backup Service and the Turnkey activity that creates the OIDC provider.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Currently disabled.`}),` Adding a Passkey when an OIDC factor exists is `,_jsx(_components.em,{children:`not`}),` supported today. Removing a Passkey while an OIDC factor exists is also not supported, because the Passkey is the fallback path for Turnkey when the Sync Factor’s Turnkey credentials are no longer valid (see `,_jsx(_components.a,{href:`/world-app/backup/advanced#unauthorized-device`,children:`Unauthorized Device`}),`).`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-4-backup-sync`,children:`BF-4: Backup Sync`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` The user takes an action that produces a new file (e.g., orb verification yields a new PCP) or modifies the credential vault.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` Sync runs silently — it only uses the `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),`, not a `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),`. The client retains the public half of the `,_jsx(_MdxComponentBoundary,{name:`BackupEncryptionKeypair`,children:_jsx(BackupEncryptionKeypair,{})}),` from creation/recovery, which is enough to re-encrypt the new `,_jsx(_MdxComponentBoundary,{name:`SealedBackup`,children:_jsx(SealedBackup,{})}),` without unlocking any factor secret.`]}),`\n`,_jsxs(_components.p,{children:[`The flow is gated by the manifest hash. If the local manifest is stale (the user updated their backup on another device), the sync attempt fails with `,_jsx(_components.code,{children:`manifest_hash_mismatch`}),` and the UI escalates to BF-5.`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-5-remote-update-detection`,children:`BF-5: Remote-Update Detection`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` App launch, and on demand from sync failures.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` This is the only flow that prompts re-authentication of a Main Factor `,_jsx(_components.em,{children:`outside`}),` of explicit user intent. Because background sync cannot fetch encrypted backup contents (the `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),` can’t decrypt), reconciling a remote update requires a Main Factor.`]}),`\n`,_jsx(_components.p,{children:`The client simply fetches the remote manifest hash; if it doesn’t match the local hash, the UI presents a recovery-style prompt and the user re-authenticates a Main Factor to download the updated backup. After download, local sync resumes normally.`}),`\n`,_jsx(Heading,{level:`1`,id:`bf-6-multi-device-sync`,children:`BF-6: Multi-Device Sync`}),`\n`,_jsxs(_components.p,{children:[`This is not a separate flow but a consequence of BF-4 and BF-5 interacting. See `,_jsx(_components.a,{href:`/world-app/backup/advanced#multiple-device-sync`,children:`Advanced Topics — Multiple Device Sync`}),`.`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-7-factor-deletion`,children:`BF-7: Factor Deletion`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` The user removes a recovery method from Settings.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` Two systems need updating: the Backup Service (remove from `,_jsx(_MdxComponentBoundary,{name:`BackupMetadata`,children:_jsx(BackupMetadata,{})}),`) and Turnkey (remove the corresponding OIDC provider, or delete the sub-organization if it’s the last OIDC factor). Both deletions happen using the `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),`, not a Main Factor — Turnkey policy explicitly authorizes the Sync Factor for these specific deletion activities (see `,_jsx(_components.a,{href:`/world-app/backup/components#turnkey`,children:`Components \u0026 Parties — Turnkey`}),`). This avoids a passkey prompt on every Settings interaction.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Failure handling.`}),` If the Sync Factor is no longer valid in Turnkey (`,_jsx(_components.code,{children:`PUBLIC_KEY_NOT_FOUND`}),` — see `,_jsx(_components.a,{href:`/world-app/backup/advanced#unauthorized-device`,children:`Unauthorized Device`}),`), the client falls back to the user’s Passkey to perform the Turnkey operation. This is one of the reasons a Passkey is currently required to manage other factors.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Last factor.`}),` Deleting the last `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),` cascades into BF-8.`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-8-backup-deletion`,children:`BF-8: Backup Deletion`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` The user removes their last `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),`, or initiates full account deletion in World App.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` Deletion clears state across three places — the Backup Service (metadata + sealed blob + factor lookup), Turnkey (entire sub-organization, if one exists), and local device (Sync Factor keypair, plus the iCloud Keychain factor on iOS). All three deletions are issued from the client with retries; failures are logged but do not block the user-visible “deleted” outcome, because the Backup Service’s deletion is authoritative.`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-9-disaster-recovery-via-/v1/reset`,children:`BF-9: Disaster Recovery via /v1/reset`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` The user has lost every `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),` and every `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),` but still controls the original device (and therefore the Root Key). This is the last-resort path; see `,_jsx(_components.a,{href:`/world-app/backup/advanced#disaster-recovery-via-v1-reset`,children:`Disaster Recovery via /v1/reset`}),` for the full rationale and preconditions.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` This is a destructive `,_jsx(_components.em,{children:`wipe`}),`, not a recovery of backup contents. This process clears the backup so the user can re-enroll from scratch. It’s authorized by the `,_jsx(_MdxComponentBoundary,{name:`BackupAccountKey`,children:_jsx(BackupAccountKey,{})}),` the user reproduces locally, so nothing here depends on a Main or Sync Factor:`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`The Backup Service `,_jsx(_components.code,{children:`/v1/reset`}),` deletes the metadata, sealed blob, and factor-lookup entries. This deletion is authoritative.`]}),`\n`,_jsxs(_components.li,{children:[`The Turnkey sub-organization is torn down. The client submits a `,_jsx(_components.code,{children:`deleteSubOrganization`}),` activity stamped with the Backup Account Key acting as the `,_jsx(_components.code,{children:`break_glass_user`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`1`,id:`bf-10-turnkey-account-migration`,children:`BF-10: Turnkey Account Migration`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When.`}),` After every login, and periodically thereafter. Not user-initiated.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Non-obvious.`}),` This is housekeeping, not a user flow, but it is the only mechanism that can correct a Turnkey sub-organization created by an older client or that has unexpectedly drifted as nothing server-side has the authority to write to it. The client calls Bedrock’s `,_jsx(_components.code,{children:`TurnkeyManager.run_migrations`}),` with the `,_jsx(_MdxComponentBoundary,{name:`SyncFactor`,children:_jsx(SyncFactor,{})}),` and, when available, a `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Migrations mostly require a `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),` to write, which the client does not have outside a login. So if a `,_jsx(_MdxComponentBoundary,{name:`MainFactor`,children:_jsx(MainFactor,{})}),` is required, the user is prompted to authenticate, similar to the `,_jsx(_components.strong,{children:`Authorize Device`}),` flow. See `,_jsx(_components.a,{href:`/world-app/backup/components#turnkey-migrations`,children:`Turnkey Migrations`}),`.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{BackupAccountKey,EncryptedBackupEncryptionKeypair,BackupMetadata,SealedBackup,FactorSecret,BackupEncryptionKeypair,SyncFactor,MainFactor,default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Backup Flows","sidebarTitle":"Flows","description":"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.","href":"/world-app/backup/flows"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Conventions","slug":"conventions","depth":1,"children":[]},{"title":"BF-1: Backup Creation","slug":"bf-1-backup-creation","depth":1,"children":[]},{"title":"BF-2: Backup Retrieval","slug":"bf-2-backup-retrieval","depth":1,"children":[]},{"title":"BF-3: Adding a Main Factor","slug":"bf-3-adding-a-main-factor","depth":1,"children":[]},{"title":"BF-4: Backup Sync","slug":"bf-4-backup-sync","depth":1,"children":[]},{"title":"BF-5: Remote-Update Detection","slug":"bf-5-remote-update-detection","depth":1,"children":[]},{"title":"BF-6: Multi-Device Sync","slug":"bf-6-multi-device-sync","depth":1,"children":[]},{"title":"BF-7: Factor Deletion","slug":"bf-7-factor-deletion","depth":1,"children":[]},{"title":"BF-8: Backup Deletion","slug":"bf-8-backup-deletion","depth":1,"children":[]},{"title":"BF-9: Disaster Recovery via /v1/reset","slug":"bf-9-disaster-recovery-via-/v1/reset","depth":1,"children":[]},{"title":"BF-10: Turnkey Account Migration","slug":"bf-10-turnkey-account-migration","depth":1,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"tfh-docs","siteName":"TFH Docs","title":"Backup Flows - TFH Docs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-08-10T13:19:27.490Z","gitLastModified":"2026-08-10T13:19:04.000Z","originalFileLocation":"world-app/backup/flows.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\">\u003cmeta data-mint-head name=\"application-name\" content=\"TFH Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/svg+xml\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon.svg\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon.svg\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon.svg\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon.svg\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon-dark.svg\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/svg+xml\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon-dark.svg\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/svg+xml\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/favicon-dark.svg\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Backup Flows - TFH Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"TFH Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.toolsforhumanity.com/world-app/backup/flows\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://tfh-docs.mintlify.app/_mintlify/api/og/v2?division=Backup+%26+Recovery\u0026amp;title=Backup+Flows\u0026amp;description=The+key+user-facing+flows.+Focused+on+non-obvious+behavior+and+decisions+rather+than+step-by-step+UI+scripts.\u0026amp;theme=0fdb4697fe312965391666ce\u0026amp;signature=b4c24a8cc52cc4e329b48620e192aa99ef247443feb9d1c2a2310587e32eacec\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Backup Flows - TFH Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://tfh-docs.mintlify.app/_mintlify/api/og/v2?division=Backup+%26+Recovery\u0026amp;title=Backup+Flows\u0026amp;description=The+key+user-facing+flows.+Focused+on+non-obvious+behavior+and+decisions+rather+than+step-by-step+UI+scripts.\u0026amp;theme=0fdb4697fe312965391666ce\u0026amp;signature=b4c24a8cc52cc4e329b48620e192aa99ef247443feb9d1c2a2310587e32eacec\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"TFH Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#000000\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.toolsforhumanity.com/world-app/backup/flows\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/world-app/backup/flows.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.toolsforhumanity.com/#organization\",\"name\":\"TFH Docs\",\"url\":\"https://docs.toolsforhumanity.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/tfh-docs/mf_bptVMfIjmPmfI/images/tfh-logo.svg?fit=max\u0026auto=format\u0026n=mf_bptVMfIjmPmfI\u0026q=85\u0026s=3b03e00cfb34cd8e527991e29403307c\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.toolsforhumanity.com#website\",\"name\":\"TFH Docs\",\"url\":\"https://docs.toolsforhumanity.com\",\"publisher\":{\"@id\":\"https://docs.toolsforhumanity.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.toolsforhumanity.com/world-app/backup/flows#webpage\",\"url\":\"https://docs.toolsforhumanity.com/world-app/backup/flows\",\"name\":\"Backup Flows\",\"description\":\"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\",\"dateModified\":\"2026-08-10T13:19:04.000Z\",\"isPartOf\":{\"@id\":\"https://docs.toolsforhumanity.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.toolsforhumanity.com/world-app/backup/flows#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.toolsforhumanity.com/world-app/backup/flows#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Backup \u0026 Recovery\",\"item\":\"https://docs.toolsforhumanity.com/world-app/backup/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Backup Flows\",\"item\":\"https://docs.toolsforhumanity.com/world-app/backup/flows\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.toolsforhumanity.com/world-app/backup/flows#article\",\"headline\":\"Backup Flows\",\"name\":\"Backup Flows\",\"description\":\"The key user-facing flows. Focused on non-obvious behavior and decisions rather than step-by-step UI scripts.\",\"url\":\"https://docs.toolsforhumanity.com/world-app/backup/flows\",\"mainEntityOfPage\":{\"@id\":\"https://docs.toolsforhumanity.com/world-app/backup/flows#webpage\"},\"dateModified\":\"2026-08-10T13:19:04.000Z\",\"publisher\":{\"@id\":\"https://docs.toolsforhumanity.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.toolsforhumanity.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"TFH Docs\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"TFH Docs","nav":{"global":{"anchors":[{"anchor":"Mini Apps","icon":"https://mintlify.s3.us-west-1.amazonaws.com/tfh-docs/images/mini-apps-card.svg","color":{"light":"#fff","dark":"#fff"},"href":"https://docs.world.org/mini-apps"}]},"tabs":[{"tab":"Home","pages":[{"title":"Home","href":""}]},{"tab":"World App","pages":[{"title":"Introduction","href":"/world-app"},{"title":"Bedrock — The Foundational Library","sidebarTitle":"Bedrock","href":"/world-app/bedrock"},{"group":"Wallet","pages":[{"title":"Client-side Transactions","sidebarTitle":"Client-side Transactions","href":"/world-app/transactions"}]},{"group":"Backup \u0026 Recovery","pages":[{"title":"Introduction to Backup","sidebarTitle":"Introduction","href":"/world-app/backup/index"},{"title":"Authentication Factors","sidebarTitle":"Factors","href":"/world-app/backup/factors"},{"title":"Backup Structure \u0026 Sync","sidebarTitle":"Structure \u0026 Sync","description":"What's inside the backup, how the manifest enforces consistent updates, and how sync works.","href":"/world-app/backup/structure-and-sync"},{"title":"Backup Flows","sidebarTitle":"Flows","href":"/world-app/backup/flows"},{"title":"Components \u0026 Parties","sidebarTitle":"Components \u0026 Parties","description":"What the Backup Service and Turnkey actually do, what they store, and where their authority ends.","href":"/world-app/backup/components"},{"title":"Advanced Topics","sidebarTitle":"Advanced Topics","href":"/world-app/backup/advanced"}]},{"group":"Advanced","pages":[{"title":"Cryptography","href":"/world-app/cryptography"}]}]},{"tab":"Orb","pages":[{"title":"Orb","href":"/orb"}]}]},"basePath":"","title":"Backup Flows - TFH Docs","buildId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","deploymentId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","dynamics":[],"chunks":[]}