@terreno/mcp 57.0.0-beta.1 → 57.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/dist/bootstrap.d.ts +1 -1
  2. package/dist/bootstrap.d.ts.map +1 -1
  3. package/dist/bootstrap.js +381 -191
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
  6. package/dist/docs/resources/overview.md +6 -1
  7. package/dist/docs/resources/rtk.md +3 -1
  8. package/dist/docs/resources/syncdb.md +43 -0
  9. package/dist/docs/upgrades/56.0.0-beta.2.md +34 -0
  10. package/dist/docs/upgrades/57.0.0.md +49 -0
  11. package/dist/docs/upgrades/57.1.0.md +126 -0
  12. package/dist/docs/versioned/next/README.md +15 -3
  13. package/dist/docs/versioned/next/explanation/README.md +3 -0
  14. package/dist/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
  15. package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
  16. package/dist/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
  17. package/dist/docs/versioned/next/explanation/authentication.md +51 -58
  18. package/dist/docs/versioned/next/explanation/local-first-data.md +52 -0
  19. package/dist/docs/versioned/next/explanation/loop-engineering.md +117 -0
  20. package/dist/docs/versioned/next/explanation/repository-settings.md +8 -0
  21. package/dist/docs/versioned/next/explanation/roadmap-process.md +22 -9
  22. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
  23. package/dist/docs/versioned/next/how-to/README.md +3 -0
  24. package/dist/docs/versioned/next/how-to/admin-add-model.md +41 -0
  25. package/dist/docs/versioned/next/how-to/admin-custom-home.md +31 -0
  26. package/dist/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
  27. package/dist/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
  28. package/dist/docs/versioned/next/how-to/circleci.md +173 -0
  29. package/dist/docs/versioned/next/how-to/configure-better-auth.md +13 -10
  30. package/dist/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
  31. package/dist/docs/versioned/next/how-to/install-agent-skills.md +46 -0
  32. package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
  33. package/dist/docs/versioned/next/how-to/websocket-integration.md +2 -1
  34. package/dist/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
  35. package/dist/docs/versioned/next/implementationPlans/README.md +31 -17
  36. package/dist/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
  37. package/dist/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
  38. package/dist/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
  39. package/dist/docs/versioned/next/implementationPlans/admin-only.md +3 -1
  40. package/dist/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
  41. package/dist/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
  42. package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
  43. package/dist/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
  44. package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
  45. package/dist/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
  46. package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
  47. package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
  48. package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
  49. package/dist/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
  50. package/dist/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
  51. package/dist/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
  52. package/dist/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
  53. package/dist/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
  54. package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
  55. package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
  56. package/dist/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
  57. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
  58. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
  59. package/dist/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
  60. package/dist/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
  61. package/dist/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
  62. package/dist/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
  63. package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
  64. package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
  65. package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
  66. package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
  67. package/dist/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
  68. package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
  69. package/dist/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
  70. package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
  71. package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
  72. package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
  73. package/dist/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
  74. package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
  75. package/dist/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
  76. package/dist/docs/versioned/next/reference/README.md +6 -1
  77. package/dist/docs/versioned/next/reference/admin-config.md +51 -0
  78. package/dist/docs/versioned/next/reference/ai.md +15 -1
  79. package/dist/docs/versioned/next/reference/api.md +18 -0
  80. package/dist/docs/versioned/next/reference/comms.md +88 -7
  81. package/dist/docs/versioned/next/reference/environment-variables.md +9 -1
  82. package/dist/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
  83. package/dist/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
  84. package/dist/docs/versioned/next/reference/mcp-server.md +7 -0
  85. package/dist/docs/versioned/next/reference/syncdb.md +30 -3
  86. package/dist/docs/versioned/next/tasks/README.md +21 -10
  87. package/dist/docs/versioned/next/tasks/admin-improvements.md +189 -353
  88. package/dist/docs/versioned/next/tasks/admin-only.md +2 -0
  89. package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
  90. package/dist/docs/versioned/next/tasks/comms-abstraction.md +30 -24
  91. package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
  92. package/dist/docs/versioned/next/tasks/consent-forms.md +2 -0
  93. package/dist/docs/versioned/next/tasks/feature-flags.md +2 -0
  94. package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
  95. package/dist/docs/versioned/next/tasks/model-router-actions.md +2 -0
  96. package/dist/docs/versioned/next/tasks/model-router-mcp.md +27 -27
  97. package/dist/docs/versioned/next/tasks/offline-mode.md +2 -0
  98. package/dist/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
  99. package/dist/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
  100. package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
  101. package/dist/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
  102. package/dist/docs/versioned/next/tasks/upgrade-banner.md +2 -0
  103. package/dist/index.js +24 -55
  104. package/dist/index.js.map +1 -1
  105. package/dist/local/localServer.d.ts.map +1 -1
  106. package/dist/local/localServer.js +9 -8
  107. package/dist/local/localServer.js.map +1 -1
  108. package/dist/local/localTools.d.ts +1 -1
  109. package/dist/local/localTools.d.ts.map +1 -1
  110. package/dist/prompts.d.ts.map +1 -1
  111. package/dist/prompts.js +44 -45
  112. package/dist/prompts.js.map +1 -1
  113. package/dist/resources.d.ts.map +1 -1
  114. package/dist/resources.js +9 -2
  115. package/dist/resources.js.map +1 -1
  116. package/dist/tools.d.ts +1 -1
  117. package/dist/tools.d.ts.map +1 -1
  118. package/dist/tools.js +4 -2
  119. package/dist/tools.js.map +1 -1
  120. package/package.json +7 -3
  121. package/src/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
  122. package/src/docs/resources/overview.md +6 -1
  123. package/src/docs/resources/rtk.md +3 -1
  124. package/src/docs/resources/syncdb.md +43 -0
  125. package/src/docs/upgrades/56.0.0-beta.2.md +34 -0
  126. package/src/docs/upgrades/57.0.0.md +49 -0
  127. package/src/docs/upgrades/57.1.0.md +126 -0
  128. package/src/docs/versioned/next/README.md +15 -3
  129. package/src/docs/versioned/next/explanation/README.md +3 -0
  130. package/src/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
  131. package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
  132. package/src/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
  133. package/src/docs/versioned/next/explanation/authentication.md +51 -58
  134. package/src/docs/versioned/next/explanation/local-first-data.md +52 -0
  135. package/src/docs/versioned/next/explanation/loop-engineering.md +117 -0
  136. package/src/docs/versioned/next/explanation/repository-settings.md +8 -0
  137. package/src/docs/versioned/next/explanation/roadmap-process.md +22 -9
  138. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
  139. package/src/docs/versioned/next/how-to/README.md +3 -0
  140. package/src/docs/versioned/next/how-to/admin-add-model.md +41 -0
  141. package/src/docs/versioned/next/how-to/admin-custom-home.md +31 -0
  142. package/src/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
  143. package/src/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
  144. package/src/docs/versioned/next/how-to/circleci.md +173 -0
  145. package/src/docs/versioned/next/how-to/configure-better-auth.md +13 -10
  146. package/src/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
  147. package/src/docs/versioned/next/how-to/install-agent-skills.md +46 -0
  148. package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
  149. package/src/docs/versioned/next/how-to/websocket-integration.md +2 -1
  150. package/src/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
  151. package/src/docs/versioned/next/implementationPlans/README.md +31 -17
  152. package/src/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
  153. package/src/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
  154. package/src/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
  155. package/src/docs/versioned/next/implementationPlans/admin-only.md +3 -1
  156. package/src/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
  157. package/src/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
  158. package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
  159. package/src/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
  160. package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
  161. package/src/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
  162. package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
  163. package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
  164. package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
  165. package/src/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
  166. package/src/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
  167. package/src/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
  168. package/src/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
  169. package/src/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
  170. package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
  171. package/src/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
  172. package/src/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
  173. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
  174. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
  175. package/src/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
  176. package/src/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
  177. package/src/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
  178. package/src/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
  179. package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
  180. package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
  181. package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
  182. package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
  183. package/src/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
  184. package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
  185. package/src/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
  186. package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
  187. package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
  188. package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
  189. package/src/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
  190. package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
  191. package/src/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
  192. package/src/docs/versioned/next/reference/README.md +6 -1
  193. package/src/docs/versioned/next/reference/admin-config.md +51 -0
  194. package/src/docs/versioned/next/reference/ai.md +15 -1
  195. package/src/docs/versioned/next/reference/api.md +18 -0
  196. package/src/docs/versioned/next/reference/comms.md +88 -7
  197. package/src/docs/versioned/next/reference/environment-variables.md +9 -1
  198. package/src/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
  199. package/src/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
  200. package/src/docs/versioned/next/reference/mcp-server.md +7 -0
  201. package/src/docs/versioned/next/reference/syncdb.md +30 -3
  202. package/src/docs/versioned/next/tasks/README.md +21 -10
  203. package/src/docs/versioned/next/tasks/admin-improvements.md +189 -353
  204. package/src/docs/versioned/next/tasks/admin-only.md +2 -0
  205. package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
  206. package/src/docs/versioned/next/tasks/comms-abstraction.md +30 -24
  207. package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
  208. package/src/docs/versioned/next/tasks/consent-forms.md +2 -0
  209. package/src/docs/versioned/next/tasks/feature-flags.md +2 -0
  210. package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
  211. package/src/docs/versioned/next/tasks/model-router-actions.md +2 -0
  212. package/src/docs/versioned/next/tasks/model-router-mcp.md +27 -27
  213. package/src/docs/versioned/next/tasks/offline-mode.md +2 -0
  214. package/src/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
  215. package/src/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
  216. package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
  217. package/src/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
  218. package/src/docs/versioned/next/tasks/upgrade-banner.md +2 -0
  219. package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
  220. package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
  221. package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
  222. package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
@@ -1,30 +1,59 @@
1
1
  # Authentication Architecture
2
2
 
3
- Understanding how authentication works in @terreno/api — from JWT tokens to OAuth strategies to automatic token refresh.
3
+ Understanding how authentication works in @terreno/api — Better Auth sessions for new apps, with JWT/Passport documented for legacy consumers.
4
4
 
5
5
  ## Overview
6
6
 
7
- @terreno/api provides two complete authentication systems to choose from:
7
+ **Better Auth is the default path** for new Terreno apps. It provides session-based authentication with MongoDB storage, built-in social OAuth (Google, GitHub, Apple), and clean integration with `@terreno/syncdb` (`betterAuthAdapter`, `RealtimeApp` socket sessions).
8
8
 
9
- **JWT/Passport Authentication (Default)**
10
- - **JWT (JSON Web Tokens)** for stateless session management
11
- - **Passport.js** for authentication strategy management
12
- - **Multiple strategies**: Email/password, GitHub OAuth, Anonymous
13
- - **Automatic token refresh** to maintain long-lived sessions
14
- - **Token storage utilities** for secure frontend storage (via @terreno/rtk)
9
+ Set `AUTH_PROVIDER=better-auth` and register `BetterAuthApp` on the server. On the client, use `createBetterAuthClient` + `generateBetterAuthSlice` from `@terreno/rtk` for session Redux state, then wire `betterAuthAdapter` into `createSyncDb`.
15
10
 
16
- **Better Auth (Optional)**
17
- - **Session-based authentication** with MongoDB storage
18
- - **Built-in OAuth providers**: Google, GitHub, Apple
19
- - **Modern OAuth 2.0 flows** with PKCE
20
- - **Automatic session management** via cookies
21
- - **Redux integration** for session state (via @terreno/rtk)
11
+ **JWT/Passport (legacy)** remains supported through the current major release line for existing deployments. It uses stateless tokens, Passport strategies (email/password, GitHub OAuth, anonymous), and manual token refresh via `@terreno/rtk`. New projects should not start on JWT unless they have a specific requirement (custom token contracts, non-cookie clients, or a phased migration).
22
12
 
23
- Choose your authentication provider via `AUTH_PROVIDER` environment variable. Both systems can run in parallel, allowing gradual migration.
13
+ Both systems can run in parallel during migration (`AUTH_PROVIDER` selects the primary path; legacy JWT routes stay available).
14
+
15
+ ## When to choose which
16
+
17
+ | Choose Better Auth | Stay on JWT (legacy) |
18
+ |--------------------|----------------------|
19
+ | New app or greenfield screen | Existing production JWT deployment |
20
+ | Social login (Google, GitHub, Apple) | Custom JWT payload requirements |
21
+ | `@terreno/syncdb` local-first data | Non-cookie API clients only |
22
+ | Socket sessions via `RealtimeApp` | Gradual migration in progress |
23
+
24
+ **Setup:** [Configure Better Auth](../how-to/configure-better-auth.md). **Data layer:** migrate auth before or with syncdb — see [Migrate from RTK to syncdb](../how-to/migrate-rtk-to-syncdb.md) §7.
24
25
 
25
26
  ## Authentication Strategies
26
27
 
27
- ### Email/Password (Local Strategy)
28
+ ### Better Auth (default)
29
+
30
+ Modern session-based authentication with built-in social OAuth support.
31
+
32
+ **Flow:**
33
+ 1. Configure Better Auth with `AUTH_PROVIDER=better-auth` and register `BetterAuthApp`
34
+ 2. User chooses social provider (Google, GitHub, Apple) or email/password
35
+ 3. Backend redirects to OAuth provider or validates credentials
36
+ 4. Better Auth creates session in MongoDB
37
+ 5. Frontend receives session cookie (web) or bearer session token (native)
38
+ 6. Session middleware populates `req.user` for subsequent requests
39
+
40
+ **Key properties:**
41
+ - Session-based (cookies / bearer session) vs. stateless JWT
42
+ - Built-in OAuth providers with PKCE
43
+ - `betterAuthAdapter` for syncdb socket auth
44
+ - `sync:auth-expired` socket event when the session is no longer valid
45
+
46
+ **Endpoints (when enabled):**
47
+ - `POST /api/auth/signup/email` — Email/password signup
48
+ - `POST /api/auth/signin/email` — Email/password signin
49
+ - `GET /api/auth/signin/{provider}` — Initiate OAuth flow (google, github, apple)
50
+ - `GET /api/auth/callback/{provider}` — OAuth callback handler
51
+ - `POST /api/auth/signout` — Sign out session
52
+ - `GET /api/auth/session` — Get current session
53
+
54
+ **Learn more:** [Configure Better Auth](../how-to/configure-better-auth.md)
55
+
56
+ ### Email/Password (JWT / Local Strategy — legacy)
28
57
 
29
58
  Traditional username/password authentication using `passport-local-mongoose`.
30
59
 
@@ -39,7 +68,7 @@ Traditional username/password authentication using `passport-local-mongoose`.
39
68
  - `POST /auth/signup` — Create new user account
40
69
  - `POST /auth/login` — Authenticate and receive tokens
41
70
 
42
- ### GitHub OAuth Strategy
71
+ ### GitHub OAuth Strategy (JWT — legacy)
43
72
 
44
73
  OAuth 2.0 authentication with GitHub.
45
74
 
@@ -60,45 +89,7 @@ OAuth 2.0 authentication with GitHub.
60
89
 
61
90
  **Learn more:** [How to add GitHub OAuth](../how-to/add-github-oauth.md)
62
91
 
63
- ### Better Auth Strategy
64
-
65
- Modern session-based authentication with built-in social OAuth support. Better Auth runs **alongside** JWT/Passport authentication as an optional alternative.
66
-
67
- **Flow:**
68
- 1. Configure Better Auth with `AUTH_PROVIDER=better-auth`
69
- 2. User chooses social provider (Google, GitHub, Apple) or email/password
70
- 3. Backend redirects to OAuth provider or validates credentials
71
- 4. Better Auth creates session in MongoDB
72
- 5. Frontend receives session cookie
73
- 6. Session middleware populates `req.user` for subsequent requests
74
-
75
- **Key differences from JWT auth:**
76
- - Session-based (cookies) vs. stateless (tokens)
77
- - Built-in OAuth providers vs. custom Passport strategies
78
- - Automatic session management vs. manual token refresh
79
- - Modern OAuth 2.0 flows with PKCE
80
-
81
- **Use Better Auth when you need:**
82
- - Social login (Google, GitHub, Apple)
83
- - Session-based authentication
84
- - Modern OAuth 2.0 flows
85
-
86
- **Use JWT authentication when you need:**
87
- - Stateless authentication
88
- - Simpler token-based auth
89
- - No social login required
90
-
91
- **Endpoints (when enabled):**
92
- - `POST /api/auth/signup/email` — Email/password signup
93
- - `POST /api/auth/signin/email` — Email/password signin
94
- - `GET /api/auth/signin/{provider}` — Initiate OAuth flow (google, github, apple)
95
- - `GET /api/auth/callback/{provider}` — OAuth callback handler
96
- - `POST /api/auth/signout` — Sign out session
97
- - `GET /api/auth/session` — Get current session
98
-
99
- **Learn more:** [Configure Better Auth](../how-to/configure-better-auth.md)
100
-
101
- ### Anonymous Strategy
92
+ ### Anonymous Strategy (JWT — legacy)
102
93
 
103
94
  Allows limited access without authentication.
104
95
 
@@ -116,7 +107,9 @@ modelRouter(Model, {
116
107
  });
117
108
  ``````
118
109
 
119
- ## JWT Token System
110
+ ## JWT Token System (legacy)
111
+
112
+ > JWT/Passport auth is **legacy**. It remains supported through the current major line but is not the recommended path for new apps. Prefer Better Auth above.
120
113
 
121
114
  ### Token Types
122
115
 
@@ -435,4 +428,4 @@ router.post("/webhook", asyncHandler(async (req, res) => {
435
428
  - [Add GitHub OAuth](../how-to/add-github-oauth.md)
436
429
  - [Create a model](../how-to/create-a-model.md)
437
430
  - [API reference](../reference/api.md)
438
- - [@terreno/rtk reference](../reference/rtk.md)
431
+ - [@terreno/rtk reference (legacy)](../reference/legacy/rtk.md)
@@ -0,0 +1,52 @@
1
+ # Local-first data in Terreno
2
+
3
+ Terreno's default frontend data path is **local-first**: the on-device store is what your UI reads and writes, and the server reconciles changes asynchronously. This is a different mental model from request/response fetching with RTK Query.
4
+
5
+ ## What local-first means here
6
+
7
+ In `@terreno/syncdb`, a TinyBase `MergeableStore` on the device is the **UI source of truth**. When a user taps "save," the mutation applies to local state immediately and lands in a durable outbox. The client then pushes the change to `@terreno/api` over the sync protocol (socket deltas with HTTP snapshot catch-up). The server remains the **authority** for permissions, validation, and conflict resolution — but the UI does not wait on the network for every write.
8
+
9
+ There is no server-first mode and no opt-in flag: if you use syncdb, you adopt this model for every synced collection.
10
+
11
+ ## Mental model shift
12
+
13
+ | Server-first (RTK Query) | Local-first (syncdb) |
14
+ |--------------------------|----------------------|
15
+ | UI reads from cache filled by HTTP | UI reads from the local store |
16
+ | Writes call the API, then invalidate/refetch | Writes apply locally, then reconcile |
17
+ | Loading spinners track request lifecycle | Sync status tracks outbox + connectivity |
18
+ | Optimistic updates are manual and fragile | Optimistic state is the default path |
19
+ | Conflicts are rare / ignored | Conflicts are explicit and must be resolved |
20
+
21
+ Think **apply locally, then reconcile** instead of **request, wait, update cache**.
22
+
23
+ ## What you stop doing
24
+
25
+ 1. **Manual optimistic updates** — `onQueryStarted` patches, temporary IDs, and rollback logic for writes.
26
+ 2. **Write-level loading spinners** — `isLoading` on mutations for "saving…" UX; the row updates instantly.
27
+ 3. **Refetch orchestration** — `invalidatesTags`, `refetch()`, and list/detail cache coordination after mutations.
28
+ 4. **Treating the network as the read path** — list screens blocked on `isLoading` for every navigation.
29
+
30
+ RTK Query remains appropriate for **non-synced** endpoints: `/auth/me`, admin RPC, AI routes, and anything that should stay request/response.
31
+
32
+ ## What you start doing
33
+
34
+ 1. **Conflict resolution UI** — When the server rejects a mutation (409 / `sync:nack`), the user must choose a strategy (`useServer` or `keepMine`). Use `ConflictSheet` from `@terreno/ui` or build your own with `useConflicts`.
35
+ 2. **Sync-status UX** — Surface offline state, queued mutations, and drain progress with `useSyncStatus` (and optionally `SyncStatusBanner`).
36
+ 3. **Encryption at rest (web)** — Web persistence uses AES-GCM via the default `createServerKeyProvider`; understand key fetch and `onDecryptFailure` for support flows.
37
+ 4. **Key lifecycle on logout** — Call `syncDb.stop()` and consider `wipeLocalData` when the authenticated user changes so one account does not read another's local store.
38
+ 5. **Backend sync registration** — Every synced collection needs `syncPlugin`, `isDeletedPlugin`, and a `sync` block on `modelRouter`, plus `SyncApp` and `RealtimeApp` on the server.
39
+
40
+ ## Tradeoffs
41
+
42
+ **Gains:** instant UI, offline writes with a durable outbox, simpler screen code, and one write path on the server (sync and REST share `modelRouter`).
43
+
44
+ **Costs:** larger conceptual surface (conflicts, sync status, local storage), mandatory replica-set MongoDB for realtime, and migration work for existing RTK Query screens.
45
+
46
+ Server-first fetching is simpler when you only need online CRUD with no offline requirement — but Terreno's blessed path for collection data is local-first.
47
+
48
+ ## Related docs
49
+
50
+ - [syncdb reference](../reference/syncdb.md) — API ground truth
51
+ - [Migrate from RTK to syncdb](../how-to/migrate-rtk-to-syncdb.md) — step-by-step migration
52
+ - [Authentication architecture](authentication.md) — Better Auth + socket sessions
@@ -0,0 +1,117 @@
1
+ # Loop engineering
2
+
3
+ Terreno separates engineering method from orchestration:
4
+
5
+ ```text
6
+ LOOP
7
+ orchestrate / persist / wait
8
+ retry / stop / escalate
9
+ |
10
+ v
11
+ GROW
12
+ shape
13
+ |
14
+ v
15
+ PICK
16
+ build
17
+ |
18
+ v
19
+ ROAST
20
+ prove
21
+ |
22
+ v
23
+ BREW
24
+ submit
25
+ |
26
+ v
27
+ TASTE
28
+ react once
29
+ ```
30
+
31
+ Repository knowledge composes underneath every invocation:
32
+
33
+ ```text
34
+ lifecycle stage + project skills + IP/task/state + evidence
35
+ ```
36
+
37
+ ## Why fresh invocations
38
+
39
+ One enormous agent context accumulates assumptions, stale external state, and confidence
40
+ in its own implementation. The lifecycle instead makes every stage reconstructable from
41
+ durable artifacts. Pick can retry from exact Roast evidence; Roast can verify without the
42
+ implementer's assumptions; Taste can react to the current PR head rather than an old
43
+ green result.
44
+
45
+ The outer loop decides **when, who, what next, when to retry, when to wait, and when to
46
+ escalate**. Stages decide how to perform one transition correctly.
47
+
48
+ ## The five transitions
49
+
50
+ | Stage | Question | Primary evidence |
51
+ | --- | --- | --- |
52
+ | Grow | Is the work shaped and approved? | IP/tasks, decisions, criterion→verification map |
53
+ | Pick | Was this slice implemented carefully? | red/green tests, checks, internal reviews |
54
+ | Roast | Does the result actually satisfy the IP? | independent requirement→evidence verdict |
55
+ | Brew | Is the verified result correctly submitted? | final checks, commit/head, PR, artifacts |
56
+ | Taste | What is actionable on the current PR head now? | CI, mergeability, reviews, bounded fixes |
57
+
58
+ Roast is not another implementation review. It independently proves or disproves
59
+ acceptance criteria. Taste is not a resident watcher. It observes once, acts once, emits
60
+ `PASS`, `FAIL`, `BLOCKED`, or `PENDING`, then exits.
61
+
62
+ ## Portable plugin, local knowledge
63
+
64
+ The reusable plugin defines contracts, invariants, evidence, and transitions. Repo-local
65
+ skills define exact API/UI/database patterns, commands, test environments, generated
66
+ code, deployment, and safety rules.
67
+
68
+ Each stage inspects available skills and loads those whose descriptions match the
69
+ affected domain. A useful skill is optional when absent; a capability required by
70
+ repository policy is a hard gate and produces `BLOCKED` if unavailable.
71
+
72
+ Stages also load architecture docs before acting. Docs are the design; code implements
73
+ them. Missing docs for a user-visible or architectural change is `FAIL`.
74
+
75
+ This lets the same Pick method compose with backend API and test-environment knowledge,
76
+ while Roast composes with UI conventions and real-app verification.
77
+
78
+ ### Terreno's current project-skill layer
79
+
80
+ The canonical sources remain under `.rulesync/skills/` and are generated for supported
81
+ agents. The current high-value composition points include:
82
+
83
+ | Domain | Repo-local skills stages may discover |
84
+ | --- | --- |
85
+ | Backend/API/data | `terreno-backend-api`, `mongoose-schema-safety`, `backend-test-env`, `generate-sdk`, `terreno-data-fetching` |
86
+ | UI/app | `terreno-ui`, `building-terreno-apps`, `building-native-ui`, `verify-ui-changes` |
87
+ | AI/prompts | `ai-prompt-governance` |
88
+ | Docs/submission | `update-docs`, `commit`, `create-pr`, `fix-conflicts` |
89
+ | Deployment/runtime | `deploy-gcp`, Expo deployment/workflow skills |
90
+
91
+ This inventory is descriptive, not a plugin dependency list. Stages inspect the actual
92
+ catalog on every invocation.
93
+
94
+ ## State and evidence
95
+
96
+ The IP remains the design/scope source of truth. The task file remains the execution
97
+ checklist. Lightweight loop-owned state stores only current stage/attempt/task,
98
+ branch/head/PR, the previous structured result, artifacts, attempted approaches, and next
99
+ transition.
100
+
101
+ The fallback state location is `.terreno/pipeline/<slug>.json`; the outer loop preserves
102
+ or transports it and Brew excludes it from commits unless repository policy says
103
+ otherwise. Stage results follow the plugin's JSON-schema-backed YAML contract and never
104
+ contain chain-of-thought or transcripts.
105
+
106
+ ## Retry and stop rules
107
+
108
+ - Roast failure returns exact expected/actual evidence to a fresh Pick.
109
+ - Engineering retries require a new hypothesis and preserve failed approaches.
110
+ - Taste `PENDING` lets the outer loop wait and invoke fresh Taste against current state.
111
+ - Human decisions are `BLOCKED`, never arbitrary retries.
112
+ - Taste `PASS` requires all current-head checks terminal/non-failing, no conflicts, and
113
+ no actionable review findings.
114
+
115
+ The detailed contract, schemas, and three execution scenarios live under
116
+ [`plugins/terreno-planning/references/`](https://github.com/FlourishHealth/terreno/tree/master/plugins/terreno-planning/references).
117
+
@@ -36,6 +36,14 @@ descriptions):
36
36
  - Require branches to be up to date before merging
37
37
  - Do not allow bypassing the above settings
38
38
 
39
+ ### CircleCI dual-run (in progress)
40
+
41
+ Package CI / policy / Playwright twins live under `.circleci/` (see
42
+ [how-to/circleci.md](../how-to/circleci.md)). **Keep requiring the existing GitHub
43
+ Actions check names** until a twin is trusted; then add the CircleCI job name and
44
+ remove the GHA workflow. Do not require CircleCI deploy jobs yet (deploys not
45
+ ported).
46
+
39
47
  ## Merge settings
40
48
 
41
49
  **Path:** Settings → General → Pull Requests
@@ -22,10 +22,10 @@ Discussion (Ideas/RFC)
22
22
  ▼
23
23
  Issue: Status = Shaping ─────────────────────────────┐
24
24
  │ IP approved → roadmap-item
25
- Blend writes IP + task list ────────────────────────┤ (sets IP field, Shaping → Planned)
25
+ Grow writes IP + task list ────────────────────────┤ (sets IP field, Shaping → Planned)
26
26
  (docs/implementationPlans/ + docs/tasks/) ▼
27
27
  Issue: Status = Planned
28
- │ Roast → Cupping → Pour
28
+ │ Pick → Roast → Brew
29
29
  ▼
30
30
  PR: Fixes #NNN
31
31
  │ merge
@@ -34,17 +34,17 @@ Blend writes IP + task list ─────────────────
34
34
  ```
35
35
 
36
36
  The planning pipeline (the `terreno-planning` plugin) drives the design-and-build half;
37
- the roadmap skills drive the public-tracking half. They meet at one handoff: **Blend
37
+ the roadmap skills drive the public-tracking half. They meet at one handoff: **Grow
38
38
  writes the IP, and once it is Approved hands off to `roadmap-item`.**
39
39
 
40
40
  | Transition | Who owns it | Authoritative artifact |
41
41
  | ---------- | ----------- | ---------------------- |
42
42
  | Idea debated and shaped | Community + maintainers | GitHub Discussion |
43
43
  | Discussion → first tracking issue (`Shaping`) | `roadmap-promote` | GitHub Issue + Project |
44
- | Design, scope, acceptance criteria | `terreno-1-blend` / `ip` | `docs/implementationPlans/<slug>.md` |
45
- | Task breakdown for implementation | `terreno-1-blend` / `ip` | `docs/tasks/<slug>.md` |
44
+ | Design, scope, acceptance criteria | `terreno-1-grow` | `docs/implementationPlans/<slug>.md` |
45
+ | Task breakdown for implementation | `terreno-1-grow` | `docs/tasks/<slug>.md` |
46
46
  | Approved IP → issue `Planned` + `IP` field set | `roadmap-item` | GitHub Issue + Project |
47
- | Implement, verify, submit, review | `terreno-2-roast` … `terreno-5-dialin` | the PR |
47
+ | Implement, verify, submit, review | `terreno-2-pick` … `terreno-5-taste` | the PR |
48
48
  | Sprint estimates, assignees, internal-only work | Linear | Linear |
49
49
  | Public rendered list | CI (`roadmap:generate`) | `ROADMAP.md` |
50
50
 
@@ -60,7 +60,7 @@ The `terreno-planning` plugin is meant to run in any Terreno repo, including one
60
60
  Discussions and no roadmap board (Flourish, most consumer apps). There, only the design-and-build
61
61
  half applies:
62
62
 
63
- - **Blend** still writes the IP + task list — that dual-file model is the source of truth
63
+ - **Grow** still writes the IP + task list — that dual-file model is the source of truth
64
64
  everywhere. It detects the absence of `.github/roadmap-fields.yml` and the `roadmap-item`
65
65
  skill and **skips the roadmap handoff** instead of inventing issues or labels.
66
66
  - Sprint execution is tracked in Linear and linked from the IP header; it is never copied
@@ -236,9 +236,9 @@ is the variable the generator reads.
236
236
 
237
237
  ## Maintainer skills
238
238
 
239
- Four agent skills cover the recurring roadmap work. Each one researches, proposes, and then
239
+ Five agent skills cover the recurring roadmap work. Each one researches, proposes, and then
240
240
  **stops for a maintainer to approve** before touching GitHub — roadmap decisions are the most
241
- human part of the process, so none of them mutate state on their own. All four are
241
+ human part of the process, so none of them mutate state on their own. All five are
242
242
  `disable-model-invocation`, meaning an agent will not start them on its own initiative;
243
243
  you invoke them explicitly.
244
244
 
@@ -248,6 +248,19 @@ you invoke them explicitly.
248
248
  | `roadmap-promote` | Maintainers accepted an Ideas or RFC discussion and it needs a tracked issue that links back to the thread |
249
249
  | `roadmap-item` | An approved IP needs its public tracking issue, or an existing entry's scope changed |
250
250
  | `roadmap-review` | Recurring hygiene: status drift, stale items, untriaged backlog, promotion candidates, then regenerate `ROADMAP.md` |
251
+ | `roadmap-frontier` | A destination is too large or uncertain for one IP/context and needs a map, a small unblocked frontier, and repeated Grow → Taste delivery loops |
252
+
253
+ ### Huge features: frontier maps
254
+
255
+ A frontier map is one low-resolution roadmap issue with an observable destination,
256
+ resolved-decision index, current frontier, fog, and explicit out-of-scope boundary. Child
257
+ tickets hold the detail and native blocking relationships. Work only the **frontier**:
258
+ open, unblocked, unclaimed tickets.
259
+
260
+ Decision tickets resolve one question. Delivery tickets link one approved IP/task pair and
261
+ run the complete planning pipeline. After each ticket, update the map, graduate clarified
262
+ fog into precise tickets, and return to the frontier with a fresh agent context. The map
263
+ closes only when the destination is reached and no in-scope fog or open child tickets remain.
251
264
 
252
265
  Sources live in `.rulesync/skills/`; run `bun run rules` after editing to regenerate the
253
266
  per-agent mirrors.
@@ -885,3 +885,42 @@ ad-hoc backfill scripts.
885
885
  - **Tasks:** *(not yet written)*
886
886
  - **RTK flag:** None
887
887
  - **Depends on:** —
888
+
889
+ ---
890
+
891
+ # Shipped, umbrella, and declined IPs
892
+
893
+ Tracking issues created for IPs that previously lacked a `**Roadmap issue:**` header.
894
+ Add each to the **Terreno Roadmap** project with the `IP` field set to the slug below.
895
+
896
+ | IP slug | GitHub issue | Status |
897
+ |---------|--------------|--------|
898
+ | `admin-only` | https://github.com/FlourishHealth/terreno/issues/1075 | Shipped |
899
+ | `admin-ui-v2-django-parity` | https://github.com/FlourishHealth/terreno/issues/1076 | Shipped |
900
+ | `admin-script-runner` | https://github.com/FlourishHealth/terreno/issues/1077 | Shipped |
901
+ | `consent-forms` | https://github.com/FlourishHealth/terreno/issues/1078 | Shipped |
902
+ | `upgrade-banner` | https://github.com/FlourishHealth/terreno/issues/1079 | Shipped |
903
+ | `apierror-standard-error-redesign` | https://github.com/FlourishHealth/terreno/issues/1080 | Shipped |
904
+ | `syncdb-local-first` | https://github.com/FlourishHealth/terreno/issues/1081 | Shipped |
905
+ | `feature-flags-openfeature` | https://github.com/FlourishHealth/terreno/issues/1082 | Shipped |
906
+ | `design-blend-skill` | https://github.com/FlourishHealth/terreno/issues/1083 | Shipped |
907
+ | `ModularAPI` | https://github.com/FlourishHealth/terreno/issues/1084 | Shipped |
908
+ | `mcp-boost-parity` | https://github.com/FlourishHealth/terreno/issues/1085 | In progress |
909
+ | `docs-site-and-versioning` | https://github.com/FlourishHealth/terreno/issues/1086 | Planned |
910
+ | `syncdb-codegen` | https://github.com/FlourishHealth/terreno/issues/1087 | Planned |
911
+ | `migrate-cicd-to-circleci` | https://github.com/FlourishHealth/terreno/issues/1088 | Planned |
912
+ | `rbac-permissions` | https://github.com/FlourishHealth/terreno/issues/1089 | Planned |
913
+ | `infra-mcp` | https://github.com/FlourishHealth/terreno/issues/1090 | Planned (blocked) |
914
+ | `comms-admin-dashboard` | https://github.com/FlourishHealth/terreno/issues/1091 | Planned |
915
+ | `model-router-mcp` | https://github.com/FlourishHealth/terreno/issues/1092 | Planned |
916
+ | `terreno-langfuse-integration` | https://github.com/FlourishHealth/terreno/issues/1093 | Future |
917
+ | `oss-launch-program` | https://github.com/FlourishHealth/terreno/issues/1094 | In progress |
918
+ | `b2b-platform-program` | https://github.com/FlourishHealth/terreno/issues/1095 | Planned |
919
+ | `offline-mode` | https://github.com/FlourishHealth/terreno/issues/1096 | Declined |
920
+ | `model-router-actions` | https://github.com/FlourishHealth/terreno/issues/1097 | Declined |
921
+ | `feature-flags` | https://github.com/FlourishHealth/terreno/issues/1098 | Declined |
922
+ | `admin-improvements` | https://github.com/FlourishHealth/terreno/issues/1099 | Declined |
923
+
924
+ Research and design sub-documents share the parent IP's issue: `admin-only-research` →
925
+ #1075; `infra-mcp-research` → #1090; `migrate-cicd-to-circleci-research` → #1088;
926
+ `syncdb-phase-c-design`, `terreno-syncdb-2`, and `syncdb-api-inventory` → #1081.
@@ -12,10 +12,13 @@ Problem-oriented, practical steps. Use these when you know what you want to do.
12
12
 
13
13
  ## Contents
14
14
 
15
+ - [CircleCI](circleci.md) — Dual-run CI on CircleCI (package CI / policy / e2e; deploys later)
15
16
  - [Create a Mongoose model](create-a-model.md) — Define models with proper conventions
16
17
  - [Add GitHub OAuth authentication](add-github-oauth.md) — Enable GitHub login for your API
17
18
  - [Configure Better Auth](configure-better-auth.md) — Set up Better Auth with social OAuth (Google, GitHub, Apple)
18
19
  - [Add WebSocket integration](websocket-integration.md) — Set up real-time Socket.io connections
20
+ - [Expose Model Context Protocol tools](expose-mcp-tools.md) — Turn `modelRouter` models into MCP tools an LLM can call
21
+ - [Install agent skills](install-agent-skills.md) — Install Grow/Pick/Roast/Brew/Taste and domain skills with `npx skills`
19
22
  - [Call external APIs](call-external-apis.md) — Authenticated HTTP client, retries, and error normalization for third-party integrations
20
23
  - [Deploy to Google Cloud Platform](deploy-to-gcp.md) — Deploy demo and example apps to GCS with CDN
21
24
  - [Migrate from @terreno/rtk to @terreno/syncdb](migrate-rtk-to-syncdb.md) — Move data sync to the local-first layer
@@ -0,0 +1,41 @@
1
+ # Add a model to the admin
2
+
3
+ Add `admin` directly to the model's existing `modelRouter` options:
4
+
5
+ ```ts
6
+ export const userRouter = modelRouter("/users", User, {
7
+ admin: {
8
+ displayName: "Users",
9
+ listFields: ["email", "name", "admin", "created"],
10
+ searchFields: ["email", "name"],
11
+ sortableFields: ["email", "name", "created"],
12
+ filters: [{field: "admin", kind: "boolean", label: "Admin user"}],
13
+ },
14
+ permissions: {
15
+ create: [Permissions.IsAdmin],
16
+ delete: [Permissions.IsAdmin],
17
+ list: [Permissions.IsAdmin],
18
+ read: [Permissions.IsAdmin],
19
+ update: [Permissions.IsAdmin],
20
+ },
21
+ });
22
+ ```
23
+
24
+ Register that router with `TerrenoApp`, then register `AdminApp`. The model appears in
25
+ `GET /admin/config` and at `/admin/User` without a duplicate `AdminApp.models` entry.
26
+
27
+ If the same Mongoose model is mounted at two `routePath`s (different filters or list
28
+ columns), `/admin/config` keeps `name` as the model name for the registered entry and
29
+ suffixes the others with the route slug (for example `Food-archived-foods`) so each list
30
+ is reachable.
31
+
32
+ Common fields:
33
+
34
+ - `listFields`: columns and fields exposed to admin CRUD.
35
+ - `searchFields`: string fields matched by the list search box (`q`) as a
36
+ case-insensitive partial (`$regex`) query.
37
+ - `sortableFields`: the only columns with sorting enabled.
38
+ - `filters`: typed filter drawer controls.
39
+ - `fieldsets`: grouped form sections.
40
+ - `readonlyFields` / `hiddenFields`: display-only or omitted form fields.
41
+ - `adminPermissions`: optional admin-specific permission methods.
@@ -0,0 +1,31 @@
1
+ # Customize the admin home
2
+
3
+ Configure home slots on `AdminApp`:
4
+
5
+ ```ts
6
+ new AdminApp({
7
+ home: {
8
+ title: "Operations",
9
+ slots: {
10
+ contentTop: ["feature-flags-overrides"],
11
+ main: ["modelStats"],
12
+ navGlobal: ["scriptRunner"],
13
+ sidebar: ["versionConfig", "recentActivity"],
14
+ },
15
+ },
16
+ });
17
+ ```
18
+
19
+ Built-in IDs include `modelStats`, `modelsGrid`, `scriptRunner`, `versionConfig`, and
20
+ `recentActivity`. Plugins add IDs such as `feature-flags-overrides`.
21
+
22
+ For an app-specific widget, implement `AdminHomeWidgetProps` and register it:
23
+
24
+ ```tsx
25
+ <AdminProvider widgets={{home: {operationsSummary: OperationsSummary}}} api={api}>
26
+ <AdminHome api={api} />
27
+ </AdminProvider>
28
+ ```
29
+
30
+ Then place `"operationsSummary"` in a home slot. Unknown IDs render a visible missing-widget
31
+ placeholder in development instead of crashing the dashboard.
@@ -0,0 +1,42 @@
1
+ # Add a custom admin field widget
2
+
3
+ 1. Name the widget in model admin metadata:
4
+
5
+ ```ts
6
+ admin: {
7
+ displayName: "Articles",
8
+ listFields: ["title", "body"],
9
+ fieldOverrides: {body: {widget: "rich-text"}},
10
+ }
11
+ ```
12
+
13
+ 2. Implement the field widget:
14
+
15
+ ```tsx
16
+ const RichTextWidget: React.FC<AdminFieldWidgetProps> = ({
17
+ value,
18
+ onChange,
19
+ readOnly,
20
+ }) => (
21
+ <RichTextEditor
22
+ disabled={Boolean(readOnly)}
23
+ onChange={onChange}
24
+ value={typeof value === "string" ? value : ""}
25
+ />
26
+ );
27
+ ```
28
+
29
+ 3. Register it once around the admin routes:
30
+
31
+ ```tsx
32
+ <AdminProvider
33
+ api={api}
34
+ apiBase="/admin"
35
+ routeBase="/admin"
36
+ widgets={{fields: {"rich-text": RichTextWidget}}}
37
+ >
38
+ <AdminRoutes />
39
+ </AdminProvider>
40
+ ```
41
+
42
+ Host registrations override built-ins with the same ID.
@@ -0,0 +1,25 @@
1
+ # Import pre-built admins
2
+
3
+ Register first-party plugins on the same `TerrenoApp` as `AdminApp`:
4
+
5
+ ```ts
6
+ const app = new TerrenoApp({userModel: User})
7
+ .register(new FeatureFlagsApp())
8
+ .register(new ConsentApp({auditTrail: true}))
9
+ .register(new DocumentStorageApp({bucketName: process.env.GCS_BUCKET ?? ""}))
10
+ .register(new AIAdminApp())
11
+ .register(new AdminApp({home: {slots: {main: ["modelStats"]}}}));
12
+ ```
13
+
14
+ `AdminApp` aggregates each plugin's `adminContribution()`:
15
+
16
+ - `FeatureFlagsApp`: FeatureFlag model and `feature-flags-overrides` home widget.
17
+ - `ConsentApp`: ConsentForm and ConsentResponse models plus consent field-widget IDs.
18
+ - `DocumentStorageApp`: `documents` custom screen.
19
+ - `AIAdminApp`: `ai-requests` custom screen and explorer API.
20
+
21
+ Wrap frontend admin routes in `AdminProvider`. First-party widgets are already in the built-in
22
+ registry, so no consumer-side switch statement or custom-screen map is required.
23
+
24
+ `featureFlagAdminConfig` and `AdminApp.models` remain compatibility paths, but new integrations
25
+ should use plugin contributions and `modelRouter({admin: ...})`.