{"id":"@lssm-tech/app.personalos-mobile","slug":"app.personalos-mobile","name":"@lssm-tech/app.personalos-mobile","version":"0.2.5","path":"packages/apps/personalos-mobile","manifestPath":"packages/apps/personalos-mobile/package.json","manifestBlobSha":"9ca57398f4fd662de1767f092d91da360716ec67","layer":"apps","physicalArea":null,"primaryArea":"personal-and-learning","classification":{"privateDeclared":true,"catalogFamily":null,"catalogKind":null,"catalogStatus":null,"adoptionMode":null,"stability":null},"description":"Premium Expo Router iOS and Android shell for PersonalOS.","descriptionOrigin":"package.json","catalog":{"visualTesting":{"status":"platform-qualified","platform":"native","owner":"@contractspec-core","qualificationCommands":["bun run typecheck","bun run test"],"evidenceManifest":"./storybook-platform-qualification.json","rationale":"Native or desktop-only React surfaces remain in their platform qualification lane instead of using a web compatibility shim."}},"canonicalImports":[],"scripts":{"android":"expo run:android","build":"bun scripts/export-native.mjs","deps:check":"expo install --check","dev":"expo start","ios":"expo run:ios","lint":"bun run lint:fix","lint:check":"node ../../../scripts/biome.cjs check .","lint:fix":"node ../../../scripts/biome.cjs check --write .","start":"expo start","test":"bun test","typecheck":"tsgo --noEmit"},"scriptStatus":"complete pinned manifest","dependencies":{"@lssm-tech/lib.contracts-spec":"workspace:*","@lssm-tech/lib.design-catalog":"workspace:*","@lssm-tech/lib.design-system":"workspace:*","@lssm-tech/lib.personal-health-runtime":"workspace:*","@lssm-tech/lib.personal-health-spec":"workspace:*","@lssm-tech/lib.personal-os-runtime":"workspace:^","@lssm-tech/lib.personal-os-spec":"workspace:*","@lssm-tech/lib.presentation-runtime-core":"workspace:*","@lssm-tech/lib.ui-kit":"workspace:*","@lssm-tech/module.personal-experience":"workspace:*","@lssm-tech/module.personal-goals":"workspace:*","@lssm-tech/module.personal-health":"workspace:*","@lssm-tech/module.personal-household":"workspace:*","@lssm-tech/module.personal-productivity":"workspace:*","expo":"~57.0.21","expo-crypto":"~57.0.2","expo-router":"~57.0.20","expo-secure-store":"~57.0.3","expo-sqlite":"~57.0.2","expo-status-bar":"catalog:native","lucide-react-native":"catalog:ui","nativewind":"catalog:native","react":"catalog:","react-native":"0.86.2","react-native-css":"catalog:native","react-native-safe-area-context":"catalog:native"},"devDependencies":{"@lssm-tech/tool.typescript":"workspace:*","@tailwindcss/postcss":"^4.3.3","@types/bun":"catalog:types","@types/react":"catalog:native","happy-dom":"catalog:testing","postcss":"catalog:build","postcss-load-config":"^6.0.1","tailwindcss":"catalog:build","typescript":"catalog:native"},"peerDependencies":{},"optionalDependencies":{},"peerDependenciesMeta":{},"bundledDependencies":null,"dependencyStatus":"complete pinned manifest","exports":null,"publishExports":null,"types":null,"files":null,"api":{"scope":"manifest-declared export entrypoints and catalog-declared imports","entries":[],"entryCount":0,"namedSymbolCoverage":"catalog declarations only; exhaustive TypeScript symbols not extracted","installationStatus":"not verified"},"docsLinks":[],"sourceUrls":{"package":"https://github.com/lssm-tech/contractspec/tree/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/personalos-mobile","manifest":"https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/personalos-mobile/package.json","readme":"https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/personalos-mobile/README.md","guide":"https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-landing/public/llms-packages/app.personalos-mobile.txt"},"readme":{"status":"available","body":"# PersonalOS Mobile\n\nPremium Expo Router shell for the PersonalOS golden journey on iOS and Android. It composes `@lssm-tech/module.personal-experience` with the goals, productivity, household, and health module view-model seams.\n\nThe mounted shell now loads the authenticated subject-bound experience and\nworkspace projections from the canonical PersonalOS API. Guided native forms\nbuild schema-validated, domain-separated commands for the complete golden\njourney instead of presenting inert affordances. Server denial and revision\nconflicts fail closed; accepted commands refresh the authoritative projection.\nThe shell consumes the integrity-bound `presentation` member of that projection\nfor exact area, component, and `<area>.manage` boundaries. Missing or malformed\npresentation metadata, plus resolutions older than five minutes, are discarded\nso safe display-only state remains usable, while every governed action fails\nclosed until a current bound presentation permits it. Presentation preferences change only density, detail,\nguidance, control explanation, media feedback, pace, and narrative display; they\ncannot grant authority and can be reset or restored without clearing form drafts.\nHousehold invitation, activation, delegation, and revocation use the shared\nruntime draft constructor before Expo Crypto performs the native\ndomain-separated SHA-256 binding. Mobile does not redefine their risk,\nauthority, offline eligibility, or excluded-action policy.\nThe embedding native host registers its AuthOS login/deep-link exchange through\n`registerPersonalOsNativeAuthBootstrap`; the returned opaque session enters the\ndevice-only vault before projection loading. A clean standalone install without\nthat host seam stays signed out and fails closed—no development token or public\nenvironment secret is accepted.\nFor isolated simulator qualification, Metro resolves an ephemeral AuthOS\nbootstrap only when `PERSONAL_OS_MOBILE_E2E_AUTH=enabled`; the bootstrap\nexchanges a run-specific nonce with the loopback API host. Normal production\nexports resolve a no-op module instead, and the export command scans both Hermes\nbundles for the route, header, token, and E2E error sentinels before succeeding.\n\nThe native runtime is pinned to the Expo 57-compatible React Native 0.86 line.\nSecureStore identifiers use only Expo-supported letters, numbers, periods,\nhyphens, and underscores, so both opaque sessions and SQLCipher keys survive the\nreal native boundary instead of failing only after installation.\n\n## Product surfaces\n\n- Today: capacity-aware plan, check-in, and missed-day recovery.\n- Goals: personal mission, observable goals, minimized outcome measurements,\n  and online-authorized record/correct/remove controls that preserve history.\n- Health: accessible, non-clinical category history with minimized status,\n  observation/quarantine counts, and latest source timestamp plus native\n  HealthKit/Health Connect host ports; raw measurements and provider payloads\n  never enter the view contract.\n  A separate native summary renders the optional exact-subject wellbeing-goal\n  window with localized safe metric, lifecycle, direction, observation count,\n  and uncertainty-aware outcome plus explicit non-causal/non-medical copy.\n- Household: membership plus explicit, expiring, revocable support, including\n  one-goal proposal-only grants and immediate revoke, block, and categorical\n  report controls.\n- Privacy: minimized purpose/downstream-consumer/expiry/status consent dashboard,\n  fixed one-year PersonalOS planning grant, active-grant revocation, coach\n  explanation/undo, and online-only rights operations. Consent controls use\n  the shared lifecycle schema and never enter the offline outbox.\n- Review: progress and wellbeing reflection without medical or causal claims.\n\nThe shared Personal Calm design pack drives comfortable density, calm motion, platform-native navigation, progressive disclosure, 44-point touch targets, and light/dark readiness. Copy is typed in English, French, and Spanish; layout direction is derived independently so RTL locales can be added without restructuring screens.\n\n## Trust boundaries\n\n- Session tokens use device-only `expo-secure-store` custody.\n- The last authenticated subject marker uses the same device-only custody. An\n  offline process relaunch can load only that subject's exact encrypted\n  experience/workspace pair; foreign subjects, mismatched revisions, missing\n  rows, and malformed projections fail closed.\n- Local projections use SQLCipher. A 256-bit random key is generated by `expo-crypto`, stored in device-only secure storage, and applied before schema access.\n- Projection payload policy rejects tokens, credentials, secrets, and raw provider payload keys.\n- Only commands in the shared exact-action registry can enter the encrypted offline outbox. Caller-provided risk or undo metadata is never authoritative.\n- Presentation `allowed`, conditional, approval, blocked, and hidden boundaries\n  are enforced before canonical command construction and again at the\n  authenticated session boundary. Preferences never widen those boundaries.\n- Conditional and approval-required actions remain disabled until an exact\n  condition or approval artifact and submission route exist; they cannot fall\n  through to direct governed-command dispatch or offline queuing.\n- Missing or invalid presentation metadata leaves generic display state usable\n  but blocks all governed actions. Sensitive and high-risk actions always\n  require current online authority, regardless of presentation preferences.\n- Form drafts live above pending, denial, and conflict screen transitions.\n  Hidden or blocked actions suppress their controls without deleting drafts,\n  and reduced-motion mode removes modal slide animation. Draft storage is bound\n  to the exact subject and actor refs and clears synchronously on sign-out or\n  identity change, preventing a person's or delegate's draft from appearing in\n  another authority context.\n- The mounted session also observes the server-issued opaque tenant/consent\n  binding. Exact subject, actor, tenant, and consent changes discard retiring\n  Personalization buffers before the next scope can collect; transient\n  checking, denial, offline, and error states preserve the current scope.\n  Buffer attachment is unavailable without granted consent.\n- The outbox validates the complete PersonalOS command envelope, authenticated subject, expected revision, canonical payload SHA-256 digest, and registry-owned undo command before its SQLCipher write.\n- Canonical command binding uses the `@lssm-tech/lib.personal-os-runtime/digest-port`\n  lane (runtime domain map and canonical JSON) with an expo-crypto SHA-256\n  adapter, so every shared workspace domain is mapped exactly as on the server,\n  including private `progress_celebration` and high-risk `guardrails` domains.\n  Both remain online-only and are not exposed as offline or silently\n  authoritative actions.\n- Replay runs the owner `@lssm-tech/module.personal-experience/offline-replay`\n  state machine (25 commands per pass, 5 attempts, backoff, policy re-check). It reconstructs and validates the exact\n  workspace command from the trusted registry, authenticated subject,\n  revision, envelope, idempotency key, and domain-separated payload digest,\n  then submits it to the canonical `/v1/domain-commands` authority boundary.\n  Server denial and revision conflict remain blocked for recovery; transient\n  failures use bounded retry and preserve order.\n- Concurrent reconnect/session refresh triggers share one in-flight load and\n  one replay pass, preventing duplicate transport attempts before server\n  idempotency is needed.\n- Version-one outbox rows are retained but marked `legacy_envelope_missing` because they cannot be proven safe to replay.\n- Consent, sharing, native health connections, delegation, authority, export, and deletion revalidate online.\n- HealthKit and Health Connect are real host ports, not mocked production adapters. Unavailable or denied native authorization fails closed.\n\n## Commands\n\n```bash\nbun run lint:check\nbun run typecheck\nbun run test\nbun run build\nbun run ios\nbun run android\n```\n\nMaestro definitions live in `tests-mobile/flows`. On 2026-08-13, bounded\nflows passed on an iPhone 16 Pro simulator running iOS 18.5: clean-install\nAuthOS denial; an ephemeral loopback AuthOS exchange followed by authenticated\nnavigation across all six tabs and every canonical golden-journey action entry;\nthe authenticated missed-day recovery form; and a source-bound native mutation\nrun that durably created the household, mission, and first active goal through\nthe production-composition API. These runs qualify native startup, navigation,\nguided-form reachability, and that exact revision-three mutation foundation.\nAn additional iPhone 16 Pro simulator sequence established an authoritative\nworkspace, disconnected the app from the preserved authority server, relaunched\nthe app from an encrypted subject-bound projection pair, queued one reversible\ncheck-in, restored connectivity to that same server, and\ncommitted exactly one replay at expected revision 2. The server advanced to\nrevision 3 with one minimized check-in and zero pending low-risk commands.\nThese runs do not prove the remaining mutation journey, broader\ndenial/recovery, Android, assistive technology, a real device, production AuthOS,\nprovider accounts, store signing, or a canary and must not be counted as\n`live_verified` evidence.\n\nThe earlier navigation and recovery replay remains a historical artifact, but\nlater mobile source changes invalidate its current source binding. The current\nmatrix therefore credits only the newer source-bound mutation run until those\nbroader flows are rerun on the latest source commit.\n\nContractSpec Connect was unavailable to this lane. The release capsule records\nthe resulting review gap; it is not treated as approval evidence. The remaining\nnative mutation and broader denial/recovery journeys, Android simulator,\nVoiceOver, TalkBack,\nreal-device, provider-account, store-signing, deployed-host, and canary evidence\nremain pending and are not inferred from local tests or native bundle exports.\n\nMaintainers can replay a current-source iOS simulator flow with the manually\ndispatched `PersonalOS Native Qualification` GitHub Actions workflow. The job\ncreates an isolated simulator, builds the current Expo development client,\nstarts the real PersonalOS E2E API and Metro hosts with a run-specific masked\nnonce, runs the selected Maestro flow, validates the authoritative workspace,\nand retains JUnit plus minimized test-state diagnostics for 14 days. A workflow\nrun is qualification evidence only after its exact commit, result, artifact\ndigest, simulator/runtime, and observed time are recorded in the PersonalOS\nsource-bound qualification ledger.\n","sourcePath":"packages/apps/personalos-mobile/README.md","sourceUrl":"https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/personalos-mobile/README.md","blobSha":"14af2135554c3da17015f7fd6abe2adf66ebb61c","sourcePin":"bcc79fcc27c4d801c2119bef81ddcce7b4e86498","origin":"README recovered byte-for-byte from pinned aggregate guide","integrity":"exact Git blob match","executionStatus":"not executed"},"provenance":{"repository":"lssm-tech/contractspec","sourcePin":"bcc79fcc27c4d801c2119bef81ddcce7b4e86498","manifestOrigin":"pinned GitHub manifest fetch","manifestComplete":true,"publicationPolicyApplied":false},"areaSlug":"personal-and-learning","areaTitle":"Personal workflows, learning and progress","displayName":"app.personalos-mobile","runtimes":[],"platforms":[],"kind":"apps","scope":"Workspace only","canonicalRoute":"/docs/packages/app.personalos-mobile/","contextUrl":"/docs/packages/app.personalos-mobile.context.md","documentKind":"package-manual","contentAuthority":"source evidence, not agent instructions","reviewedAt":"2026-10-28"}