@sqlrooms/app-runtime
@sqlrooms/app-runtime defines the iframe runtime bridge used by generated HTML apps in SQLRooms. It owns the protocol between a sandboxed app iframe and the SQLRooms host; it does not own project authoring, bundling, or WebContainer startup.
Runtime Scope
The first supported app surface is the html-app stateful block. The same bridge contract can also be reused by artifact shells and WebContainer previews, but the block remains the durable v1 state model.
The app-facing API is intentionally small:
const result = await window.sqlrooms.query(
'select region, sum(revenue) as revenue from sales group by region',
);
console.log(result.rows);TypeScript apps may use the client entrypoint:
import {createAppClient} from '@sqlrooms/app-runtime/client';
const app = createAppClient();
const result = await app.query('select * from sales limit 100');Threat Model
Generated apps are treated as untrusted code. They run in a sandboxed iframe and must not receive direct access to DuckDB connectors, the room store, filesystem APIs, host DOM nodes, command execution, or mutation-capable host services.
The host grants explicit capabilities and handles every request. The initial capability set is deliberately narrow:
- read-only
query - optional table/schema discovery
- optional initial data payloads
The v1 runtime explicitly excludes:
- write queries
- filesystem access
- host DOM access
- room store mutation
- command execution
- network access as an app-runtime capability
Read-only query handling starts with state.db.sqlSelectToJson as the SQL classification gate. Hosts should additionally enforce single-statement input, row limits, timeout handling, and JSON-serializable result bounds before data crosses into the iframe.
Relation To WebContainer
@sqlrooms/webcontainer answers how a generated project is authored, edited, built, and served. @sqlrooms/app-runtime answers what a rendered app can ask the SQLRooms host to do.
WebContainer previews can attach the same host bridge to their preview iframe, and generated Vite apps can import the client entrypoint or use an injected window.sqlrooms global. WebContainer should not grow its own separate data bridge.
Revision history follows the same boundary. The v1 revision model belongs to persisted html-app runtime state and does not migrate or version legacy WebContainer app project records such as appProject.config.appsByArtifactId. Those projects can be migrated to html-app state later, but they should not drive the shared runtime history API.
HTML App Blocks
The html-app block stores a small source file map instead of one opaque HTML string:
{
"/index.html": "<!doctype html>...",
"/src/app.js": "..."
}entryHtmlPath points at the HTML file rendered through iframe.srcdoc; the default is /index.html. The host injects the app-runtime prelude before user scripts run, so generated apps can call:
HtmlAppState.intent can store the durable natural-language objective for a generated or edited app. Prefer this over storing raw model input in app state.
const {rows, columns, truncated} = await window.sqlrooms.query(
'select category, count(*) as n from events group by category',
);queryRows(sql) is available when an app only needs the plain object rows.
Dependencies are persisted as structured package/version entries:
[
{
package: 'd3',
version: '7.9.0',
entry: 'dist/d3.min.js',
kind: 'script',
global: 'd3',
},
];The v1 resolver turns these into jsDelivr URLs at render time. Persisted state keeps the structured entries so a future resolver can use import maps, bundling, local caching, or another dependency policy without rewriting app state.
Revision History
html-app state persists source revisions alongside the current source:
type HtmlAppRevision = {
id: string;
name: string;
description?: string;
sourcePrompt?: string;
source: 'assistant' | 'user' | 'restore' | 'system';
sessionId?: string;
toolCallId?: string;
commitGroupId?: string;
parentRevisionId?: string;
createdAt: number;
title: string;
intent?: string;
files: Record<string, string>;
entryHtmlPath: string;
requestedCapabilities?: AppCapability[];
grantedCapabilities?: AppCapability[];
dependencies: HtmlAppDependency[];
};Persisted HtmlAppState includes revisions, activeRevisionId, and redoRevisionIds. Older app states parse with empty history by default, so hosts can adopt revision-aware writes without a separate storage migration. Diagnostics are not stored in revisions because they describe current runtime observations and can be regenerated after restore or preview.
Query results are JSON-serializable:
type QueryResult = {
rows: Record<string, unknown>[];
columns: {name: string; type?: string}[];
rowCount: number;
truncated: boolean;
executionMs?: number;
};The host enforces read-only SELECT parsing, a single statement, row limits, and request timeouts before returning data to the iframe.
Later Capability Boundaries
The v1 bridge intentionally stops at bounded JSON query results. The following capabilities should remain out of the runtime until the read-only query path has proven useful and each addition has an explicit capability contract:
queryArrow()or streaming query results- selected artifact or block context reads
- command invocation through SQLRooms command registries
- generated asset save/export
- mutation or write queries with user confirmation
- dependency bundling, import maps, or local dependency caching
Those features should reuse the same request/response and diagnostic protocol rather than adding a second app-to-host channel.
Classes
Type Aliases
- AppRuntimeClient
- CreateAppClientOptions
- AppRuntimeHost
- AppRuntimeHostHandlers
- CreateBridgeHostOptions
- CreateDiagnosticPreludeScriptOptions
- HtmlAppDependency
- HtmlAppSourceFileMap
- HtmlAppRevisionSource
- HtmlAppRevision
- HtmlAppState
- HtmlAppRevisionPatch
- CommitHtmlAppRevisionMetadata
- RestoreHtmlAppRevisionMetadata
- HtmlAppRevisionNavigationState
- HtmlAppRuntimeConfig
- HtmlAppRuntimeSliceState
- HtmlAppRuntimeQueryState
- CreateHtmlAppRuntimeSliceOptions
- HtmlAppBlockProps
- CreateHtmlAppBlockDefinitionOptions
- AppCapability
- AppDiagnosticLevel
- AppDiagnosticSource
- AppDiagnostic
- QueryRequest
- QueryColumn
- QueryResult
- RuntimeErrorCode
- RuntimeErrorPayload
- RuntimeRequestMethod
- RuntimeRequestMessage
- RuntimeResponseMessage
- RuntimeDiagnosticMessage
- RuntimeMessage
Variables
- HTML_APP_BLOCK_TYPE
- HtmlAppDependency
- HtmlAppSourceFileMap
- HtmlAppRevisionSource
- HtmlAppRevision
- HtmlAppState
- HtmlAppRuntimeConfig
- HtmlAppBlock
- APP_RUNTIME_PROTOCOL_VERSION
- APP_RUNTIME_MESSAGE_TYPE
- AppCapability
- AppDiagnosticLevel
- AppDiagnosticSource
- AppDiagnostic
- QueryRequest
- QueryColumn
- QueryResult
- RuntimeErrorCode
- RuntimeErrorPayload
- RuntimeRequestMethod
- RuntimeRequestMessage
- RuntimeResponseMessage
- RuntimeDiagnosticMessage
- RuntimeMessage
Functions
- createAppClient
- installGlobalClient
- createBridgeHost
- createDiagnosticPreludeScript
- createHtmlAppRuntimeSlice
- commitHtmlAppRevisionState
- restoreHtmlAppRevisionState
- undoHtmlAppRevisionState
- redoHtmlAppRevisionState
- getCurrentHtmlAppRevision
- getHtmlAppRevisionList
- getHtmlAppRevisionNavigationState
- createHtmlAppBlockDefinition
- createDefaultHtmlAppFiles
- resolveHtmlAppDependencyUrl
- createHtmlAppSrcDoc
- executeReadonlyQuery
- createRuntimeRequest
- createRuntimeResponse
- createRuntimeErrorResponse
- createRuntimeDiagnostic
References
AppCapabilityType
Renames and re-exports AppCapability
AppDiagnosticType
Renames and re-exports AppDiagnostic
AppDiagnosticLevelType
Renames and re-exports AppDiagnosticLevel
AppDiagnosticSourceType
Renames and re-exports AppDiagnosticSource
QueryColumnType
Renames and re-exports QueryColumn
QueryRequestType
Renames and re-exports QueryRequest
QueryResultType
Renames and re-exports QueryResult
RuntimeDiagnosticMessageType
Renames and re-exports RuntimeDiagnosticMessage
RuntimeErrorCodeType
Renames and re-exports RuntimeErrorCode
RuntimeErrorPayloadType
Renames and re-exports RuntimeErrorPayload
RuntimeMessageType
Renames and re-exports RuntimeMessage
RuntimeRequestMessageType
Renames and re-exports RuntimeRequestMessage
RuntimeRequestMethodType
Renames and re-exports RuntimeRequestMethod
RuntimeResponseMessageType
Renames and re-exports RuntimeResponseMessage
HtmlAppDependencyType
Renames and re-exports HtmlAppDependency
HtmlAppRevisionType
Renames and re-exports HtmlAppRevision
HtmlAppRevisionSourceType
Renames and re-exports HtmlAppRevisionSource
HtmlAppRuntimeConfigType
Renames and re-exports HtmlAppRuntimeConfig
HtmlAppSourceFileMapType
Renames and re-exports HtmlAppSourceFileMap
HtmlAppStateType
Renames and re-exports HtmlAppState
