@terreno/mcp 0.31.0 → 56.0.0-beta.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 (209) hide show
  1. package/dist/bootstrap.d.ts.map +1 -1
  2. package/dist/bootstrap.js +15 -16
  3. package/dist/bootstrap.js.map +1 -1
  4. package/dist/docs/templates/bootstrap/backend/types/models/userTypes.template.md +4 -5
  5. package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
  6. package/dist/docs/templates/tools/model.template.md +2 -4
  7. package/dist/docs/versioned/next/README.md +1 -0
  8. package/dist/docs/versioned/next/explanation/README.md +1 -7
  9. package/dist/docs/versioned/next/how-to/README.md +2 -8
  10. package/dist/docs/versioned/next/how-to/deploy-to-gcp.md +228 -20
  11. package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
  12. package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +4 -57
  13. package/dist/docs/versioned/next/implementationPlans/README.md +30 -56
  14. package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +1 -2
  15. package/dist/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +0 -1
  16. package/dist/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +0 -1
  17. package/dist/docs/versioned/next/implementationPlans/deploy-to-gcp.md +0 -1
  18. package/dist/docs/versioned/next/implementationPlans/deploy-to-vercel.md +0 -1
  19. package/dist/docs/versioned/next/implementationPlans/deployment-foundation.md +0 -1
  20. package/dist/docs/versioned/next/implementationPlans/docs-reference-coverage.md +0 -1
  21. package/dist/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +0 -1
  22. package/dist/docs/versioned/next/implementationPlans/examples-demo-coverage.md +0 -1
  23. package/dist/docs/versioned/next/implementationPlans/oss-governance-baseline.md +0 -1
  24. package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +0 -1
  25. package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +0 -1
  26. package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
  27. package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
  28. package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
  29. package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
  30. package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
  31. package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
  32. package/dist/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +0 -1
  33. package/dist/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +0 -1
  34. package/dist/docs/versioned/next/reference/README.md +1 -4
  35. package/dist/docs/versioned/next/reference/environment-variables.md +382 -220
  36. package/dist/docs/versioned/next/reference/syncdb.md +456 -0
  37. package/dist/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
  38. package/dist/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
  39. package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
  40. package/dist/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
  41. package/dist/docs/versioned/next/tasks/deployment-foundation.md +12 -12
  42. package/dist/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
  43. package/dist/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
  44. package/dist/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
  45. package/dist/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
  46. package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
  47. package/dist/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
  48. package/dist/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
  49. package/package.json +4 -5
  50. package/src/docs/templates/bootstrap/backend/types/models/userTypes.template.md +4 -5
  51. package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
  52. package/src/docs/templates/tools/model.template.md +2 -4
  53. package/src/docs/versioned/next/README.md +1 -0
  54. package/src/docs/versioned/next/explanation/README.md +1 -7
  55. package/src/docs/versioned/next/how-to/README.md +2 -8
  56. package/src/docs/versioned/next/how-to/deploy-to-gcp.md +228 -20
  57. package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
  58. package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +4 -57
  59. package/src/docs/versioned/next/implementationPlans/README.md +30 -56
  60. package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +1 -2
  61. package/src/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +0 -1
  62. package/src/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +0 -1
  63. package/src/docs/versioned/next/implementationPlans/deploy-to-gcp.md +0 -1
  64. package/src/docs/versioned/next/implementationPlans/deploy-to-vercel.md +0 -1
  65. package/src/docs/versioned/next/implementationPlans/deployment-foundation.md +0 -1
  66. package/src/docs/versioned/next/implementationPlans/docs-reference-coverage.md +0 -1
  67. package/src/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +0 -1
  68. package/src/docs/versioned/next/implementationPlans/examples-demo-coverage.md +0 -1
  69. package/src/docs/versioned/next/implementationPlans/oss-governance-baseline.md +0 -1
  70. package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +0 -1
  71. package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +0 -1
  72. package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
  73. package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
  74. package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
  75. package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
  76. package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
  77. package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
  78. package/src/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +0 -1
  79. package/src/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +0 -1
  80. package/src/docs/versioned/next/reference/README.md +1 -4
  81. package/src/docs/versioned/next/reference/environment-variables.md +382 -220
  82. package/src/docs/versioned/next/reference/syncdb.md +456 -0
  83. package/src/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
  84. package/src/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
  85. package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
  86. package/src/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
  87. package/src/docs/versioned/next/tasks/deployment-foundation.md +12 -12
  88. package/src/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
  89. package/src/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
  90. package/src/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
  91. package/src/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
  92. package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
  93. package/src/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
  94. package/src/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
  95. package/LICENSE +0 -21
  96. package/dist/__tests__/bootstrap.test.d.ts +0 -2
  97. package/dist/__tests__/bootstrap.test.d.ts.map +0 -1
  98. package/dist/__tests__/bootstrap.test.js +0 -299
  99. package/dist/__tests__/bootstrap.test.js.map +0 -1
  100. package/dist/__tests__/databaseQuery.test.d.ts +0 -2
  101. package/dist/__tests__/databaseQuery.test.d.ts.map +0 -1
  102. package/dist/__tests__/databaseQuery.test.js +0 -83
  103. package/dist/__tests__/databaseQuery.test.js.map +0 -1
  104. package/dist/__tests__/docsRoot.test.d.ts +0 -2
  105. package/dist/__tests__/docsRoot.test.d.ts.map +0 -1
  106. package/dist/__tests__/docsRoot.test.js +0 -59
  107. package/dist/__tests__/docsRoot.test.js.map +0 -1
  108. package/dist/__tests__/inferPackages.test.d.ts +0 -2
  109. package/dist/__tests__/inferPackages.test.d.ts.map +0 -1
  110. package/dist/__tests__/inferPackages.test.js +0 -35
  111. package/dist/__tests__/inferPackages.test.js.map +0 -1
  112. package/dist/__tests__/preload.d.ts +0 -2
  113. package/dist/__tests__/preload.d.ts.map +0 -1
  114. package/dist/__tests__/preload.js +0 -12
  115. package/dist/__tests__/preload.js.map +0 -1
  116. package/dist/__tests__/prompts.test.d.ts +0 -2
  117. package/dist/__tests__/prompts.test.d.ts.map +0 -1
  118. package/dist/__tests__/prompts.test.js +0 -295
  119. package/dist/__tests__/prompts.test.js.map +0 -1
  120. package/dist/__tests__/resources.test.d.ts +0 -2
  121. package/dist/__tests__/resources.test.d.ts.map +0 -1
  122. package/dist/__tests__/resources.test.js +0 -352
  123. package/dist/__tests__/resources.test.js.map +0 -1
  124. package/dist/__tests__/search.test.d.ts +0 -2
  125. package/dist/__tests__/search.test.d.ts.map +0 -1
  126. package/dist/__tests__/search.test.js +0 -163
  127. package/dist/__tests__/search.test.js.map +0 -1
  128. package/dist/__tests__/tools.test.d.ts +0 -2
  129. package/dist/__tests__/tools.test.d.ts.map +0 -1
  130. package/dist/__tests__/tools.test.js +0 -540
  131. package/dist/__tests__/tools.test.js.map +0 -1
  132. package/dist/__tests__/upgradeGuide.test.d.ts +0 -2
  133. package/dist/__tests__/upgradeGuide.test.d.ts.map +0 -1
  134. package/dist/__tests__/upgradeGuide.test.js +0 -22
  135. package/dist/__tests__/upgradeGuide.test.js.map +0 -1
  136. package/dist/docs/upgrades/0.31.0.md +0 -60
  137. package/dist/docs/versioned/next/explanation/deployment-architecture-gcp.md +0 -65
  138. package/dist/docs/versioned/next/explanation/deployment-baseline.md +0 -78
  139. package/dist/docs/versioned/next/explanation/positioning.md +0 -164
  140. package/dist/docs/versioned/next/explanation/repository-settings.md +0 -44
  141. package/dist/docs/versioned/next/explanation/roadmap-process.md +0 -330
  142. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +0 -866
  143. package/dist/docs/versioned/next/how-to/build-for-web.md +0 -69
  144. package/dist/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +0 -115
  145. package/dist/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +0 -183
  146. package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +0 -114
  147. package/dist/docs/versioned/next/implementationPlans/billing-stripe.md +0 -158
  148. package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +0 -240
  149. package/dist/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +0 -107
  150. package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +0 -107
  151. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +0 -102
  152. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +0 -93
  153. package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +0 -188
  154. package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +0 -269
  155. package/dist/docs/versioned/next/implementationPlans/native-module-baseline.md +0 -105
  156. package/dist/docs/versioned/next/implementationPlans/orgs-and-teams.md +0 -158
  157. package/dist/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +0 -147
  158. package/dist/docs/versioned/next/reference/admin-spa.md +0 -130
  159. package/dist/docs/versioned/next/reference/ai.md +0 -519
  160. package/dist/docs/versioned/next/reference/test.md +0 -108
  161. package/dist/docs/versioned/next/roadmap.md +0 -9
  162. package/dist/docs/versioned/next/tasks/README.md +0 -42
  163. package/dist/docs/versioned/next/tasks/billing-stripe.md +0 -75
  164. package/dist/docs/versioned/next/tasks/comms-abstraction.md +0 -77
  165. package/dist/docs/versioned/next/tasks/comms-adapter-expo-push.md +0 -29
  166. package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +0 -29
  167. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +0 -29
  168. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +0 -19
  169. package/dist/docs/versioned/next/tasks/infra-mcp.md +0 -43
  170. package/dist/docs/versioned/next/tasks/native-module-baseline.md +0 -42
  171. package/dist/docs/versioned/next/tasks/orgs-and-teams.md +0 -70
  172. package/dist/docs/versioned/next/tasks/password-reset-and-email-verification.md +0 -60
  173. package/src/docs/upgrades/0.31.0.md +0 -60
  174. package/src/docs/versioned/next/explanation/deployment-architecture-gcp.md +0 -65
  175. package/src/docs/versioned/next/explanation/deployment-baseline.md +0 -78
  176. package/src/docs/versioned/next/explanation/positioning.md +0 -164
  177. package/src/docs/versioned/next/explanation/repository-settings.md +0 -44
  178. package/src/docs/versioned/next/explanation/roadmap-process.md +0 -330
  179. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +0 -866
  180. package/src/docs/versioned/next/how-to/build-for-web.md +0 -69
  181. package/src/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +0 -115
  182. package/src/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +0 -183
  183. package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +0 -114
  184. package/src/docs/versioned/next/implementationPlans/billing-stripe.md +0 -158
  185. package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +0 -240
  186. package/src/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +0 -107
  187. package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +0 -107
  188. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +0 -102
  189. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +0 -93
  190. package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +0 -188
  191. package/src/docs/versioned/next/implementationPlans/infra-mcp.md +0 -269
  192. package/src/docs/versioned/next/implementationPlans/native-module-baseline.md +0 -105
  193. package/src/docs/versioned/next/implementationPlans/orgs-and-teams.md +0 -158
  194. package/src/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +0 -147
  195. package/src/docs/versioned/next/reference/admin-spa.md +0 -130
  196. package/src/docs/versioned/next/reference/ai.md +0 -519
  197. package/src/docs/versioned/next/reference/test.md +0 -108
  198. package/src/docs/versioned/next/roadmap.md +0 -9
  199. package/src/docs/versioned/next/tasks/README.md +0 -42
  200. package/src/docs/versioned/next/tasks/billing-stripe.md +0 -75
  201. package/src/docs/versioned/next/tasks/comms-abstraction.md +0 -77
  202. package/src/docs/versioned/next/tasks/comms-adapter-expo-push.md +0 -29
  203. package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +0 -29
  204. package/src/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +0 -29
  205. package/src/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +0 -19
  206. package/src/docs/versioned/next/tasks/infra-mcp.md +0 -43
  207. package/src/docs/versioned/next/tasks/native-module-baseline.md +0 -42
  208. package/src/docs/versioned/next/tasks/orgs-and-teams.md +0 -70
  209. package/src/docs/versioned/next/tasks/password-reset-and-email-verification.md +0 -60
@@ -1,240 +0,0 @@
1
- # Implementation Plan: Pluggable communications layer (@terreno/comms)
2
-
3
- **Status:** Draft
4
- **Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1018
5
- **Priority:** High
6
- **Effort:** Big batch
7
- **Owner:** unassigned
8
- **Created:** 2026-08-09
9
- **Program:** [B2B platform](b2b-platform-program.md)
10
- **Depends on:** none (inbound-webhooks is needed only by adapter delivery-callback phases)
11
- **RTK deprecation flag:** None — backend-only package
12
-
13
- ## Goal
14
-
15
- Terreno backends cannot send email, SMS, or push notifications: there is no mail
16
- integration at all, `expo-server-sdk` sits unused in `@terreno/api`, and the RTK client's
17
- `resetPassword` call has no backend to talk to. This IP creates `@terreno/comms`, a new
18
- workspace package that defines **provider interfaces** for the four outbound channels
19
- (mail, SMS, push, OTP verification), a **`CommsApp`** TerrenoPlugin that registers
20
- configured providers and exposes send services to routes and other plugins, **push-token
21
- registration** routes and model, a **delivery log**, and **console adapters** so every
22
- channel works in development with zero external accounts.
23
-
24
- Concrete providers (Twilio, SendGrid, Expo push) are separate IPs — one per adapter — so
25
- consumer apps install only the SDKs they use.
26
-
27
- ## Non-Goals
28
-
29
- - Any concrete provider SDK integration (see `comms-adapter-*` IPs).
30
- - In-app notification center, inbox UI, or user notification preferences
31
- (`notification-center` item).
32
- - Password reset / email verification flows (`password-reset-and-email-verification` item
33
- — a consumer of this layer).
34
- - Inbound webhook handling (`inbound-webhooks` item); this IP only defines the
35
- `DeliveryEvent` type adapters will feed from callbacks.
36
- - Broadcast/bulk campaign tooling.
37
-
38
- ## Decisions
39
-
40
- | Question | Decision |
41
- |----------|----------|
42
- | New package or `@terreno/api` module? | New package `@terreno/comms`, mirroring `@terreno/feature-flags` — keeps provider SDKs out of the core dependency tree |
43
- | How do provider SDKs stay optional? | Adapters live in subpath exports (`@terreno/comms/adapters/<name>`) with their SDKs as `peerDependencies` marked optional; core package has zero provider SDKs |
44
- | Precedent to follow | `secretProviders.ts` (env + GCP behind one interface) and the OpenFeature provider in `@terreno/feature-flags` |
45
- | Templates | Minimal: `{subject, text, html}` render helper with variable interpolation; no template builder |
46
- | Where do send calls log? | `CommsMessage` Mongoose model, mirroring the `AIRequest.logRequest` pattern — logging failures never break the send |
47
- | Dev experience | `ConsoleMailProvider` / `ConsoleSmsProvider` / `ConsolePushProvider` / `ConsoleVerificationProvider` print to logger and record to `CommsMessage`; default when no provider configured in non-production |
48
-
49
- ## Architecture
50
-
51
- ```
52
- @terreno/comms
53
- src/
54
- types.ts # Provider interfaces + message/result types
55
- commsApp.ts # CommsApp TerrenoPlugin
56
- commsService.ts # sendMail/sendSms/sendPush/startVerification/checkVerification
57
- models/
58
- commsMessage.ts # Delivery log
59
- pushToken.ts # Device push token registry
60
- routes/
61
- pushTokens.ts # modelRouter for token registration
62
- commsExplorer.ts # Admin-only delivery log explorer
63
- adapters/
64
- console.ts # Dev adapters for all four channels
65
- templates.ts # renderTemplate({subject, text, html}, data)
66
- ```
67
-
68
- ### Provider interfaces (types.ts)
69
-
70
- ```typescript
71
- export interface SendResult {
72
- providerMessageId?: string;
73
- accepted: boolean;
74
- error?: string;
75
- }
76
-
77
- export interface MailMessage {
78
- to: string | string[];
79
- from?: string; // default from CommsApp options
80
- subject: string;
81
- text?: string;
82
- html?: string;
83
- replyTo?: string;
84
- metadata?: Record<string, string>;
85
- }
86
-
87
- export interface MailProvider {
88
- readonly id: string; // "console" | "sendgrid" | ...
89
- sendMail(message: MailMessage): Promise<SendResult>;
90
- }
91
-
92
- export interface SmsProvider {
93
- readonly id: string;
94
- sendSms(message: {to: string; body: string}): Promise<SendResult>;
95
- }
96
-
97
- export interface PushMessage {
98
- tokens: string[];
99
- title: string;
100
- body: string;
101
- data?: Record<string, unknown>;
102
- badge?: number;
103
- sound?: string | null;
104
- }
105
-
106
- export interface PushProvider {
107
- readonly id: string;
108
- sendPush(message: PushMessage): Promise<SendResult[]>; // one per token
109
- }
110
-
111
- export interface VerificationProvider {
112
- readonly id: string;
113
- startVerification(options: {to: string; channel: "sms" | "email"}): Promise<SendResult>;
114
- checkVerification(options: {to: string; code: string}): Promise<{valid: boolean}>;
115
- }
116
-
117
- export interface DeliveryEvent {
118
- channel: "mail" | "sms" | "push";
119
- providerMessageId: string;
120
- status: "delivered" | "bounced" | "failed" | "opened";
121
- raw?: unknown;
122
- }
123
- ```
124
-
125
- ### CommsApp (TerrenoPlugin)
126
-
127
- ```typescript
128
- export interface CommsOptions {
129
- mail?: MailProvider;
130
- sms?: SmsProvider;
131
- push?: PushProvider;
132
- verification?: VerificationProvider;
133
- defaultFrom?: string; // mail from fallback
134
- logMessages?: boolean; // default true → CommsMessage
135
- onDeliveryEvent?: (event: DeliveryEvent) => Promise<void>;
136
- }
137
-
138
- new TerrenoApp({userModel: User})
139
- .register(new CommsApp({mail: new ConsoleMailProvider(), push: new ExpoPushProvider()}))
140
- .start();
141
- ```
142
-
143
- `CommsApp.register()` mounts the push-token routes and admin explorer;
144
- `getCommsService()` (module-level accessor, mirroring how `FeatureFlagsApp` exposes
145
- evaluation) gives routes and other plugins `sendMail` / `sendSms` / `sendPushToUser` /
146
- `startVerification` / `checkVerification`. `sendPushToUser(userId, message)` resolves the
147
- user's active `PushToken`s and prunes tokens the provider reports dead.
148
-
149
- Unconfigured channel behavior: in production, throw `APIError({status: 501, title:
150
- "Comms channel not configured"})`; in development, fall back to the console adapter with a
151
- `logger.warn`.
152
-
153
- ## Models
154
-
155
- All fields carry `description`; both models use `createdUpdatedPlugin` + `isDeletedPlugin`
156
- and live per the five-type pattern (`CommsMessageDocument`, etc.).
157
-
158
- **PushToken** — `userId` (ref User, required, indexed), `token` (string, required, unique),
159
- `platform` ("ios" | "android" | "web"), `deviceId` (string, optional), `active` (boolean,
160
- default true), `lastSeenAt` (date).
161
-
162
- **CommsMessage** — `channel` ("mail" | "sms" | "push" | "verification"), `provider`
163
- (string), `to` (string, redacted-at-rest for sms/mail per option), `subject` (string,
164
- optional), `userId` (ref User, optional), `status` ("sent" | "failed" | "delivered" |
165
- "bounced"), `providerMessageId` (string, indexed), `error` (string, optional), `metadata`
166
- (Mixed). Static `logSend()` mirrors `AIRequest.logRequest`.
167
-
168
- ## APIs
169
-
170
- | Method | Path | Permissions | Notes |
171
- |---|---|---|---|
172
- | POST | `/comms/pushTokens` | IsAuthenticated | Upsert by `token`; sets `userId`, `platform`, `lastSeenAt` |
173
- | GET | `/comms/pushTokens` | IsOwner via queryFilter | List own device tokens |
174
- | DELETE | `/comms/pushTokens/:id` | IsOwner | Deactivate on logout/uninstall |
175
- | GET | `/comms/messages` | IsAdmin | Paginated delivery log explorer; filters: `channel`, `status`, `userId`, date range |
176
-
177
- Push token routes via `modelRouter` with `preCreate` owner injection and
178
- `OwnerQueryFilter`; explorer via `createOpenApiBuilder`, modeled on
179
- `addAiRequestsExplorerRoutes`.
180
-
181
- ## Notifications
182
-
183
- None beyond the feature itself.
184
-
185
- ## UI
186
-
187
- None in this IP. example-frontend gains a settings row that registers the Expo push token
188
- (client helper already exists in `store/utils.ts`) once the Expo adapter lands.
189
-
190
- ## Phases
191
-
192
- 1. **Package + contracts:** `@terreno/comms` package scaffold, `types.ts`, console
193
- adapters, `CommsMessage` + logging, `commsService`, unit tests.
194
- 2. **CommsApp + routes:** plugin registration, `PushToken` model + routes, admin explorer,
195
- OpenAPI, supertest coverage.
196
- 3. **Integration:** example-backend registers `CommsApp` (console adapters), seed docs,
197
- `docs/reference/comms.md`, catalog entries, publish wiring in `publish-on-tag.yml`.
198
-
199
- ## Feature Flags & Migrations
200
-
201
- None. New collections only; no existing data touched.
202
-
203
- ## Activity Log & User Updates
204
-
205
- Every send attempt is a `CommsMessage` row (that is the audit surface). No user-facing
206
- updates.
207
-
208
- ## Not Included / Future Work
209
-
210
- - Adapter IPs: `comms-adapter-expo-push`, `comms-adapter-twilio-sms`,
211
- `comms-adapter-twilio-verify`, `comms-adapter-sendgrid`.
212
- - Notification center, user notification preferences.
213
- - Queue-backed sending with retries — arrives with `job-queues`; until then sends are
214
- inline with one retry.
215
-
216
- ## Files to Create / Modify
217
-
218
- - `comms/` (new workspace package: `package.json`, `tsconfig.json`, `biome.jsonc`, `src/*`
219
- as in Architecture)
220
- - Root `package.json` — workspace entry + scripts (`comms:compile|lint|test`)
221
- - `example-backend/src/server.ts` — register `CommsApp`
222
- - `docs/reference/comms.md`, `.cursor/rules/comms/00-comms.mdc` (via rulesync)
223
- - `.github/workflows/publish-on-tag.yml`, new `comms-ci` workflow
224
-
225
- ## Task List
226
-
227
- See [docs/tasks/comms-abstraction.md](../tasks/comms-abstraction.md).
228
-
229
- ## Acceptance Criteria
230
-
231
- - [ ] A Terreno app with only console adapters can call `sendMail`, `sendSms`,
232
- `sendPushToUser`, and `startVerification`/`checkVerification` in development, each
233
- producing a logger line and a `CommsMessage` row.
234
- - [ ] `POST /comms/pushTokens` registers a device token for the authenticated user;
235
- re-posting the same token updates rather than duplicates; other users cannot list or
236
- delete it.
237
- - [ ] `GET /comms/messages` is admin-only, paginated, and filterable by channel and status.
238
- - [ ] Production apps with an unconfigured channel get a 501 `APIError`, not a silent no-op.
239
- - [ ] `@terreno/comms` core has zero provider SDKs in `dependencies`.
240
- - [ ] All routes appear in `/openapi.json` and the generated SDK compiles.
@@ -1,107 +0,0 @@
1
- # Implementation Plan: Comms adapter — Expo push notifications
2
-
3
- **Status:** Draft
4
- **Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1019
5
- **Priority:** High
6
- **Effort:** Small batch
7
- **Owner:** unassigned
8
- **Created:** 2026-08-09
9
- **Program:** [B2B platform](b2b-platform-program.md)
10
- **Depends on:** [comms-abstraction](comms-abstraction.md)
11
- **RTK deprecation flag:** None — backend adapter; client token registration already exists
12
-
13
- ## Goal
14
-
15
- Implement `PushProvider` on Expo's push service so `sendPushToUser` delivers real
16
- notifications to iOS/Android devices. `expo-server-sdk` is already a dependency of
17
- `@terreno/api` (currently unused — it moves to this adapter's peer deps); the client-side
18
- token fetch (`getExpoPushTokenAsync`) already exists in `example-frontend/store/utils.ts`.
19
-
20
- ## Non-Goals
21
-
22
- - Direct FCM/APNs integration (future adapter if demand appears).
23
- - Notification center / inbox UI.
24
- - Rich notification content (images, actions) beyond title/body/data/badge/sound.
25
-
26
- ## Decisions
27
-
28
- | Question | Decision |
29
- |----------|----------|
30
- | SDK | `expo-server-sdk` as optional peer of `@terreno/comms` (subpath `adapters/expoPush`); removed from `@terreno/api` deps |
31
- | Receipts | Poll receipts after send (Expo's required pattern); surface as `DeliveryEvent`s to `onDeliveryEvent` |
32
- | Dead tokens | `DeviceNotRegistered` receipt → `SendResult.accepted: false` with permanent-failure marker so core pruning deactivates the `PushToken` |
33
- | Chunking | Use the SDK's `chunkPushNotifications`; one `SendResult` per token preserved through chunks |
34
-
35
- ## Architecture
36
-
37
- ```typescript
38
- // @terreno/comms/adapters/expoPush
39
- export class ExpoPushProvider implements PushProvider {
40
- readonly id = "expo";
41
- constructor(options?: {accessToken?: string; receiptPollDelayMs?: number});
42
- sendPush(message: PushMessage): Promise<SendResult[]>;
43
- }
44
- ```
45
-
46
- Send flow: validate tokens with `Expo.isExpoPushToken` → chunk → send → collect tickets →
47
- schedule one receipt poll (default 15 min, configurable; inline timer until `job-queues`
48
- lands) → map receipt errors to `DeliveryEvent`s and permanent-failure results.
49
-
50
- ## Models
51
-
52
- None new — uses `PushToken` and `CommsMessage` from the abstraction.
53
-
54
- ## APIs
55
-
56
- None new.
57
-
58
- ## Notifications
59
-
60
- This is the notification plumbing itself.
61
-
62
- ## UI
63
-
64
- example-frontend: register the push token on login via `POST /comms/pushTokens` (guarded by
65
- `expo-device` physical-device check once the native baseline lands) and a profile-screen
66
- test-send row in dev builds.
67
-
68
- ## Phases
69
-
70
- Single phase.
71
-
72
- ## Feature Flags & Migrations
73
-
74
- None.
75
-
76
- ## Activity Log & User Updates
77
-
78
- Sends and receipt failures logged to `CommsMessage`.
79
-
80
- ## Not Included / Future Work
81
-
82
- - Queue-backed receipt polling (moves to `job-queues` when available).
83
- - Web push (Expo tokens cover native only; web is a future adapter).
84
-
85
- ## Files to Create / Modify
86
-
87
- - `comms/src/adapters/expoPush.ts` + tests (mock `Expo` client)
88
- - `comms/package.json` — optional peer `expo-server-sdk`
89
- - `api/package.json` — remove unused `expo-server-sdk`
90
- - `example-frontend/app/(tabs)/profile.tsx`, `store/utils.ts` — token registration wiring
91
- - `docs/reference/comms.md` — adapter section
92
-
93
- ## Task List
94
-
95
- See [docs/tasks/comms-adapter-expo-push.md](../tasks/comms-adapter-expo-push.md).
96
-
97
- ## Acceptance Criteria
98
-
99
- - [ ] With a mocked Expo client, `sendPush` returns one `SendResult` per token across chunk
100
- boundaries.
101
- - [ ] A `DeviceNotRegistered` receipt deactivates the corresponding `PushToken` via core
102
- pruning.
103
- - [ ] Invalid tokens are rejected before hitting the SDK and logged as failed
104
- `CommsMessage` rows.
105
- - [ ] `@terreno/api` no longer lists `expo-server-sdk`; apps not using the adapter install
106
- nothing new.
107
- - [ ] example-frontend registers its token after login on a physical device build.
@@ -1,107 +0,0 @@
1
- # Implementation Plan: Comms adapter — transactional email (SendGrid)
2
-
3
- **Status:** Draft
4
- **Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1022
5
- **Priority:** High
6
- **Effort:** Small batch
7
- **Owner:** unassigned
8
- **Created:** 2026-08-09
9
- **Program:** [B2B platform](b2b-platform-program.md)
10
- **Depends on:** [comms-abstraction](comms-abstraction.md); inbound-webhooks (Phase 2 only)
11
- **RTK deprecation flag:** None — backend only
12
-
13
- ## Goal
14
-
15
- Implement `MailProvider` on Twilio SendGrid (decision D2 — first mail adapter, sharing the
16
- Twilio account story with the SMS and Verify adapters) so `sendMail` delivers real
17
- transactional email. This unblocks `password-reset-and-email-verification` and
18
- `invitations-and-seats`.
19
-
20
- ## Non-Goals
21
-
22
- - Other mail providers (Resend/SES/SMTP — items when demand appears).
23
- - Marketing campaigns, contact lists, SendGrid dynamic template management.
24
- - Inbound email parsing.
25
-
26
- ## Decisions
27
-
28
- | Question | Decision |
29
- |----------|----------|
30
- | SDK | `@sendgrid/mail` as optional peer, subpath `@terreno/comms/adapters/sendgrid` |
31
- | Auth | `SENDGRID_API_KEY` env or constructor option; fail fast at registration when missing |
32
- | From address | Constructor `fromEmail`/`fromName` falling back to `CommsApp.defaultFrom`; sender verification is a documented SendGrid prerequisite, not automated |
33
- | Templates | Terreno-side rendering (`templates.ts` from the abstraction) sent as `text`/`html`; SendGrid dynamic templates supported pass-through via `templateId` + `dynamicTemplateData` but not required |
34
- | Sandbox | SendGrid `mail_settings.sandbox_mode` toggle for CI/e2e so tests never send |
35
- | Delivery events | Phase 2: SendGrid Event Webhook (delivered/bounce/dropped/open) with ECDSA signature verification via the inbound-webhooks framework, mapped to `DeliveryEvent`s |
36
-
37
- ## Architecture
38
-
39
- ```typescript
40
- // @terreno/comms/adapters/sendgrid
41
- export class SendGridMailProvider implements MailProvider {
42
- readonly id = "sendgrid";
43
- constructor(options?: {
44
- apiKey?: string; // default env SENDGRID_API_KEY
45
- fromEmail?: string;
46
- fromName?: string;
47
- sandboxMode?: boolean; // default true when NODE_ENV === "test"
48
- });
49
- sendMail(message: MailMessage): Promise<SendResult>;
50
- }
51
- ```
52
-
53
- Error mapping: SendGrid 4xx (bad address, unverified sender) → `accepted: false` with the
54
- response body's first error message in `SendResult.error` and full body in
55
- `CommsMessage.metadata`; 429/5xx retried once by the core facade. The provider never
56
- throws through `sendMail`.
57
-
58
- ## Models / APIs / Notifications / UI
59
-
60
- None new. Phase 2 adds one webhook route via the inbound-webhooks framework.
61
-
62
- ## Phases
63
-
64
- 1. **Send path:** provider, config resolution, sandbox mode, error mapping, mocked-client
65
- tests; example-backend env-gated registration; docs (including the sender-verification
66
- prerequisite checklist).
67
- 2. **Delivery events** *(gated on inbound-webhooks IP)*: Event Webhook route with ECDSA
68
- signature verification; delivered/bounce/dropped/open → `DeliveryEvent` →
69
- `CommsMessage.status`.
70
-
71
- ## Feature Flags & Migrations
72
-
73
- None.
74
-
75
- ## Activity Log & User Updates
76
-
77
- All sends logged to `CommsMessage` with provider `sendgrid`.
78
-
79
- ## Not Included / Future Work
80
-
81
- - Suppression-list management, unsubscribe groups.
82
- - Batch sending beyond the multiple-recipient `to` array.
83
-
84
- ## Files to Create / Modify
85
-
86
- - `comms/src/adapters/sendgrid.ts` + tests
87
- - `comms/package.json` — optional peer `@sendgrid/mail`
88
- - `example-backend/src/server.ts` — env-gated registration
89
- - `docs/reference/comms.md`, `docs/reference/environment-variables.md`
90
-
91
- ## Task List
92
-
93
- See [docs/tasks/comms-adapter-sendgrid.md](../tasks/comms-adapter-sendgrid.md).
94
-
95
- ## Acceptance Criteria
96
-
97
- - [ ] `sendMail` delivers text/html mail with from-address fallback chain (provider option
98
- → `CommsApp.defaultFrom`), and passes `templateId`/`dynamicTemplateData` through when
99
- given.
100
- - [ ] Sandbox mode is on by default under test and produces accepted results without real
101
- sends.
102
- - [ ] SendGrid 4xx errors surface as `accepted: false` with the SendGrid error message;
103
- nothing throws through the facade.
104
- - [ ] Missing API key fails fast at `CommsApp` registration with a clear error.
105
- - [ ] Apps not using the adapter do not install `@sendgrid/mail`.
106
- - [ ] (Phase 2) Event webhook updates `CommsMessage.status` only for
107
- signature-verified payloads.
@@ -1,102 +0,0 @@
1
- # Implementation Plan: Comms adapter — Twilio SMS
2
-
3
- **Status:** Draft
4
- **Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1020
5
- **Priority:** Medium
6
- **Effort:** Small batch
7
- **Owner:** unassigned
8
- **Created:** 2026-08-09
9
- **Program:** [B2B platform](b2b-platform-program.md)
10
- **Depends on:** [comms-abstraction](comms-abstraction.md); inbound-webhooks (Phase 2 only)
11
- **RTK deprecation flag:** None — backend only
12
-
13
- ## Goal
14
-
15
- Implement `SmsProvider` on Twilio Programmable Messaging so Terreno apps can send
16
- transactional SMS (OTP fallback, alerts, invitation nudges) through the `@terreno/comms`
17
- facade with delivery logging.
18
-
19
- ## Non-Goals
20
-
21
- - OTP verification (that is `comms-adapter-twilio-verify`, on Twilio Verify).
22
- - Push via Twilio (dropped by decision D5 — Expo push is the push adapter).
23
- - Bulk/campaign messaging, MMS/RCS.
24
- - Phone-number provisioning automation.
25
-
26
- ## Decisions
27
-
28
- | Question | Decision |
29
- |----------|----------|
30
- | SDK | `twilio` as optional peer, subpath `@terreno/comms/adapters/twilioSms` |
31
- | Sender config | Prefer `TWILIO_MESSAGING_SERVICE_SID`; fall back to `TWILIO_FROM_NUMBER`; constructor options override env |
32
- | Number validation | Validate/normalize to E.164 with `libphonenumber-js` (already in catalog) before hitting the API |
33
- | Delivery status | Phase 2: status callback endpoint via the inbound-webhooks framework mapping Twilio statuses to `DeliveryEvent`s |
34
- | Secrets | `TWILIO_ACCOUNT_SID` + `TWILIO_AUTH_TOKEN` via env or the existing secret-provider layer |
35
-
36
- ## Architecture
37
-
38
- ```typescript
39
- // @terreno/comms/adapters/twilioSms
40
- export class TwilioSmsProvider implements SmsProvider {
41
- readonly id = "twilio";
42
- constructor(options?: {
43
- accountSid?: string; // default env TWILIO_ACCOUNT_SID
44
- authToken?: string; // default env TWILIO_AUTH_TOKEN
45
- messagingServiceSid?: string;
46
- fromNumber?: string;
47
- statusCallbackUrl?: string; // Phase 2
48
- });
49
- sendSms(message: {to: string; body: string}): Promise<SendResult>;
50
- }
51
- ```
52
-
53
- Errors map Twilio exception codes to `SendResult.error` with the Twilio error code kept in
54
- `CommsMessage.metadata` for triage. Invalid destination numbers fail fast with a
55
- `BadRequestError` before any API call.
56
-
57
- ## Models / APIs / Notifications / UI
58
-
59
- None new — Phase 2 adds one webhook route via the inbound-webhooks framework.
60
-
61
- ## Phases
62
-
63
- 1. **Send path:** provider, config resolution, E.164 validation, error mapping, tests with
64
- mocked Twilio client; example-backend env-gated registration; docs.
65
- 2. **Delivery callbacks** *(gated on inbound-webhooks IP)*: status callback route with
66
- Twilio signature verification, statuses → `DeliveryEvent` → `CommsMessage.status`
67
- updates.
68
-
69
- ## Feature Flags & Migrations
70
-
71
- None.
72
-
73
- ## Activity Log & User Updates
74
-
75
- All sends logged to `CommsMessage` with provider `twilio`.
76
-
77
- ## Not Included / Future Work
78
-
79
- - Inbound SMS (replies) handling.
80
- - Alphanumeric sender IDs, international compliance tooling.
81
-
82
- ## Files to Create / Modify
83
-
84
- - `comms/src/adapters/twilioSms.ts` + tests
85
- - `comms/package.json` — optional peer `twilio`
86
- - `example-backend/src/server.ts` — env-gated registration
87
- - `docs/reference/comms.md`, `docs/reference/environment-variables.md`
88
-
89
- ## Task List
90
-
91
- See [docs/tasks/comms-adapter-twilio-sms.md](../tasks/comms-adapter-twilio-sms.md).
92
-
93
- ## Acceptance Criteria
94
-
95
- - [ ] `sendSms` delivers via messaging service or from-number config, preferring the
96
- messaging service when both are present.
97
- - [ ] A non-E.164 destination fails with a 400 `APIError` before any Twilio call.
98
- - [ ] Twilio API errors produce `accepted: false` results with the Twilio error code in
99
- `CommsMessage.metadata`; nothing throws through the facade.
100
- - [ ] Apps not using the adapter do not install the `twilio` SDK.
101
- - [ ] (Phase 2) Status callbacks flip `CommsMessage.status` to `delivered`/`failed` with
102
- verified Twilio signatures.
@@ -1,93 +0,0 @@
1
- # Implementation Plan: Comms adapter — Twilio Verify (OTP)
2
-
3
- **Status:** Draft
4
- **Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1021
5
- **Priority:** Medium
6
- **Effort:** Small batch
7
- **Owner:** unassigned
8
- **Created:** 2026-08-09
9
- **Program:** [B2B platform](b2b-platform-program.md)
10
- **Depends on:** [comms-abstraction](comms-abstraction.md)
11
- **RTK deprecation flag:** None — backend only
12
-
13
- ## Goal
14
-
15
- Implement `VerificationProvider` on Twilio Verify so Terreno apps get managed one-time-code
16
- flows (SMS and email channels) without storing, expiring, or rate-limiting codes
17
- themselves. This is the delivery channel the future `mfa-step-up-auth` work builds on, and
18
- it is immediately usable for phone-number verification.
19
-
20
- ## Non-Goals
21
-
22
- - The MFA enrollment/step-up product itself (`mfa-step-up-auth` item).
23
- - TOTP (app-authenticator) support — that is code-local (`otpauth`), not a Verify concern.
24
- - Custom code storage or self-managed rate limiting (Verify owns both).
25
-
26
- ## Decisions
27
-
28
- | Question | Decision |
29
- |----------|----------|
30
- | SDK | `twilio` optional peer (shared with the SMS adapter), subpath `@terreno/comms/adapters/twilioVerify` |
31
- | Service config | `TWILIO_VERIFY_SERVICE_SID` env or constructor option |
32
- | Channels | `sms` and `email` (Verify's email channel requires a configured Verify email integration; documented, not automated) |
33
- | Abuse control | Rely on Verify's built-in rate limits; add Terreno-side per-user attempt caps only when `rate-limiting` IP lands |
34
- | Logging | Start/check attempts logged to `CommsMessage` with channel `verification`, never logging the code |
35
-
36
- ## Architecture
37
-
38
- ```typescript
39
- // @terreno/comms/adapters/twilioVerify
40
- export class TwilioVerifyProvider implements VerificationProvider {
41
- readonly id = "twilio-verify";
42
- constructor(options?: {accountSid?: string; authToken?: string; verifyServiceSid?: string});
43
- startVerification(options: {to: string; channel: "sms" | "email"}): Promise<SendResult>;
44
- checkVerification(options: {to: string; code: string}): Promise<{valid: boolean}>;
45
- }
46
- ```
47
-
48
- `checkVerification` maps Verify's `approved` status to `valid: true`; `pending`, `expired`,
49
- and max-attempt states return `valid: false` with reason in the result error, letting
50
- callers throw the appropriate `APIError`.
51
-
52
- ## Models / APIs / Notifications / UI
53
-
54
- None new. Consumer routes (e.g. `POST /auth/verifyPhone`) arrive with the features that
55
- need them; this IP ships the provider plus example-backend registration only.
56
-
57
- ## Phases
58
-
59
- Single phase.
60
-
61
- ## Feature Flags & Migrations
62
-
63
- None.
64
-
65
- ## Activity Log & User Updates
66
-
67
- Verification attempts logged to `CommsMessage` (no codes, destination redacted to
68
- last-4).
69
-
70
- ## Not Included / Future Work
71
-
72
- - MFA enrollment, recovery codes, biometric step-up (`mfa-step-up-auth`).
73
- - WhatsApp/voice channels.
74
- - Android SMS autofill hash configuration (`react-native-otp-verify`, decision D7).
75
-
76
- ## Files to Create / Modify
77
-
78
- - `comms/src/adapters/twilioVerify.ts` + tests (mocked Twilio client)
79
- - `example-backend/src/server.ts` — env-gated registration
80
- - `docs/reference/comms.md`, `docs/reference/environment-variables.md`
81
-
82
- ## Task List
83
-
84
- See [docs/tasks/comms-adapter-twilio-verify.md](../tasks/comms-adapter-twilio-verify.md).
85
-
86
- ## Acceptance Criteria
87
-
88
- - [ ] `startVerification` creates a Verify verification on the configured service for sms
89
- and email channels.
90
- - [ ] `checkVerification` returns `valid: true` only for `approved`; expired and
91
- max-attempt states return `valid: false` with a reason.
92
- - [ ] No OTP code ever appears in logs or `CommsMessage` rows; destinations are redacted.
93
- - [ ] Missing `TWILIO_VERIFY_SERVICE_SID` fails fast at registration with a clear error.