Skip to content

Releases

58.0.6

Choose a tag to compare

@joshgachnang joshgachnang released this 14 Nov 03:05
Immutable release. Only release title and notes can be modified.
434c40d

Fixes

  • @terreno/ai accepts @ai-sdk/mcp from ^1.0.21 again. 58.0.5 required ^1.0.104, a version published days earlier, which apps enforcing a minimum release age could not resolve. (#1715)

Full Changelog: 58.0.5...58.0.6

58.0.5

Choose a tag to compare

@joshgachnang joshgachnang released this 14 Nov 02:27
Immutable release. Only release title and notes can be modified.
a39df96

Fixes

  • GPT chat no longer shows an image twice for Gemini image models such as gemini-3-pro-image. Draft images Gemini returns while it reasons (thought: true) are no longer streamed or saved; the last draft is kept only when a reply has no final image. (#1713)
  • @terreno/ai works with Gemini and Vertex on ai 6 again. 58.0.0 moved the Google providers to the ai 7 line, whose models ai 6 rejects with Unsupported model version v4. The @ai-sdk/google-vertex peer is back to ^4.0.199, the @ai-sdk/provider peer is removed, and @ai-sdk/mcp is back to ^1.0.104. Apps should install @ai-sdk/google-vertex 4.x and @ai-sdk/google 3.x. (#1713)

Docs & tooling

  • Agent skills moved to TerrenoLabs/terreno-skills; the bundled copies are removed. (#1712)
  • Codebase audit report and approved implementation plans from the 58.0.4 audit. (#1705, #1707)

Full Changelog: 58.0.4...58.0.5

58.0.4

Choose a tag to compare

@joshgachnang joshgachnang released this 12 Nov 01:39
Immutable release. Only release title and notes can be modified.
58.0.4
7f4ca86

Fixes

  • The admin consent form list loads again. ConsentFormList sorts by -created and by its data columns, but the /consent-forms router did not allow those sorts, so the list returned 400 sort-field-not-allowed. /consent-forms and /consent-responses now allow sorting by the fields their admin metadata marks sortable. (#1702)

Docs & tooling

  • api-ci runs its tests as one shard: both shards shared the job's single sidecar mongod and database and cleared each other's collections mid-test. (#1703)

Full Changelog: 58.0.3...58.0.4

58.0.3

Choose a tag to compare

@joshgachnang joshgachnang released this 11 Nov 23:00
Immutable release. Only release title and notes can be modified.
58.0.3
3af5f4d

Features

  • @terreno/syncdb: registerTerrenoDevClientDispatch, registerTerrenoDevStorage, and registerTerrenoDevCommand for terreno-mcp-local dev tooling. (#1682)
  • @terreno/mcp-server: read_logs gains network and native sources, plus client action dispatch, storage read/write, dev commands, and CDP network capture with header redaction. (#1682)

Fixes

  • Avatar no longer freezes release builds when its image fails to load. The error handler passed the native event to console.warn, and Sentry hung while turning it into a breadcrumb; it now logs only the error message. (#1700)
  • Mongo filters built from request values reject non-string input with 400 instead of running it as a query operator, and nested-path helpers skip __proto__, constructor, and prototype. (#1697)
  • Removed polynomial-time regexes from bearer-header parsing, trailing-slash trimming, prompt references, judge score ranges, AI JSON fence stripping, and the MCP import parser. Dataset schema validation stops at the first error. (#1697)
  • isTestUser matches nang.io and example.com as the email domain or a subdomain, not as a substring. MCP OAuth metadata sets an explicit JSON content type. (#1697)

Docs & tooling

  • fix-code-scanning-alerts skill; CodeQL now also scans pull requests and ignores test files. (#1697)
  • Package tests run as concurrent bun test --shard processes, and CircleCI pins Bun 1.4.4. (#1699)

Tests & housekeeping

Chore commits
  • MCP agent debugger gaps IP and task list (#1682)
  • Assemble Terreno 58.0.3 release notes (#1701)

Full Changelog: 58.0.2...58.0.3

58.0.2

Choose a tag to compare

@joshgachnang joshgachnang released this 09 Nov 23:11
Immutable release. Only release title and notes can be modified.
b02903b

Fixes

  • Patch the remaining critical and high dependency advisories. @terreno/ui now asks for @react-navigation/native ^7.5.1, which drops the vulnerable decode-uri-component (high) from apps that install it. (#1693)
  • Docs site: tinypool 2.2.0 (critical, prototype pollution to RCE) and serialize-javascript 7.1.4 (high). (#1690, #1691)
  • Dev tooling: Metro's stale nested copy no longer brings in image-size 1.x (high), and rulesync 43.8.0 drops its pinned zod 4.6.5 (high). (#1694, #1695)

Still open: zod 3.25.76 inside Expo's CLI tooling has no fixed 3.x release and waits for an Expo update.

Docs & tooling

  • Dependabot opens one security PR per advisory instead of one grouped PR per package block, so each fix can merge on its own. (#1689)
  • Compare options for high-churn fields in syncdb (design doc). (#1692)

Tests & housekeeping

Roadmap commits
  • Reconcile roadmap entries with implementation plans
  • Regenerate ROADMAP.md from the project board

Full Changelog: 58.0.1...58.0.2

58.0.1

Choose a tag to compare

@joshgachnang joshgachnang released this 09 Nov 17:22
Immutable release. Only release title and notes can be modified.
26be2c0

Added

  • @terreno/api/sentry exports SENTRY_V10_DATA_COLLECTION, a Sentry 11 dataCollection setting that keeps Sentry 10's privacy defaults: no cookies, user info, database query data, HTTP bodies, or AI inputs and outputs, and IP-like headers and query params denied. Pass it to Sentry.init({dataCollection}). (#1687)

Fixed

  • Patch security advisories in Terreno's dependencies: Better Auth 1.7.7 (critical), multer 2.5.0, @modelcontextprotocol/node 2.1.2, @modelcontextprotocol/sdk 1.32.2, markdown-it 14.3.3, @hono/node-server 2.1.3, smol-toml 1.9.1, csv-parse 7, plus in-range lockfile fixes (undici, zod, dompurify, body-parser, qs, follow-redirects, and others). bun audit drops from 111 advisories to 15, all in transitive build and dev tooling. (#1687)
  • Upgrade to Sentry 11 and Biome 2.5.13. (#1687)

Full Changelog: 58.0.0...58.0.1

58.0.0

Choose a tag to compare

@joshgachnang joshgachnang released this 06 Nov 19:10
Immutable release. Only release title and notes can be modified.
58.0.0
32404d6

Breaking

  • @terreno/admin-spa now server-renders every admin page in the backend's Express process, behind an access gate that runs before anything renders. The first HTML holds the login form, the shell and the screen's data. Upgrade steps: Upgrade to the server-rendered admin SPA.
  • AdminSpaServeApp's distDir (and example-backend's ADMIN_SPA_DIST_DIR) now names the export root, which holds client/ and server/. build:web no longer writes dist/index.html. Rebuild, and copy the whole dist into images. Without dist/server the plugin answers 503 on /console/*.
  • basePath must equal the experiments.baseUrl baked into the bundle (/console by default), or register() throws. Any other mount needs experiments.baseUrl set in admin-spa/app.json and a rebuild from source; the published package ships only the /console build. Mounting at the site root (basePath: "/") is no longer supported.
  • Terreno 58 targets Expo SDK 58 (~58.0.14), React Native 0.88.0, and React 19.3.0. @terreno/ui peers react-native 0.88.0. Native catalog moves with the SDK: react-native-gesture-handler ~3.3.0, react-native-reanimated 4.7.1 + react-native-worklets 0.13.0, react-native-screens ~4.30.0, react-native-webview 14.0.1, @sentry/react-native ~8.28.0, @shopify/flash-list 2.3.2, @shopify/react-native-skia 2.14.0. Rebuild dev clients and store binaries.
  • Expo Router 58: set export const unstable_settings = {initialRouteName} on the layout instead of passing initialRouteName to <Slot> / navigators. SidebarNavigation ignores the prop.
  • Expo Router 58 static rendering: a custom app/+html.tsx must render headNodes and bodyNodes from useServerDocumentContext() (expo-router/html), or exported pages ship without their JavaScript. example-frontend is updated.
  • React Native 0.88 generated types: type refs as ViewInstance, TextInstance, ScrollViewInstance, and TextInputInstance (Box.scrollRef, TextField.inputRef, Text ref).
  • create-terreno-app scaffolds Expo ~58.0.14, React Native 0.88.0, and React 19.3.0.
  • The Terreno 58 native module baseline lands in example-frontend and demo: @stripe/stripe-react-native 0.81.0, react-native-purchases and react-native-purchases-ui 10.12.2, expo-device, expo-crypto, expo-local-authentication, expo-system-ui, and expo-build-properties (Android Kotlin 2.2.21 and compileSdkVersion 37 pins). Rebuild every dev client and store binary. react-native-otp-verify is left out because it does not support the New Architecture. The demo has a hidden Native Modules page that shows each module's version and whether the running binary links it. See the 58.0.0 upgrade note.
  • TerrenoApp turns HTTP rate limiting on by default. Omitting rateLimit now mounts the limiter with the memory store (auth 20 / 15 min, api 600 / 15 min). Pass rateLimit: false to turn it off. On Cloud Run pass rateLimit: {trustProxy: 1} so unauthenticated traffic keys by client IP. See the 58.0.0 upgrade note.
  • @terreno/admin-frontend no longer takes an RTK api. The api prop is removed from every admin component (AdminProvider, AdminShellLayout, AdminHome, AdminModelList, AdminModelTable, AdminModelForm, AdminScreenRouter, ConfigurationScreen, DocumentStorageBrowser, ConsentHistory, comms, jobs, org, consent, and announcement screens, and widget props), and admin hooks drop their api argument (useAdminConfig(apiBase), useAdminScripts(apiBase), useAdminRoles(apiBase), useConfigurationApi({basePath}), useDocumentStorageApi(basePath), useConsentHistory(baseUrl), useOrganizationsApi(basePath), useCommsDashboardApi(), useJobsDashboardApi(), and the useAiObservability*Api() hooks).
  • useAdminApi(api, routePath, modelName) is removed. Use useAdminModelApi(routePath, modelName), which keeps the same hook names and calls the same /admin/{routePath} URLs through the admin fetch client. AdminApi, EndpointBuilder, and admin injectEndpoints are gone; @reduxjs/toolkit and react-redux are no longer peers of admin-frontend.
  • AdminProvider is now the required auth binding for every admin request, including ObjectId and API-only model CRUD. Cookie SPAs pass credentials="same-origin"; embedded apps pass apiOrigin and getAuthHeaders. Product screens that reuse admin components wrap them in AdminProvider. See the 58.0.0 upgrade guide.
  • Removed the legacy RTK realtime path. Use sync on modelRouter with @terreno/syncdb for live collection updates. RealtimeApp, SyncApp, socket auth, sync:delta, and admin admin:model.changed events are unchanged. See the 58.0.0 upgrade note.
  • @terreno/api: modelRouter no longer accepts realtime (now a TypeScript error), and the change stream no longer emits the sync websocket event. Removed RealtimeConfig, RealtimeEvent, DocumentSubscription, QuerySubscription, registerRealtime, getRealtimeRegistry, findRegistryEntryByCollection, findRegistryEntryByRoutePath, updateRealtimeRegistryOptions, clearRealtimeRegistry, RealtimeRegistryEntry, the query-subscription store (addQuerySubscription, removeQuerySubscription, removeAllSocketQueries, getQuerySubscriptionsForCollection, computeQueryId, clearQueryStore), and MAX_MODEL_SUBSCRIPTIONS / MAX_DOCUMENT_SUBSCRIPTIONS / MAX_QUERY_SUBSCRIPTIONS. Sockets no longer handle subscribe:model, subscribe:document, or subscribe:query.
  • @terreno/rtk: removed realtimeList, realtimeDocument, setRealtimeSocket, getRealtimeSocket, useSyncConnection, and the RealtimeEvent type. The rest of @terreno/rtk (including useSocketConnection and useRealtimeDebug) is removed in the same release; see remove-rtk.md.
  • Removed @terreno/rtk and every Redux dependency (@reduxjs/toolkit, react-redux, redux-persist, @rtk-query/codegen-openapi). @terreno/rtk is not published for 58. @terreno/syncdb is the only frontend data, request, and session layer. Follow docs/how-to/migrate-rtk-to-syncdb.md, which maps every removed export to its replacement, and the 58.0.0 upgrade note.
  • @terreno/syncdb adds @terreno/syncdb/api (createApiClient, ApiError), request hooks in @terreno/syncdb/react (ApiClientProvider, useApiQuery, useLazyApiQuery, useApiMutation, useSocketEvent), @terreno/syncdb/config (baseUrl, baseWebsocketsUrl, appHeaders), @terreno/syncdb/auth (createBetterAuthClient, SessionProvider, useSession, jwtAuthAdapter, useJwtAuth, token-expiry helpers), @terreno/syncdb/flags (useFeatureFlags, useTerrenoFeatureFlags on the sync socket), @terreno/syncdb/app (useUpgradeCheck, hasPermission, canOpenAdminPage, installDevConsoleLogger), @terreno/syncdb/mcp (useMCPTools), and @terreno/syncdb/buildNumber.
  • terreno-syncdb-codegen --api-out generates typed hooks for every non-synced OpenAPI operation (same names as the RTK codegen), replacing @rtk-query/codegen-openapi. bun run sdk writes store/apiSdk.ts.
  • @terreno/ui ConsentNavigator, AnnouncementNavigator, useConsentForms, useSubmitConsent, useAnnouncements, and useAcknowledgeAnnouncement take a request client instead of an RTK api.
  • GptHistory (gpt/histories) is a synced collection and keeps its ObjectId _id (no migration). McpServiceToken (mcp/service-tokens, read-only) is a synced collection with String ids; run mcpServiceTokenStringIdsMigration (@terreno/api) before deploying 58 frontends.
  • create-terreno-app, the terreno_bootstrap prompt, and the terreno_generate_screen tool scaffold apps without Redux or @terreno/rtk. The terreno-mcp-local get_rtk_state tool, the MCP resource terreno://docs/rtk, and terreno state --slice rtk are removed; use get_syncdb_state and terreno state.
  • @terreno/syncdb: useMCPTools (and MCPToolInfo, UseMCPToolsOptions, UseMCPToolsResult) moved from @terreno/syncdb/app to the new @terreno/syncdb/mcp entry point. Change import {useMCPTools} from "@terreno/syncdb/app" to import {useMCPTools} from "@terreno/syncdb/mcp". The hook imports the optional @modelcontextprotocol/client peer at the top level, so exporting it from /app broke every app that imported /app without that package installed, including apps scaffolded by create-terreno-app, which import installDevConsoleLogger from /app.

Added

  • AdminSpaServeApp options internalOrigin (where server renders fetch API data, default http://127.0.0.1:${PORT ?? 4000}) and ssrApiPrefixes (API paths a render may fetch). The plugin also serves Expo's root /_expo/loaders/*, with Cache-Control: no-store, private on pages and loader data.
  • @terreno/syncdb: SessionProvider / session store initialSession, and the request client's primeQuery(args, data), to start from data a server render already read.
  • @terreno/admin-frontend: AdminRpcSeed and adminRpcSeedKey seed useAdminRpcQuery with server-fetched bodies; buildAdminReadUrl, buildAdminListQueryParams, buildAdminApiListQueryRequest and homeWidgetUrls build the exact URLs the screens request.
  • DataTable columns size themselves when width is omitted. Each auto column starts at the wider of its header and its content (sampled from at most 50 rows, measured with a canvas on web and estimated on native), clamped to 80–360px, and auto columns grow to fill the table's container. Columns that set width keep it. DataTableColumn.width is now optional.
  • @terreno/syncdb createSyncDb({idFormats}) mints 24-hex ObjectIds for a collection set to "objectId", so a model that keeps Mongoose's default ObjectId _id can sync without migrating its ids. mutate() throws on an explicit non-hex id for such a collection. generateObjectId and the SyncIdFormat type are exported.
  • Sync validation nacks carry an...
Read more

58.0.0-beta.4

58.0.0-beta.4 Pre-release
Pre-release

Choose a tag to compare

@joshgachnang joshgachnang released this 05 Nov 06:34
Immutable release. Only release title and notes can be modified.
58.0.0-beta.4
64ee8d1

Upgrade note: mcp-server/src/docs/upgrades/58.0.0-beta.4.md.

Breaking

  • @terreno/admin-spa now server-renders every admin page in the backend's Express process, behind an access gate that runs before anything renders. The first HTML holds the login form, the shell and the screen's data. Upgrade steps: Upgrade to the server-rendered admin SPA.
  • AdminSpaServeApp's distDir (and example-backend's ADMIN_SPA_DIST_DIR) now names the export root, which holds client/ and server/. build:web no longer writes dist/index.html. Rebuild, and copy the whole dist into images. Without dist/server the plugin answers 503 on /console/*.
  • basePath must equal the experiments.baseUrl baked into the bundle (/console by default), or register() throws. Any other mount needs experiments.baseUrl set in admin-spa/app.json and a rebuild from source; the published package ships only the /console build. Mounting at the site root (basePath: "/") is no longer supported.
  • Terreno 58 targets Expo SDK 58 (~58.0.14), React Native 0.88.0, and React 19.3.0. @terreno/ui peers react-native 0.88.0. Native catalog moves with the SDK: react-native-gesture-handler ~3.3.0, react-native-reanimated 4.7.1 + react-native-worklets 0.13.0, react-native-screens ~4.30.0, react-native-webview 14.0.1, @sentry/react-native ~8.28.0, @shopify/flash-list 2.3.2, @shopify/react-native-skia 2.14.0. Rebuild dev clients and store binaries.
  • Expo Router 58: set export const unstable_settings = {initialRouteName} on the layout instead of passing initialRouteName to <Slot> / navigators. SidebarNavigation ignores the prop.
  • Expo Router 58 static rendering: a custom app/+html.tsx must render headNodes and bodyNodes from useServerDocumentContext() (expo-router/html), or exported pages ship without their JavaScript. example-frontend is updated.
  • React Native 0.88 generated types: type refs as ViewInstance, TextInstance, ScrollViewInstance, and TextInputInstance (Box.scrollRef, TextField.inputRef, Text ref).
  • create-terreno-app scaffolds Expo ~58.0.14, React Native 0.88.0, and React 19.3.0.
  • The Terreno 58 native module baseline lands in example-frontend and demo: @stripe/stripe-react-native 0.81.0, react-native-purchases and react-native-purchases-ui 10.12.2, expo-device, expo-crypto, expo-local-authentication, expo-system-ui, and expo-build-properties (Android Kotlin 2.2.21 and compileSdkVersion 37 pins). Rebuild every dev client and store binary. react-native-otp-verify is left out because it does not support the New Architecture. The demo has a hidden Native Modules page that shows each module's version and whether the running binary links it. See the 58.0.0 upgrade note.
  • TerrenoApp turns HTTP rate limiting on by default. Omitting rateLimit now mounts the limiter with the memory store (auth 20 / 15 min, api 600 / 15 min). Pass rateLimit: false to turn it off. On Cloud Run pass rateLimit: {trustProxy: 1} so unauthenticated traffic keys by client IP. See the 58.0.0 upgrade note.
  • @terreno/admin-frontend no longer takes an RTK api. The api prop is removed from every admin component (AdminProvider, AdminShellLayout, AdminHome, AdminModelList, AdminModelTable, AdminModelForm, AdminScreenRouter, ConfigurationScreen, DocumentStorageBrowser, ConsentHistory, comms, jobs, org, consent, and announcement screens, and widget props), and admin hooks drop their api argument (useAdminConfig(apiBase), useAdminScripts(apiBase), useAdminRoles(apiBase), useConfigurationApi({basePath}), useDocumentStorageApi(basePath), useConsentHistory(baseUrl), useOrganizationsApi(basePath), useCommsDashboardApi(), useJobsDashboardApi(), and the useAiObservability*Api() hooks).
  • useAdminApi(api, routePath, modelName) is removed. Use useAdminModelApi(routePath, modelName), which keeps the same hook names and calls the same /admin/{routePath} URLs through the admin fetch client. AdminApi, EndpointBuilder, and admin injectEndpoints are gone; @reduxjs/toolkit and react-redux are no longer peers of admin-frontend.
  • AdminProvider is now the required auth binding for every admin request, including ObjectId and API-only model CRUD. Cookie SPAs pass credentials="same-origin"; embedded apps pass apiOrigin and getAuthHeaders. Product screens that reuse admin components wrap them in AdminProvider. See the 58.0.0 upgrade guide.
  • Removed the legacy RTK realtime path. Use sync on modelRouter with @terreno/syncdb for live collection updates. RealtimeApp, SyncApp, socket auth, sync:delta, and admin admin:model.changed events are unchanged. See the 58.0.0 upgrade note.
  • @terreno/api: modelRouter no longer accepts realtime (now a TypeScript error), and the change stream no longer emits the sync websocket event. Removed RealtimeConfig, RealtimeEvent, DocumentSubscription, QuerySubscription, registerRealtime, getRealtimeRegistry, findRegistryEntryByCollection, findRegistryEntryByRoutePath, updateRealtimeRegistryOptions, clearRealtimeRegistry, RealtimeRegistryEntry, the query-subscription store (addQuerySubscription, removeQuerySubscription, removeAllSocketQueries, getQuerySubscriptionsForCollection, computeQueryId, clearQueryStore), and MAX_MODEL_SUBSCRIPTIONS / MAX_DOCUMENT_SUBSCRIPTIONS / MAX_QUERY_SUBSCRIPTIONS. Sockets no longer handle subscribe:model, subscribe:document, or subscribe:query.
  • @terreno/rtk: removed realtimeList, realtimeDocument, setRealtimeSocket, getRealtimeSocket, useSyncConnection, and the RealtimeEvent type. The rest of @terreno/rtk (including useSocketConnection and useRealtimeDebug) is removed in the same release; see remove-rtk.md.
  • Removed @terreno/rtk and every Redux dependency (@reduxjs/toolkit, react-redux, redux-persist, @rtk-query/codegen-openapi). @terreno/rtk is not published for 58. @terreno/syncdb is the only frontend data, request, and session layer. Follow docs/how-to/migrate-rtk-to-syncdb.md, which maps every removed export to its replacement, and the 58.0.0 upgrade note.
  • @terreno/syncdb adds @terreno/syncdb/api (createApiClient, ApiError), request hooks in @terreno/syncdb/react (ApiClientProvider, useApiQuery, useLazyApiQuery, useApiMutation, useSocketEvent), @terreno/syncdb/config (baseUrl, baseWebsocketsUrl, appHeaders), @terreno/syncdb/auth (createBetterAuthClient, SessionProvider, useSession, jwtAuthAdapter, useJwtAuth, token-expiry helpers), @terreno/syncdb/flags (useFeatureFlags, useTerrenoFeatureFlags on the sync socket), @terreno/syncdb/app (useUpgradeCheck, hasPermission, canOpenAdminPage, installDevConsoleLogger), @terreno/syncdb/mcp (useMCPTools), and @terreno/syncdb/buildNumber.
  • terreno-syncdb-codegen --api-out generates typed hooks for every non-synced OpenAPI operation (same names as the RTK codegen), replacing @rtk-query/codegen-openapi. bun run sdk writes store/apiSdk.ts.
  • @terreno/ui ConsentNavigator, AnnouncementNavigator, useConsentForms, useSubmitConsent, useAnnouncements, and useAcknowledgeAnnouncement take a request client instead of an RTK api.
  • GptHistory (gpt/histories) is a synced collection and keeps its ObjectId _id (no migration). McpServiceToken (mcp/service-tokens, read-only) is a synced collection with String ids; run mcpServiceTokenStringIdsMigration (@terreno/api) before deploying 58 frontends.
  • create-terreno-app, the terreno_bootstrap prompt, and the terreno_generate_screen tool scaffold apps without Redux or @terreno/rtk. The terreno-mcp-local get_rtk_state tool, the MCP resource terreno://docs/rtk, and terreno state --slice rtk are removed; use get_syncdb_state and terreno state.
  • @terreno/syncdb: useMCPTools (and MCPToolInfo, UseMCPToolsOptions, UseMCPToolsResult) moved from @terreno/syncdb/app to the new @terreno/syncdb/mcp entry point. Change import {useMCPTools} from "@terreno/syncdb/app" to import {useMCPTools} from "@terreno/syncdb/mcp". The hook imports the optional @modelcontextprotocol/client peer at the top level, so exporting it from /app broke every app that imported /app without that package installed, including apps scaffolded by create-terreno-app, which import installDevConsoleLogger from /app.

Added

  • AdminSpaServeApp options internalOrigin (where server renders fetch API data, default http://127.0.0.1:${PORT ?? 4000}) and ssrApiPrefixes (API paths a render may fetch). The plugin also serves Expo's root /_expo/loaders/*, with Cache-Control: no-store, private on pages and loader data.
  • @terreno/syncdb: SessionProvider / session store initialSession, and the request client's primeQuery(args, data), to start from data a server render already read.
  • @terreno/admin-frontend: AdminRpcSeed and adminRpcSeedKey seed useAdminRpcQuery with server-fetched bodies; buildAdminReadUrl, buildAdminListQueryParams, buildAdminApiListQueryRequest and homeWidgetUrls build the exact URLs the screens request.
  • DataTable columns size themselves when width is omitted. Each auto column starts at the wider of its header and its content (sampled from at most 50 rows, measured with a canvas on web and estimated on native), clamped to 80–360px, and auto columns grow to fill the table's container. Columns that set width keep it. DataTableColumn.width is now optional.
  • @terreno/syncdb createSyncDb({idFormats}) mints 24-hex ObjectIds for a collection set to "objectId", so a model that keeps Mongoose's default ObjectId _id can sync without migrating its ids. mutate() throws on an explicit non-hex id for s...
Read more

57.22.0

Choose a tag to compare

@joshgachnang joshgachnang released this 04 Nov 00:54
Immutable release. Only release title and notes can be modified.
cd3cd80

Upgrade note: mcp-server/src/docs/upgrades/57.22.0.md.

Breaking

  • @terreno/ai no longer integrates with Langfuse. The built-in observability prompt registry, traces, and review queue (ObservabilityApp with createLocalObservabilityPlugin()) replace it. Removed exports: LangfuseApp, LangfuseCache, getCached, setCached, invalidateCache, initLangfuseClient, getLangfuseClient, isLangfuseInitialized, shutdownLangfuseClient, compilePrompt, createPrompt, getPrompt, invalidatePromptCache, initTracing, shutdownTracing, createTelemetryConfig, preparePromptForAI, and the types ChatMessage, GetPromptOptions, LangfuseAppOptions, LangfuseCachedPrompt, PaginatedResult, PreparePromptResult, PromptListItem, ScoreSubmission, ScoringFunction, TelemetrySettings, TraceListItem. The @terreno/ai/langfuseApp and @terreno/ai/langfuseClient subpath exports are gone, along with the @langfuse/client, @langfuse/otel, and @opentelemetry/* dependencies of @terreno/ai.
  • addGptRoutes drops langfuseSystemPromptName; use systemPromptName (a registry prompt) instead. Chat turns no longer set experimental_telemetry.
  • ControlPrimary is now only "local".
  • The example backend no longer reads LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, LANGFUSE_BASE_URL, LANGFUSE_ORGANIZATION, LANGFUSE_PROJECT, or LANGFUSE_PROJECT_ID. Deploys (.github/workflows/cd.yml, scripts/ci/gcp-deploy.sh) no longer mount the Langfuse secrets, and infra/flourish/main.tf drops the backend_secret_langfuse_secret_key and backend_secret_langfuse_public_key modules, so the next terraform apply deletes those two Secret Manager secrets. Deploy a revision without the mounts before applying.

Added

  • addGptRoutes accepts systemPromptName and systemPromptLabel. A chat turn prepends that observability registry prompt to the system prompt and records its version on the trace.
  • The example chat reads chat-assistant and the generate_joke tool reads joke-generator from the observability prompt registry.
  • bun run backend:seed fills every AI Observability screen: labelled prompt versions for example-summarize, joke-generator, and chat-assistant, golden datasets, finished experiments, traces with scores, and review items in every status. Run it on an existing database with the seedAiObservabilityDemo admin script.
  • Review batches: pick a human question set and press Grab 10 recent traces to give reviewers a fixed set of inputs and outputs (POST /ai/observability/review/batches).
  • The review item screen shows one input, one output, and every question as Yes / No rows. On web, Y / N answer the highlighted question, Enter submits and moves to the next batch item, and S skips. Evaluator dimensions accept a reviewer question.
  • Run any LLM judge over a batch and see overall and per-question agreement with the human answers, plus a list of disagreements (POST /ai/observability/review/batches/:id/judgeRuns).
  • The AI observability seed adds the summary-review-questions question set, two judges for it, and a 10-item batch with 8 answers where one judge agrees 97% and the other 78%.
  • Observability registry prompts can reference other prompts with {{> base-rules}}, {{> base-rules label=staging}}, or {{> base-rules version=3}} (default label production). Shared instructions live in one prompt; PromptRegistry.get, the playground, experiments, and judges use the resolved text.
  • Every reference must resolve when it is saved. Creating a prompt, saving a version, and moving a label return 400 Invalid prompt reference for a malformed tag, an unknown prompt or version, or a label the referenced prompt does not have yet, 400 Prompt reference cycle when the change would make prompts include each other, and 400 Prompt references nested too deeply when it would nest the prompt, or any prompt that includes it, more than 5 levels.
  • Traces stay named after the called prompt. ObsTrace.prompts lists it first, then each shared prompt version it pulled in, marked with includedBy. PromptVersionRef.includes and harness prompt refs carry the same list.

Fixed

  • Review queue: Y and N answer the highlighted question when a Yes/No segment is focused. What the AI was given and What the AI wrote are headings above the field cards.
  • Review batches: Save batch sits on the New batch card. Search and More filters share a baseline.
  • Prompt hub: description, folder, and tags sit on the Versions screen with the editor. System and template fields explain what to write.
  • Evaluator detail loads the judge prompt outputSchema (so helpfulness no longer reports a missing dimension) and experiment rows open that experiment.

Full Changelog: 57.21.0...57.22.0

58.0.0-beta.3

58.0.0-beta.3 Pre-release
Pre-release

Choose a tag to compare

@joshgachnang joshgachnang released this 03 Nov 20:03
Immutable release. Only release title and notes can be modified.

Upgrade note: mcp-server/src/docs/upgrades/58.0.0-beta.3.md.

Breaking

  • Terreno 58 targets Expo SDK 58 (~58.0.14), React Native 0.88.0, and React 19.3.0. @terreno/ui peers react-native 0.88.0. Native catalog moves with the SDK: react-native-gesture-handler ~3.3.0, react-native-reanimated 4.7.1 + react-native-worklets 0.13.0, react-native-screens ~4.30.0, react-native-webview 14.0.1, @sentry/react-native ~8.28.0, @shopify/flash-list 2.3.2, @shopify/react-native-skia 2.14.0. Rebuild dev clients and store binaries.
  • Expo Router 58: set export const unstable_settings = {initialRouteName} on the layout instead of passing initialRouteName to <Slot> / navigators. SidebarNavigation ignores the prop.
  • Expo Router 58 static rendering: a custom app/+html.tsx must render headNodes and bodyNodes from useServerDocumentContext() (expo-router/html), or exported pages ship without their JavaScript. example-frontend is updated.
  • React Native 0.88 generated types: type refs as ViewInstance, TextInstance, ScrollViewInstance, and TextInputInstance (Box.scrollRef, TextField.inputRef, Text ref).
  • create-terreno-app scaffolds Expo ~58.0.14, React Native 0.88.0, and React 19.3.0.
  • The Terreno 58 native module baseline lands in example-frontend and demo: @stripe/stripe-react-native 0.81.0, react-native-purchases and react-native-purchases-ui 10.12.2, expo-device, expo-crypto, expo-local-authentication, expo-system-ui, and expo-build-properties (Android Kotlin 2.2.21 and compileSdkVersion 37 pins). Rebuild every dev client and store binary. react-native-otp-verify is left out because it does not support the New Architecture. The demo has a hidden Native Modules page that shows each module's version and whether the running binary links it. See the 58.0.0 upgrade note.
  • TerrenoApp turns HTTP rate limiting on by default. Omitting rateLimit now mounts the limiter with the memory store (auth 20 / 15 min, api 600 / 15 min). Pass rateLimit: false to turn it off. On Cloud Run pass rateLimit: {trustProxy: 1} so unauthenticated traffic keys by client IP. See the 58.0.0 upgrade note.
  • @terreno/admin-frontend no longer takes an RTK api. The api prop is removed from every admin component (AdminProvider, AdminShellLayout, AdminHome, AdminModelList, AdminModelTable, AdminModelForm, AdminScreenRouter, ConfigurationScreen, DocumentStorageBrowser, ConsentHistory, comms, jobs, org, consent, and announcement screens, and widget props), and admin hooks drop their api argument (useAdminConfig(apiBase), useAdminScripts(apiBase), useAdminRoles(apiBase), useConfigurationApi({basePath}), useDocumentStorageApi(basePath), useConsentHistory(baseUrl), useOrganizationsApi(basePath), useCommsDashboardApi(), useJobsDashboardApi(), and the useAiObservability*Api() hooks).
  • useAdminApi(api, routePath, modelName) is removed. Use useAdminModelApi(routePath, modelName), which keeps the same hook names and calls the same /admin/{routePath} URLs through the admin fetch client. AdminApi, EndpointBuilder, and admin injectEndpoints are gone; @reduxjs/toolkit and react-redux are no longer peers of admin-frontend.
  • AdminProvider is now the required auth binding for every admin request, including ObjectId and API-only model CRUD. Cookie SPAs pass credentials="same-origin"; embedded apps pass apiOrigin and getAuthHeaders. Product screens that reuse admin components wrap them in AdminProvider. See the 58.0.0 upgrade guide.
  • Removed the legacy RTK realtime path. Use sync on modelRouter with @terreno/syncdb for live collection updates. RealtimeApp, SyncApp, socket auth, sync:delta, and admin admin:model.changed events are unchanged. See the 58.0.0 upgrade note.
  • @terreno/api: modelRouter no longer accepts realtime (now a TypeScript error), and the change stream no longer emits the sync websocket event. Removed RealtimeConfig, RealtimeEvent, DocumentSubscription, QuerySubscription, registerRealtime, getRealtimeRegistry, findRegistryEntryByCollection, findRegistryEntryByRoutePath, updateRealtimeRegistryOptions, clearRealtimeRegistry, RealtimeRegistryEntry, the query-subscription store (addQuerySubscription, removeQuerySubscription, removeAllSocketQueries, getQuerySubscriptionsForCollection, computeQueryId, clearQueryStore), and MAX_MODEL_SUBSCRIPTIONS / MAX_DOCUMENT_SUBSCRIPTIONS / MAX_QUERY_SUBSCRIPTIONS. Sockets no longer handle subscribe:model, subscribe:document, or subscribe:query.
  • @terreno/rtk: removed realtimeList, realtimeDocument, setRealtimeSocket, getRealtimeSocket, useSyncConnection, and the RealtimeEvent type. The rest of @terreno/rtk (including useSocketConnection and useRealtimeDebug) is removed in the same release; see remove-rtk.md.
  • Removed @terreno/rtk and every Redux dependency (@reduxjs/toolkit, react-redux, redux-persist, @rtk-query/codegen-openapi). @terreno/rtk is not published for 58. @terreno/syncdb is the only frontend data, request, and session layer. Follow docs/how-to/migrate-rtk-to-syncdb.md, which maps every removed export to its replacement, and the 58.0.0 upgrade note.
  • Apps upgrading from @terreno/rtk must install expo-constants and expo-network themselves (rtk depended on them; @terreno/syncdb lists them as optional peers), plus the optional peers for the features they use: better-auth, @better-auth/expo, @better-auth/passkey, @openfeature/web-sdk, @openfeature/react-sdk, @modelcontextprotocol/client. See the upgrade note.
  • @terreno/syncdb adds @terreno/syncdb/api (createApiClient, ApiError), request hooks in @terreno/syncdb/react (ApiClientProvider, useApiQuery, useLazyApiQuery, useApiMutation, useSocketEvent), @terreno/syncdb/config (baseUrl, baseWebsocketsUrl, appHeaders), @terreno/syncdb/auth (createBetterAuthClient, SessionProvider, useSession, jwtAuthAdapter, useJwtAuth, token-expiry helpers), @terreno/syncdb/flags (useFeatureFlags, useTerrenoFeatureFlags on the sync socket), @terreno/syncdb/app (useUpgradeCheck, hasPermission, canOpenAdminPage, installDevConsoleLogger, useMCPTools), and @terreno/syncdb/buildNumber.
  • terreno-syncdb-codegen --api-out generates typed hooks for every non-synced OpenAPI operation (same names as the RTK codegen), replacing @rtk-query/codegen-openapi. bun run sdk writes store/apiSdk.ts.
  • @terreno/ui ConsentNavigator, AnnouncementNavigator, useConsentForms, useSubmitConsent, useAnnouncements, and useAcknowledgeAnnouncement take a request client instead of an RTK api.
  • GptHistory (gpt/histories) is a synced collection and keeps its ObjectId _id (no migration). McpServiceToken (mcp/service-tokens, read-only) is a synced collection with String ids; run mcpServiceTokenStringIdsMigration (@terreno/api) before deploying 58 frontends.
  • create-terreno-app, the terreno_bootstrap prompt, and the terreno_generate_screen tool scaffold apps without Redux or @terreno/rtk. The terreno-mcp-local get_rtk_state tool, the MCP resource terreno://docs/rtk, and terreno state --slice rtk are removed; use get_syncdb_state and terreno state.

Added

  • DataTable columns size themselves when width is omitted. Each auto column starts at the wider of its header and its content (sampled from at most 50 rows, measured with a canvas on web and estimated on native), clamped to 80–360px, and auto columns grow to fill the table's container. Columns that set width keep it. DataTableColumn.width is now optional.
  • @terreno/syncdb createSyncDb({idFormats}) mints 24-hex ObjectIds for a collection set to "objectId", so a model that keeps Mongoose's default ObjectId _id can sync without migrating its ids. mutate() throws on an explicit non-hex id for such a collection. generateObjectId and the SyncIdFormat type are exported.
  • Sync validation nacks carry an optional reason: invalid_id when an ObjectId-keyed collection gets a non-hex id (rejected before the mutation is claimed), and id_collision when a create names an _id another document holds. A collision never touches the existing document and its message never names the holder. The ledger records the reason (SyncMutation.nackReason) so a redelivery replays it.
  • GET /sync/entities leaves out non-hex ids for an ObjectId-keyed model instead of answering 400, so a rejected create queued for repair cannot fail the rest of the repair batch.

Changed

  • The repository's agent rules now generate with rulesync 17 (up from 9). The root rule .rulesync/rules/00-root.md now generates AGENTS.md, which Devin and other AGENTS.md readers load, in place of .devin/rules/00-root.md. Never edit AGENTS.md by hand: edit the root rule and run bun run rules. The examples that existed only in the old hand-edited AGENTS.md (syncdb and RTK SDK usage) moved into the root rule, so CLAUDE.md, the Cursor root rule, and Copilot instructions get them too. Links in the root rule now resolve from the repository root. Generated Copilot hooks use the portable command field. Generated Copilot subagents no longer list agent/runSubagent as their only tool, so they get every default tool. Generated skills carry their license, disable-model-invocation, and Devin triggers frontmatter.
  • @terreno/syncdb/auth SessionProvider: logout() no longer clears the session before the server answers. The session stays in the state until authClient.signOut() finishes (signOutTimeoutMs, default 10 seconds), and then it is cleared. Meanwhile the new isSigningOut state (useSession().isSigningOut) is true; isLoading is left alone, so a navigator gated on it keeps its scre...
Read more