Skip to main content

Canonical native platform — horizontal surface

Tier: Public
Status: As-built 2026-05-27; July 2026 brewery alpha scope committed
Audience: native app maintainers, vertical/module authors, mobile-first adopters, plan executors
Resolves: operational companion to RFC-0002 native slice, PLATFORM-ARCHITECTURE.md §1.1 cross-platform commitment
Builds on: DEVELOPMENT-NATIVE-LOCAL.md, NATIVE-STRATEGY-AND-CI.md, AUTH-STRATEGY.md, ubuntu-touch-shell-strategy.md, canonical-document-rendering-surface.md

Disclaimer. This is the single source of truth for what native ships today, platform obligations for native consumers, route availability, July 2026 alpha boundaries, and post-alpha gates. RFC-0002 commits the β native slice shape; this doc tracks as-built behavior and known debt.


1. Summary

ConcernOwnerDoc / code
Native platform shared layoutapps/nativeapps/native/README.md
Route policy@umbraculum/navigationpackages/platform/navigation/src/index.ts
Module registration (native)@umbraculum/module-sdkregisterNativeModule()registerNativeModule.ts
Auth transport@umbraculum/api-clientbearerTokenAuthAUTH-STRATEGY.md
Render jobs (client)@umbraculum/api-clientrenderJob.ts
Validation@umbraculum/contractsRFC-0003 — parse at HTTP boundaries
File outputPlatform renderingRFC-0007no PDF/XLSX libs in native

Native MUST NOT bundle Gotenberg, exceljs, pdfkit, or a private render queue. Binary artifacts use async render jobs + signed URL download.


2. Current as-built (2026-05-27)

2.1 Physical layout

Per RFC-0002 β:

SliceBrewery (tier-6 vertical)Canonical modules (mrp, crp, pim, wms, …)
Nativeapps/native/src/modules/brewery/screens/Not wiredapps/native/src/modules/<code>/ reserved
Contracts@umbraculum/contracts + @umbraculum/brewery-beerjson@umbraculum/mrp-contracts, @umbraculum/crp-contracts, etc. consumed on web only today

Route registration in the shell is app-owned (AppNavigator.tsx). Brewery module metadata is recorded via registerNativeModule({ code: "brewery", ... }) at bootstrap (registerPlatformNativeModules.ts).

2.2 Shared packages (native consumers)

PackageRole on native
@umbraculum/uiTamagui primitives (Screen, Button, charts)
@umbraculum/brewery-recipes-uiRecipe editors, mash/water UI
@umbraculum/brewery-beerjsonBeerJSON types/helpers
@umbraculum/api-clientHTTP + bearer auth + render-job helpers
@umbraculum/contractsZod-backed parseXxx() at boundaries
@umbraculum/navigationRouteId, getRouteAvailability, routeToNativeTarget
@umbraculum/i18n / @umbraculum/i18n-reactCatalog + useT()
@umbraculum/mediaAsset URLs

2.3 Auth and web fallback

  • Native: bearer token in expo-secure-store; POST /auth/login/native.
  • Web bridge: POST /auth/webview-exchange → system browser with cookie session — openWebFallback.ts.
  • Whitelisted web-only routes: see §3 (WEBVIEW_WHITELIST_ROUTE_IDS).

3. Route availability matrix

Source: packages/platform/navigation/src/index.ts. Native uses block by default; routes promote to available via module registration + configureNativeRoutePolicy().

3.1 Native-available (getRouteAvailability(id, "native") === "available")

Brewery brew-day routes (from registerNativeModule for brewery):

RouteIdNative screen
recipesRecipesListScreen
recipeEditRecipeEditScreen
equipmentEquipmentScreen
waterHub, waterMash, waterSparge, waterBoilWater* screens
waterProfilesWaterProfilesScreen
fermDataIntegrationFermDataIntegrationScreen
yeastYeastScreen
brewdayStepsSettingsBrewdayStepsSettingsScreen

dashboard is available via tab shell (not in module registry list but always reachable).

3.2 Web fallback (whitelisted_web_fallback)

RouteIdBehavior
inventoryBlockedRouteScreen offers Open on web

Extend via WEBVIEW_WHITELIST_ROUTE_IDS in navigation (product decision per route).

3.3 Blocked on native (web-only today)

ModuleRouteIds
automationvessels, vesselDetail
pimproducts, productDetail, categories, attributeSets, attributeSetDetail
mrpproductionOrders, productionOrderDetail, materialRequirements
crpcapacity, schedule, resources, resourceDetail
otherquality, login (native has own login stack)

Callers MUST check getRouteAvailability before routeToNativeTarget — web-only IDs throw if gated incorrectly.

3.4 Ubuntu Touch (Morph webapp wrapper — not this doc)

iOS/Android obligations in §3–§4 apply to apps/native (Expo) only. Ubuntu Touch reuses the web slice in a Lomiri Click webapp (webapp-container + Morph); route availability follows web, not native. Native-only brew-day screens and offline SQLite do not ship on UT. Decision-of-record: ubuntu-touch-shell-strategy.md.


4. Platform obligations for native consumers

  1. RFC-0003: Treat API JSON as unknown; validate with parseXxx() from @umbraculum/contracts (or module contract packages when native consumes them). Avoid as SomeDto on wire payloads.
  2. RFC-0007: Submit render jobs via API; poll job status; download via signed URL with bearer auth. Use @umbraculum/api-client runAsyncRenderJobExport / resolveArtifactDownloadUrl.
  3. RFC-0002: New module UI lives under apps/native/src/modules/<code>/; register with registerNativeModule.
  4. i18n: User-visible strings only in packages/platform/i18n catalogs; npm run i18n:guardrail -w @umbraculum/native.
  5. No parallel stacks: No module-owned PDF/XLSX/barcode libraries on device.

5. July 2026 native EAS demo scope (brewery-only)

Demo vs cloud. The hosted demonstration stack is https://demo.umbraculum.dev (demo-host-runbook.md) — illustrative seed data, documented demo accounts, resets OK. Not production brewery data and not future customer-facing cloud.umbraculum.dev (cloud-hosted-product-track.md).

In scope

  • Auth: login, workspace select, bearer session.
  • All brewery screens under apps/native/src/modules/brewery/screens/ (13 screens).
  • Dashboard + tab navigation (Dashboard, Recipes; Inventory → web fallback).
  • EAS internal distribution (Android minimum; iOS via EAS cloud).
  • Expo Go dev loop unchanged (DEVELOPMENT-NATIVE-LOCAL.md).

Out of scope

  • Native UI for MRP, CRP, PIM, automation.
  • Native inventory list (web fallback only).
  • registerNativeModule required for all modules (brewery registered; others deferred).
  • React minor ahead of Expo Go ABI (monorepo aligned on 19.1.0 as of expo-doctor remediation 2026-06-07).
  • Store-wide public release; cloud.umbraculum.dev hosted product.

5.1 Device smoke checklist (EAS preview → demo host)

  • expo install --check passes (CI: .github/workflows/native-deps.yml) — 2026-05-27 pre-build.
  • ./scripts/check-packages-dist-up-to-date.sh passes before release branch — 2026-05-27.
  • Login → select workspace → recipes list → open recipe → water hub on device (EAS APK against demo) — 2026-06-03.
  • API health on dashboard against demo — 2026-06-03.
  • Inventory tab shows blocked + Open on web succeeds (same origin as demo) — 2026-06-03.
  • EAS Android internal build installs and launches — 2026-06-03.

Optional (not a G1 gate): Brew session Export work order (PDF) on native — FAIL on EAS preview APK (2026-06-03); PASS on demo web (e2e session). Tracked in native-eas-demo-build-log.md § Known gaps; fix deferred.

5.2 Demo distribution

  • Demo URL: https://demo.umbraculum.dev — API + web + media on one origin; see demo-host-runbook.md.
  • EAS project: apps/native/eas.jsonpreview profile bakes EXPO_PUBLIC_API_BASE_URL / EXPO_PUBLIC_MEDIA_BASE_URL to demo; development, production profiles unchanged.
  • Build log: native-eas-demo-build-log.md.
  • Credentials: Expo account + EXPO_TOKEN for .github/workflows/native-eas-build.yml; demo login per runbook (passwords not in git).

6. Known validation debt (native)

Tracked for post-alpha cleanup; not blocking July alpha.

AreaStatus
Brew session PDF export (native)FAIL EAS preview vs demo (2026-06-03); PASS demo web + localhost web — render pipeline OK; native runAsyncRenderJobExport + Linking.openURL path — see build log § Known gaps
Water screensLargely use parseXxx from @umbraculum/contracts
RecipesListScreen, BrewSessionsListScreenUse parseRecipesListResponse / parseBrewSessionsListResponse (2026-05-27)
YeastScreen, RecipeEditScreenPartial — BeerJSON/recipe body still uses narrowed records + some casts for editor state
EquipmentScreen, FermDataIntegrationScreenparseAuthMeResponse where applicable

Full cast elimination is scheduled with pr3-routes-migration-handoff.md co-landing.


7. Strategic forks (platform direction)

PathSummaryWhen
A — Status quo+Manual navigator + docs + Zod parity + web fallbackJuly alpha
B — Structured catch-up (default)A + registerNativeModule + shared render-job client + this surface doc2026 H1
C — WMS-first mobileNative-mandatory warehouse flows; Re.Pack vs PWA gateH2 2027 per ROADMAP.md

Committed: Path B platform primitives; Path A scope for July 2026 ship.


8. Post-alpha roadmap gates

GateConditionWork
G0This doc acceptedPhase 1 EAS copy
G1Native EAS demo loop core closed (§5.1 rows 1–5 on device vs demo, 2026-06-03); optional native brew-session PDF deferrednative-eas-demo-build-log.md
G2MRP/CRP alpha demo signed offOptional native deep links / web fallback expansion
G3WMS surface draft existsapps/native/src/modules/wms/wms.md §4
G4H2 2027Re.Pack federation spike vs PWA + scanner companion

MRP/CRP on native: Default remains web + AI advisor + exports; native gets fallback links unless floor UX research demands screens.


9. Packaging strategy (H2 2027 — not decided)

ROADMAP.md §H2 2027: Re.Pack module federation vs web+PWA+thin native scanner. Evidence recorded here when spike completes. July 2026 alpha does not depend on this decision.


10. WMS native slice (scaffold)

When WMS surface design lands: apps/native/src/modules/wms/README.md — placeholder until Phase B API + native flows.