# `coreframe_flutter`

Framework-owned Flutter host runtime for Coreframe applications.

The package owns the fixed-origin loopback runtime, persistent WebView host, native navigation and
mixed-surface presentation, startup-route application, streaming cookie proxy, and the host
half of the generated native-route bridge. Applications supply native pages, theme, upstream route
allowlists, and optional presentation capabilities.
Flutter code generation supplies the typed bridge/address/presenter aggregate and the deep-link
identity declared by `coreframe.config.ts`. Backend authentication and authorization protect native
route data and actions; the Flutter host does not make app-owned authorization decisions.

Standard single-WebView applications call `runCoreframeApplication` with a
`CoreframeApplicationConfig`. Before creating the WebView, the bootstrap selects the development or
packaged frontend, validates the production `COREFRAME_API_ORIGIN`, binds the app's fixed localhost
port, validates and applies the initial platform route, installs standard macOS
back/forward/reload forwarding, and runs
`CoreframeFlutterShell`.

The standard host also installs `NativeFilesWebCapability`. Platform adapters implement the
`coreframe/native_files` method channel, return an application-private cache namespace from
`getResourceStorageRoot`, and copy each selection into that same application's private storage
before returning `NativeFileStagedSelection` metadata to Dart. If private storage discovery fails,
the standard host leaves native files unavailable. The shared resource service
adopts that copy, enforces count and byte capacity, streams bounded loopback responses, and revokes
all ownership on a root-document change. Adapters must relinquish provider permissions and other
temporary source access as soon as staging finishes. Apps that intentionally exclude native file
access can set `CoreframeApplicationConfig(enableNativeFiles: false)`.

The app-owned configuration provides a fixed loopback port, explicit HTTP and WebSocket route
allowlists, the safe root, theme, generated
`coreframeGeneratedBindings`, and any custom transitions, native surfaces, Web capabilities, or
mobile scrollbar choice. The production API origin remains a Dart define/build-environment input; it
is never static project configuration.

The runtime is easier to read as three focused boundaries.

### Desktop runtime requirements

Packaged Windows hosts require WebView2 Runtime 109 or newer, and packaged Linux hosts require
WebKitGTK 4.1 version 2.42 or newer. Host setup fails below those floors. Every platform navigates
its WebView to the same app-owned `http://localhost:<fixed-port>` origin; packaged assets and the
development frontend are both served through that origin. Desktop hosts invalidate bridge and
dispatch authority when top-level navigation starts and restore it only after the trusted loopback
document becomes active.

### Runtime ownership

```mermaid
flowchart TD
  app["Application inputs<br/>bridge contract, route registry, native pages"]
  react["React app in the persistent WebView<br/>routes, controllers, query cache, models"]
  bridge["Versioned JS-Dart bridge"]
  shell["CoreframeFlutterShell"]
  navigation["NativeNavigationCoordinator<br/>committed physical stack"]
  mixed["FlutterMixedStackPresenter<br/>native and flutter-dom entries"]
  viewport["MixedSurfaceViewport<br/>one stable WebView slot"]
  runtime["Loopback runtime<br/>fixed localhost origin, frontend, API and WebSocket proxy"]
  upstream["Upstream app origin"]

  app --> shell
  shell --> bridge
  react -->|route intents and actions| bridge
  bridge --> navigation
  shell --> navigation
  navigation --> mixed
  mixed --> viewport
  runtime --> viewport
  viewport --> react
  runtime --> upstream
```

The shell owns the physical Flutter stack; React remains the owner of web routes and their
rendering models. The viewport keeps one persistent WebView slot while the mixed presenter changes
which surface is visible.

### Mixed navigation handoff

```mermaid
sequenceDiagram
  participant React as React route controller
  participant Bridge as JS-Dart bridge
  participant Coordinator as Navigation coordinator
  participant Presenter as Mixed stack presenter
  participant Viewport as Surface viewport

  React->>Bridge: present or navigate
  Bridge->>Coordinator: validate intent
  Coordinator->>Presenter: apply native or flutter-dom entry
  alt Native route
    Presenter->>Viewport: show Flutter page
  else DOM route
    Presenter->>Viewport: prepare WebView handoff
    Viewport-->>Presenter: DOM surface ready
    Presenter->>Viewport: reveal persistent WebView
  end
  Coordinator-->>Bridge: navigation snapshot
  Bridge-->>React: snapshot, models, and action results
```

### Session and authentication boundary

```mermaid
sequenceDiagram
  participant React as React client
  participant Loopback as Flutter loopback runtime
  participant API as Upstream Worker

  React->>Loopback: same-origin Worker request with WebView cookies
  Loopback->>API: streamed request with cookies and loopback Origin
  API-->>Loopback: streamed response with status, headers, cookies, and body
  Loopback-->>React: unchanged browser response
  opt Identity observation changed
    Loopback->>Loopback: rotate native application scope
  end
```

The WebView stores the durable Better Auth session and Coreframe access JWT in host-only, HttpOnly
cookies. Dart does not store, mint, parse, or inject either credential. It forwards cookies only to
authentication and explicitly admitted Worker HTTP and WebSocket routes, always with the exact
loopback browser Origin. The runtime streams bodies in both directions and observes only the
non-secret `X-Auth-Boundary-Key` response header so identity changes can rotate native application
scope. No custom WebView origin, CORS allowance, or authentication bridge is involved.

`CoreframeFlutterShell` hides automatic Flutter scrollbars and root WebView scroll indicators on
Android and iOS by default. Set `showMobileScrollbars: true` to opt in globally; explicit Flutter
`Scrollbar` widgets and nested HTML scroll containers remain application-owned.

Set `enableWebBridgeDiagnostics: true` on `CoreframeFlutterShell`, or on
`CoreframeApplicationConfig`, to log every web-to-host and host-to-web bridge frame
and forwarded non-framework WebView console message while troubleshooting. It is disabled by
default; protocol failures and lifecycle diagnostics remain logged.

The host also records startup milestones and startup frame timings through `CoreframeStartupTrace`.
Debug and profile builds emit `[CoreframeStartup]` log lines and Dart timeline events by default.
Enable the trace in a release build with `--dart-define=COREFRAME_STARTUP_TRACE=true`, or provide an
app-owned `CoreframeStartupTrace` with an `onEvent` sink through
`CoreframeApplicationConfig.startupTrace`. Events use monotonic elapsed time and include WebView
page, web-runtime, bridge, DOM-presentation, and Flutter frame milestones. The trace stops after the
first DOM presentation or native initial-route frame.

Opt-in native integrations implement `NativeWebCapability` and are passed explicitly through
`CoreframeFlutterShell.nativeWebCapabilities`. The shell accepts their versioned request envelope
only from its trusted main-frame transport, after framework-owned session observation, navigation,
external-URL, and route protocols. Integrations must validate their own closed payload contract and
release runtime-owned resources from `endWebRuntime` and `dispose`.

Run validation from this directory:

```sh
flutter analyze
flutter test
```
