@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.
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +15 -16
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/templates/bootstrap/backend/types/models/userTypes.template.md +4 -5
- package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
- package/dist/docs/templates/tools/model.template.md +2 -4
- package/dist/docs/versioned/next/README.md +1 -0
- package/dist/docs/versioned/next/explanation/README.md +1 -7
- package/dist/docs/versioned/next/how-to/README.md +2 -8
- package/dist/docs/versioned/next/how-to/deploy-to-gcp.md +228 -20
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
- package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +4 -57
- package/dist/docs/versioned/next/implementationPlans/README.md +30 -56
- package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +1 -2
- package/dist/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/deploy-to-gcp.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/deploy-to-vercel.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/deployment-foundation.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/docs-reference-coverage.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/examples-demo-coverage.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/oss-governance-baseline.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
- package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
- package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
- package/dist/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +0 -1
- package/dist/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +0 -1
- package/dist/docs/versioned/next/reference/README.md +1 -4
- package/dist/docs/versioned/next/reference/environment-variables.md +382 -220
- package/dist/docs/versioned/next/reference/syncdb.md +456 -0
- package/dist/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
- package/dist/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
- package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
- package/dist/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
- package/dist/docs/versioned/next/tasks/deployment-foundation.md +12 -12
- package/dist/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
- package/dist/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
- package/dist/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
- package/dist/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
- package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
- package/dist/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
- package/dist/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
- package/package.json +4 -5
- package/src/docs/templates/bootstrap/backend/types/models/userTypes.template.md +4 -5
- package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
- package/src/docs/templates/tools/model.template.md +2 -4
- package/src/docs/versioned/next/README.md +1 -0
- package/src/docs/versioned/next/explanation/README.md +1 -7
- package/src/docs/versioned/next/how-to/README.md +2 -8
- package/src/docs/versioned/next/how-to/deploy-to-gcp.md +228 -20
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
- package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +4 -57
- package/src/docs/versioned/next/implementationPlans/README.md +30 -56
- package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +1 -2
- package/src/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +0 -1
- package/src/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +0 -1
- package/src/docs/versioned/next/implementationPlans/deploy-to-gcp.md +0 -1
- package/src/docs/versioned/next/implementationPlans/deploy-to-vercel.md +0 -1
- package/src/docs/versioned/next/implementationPlans/deployment-foundation.md +0 -1
- package/src/docs/versioned/next/implementationPlans/docs-reference-coverage.md +0 -1
- package/src/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +0 -1
- package/src/docs/versioned/next/implementationPlans/examples-demo-coverage.md +0 -1
- package/src/docs/versioned/next/implementationPlans/oss-governance-baseline.md +0 -1
- package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +0 -1
- package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +0 -1
- package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
- package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
- package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
- package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
- package/src/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +0 -1
- package/src/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +0 -1
- package/src/docs/versioned/next/reference/README.md +1 -4
- package/src/docs/versioned/next/reference/environment-variables.md +382 -220
- package/src/docs/versioned/next/reference/syncdb.md +456 -0
- package/src/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
- package/src/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
- package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
- package/src/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
- package/src/docs/versioned/next/tasks/deployment-foundation.md +12 -12
- package/src/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
- package/src/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
- package/src/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
- package/src/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
- package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
- package/src/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
- package/src/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
- package/LICENSE +0 -21
- package/dist/__tests__/bootstrap.test.d.ts +0 -2
- package/dist/__tests__/bootstrap.test.d.ts.map +0 -1
- package/dist/__tests__/bootstrap.test.js +0 -299
- package/dist/__tests__/bootstrap.test.js.map +0 -1
- package/dist/__tests__/databaseQuery.test.d.ts +0 -2
- package/dist/__tests__/databaseQuery.test.d.ts.map +0 -1
- package/dist/__tests__/databaseQuery.test.js +0 -83
- package/dist/__tests__/databaseQuery.test.js.map +0 -1
- package/dist/__tests__/docsRoot.test.d.ts +0 -2
- package/dist/__tests__/docsRoot.test.d.ts.map +0 -1
- package/dist/__tests__/docsRoot.test.js +0 -59
- package/dist/__tests__/docsRoot.test.js.map +0 -1
- package/dist/__tests__/inferPackages.test.d.ts +0 -2
- package/dist/__tests__/inferPackages.test.d.ts.map +0 -1
- package/dist/__tests__/inferPackages.test.js +0 -35
- package/dist/__tests__/inferPackages.test.js.map +0 -1
- package/dist/__tests__/preload.d.ts +0 -2
- package/dist/__tests__/preload.d.ts.map +0 -1
- package/dist/__tests__/preload.js +0 -12
- package/dist/__tests__/preload.js.map +0 -1
- package/dist/__tests__/prompts.test.d.ts +0 -2
- package/dist/__tests__/prompts.test.d.ts.map +0 -1
- package/dist/__tests__/prompts.test.js +0 -295
- package/dist/__tests__/prompts.test.js.map +0 -1
- package/dist/__tests__/resources.test.d.ts +0 -2
- package/dist/__tests__/resources.test.d.ts.map +0 -1
- package/dist/__tests__/resources.test.js +0 -352
- package/dist/__tests__/resources.test.js.map +0 -1
- package/dist/__tests__/search.test.d.ts +0 -2
- package/dist/__tests__/search.test.d.ts.map +0 -1
- package/dist/__tests__/search.test.js +0 -163
- package/dist/__tests__/search.test.js.map +0 -1
- package/dist/__tests__/tools.test.d.ts +0 -2
- package/dist/__tests__/tools.test.d.ts.map +0 -1
- package/dist/__tests__/tools.test.js +0 -540
- package/dist/__tests__/tools.test.js.map +0 -1
- package/dist/__tests__/upgradeGuide.test.d.ts +0 -2
- package/dist/__tests__/upgradeGuide.test.d.ts.map +0 -1
- package/dist/__tests__/upgradeGuide.test.js +0 -22
- package/dist/__tests__/upgradeGuide.test.js.map +0 -1
- package/dist/docs/upgrades/0.31.0.md +0 -60
- package/dist/docs/versioned/next/explanation/deployment-architecture-gcp.md +0 -65
- package/dist/docs/versioned/next/explanation/deployment-baseline.md +0 -78
- package/dist/docs/versioned/next/explanation/positioning.md +0 -164
- package/dist/docs/versioned/next/explanation/repository-settings.md +0 -44
- package/dist/docs/versioned/next/explanation/roadmap-process.md +0 -330
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +0 -866
- package/dist/docs/versioned/next/how-to/build-for-web.md +0 -69
- package/dist/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +0 -115
- package/dist/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +0 -183
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +0 -114
- package/dist/docs/versioned/next/implementationPlans/billing-stripe.md +0 -158
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +0 -240
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +0 -107
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +0 -107
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +0 -102
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +0 -93
- package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +0 -188
- package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +0 -269
- package/dist/docs/versioned/next/implementationPlans/native-module-baseline.md +0 -105
- package/dist/docs/versioned/next/implementationPlans/orgs-and-teams.md +0 -158
- package/dist/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +0 -147
- package/dist/docs/versioned/next/reference/admin-spa.md +0 -130
- package/dist/docs/versioned/next/reference/ai.md +0 -519
- package/dist/docs/versioned/next/reference/test.md +0 -108
- package/dist/docs/versioned/next/roadmap.md +0 -9
- package/dist/docs/versioned/next/tasks/README.md +0 -42
- package/dist/docs/versioned/next/tasks/billing-stripe.md +0 -75
- package/dist/docs/versioned/next/tasks/comms-abstraction.md +0 -77
- package/dist/docs/versioned/next/tasks/comms-adapter-expo-push.md +0 -29
- package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +0 -29
- package/dist/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +0 -29
- package/dist/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +0 -19
- package/dist/docs/versioned/next/tasks/infra-mcp.md +0 -43
- package/dist/docs/versioned/next/tasks/native-module-baseline.md +0 -42
- package/dist/docs/versioned/next/tasks/orgs-and-teams.md +0 -70
- package/dist/docs/versioned/next/tasks/password-reset-and-email-verification.md +0 -60
- package/src/docs/upgrades/0.31.0.md +0 -60
- package/src/docs/versioned/next/explanation/deployment-architecture-gcp.md +0 -65
- package/src/docs/versioned/next/explanation/deployment-baseline.md +0 -78
- package/src/docs/versioned/next/explanation/positioning.md +0 -164
- package/src/docs/versioned/next/explanation/repository-settings.md +0 -44
- package/src/docs/versioned/next/explanation/roadmap-process.md +0 -330
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +0 -866
- package/src/docs/versioned/next/how-to/build-for-web.md +0 -69
- package/src/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +0 -115
- package/src/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +0 -183
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +0 -114
- package/src/docs/versioned/next/implementationPlans/billing-stripe.md +0 -158
- package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +0 -240
- package/src/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +0 -107
- package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +0 -107
- package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +0 -102
- package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +0 -93
- package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +0 -188
- package/src/docs/versioned/next/implementationPlans/infra-mcp.md +0 -269
- package/src/docs/versioned/next/implementationPlans/native-module-baseline.md +0 -105
- package/src/docs/versioned/next/implementationPlans/orgs-and-teams.md +0 -158
- package/src/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +0 -147
- package/src/docs/versioned/next/reference/admin-spa.md +0 -130
- package/src/docs/versioned/next/reference/ai.md +0 -519
- package/src/docs/versioned/next/reference/test.md +0 -108
- package/src/docs/versioned/next/roadmap.md +0 -9
- package/src/docs/versioned/next/tasks/README.md +0 -42
- package/src/docs/versioned/next/tasks/billing-stripe.md +0 -75
- package/src/docs/versioned/next/tasks/comms-abstraction.md +0 -77
- package/src/docs/versioned/next/tasks/comms-adapter-expo-push.md +0 -29
- package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +0 -29
- package/src/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +0 -29
- package/src/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +0 -19
- package/src/docs/versioned/next/tasks/infra-mcp.md +0 -43
- package/src/docs/versioned/next/tasks/native-module-baseline.md +0 -42
- package/src/docs/versioned/next/tasks/orgs-and-teams.md +0 -70
- package/src/docs/versioned/next/tasks/password-reset-and-email-verification.md +0 -60
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
# How to Migrate from @terreno/rtk to @terreno/syncdb
|
|
2
|
+
|
|
3
|
+
This guide is **AI-context-first**: it is written for an agent (or human) performing a screen-by-screen migration, not as a codemod. Work through one concern at a time — reads, then writes, then conflicts, then sync-status UX — and delete RTK-era code as you go.
|
|
4
|
+
|
|
5
|
+
`@terreno/syncdb` supersedes `@terreno/rtk` for **data synchronization** (CRUD reads/writes, offline queue, realtime convergence). It does not replace the generated OpenAPI SDK, Better Auth Redux wiring, or feature-flag infrastructure.
|
|
6
|
+
|
|
7
|
+
## 1. Before you start
|
|
8
|
+
|
|
9
|
+
| Decision | Requirement | Why |
|
|
10
|
+
|----------|-------------|-----|
|
|
11
|
+
| **Better Auth first?** | Recommended before or in parallel with data migration | `betterAuthAdapter` is the shipped `AuthProvider`; socket sessions work cleanly with `RealtimeApp({betterAuth})`. Legacy JWT sockets still work during transition. |
|
|
12
|
+
| **Backend version** | `@terreno/api` with `SyncApp`, `RealtimeApp`, `syncPlugin`, `isDeletedPlugin` | Without backend sync registration, the client has nothing to talk to. |
|
|
13
|
+
| **MongoDB replica set** | Required for `RealtimeApp` change streams | Single-node replset is fine for dev. |
|
|
14
|
+
| **Per-collection rollout** | One synced collection at a time | REST and sync share the same write path; migrate screen-by-screen. |
|
|
15
|
+
| **Redux** | Keep Redux for auth, feature flags, app state; drop RTK Query for migrated collections | See §2. |
|
|
16
|
+
|
|
17
|
+
**Auth can migrate before data (M3).** A typical two-step order:
|
|
18
|
+
|
|
19
|
+
1. **Step A — Auth:** Move login/session to Better Auth (`generateBetterAuthSlice`, `betterAuthAdapter`, `syncDb.start()` on login). Screens can still read/write via RTK Query during this step.
|
|
20
|
+
2. **Step B — Data:** For each collection, replace RTK Query hooks with syncdb hooks and delete the RTK path for that screen.
|
|
21
|
+
|
|
22
|
+
The example app completed both steps; todos are syncdb-only while profile/admin still use generated RTK hooks.
|
|
23
|
+
|
|
24
|
+
Reference: [`docs/reference/syncdb.md`](../reference/syncdb.md), and the package [`syncdb/README.md`](https://github.com/flourishhealth/terreno/blob/release-56.0.0/syncdb/README.md).
|
|
25
|
+
|
|
26
|
+
## 2. Install and configure
|
|
27
|
+
|
|
28
|
+
### Install packages
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bun install @terreno/syncdb
|
|
32
|
+
bunx expo install expo-sqlite # native persistence — install in the app, rebuild native
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Create the sync client
|
|
36
|
+
|
|
37
|
+
**After** (`example-frontend/store/syncdb.ts`):
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import {baseUrl} from "@terreno/rtk";
|
|
41
|
+
import {betterAuthAdapter, createSyncDb} from "@terreno/syncdb";
|
|
42
|
+
import {betterAuthClient} from "@/lib/betterAuth";
|
|
43
|
+
|
|
44
|
+
const authProvider = betterAuthAdapter(betterAuthClient, {pollIntervalMs: 60_000});
|
|
45
|
+
|
|
46
|
+
export const syncDb = createSyncDb({
|
|
47
|
+
authProvider,
|
|
48
|
+
baseUrl,
|
|
49
|
+
collections: ["todos"],
|
|
50
|
+
name: "terreno-example",
|
|
51
|
+
debug: __DEV__ ? {capacity: 1000} : false,
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Start/stop on auth
|
|
56
|
+
|
|
57
|
+
**After** (`example-frontend/app/_layout.tsx`):
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!userId) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let stopped = false;
|
|
65
|
+
syncDb
|
|
66
|
+
.start()
|
|
67
|
+
.then(() => {
|
|
68
|
+
if (!stopped) {
|
|
69
|
+
setSyncDbReady(true);
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
.catch((error) => {
|
|
73
|
+
console.error("[syncdb] Failed to start client", error);
|
|
74
|
+
});
|
|
75
|
+
return () => {
|
|
76
|
+
stopped = true;
|
|
77
|
+
setSyncDbReady(false);
|
|
78
|
+
void syncDb.stop();
|
|
79
|
+
};
|
|
80
|
+
}, [userId, syncDbStartAttempt]);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Gate writes with a ready flag (`useSyncDbReady`) so `mutate()` is not called before `start()` resolves a user.
|
|
84
|
+
|
|
85
|
+
### Wrap screens with `SyncDbProvider`
|
|
86
|
+
|
|
87
|
+
**After** (`example-frontend/app/(tabs)/index.tsx`):
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import {SyncDbProvider} from "@terreno/syncdb/react";
|
|
91
|
+
import {syncDb} from "@/store/syncdb";
|
|
92
|
+
|
|
93
|
+
const TodosScreen = () => (
|
|
94
|
+
<SyncDbProvider client={syncDb}>
|
|
95
|
+
<SyncTodosScreen />
|
|
96
|
+
</SyncDbProvider>
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The example also mounts `SyncDbProvider` at the root (`_layout.tsx`) for `SyncHealthToast`.
|
|
101
|
+
|
|
102
|
+
### Redux store: keep vs remove
|
|
103
|
+
|
|
104
|
+
| Keep on Redux | Remove for migrated collections |
|
|
105
|
+
|---------------|--------------------------------|
|
|
106
|
+
| `generateBetterAuthSlice` / session | `generateAuthSlice` (JWT) once Better Auth ships |
|
|
107
|
+
| `terrenoApi` reducer for **non-synced** routes | `useGetTodosQuery` / todo mutations |
|
|
108
|
+
| `createOfflineMiddleware` + offline slice | `realtimeList` / `realtimeDocument` for that collection |
|
|
109
|
+
| Feature-flag / app-state slices | Per-screen `isLoading` spinners tied to RTK mutations |
|
|
110
|
+
|
|
111
|
+
**Before** (`origin/master:example-frontend/store/index.ts`): `generateAuthSlice`, `createOfflineMiddleware`, offline payload sessionStorage.
|
|
112
|
+
|
|
113
|
+
**After** (`example-frontend/store/index.ts`): `generateBetterAuthSlice`, `terrenoApi` only — no offline middleware.
|
|
114
|
+
|
|
115
|
+
## 3. Reads
|
|
116
|
+
|
|
117
|
+
There is no `isLoading` for reads after bootstrap — data is already in the local store.
|
|
118
|
+
|
|
119
|
+
### List reads
|
|
120
|
+
|
|
121
|
+
**Before** (`origin/master:example-frontend/app/(tabs)/index.tsx`):
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const {data: todosData, isLoading, refetch, isFetching} = useGetTodosQuery({}, {skip: !userId});
|
|
125
|
+
const todos = todosData?.data ?? [];
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**After** (`example-frontend/components/SyncTodosScreen.tsx`):
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import {useEntity, useEntityIds} from "@terreno/syncdb/react";
|
|
132
|
+
|
|
133
|
+
const incompleteIds = useEntityIds<SyncTodo>("todos", {
|
|
134
|
+
filter: (t) => !t.completed,
|
|
135
|
+
sort: sortByCreatedDesc,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Per row:
|
|
139
|
+
const {data} = useEntity<SyncTodo>("todos", id);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For small lists, `useQuery` is fine:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import {useQuery} from "@terreno/syncdb/react";
|
|
146
|
+
const todos = useQuery<Todo>("todos", {filter: (t) => !t.completed});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`filter` / `sort` run in JS — there are no server query params. Tombstones are excluded unless `{includeDeleted: true}`.
|
|
150
|
+
|
|
151
|
+
### Delete this RTK read code
|
|
152
|
+
|
|
153
|
+
- `useGetTodosQuery` / `useGet*Query` for the migrated collection
|
|
154
|
+
- `isLoading`, `isFetching`, `refetch`, `RefreshControl` wired to list fetch
|
|
155
|
+
- `skip: !userId` guards on list queries (replace with `useSyncDbReady` on writes; reads are safe once bootstrapped)
|
|
156
|
+
- `realtimeList("todos")` / `realtimeDocument("todos")` in `store/sdk.ts` for that collection
|
|
157
|
+
|
|
158
|
+
## 4. Writes
|
|
159
|
+
|
|
160
|
+
Writes are synchronous from the UI's perspective: local apply + outbox enqueue + background replay.
|
|
161
|
+
|
|
162
|
+
### Create / update / delete
|
|
163
|
+
|
|
164
|
+
**Before** (`origin/master:example-frontend/app/(tabs)/index.tsx`):
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const [createTodo, {isLoading: isCreating}] = usePostTodosMutation();
|
|
168
|
+
const [updateTodo] = usePatchTodosByIdMutation();
|
|
169
|
+
const [deleteTodo] = useDeleteTodosByIdMutation();
|
|
170
|
+
|
|
171
|
+
await createTodo({title, completed: false}).unwrap();
|
|
172
|
+
await updateTodo({id, completed: true}).unwrap();
|
|
173
|
+
await deleteTodo(id).unwrap();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**After** (`example-frontend/components/SyncTodosScreen.tsx`):
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import {generateMutationId} from "@terreno/syncdb";
|
|
180
|
+
import {useMutate} from "@terreno/syncdb/react";
|
|
181
|
+
|
|
182
|
+
const {create, update, remove} = useMutate("todos");
|
|
183
|
+
|
|
184
|
+
const id = generateMutationId();
|
|
185
|
+
create({data: {_id: id, title, completed: false, created: DateTime.now().toISO()}});
|
|
186
|
+
update({id, data: {completed: true}});
|
|
187
|
+
remove({id});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Client-minted `_id` on creates lets the optimistic row render before the server acks.
|
|
191
|
+
|
|
192
|
+
### Delete this RTK write code
|
|
193
|
+
|
|
194
|
+
- `usePost*Mutation`, `usePatch*Mutation`, `useDelete*Mutation` for the migrated collection
|
|
195
|
+
- `.unwrap()` / try-catch around mutation promises for happy-path UX
|
|
196
|
+
- **`isLoading` / `isCreating` / `isUpdating` spinners on write buttons** — syncdb writes do not await the server
|
|
197
|
+
- Manual optimistic cache updates (`updateQueryData`, `upsertQueryData`, temporary local rows in component state)
|
|
198
|
+
- `refetch()` or tag invalidation after mutate (`invalidatesTags` for that collection)
|
|
199
|
+
- `createOfflineMiddleware` endpoint list entries for that collection (`configureOfflineMutationEndpoints`)
|
|
200
|
+
- `If-Unmodified-Since` / 409 handling in custom mutation code (conflicts move to `useConflicts()`)
|
|
201
|
+
|
|
202
|
+
Server rejection surfaces later as outbox nacks — conflicts in `useConflicts()`, terminal failures in `getSyncStatus().failedCount`.
|
|
203
|
+
|
|
204
|
+
## 5. Conflicts
|
|
205
|
+
|
|
206
|
+
A **conflict** means the client's `baseVersion` (last seen `_syncSeq`) disagrees with the server. The server returns a `conflict` nack:
|
|
207
|
+
|
|
208
|
+
- HTTP: `POST /sync/mutate` → **409** with `{nack: {code: "conflict", serverDoc, serverSeq, ...}}`
|
|
209
|
+
- Socket: `sync:nack` with `code: "conflict"`
|
|
210
|
+
|
|
211
|
+
The client records the conflict locally; the UI must let the user pick a side.
|
|
212
|
+
|
|
213
|
+
### Strategies
|
|
214
|
+
|
|
215
|
+
| Strategy | When to use |
|
|
216
|
+
|----------|-------------|
|
|
217
|
+
| `useServer` | Accept canonical server data (or tombstone if server deleted the doc) |
|
|
218
|
+
| `keepMine` | Re-enqueue local changes with a fresh `baseVersion` |
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import {useConflicts} from "@terreno/syncdb/react";
|
|
222
|
+
|
|
223
|
+
const {conflicts, resolve} = useConflicts();
|
|
224
|
+
resolve({mutationId, strategy: "useServer"});
|
|
225
|
+
resolve({mutationId, strategy: "keepMine"});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Minimum UI
|
|
229
|
+
|
|
230
|
+
The example app uses:
|
|
231
|
+
|
|
232
|
+
- `SyncConflictsController` — single app-wide sheet state (`example-frontend/components/SyncConflictsController.tsx`)
|
|
233
|
+
- `ConflictSheet` rendered from `SyncHealthToast` (`example-frontend/app/_layout.tsx`)
|
|
234
|
+
- `SyncStatusBanner` conflict badge → `openConflicts("todos")` (`example-frontend/components/SyncTodosScreen.tsx`)
|
|
235
|
+
|
|
236
|
+
Copy that pattern or build equivalent: show local vs server fields, two resolution actions, block further edits on conflicted entities until resolved.
|
|
237
|
+
|
|
238
|
+
## 6. Sync status
|
|
239
|
+
|
|
240
|
+
Replace **request-loading UX** with **sync-state UX**.
|
|
241
|
+
|
|
242
|
+
| RTK era | Syncdb era |
|
|
243
|
+
|---------|------------|
|
|
244
|
+
| `isLoading` on queries | No list loading spinner (data is local) |
|
|
245
|
+
| `useOfflineStatus` / `useServerStatus` | `useSyncStatus()` |
|
|
246
|
+
| `OfflineBanner` on fetch failure | `SyncStatusBanner` + `SyncHealthToast` |
|
|
247
|
+
| Pull-to-refresh `refetch()` | Optional `client.forceResync()` for support tooling |
|
|
248
|
+
|
|
249
|
+
**After** (`example-frontend/components/SyncTodosScreen.tsx`):
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import {useSyncStatus} from "@terreno/syncdb/react";
|
|
253
|
+
import {SyncStatusBanner} from "@terreno/ui";
|
|
254
|
+
|
|
255
|
+
const syncStatus = useSyncStatus();
|
|
256
|
+
|
|
257
|
+
<SyncStatusBanner
|
|
258
|
+
isOnline={syncStatus.isOnline}
|
|
259
|
+
queuedCount={syncStatus.queuedCount}
|
|
260
|
+
conflictCount={syncStatus.conflictCount}
|
|
261
|
+
failedCount={syncStatus.failedCount}
|
|
262
|
+
paused={syncStatus.paused}
|
|
263
|
+
draining={syncStatus.draining}
|
|
264
|
+
sentThisDrain={syncStatus.sentThisDrain}
|
|
265
|
+
totalThisDrain={syncStatus.totalThisDrain}
|
|
266
|
+
onOpenConflicts={openConflictSheet}
|
|
267
|
+
onAuthRequired={handleAuthRequired}
|
|
268
|
+
/>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`SyncHealthToast` (`example-frontend/components/SyncHealthToast.tsx`) adds persistent toasts for per-collection conflicts/failures and an initial "Syncing…" toast with optional force reload.
|
|
272
|
+
|
|
273
|
+
`paused: "auth"` means replay is halted until the same user re-authenticates — wire `onAuthRequired` to your login flow.
|
|
274
|
+
|
|
275
|
+
## 7. Auth
|
|
276
|
+
|
|
277
|
+
**Auth can ship before data migration.** Complete Better Auth + `betterAuthAdapter` first; keep RTK Query for reads/writes until each screen migrates.
|
|
278
|
+
|
|
279
|
+
### Better Auth adapter
|
|
280
|
+
|
|
281
|
+
**After** (`example-frontend/store/syncdb.ts`):
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import {betterAuthAdapter, createSyncDb} from "@terreno/syncdb";
|
|
285
|
+
import {betterAuthClient} from "@/lib/betterAuth";
|
|
286
|
+
|
|
287
|
+
const authProvider = betterAuthAdapter(syncAuthClient, {pollIntervalMs: 60_000});
|
|
288
|
+
|
|
289
|
+
export const syncDb = createSyncDb({authProvider, baseUrl, collections: ["todos"], name: "terreno-example"});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`betterAuthAdapter` implements `AuthProvider`:
|
|
293
|
+
|
|
294
|
+
- `getToken()` / `getUserId()` — read session per request (not cached)
|
|
295
|
+
- `onAuthChange` — session atom subscription (example bridges `$store.atoms.session`)
|
|
296
|
+
- `refresh()` — one silent refresh per auth-pause episode
|
|
297
|
+
|
|
298
|
+
### Token storage
|
|
299
|
+
|
|
300
|
+
Better Auth session tokens live in the Better Auth client (`@terreno/rtk` `createBetterAuthClient`):
|
|
301
|
+
|
|
302
|
+
- **Native:** `expo-secure-store`
|
|
303
|
+
- **Web:** `@react-native-async-storage/async-storage`
|
|
304
|
+
|
|
305
|
+
Syncdb does not store tokens itself — it calls `authProvider` on every transport/HTTP request.
|
|
306
|
+
|
|
307
|
+
### Socket auth and `sync:auth-expired`
|
|
308
|
+
|
|
309
|
+
On connect, the socket transport sends the bearer token from `getToken()`. When the server's session re-validation sweep finds an expired/disabled session, it emits `sync:auth-expired` then disconnects (`api/src/realtime/sessionRevalidation.ts`). The client maps this to `paused: "auth"` — **no local wipe**, outbox preserved (INV-2).
|
|
310
|
+
|
|
311
|
+
### Backend
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
new RealtimeApp({betterAuth: {auth, userModel: User}})
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Required for Better Auth socket sessions. Legacy JWT sockets continue to work without it.
|
|
318
|
+
|
|
319
|
+
## 8. Codegen
|
|
320
|
+
|
|
321
|
+
### Does `bun run sdk` still work?
|
|
322
|
+
|
|
323
|
+
**Yes.** `example-frontend/package.json` still defines:
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
"sdk": "bun scripts/generate-sdk.ts && bun biome check --write scripts/generate-sdk.ts"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
It runs `@rtk-query/codegen-openapi` against `openapi-config.ts` and writes `store/openApiSdk.ts`.
|
|
330
|
+
|
|
331
|
+
### What changes post-migration
|
|
332
|
+
|
|
333
|
+
| Still generated | Stop using for migrated collections |
|
|
334
|
+
|-----------------|-------------------------------------|
|
|
335
|
+
| Auth routes, `GET /auth/me`, admin, AI explorer, version config, feature flags | `useGetTodosQuery`, `usePostTodosMutation`, etc. |
|
|
336
|
+
| Custom REST / RPC endpoints | Todo `realtimeList` / `realtimeDocument` wiring in `store/sdk.ts` |
|
|
337
|
+
|
|
338
|
+
Keep running `bun run sdk` after backend route changes — non-synced screens still import from `store/sdk.ts`.
|
|
339
|
+
|
|
340
|
+
Workflow:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
# Backend running on port 4000
|
|
344
|
+
cd example-frontend && bun run sdk
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## 9. Feature flags
|
|
348
|
+
|
|
349
|
+
Post-migration, feature flags stay on `@terreno/rtk` + OpenFeature — **not** on syncdb.
|
|
350
|
+
|
|
351
|
+
**After** (`example-frontend/app/_layout.tsx`):
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import {OpenFeatureProvider} from "@openfeature/react-sdk";
|
|
355
|
+
import {useTerrenoFeatureFlags} from "@terreno/rtk";
|
|
356
|
+
|
|
357
|
+
const OpenFeatureBridge = ({children, socket}) => {
|
|
358
|
+
const bridgeUserId = useSelector(selectBetterAuthUserId) ?? undefined;
|
|
359
|
+
useTerrenoFeatureFlags(terrenoApi, {skip: !bridgeUserId, socket, userId: bridgeUserId});
|
|
360
|
+
return <OpenFeatureProvider domain="feature-flags">{children}</OpenFeatureProvider>;
|
|
361
|
+
};
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
See [`docs/reference/feature-flags.md`](../reference/feature-flags.md) and [`docs/how-to/add-feature-flags.md`](add-feature-flags.md).
|
|
365
|
+
|
|
366
|
+
**Example app gap:** todos do **not** gate on a feature flag — `SyncTodosScreen` is syncdb-only. For a gradual rollout, add a boolean flag and render the RTK screen when off, syncdb screen when on (see §10). The reference migration intentionally skipped flag wiring to keep one data path for e2e tests.
|
|
367
|
+
|
|
368
|
+
## 10. Rollback
|
|
369
|
+
|
|
370
|
+
### Per-screen feature flag
|
|
371
|
+
|
|
372
|
+
Ship both implementations behind a flag:
|
|
373
|
+
|
|
374
|
+
- Flag **off** → legacy RTK Query screen
|
|
375
|
+
- Flag **on** → syncdb screen
|
|
376
|
+
|
|
377
|
+
Both bundles ship until you flip the default and delete the RTK path.
|
|
378
|
+
|
|
379
|
+
The example app does **not** use this pattern for todos.
|
|
380
|
+
|
|
381
|
+
### What local data survives
|
|
382
|
+
|
|
383
|
+
| Event | Local IndexedDB / SQLite | Outbox |
|
|
384
|
+
|-------|------------------------|--------|
|
|
385
|
+
| Logout / 401 | **Kept** (INV-2) | **Kept** — same user can sign back in and replay |
|
|
386
|
+
| Different-user login | **Wiped** | **Wiped** |
|
|
387
|
+
| `signOut()` default | **Kept** | **Kept** |
|
|
388
|
+
| `signOut()` with `wipeOnSignOut: true` | **Wiped** | **Wiped** |
|
|
389
|
+
| Schema version mismatch | **Wiped** + re-bootstrap | Re-built |
|
|
390
|
+
| Decrypt failure (web, default) | **Wiped** + re-bootstrap | Re-built |
|
|
391
|
+
|
|
392
|
+
`wipeLocalData` clears store tables, persisted databases, and cached encryption keys (`syncdb/src/storage/wipe.ts`).
|
|
393
|
+
|
|
394
|
+
Rolling back a **screen** to RTK does not automatically clear syncdb data — stale local todos may still exist until user switch or explicit wipe. Plan for that if you flip the flag off in production.
|
|
395
|
+
|
|
396
|
+
## 11. Checklist
|
|
397
|
+
|
|
398
|
+
Copy and track per collection:
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
[ ] 1. Backend: isDeletedPlugin + syncPlugin on schema
|
|
402
|
+
[ ] 2. Backend: modelRouter sync scope configured
|
|
403
|
+
[ ] 3. Backend: SyncApp + RealtimeApp registered; Mongo replica set running
|
|
404
|
+
[ ] 4. Backend: ensureSyncIndexes succeeds at startup
|
|
405
|
+
[ ] 5. Frontend: @terreno/syncdb installed; expo-sqlite in app (native)
|
|
406
|
+
[ ] 6. Frontend: createSyncDb client + betterAuthAdapter
|
|
407
|
+
[ ] 7. Frontend: syncDb.start()/stop() wired to auth in root layout
|
|
408
|
+
[ ] 8. Frontend: SyncDbProvider wraps migrated screens
|
|
409
|
+
[ ] 9. Reads: useGet*Query → useQuery / useEntityIds + useEntity
|
|
410
|
+
[ ] 10. Writes: usePost/Patch/Delete*Mutation → useMutate().create/update/remove
|
|
411
|
+
[ ] 11. Deleted RTK: mutation isLoading spinners, refetch-after-mutate, offline middleware entries, realtime cache patches
|
|
412
|
+
[ ] 12. Conflicts: useConflicts + resolution UI (ConflictSheet or equivalent)
|
|
413
|
+
[ ] 13. Sync status: useSyncStatus + SyncStatusBanner / health toasts (not query isLoading)
|
|
414
|
+
[ ] 14. Auth: Better Auth session + onAuthRequired → re-login when paused
|
|
415
|
+
[ ] 15. Codegen: bun run sdk still run for non-synced routes; remove todo hooks from screens
|
|
416
|
+
[ ] 16. Feature flags: OpenFeature bridge still fed via useTerrenoFeatureFlags (if used)
|
|
417
|
+
[ ] 17. Rollback plan: feature flag or accept stale local data on revert
|
|
418
|
+
[ ] 18. Verify: CRUD, offline create/edit/delete, reconnect, conflict both strategies, user switch
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Backend prerequisites (detail)
|
|
422
|
+
|
|
423
|
+
Before a collection can sync:
|
|
424
|
+
|
|
425
|
+
- [ ] `isDeletedPlugin` on schema (soft delete required)
|
|
426
|
+
- [ ] `syncPlugin` on schema (`_syncSeq` stamping)
|
|
427
|
+
- [ ] `modelRouter("/path", Model, {sync: {scope: ...}})` three-argument form
|
|
428
|
+
- [ ] Custom scopes include `snapshotFilter`
|
|
429
|
+
- [ ] `new SyncApp({getUserScopes?})` for tenant/custom scopes
|
|
430
|
+
- [ ] `new RealtimeApp({betterAuth?})` + MongoDB replica set
|
|
431
|
+
- [ ] No `updateMany`, `deleteMany`, `deleteOne`, `findOneAndDelete`, or `bulkWrite` on synced models
|
|
432
|
+
|
|
433
|
+
## What stays on @terreno/rtk
|
|
434
|
+
|
|
435
|
+
- Generated OpenAPI SDK for non-synced routes
|
|
436
|
+
- Better Auth Redux slice (`generateBetterAuthSlice`)
|
|
437
|
+
- Feature flags (`useTerrenoFeatureFlags` / `useFeatureFlags`)
|
|
438
|
+
- Socket connection for flags and legacy realtime (until removed)
|
|
439
|
+
- `@terreno/rtk` is not being removed
|
|
440
|
+
|
|
441
|
+
## Further reading
|
|
442
|
+
|
|
443
|
+
- [`docs/reference/syncdb.md`](../reference/syncdb.md) — full API reference
|
|
444
|
+
- [`syncdb/README.md`](https://github.com/flourishhealth/terreno/blob/release-56.0.0/syncdb/README.md) — architecture and protocol detail
|
|
445
|
+
- [`docs/how-to/configure-better-auth.md`](configure-better-auth.md) — Better Auth setup
|
|
@@ -9,69 +9,16 @@ Umbrella plans that coordinate several IPs.
|
|
|
9
9
|
| Program | Status | Created | IPs |
|
|
10
10
|
|---------|--------|---------|-----|
|
|
11
11
|
| [Open source launch](oss-launch-program.md) | Draft — decisions recorded; Vercel spike open | 2026-07-27 | 15 |
|
|
12
|
-
| [B2B platform](b2b-platform-program.md) | Draft — decisions D1–D7 resolved | 2026-08-09 | 9 written (+ [rbac-permissions](rbac-permissions.md)); 29 roadmap items seeded |
|
|
13
12
|
|
|
14
13
|
## Active
|
|
15
14
|
|
|
16
15
|
| Plan | Status | Created | Tasks |
|
|
17
16
|
|------|--------|---------|-------|
|
|
18
17
|
| [Admin UI v2 — Django-parity admin](admin-ui-v2-django-parity.md) | Approved | 2026-06-15 | [tasks](../tasks/admin-ui-v2-django-parity.md) |
|
|
19
|
-
| [
|
|
20
|
-
| [SyncDB
|
|
21
|
-
| [
|
|
22
|
-
| [
|
|
23
|
-
|
|
24
|
-
## Open source launch IPs
|
|
25
|
-
|
|
26
|
-
All part of the [launch program](oss-launch-program.md). The **RTK flag** column marks dependence on the `@terreno/rtk` → `@terreno/syncdb` migration in PR #869: `None` is safe to implement now, `Partial` has some blocked tasks, `Blocked` cannot start until #869 merges.
|
|
27
|
-
|
|
28
|
-
### Wave 0 — unblocked
|
|
29
|
-
|
|
30
|
-
| Plan | Status | RTK flag | Tasks |
|
|
31
|
-
|------|--------|----------|-------|
|
|
32
|
-
| [OSS governance baseline](oss-governance-baseline.md) | Draft | None | [tasks](../tasks/oss-governance-baseline.md) |
|
|
33
|
-
| [Public roadmap on GitHub](public-roadmap-github.md) | Draft | None | [tasks](../tasks/public-roadmap-github.md) |
|
|
34
|
-
| [Deploy to GCP (generalized)](deploy-to-gcp.md) | Draft | None | [tasks](../tasks/deploy-to-gcp.md) |
|
|
35
|
-
| [Agentic SDLC plugin (`/terreno-*`)](agentic-sdlc-plugin.md) | Draft | Partial | [tasks](../tasks/agentic-sdlc-plugin.md) |
|
|
36
|
-
|
|
37
|
-
### Wave 1 — gated on PR #869
|
|
38
|
-
|
|
39
|
-
| Plan | Status | RTK flag | Tasks |
|
|
40
|
-
|------|--------|----------|-------|
|
|
41
|
-
| [RTK deprecation and syncdb migration docs](rtk-to-syncdb-migration-docs.md) | Draft | **Blocked** (gating IP) | [tasks](../tasks/rtk-to-syncdb-migration-docs.md) |
|
|
42
|
-
| [Positioning — Django/Rails for TypeScript](positioning-django-rails-universal.md) | Draft | Partial | [tasks](../tasks/positioning-django-rails-universal.md) |
|
|
43
|
-
| [Reference documentation coverage](docs-reference-coverage.md) | Draft | Blocked | [tasks](../tasks/docs-reference-coverage.md) |
|
|
44
|
-
| [AI-first tutorials](docs-tutorials-ai-first.md) | Draft | Blocked | [tasks](../tasks/docs-tutorials-ai-first.md) |
|
|
45
|
-
| [Deployment foundation](deployment-foundation.md) | Draft | Partial | [tasks](../tasks/deployment-foundation.md) |
|
|
46
|
-
| [Deploy to Vercel](deploy-to-vercel.md) | Draft | Partial | [tasks](../tasks/deploy-to-vercel.md) |
|
|
47
|
-
| [Upgrade guides and skill](upgrade-guides-and-skill.md) | Draft | Blocked | [tasks](../tasks/upgrade-guides-and-skill.md) |
|
|
48
|
-
| [The AI development loop (Boost)](ai-dev-loop-boost.md) | Draft | Partial | [tasks](../tasks/ai-dev-loop-boost.md) |
|
|
49
|
-
| [Dogfooding run and launch blog post](build-terreno-app-validation.md) | Draft | Blocked | [tasks](../tasks/build-terreno-app-validation.md) |
|
|
50
|
-
| [Examples, demo, and test coverage](examples-demo-coverage.md) | Draft | Partial | [tasks](../tasks/examples-demo-coverage.md) |
|
|
51
|
-
|
|
52
|
-
### Wave 2 — independent
|
|
53
|
-
|
|
54
|
-
| Plan | Status | RTK flag | Tasks |
|
|
55
|
-
|------|--------|----------|-------|
|
|
56
|
-
| [Web SSR and admin SPA](web-ssr-and-admin-spa.md) | Draft | Partial | [tasks](../tasks/web-ssr-and-admin-spa.md) |
|
|
57
|
-
|
|
58
|
-
## B2B platform IPs
|
|
59
|
-
|
|
60
|
-
All part of the [B2B platform program](b2b-platform-program.md). Roadmap items for the
|
|
61
|
-
full program (including items whose IPs are pending decisions D1–D4) are seeded in
|
|
62
|
-
[roadmap-seed-issues.md](../explanation/roadmap-seed-issues.md).
|
|
63
|
-
|
|
64
|
-
| Plan | Status | RTK flag | Tasks |
|
|
65
|
-
|------|--------|----------|-------|
|
|
66
|
-
| [Pluggable communications layer (@terreno/comms)](comms-abstraction.md) | Draft | None | [tasks](../tasks/comms-abstraction.md) |
|
|
67
|
-
| [Comms adapter — Expo push](comms-adapter-expo-push.md) | Draft | None | [tasks](../tasks/comms-adapter-expo-push.md) |
|
|
68
|
-
| [Comms adapter — Twilio SMS](comms-adapter-twilio-sms.md) | Draft | None | [tasks](../tasks/comms-adapter-twilio-sms.md) |
|
|
69
|
-
| [Comms adapter — Twilio Verify (OTP)](comms-adapter-twilio-verify.md) | Draft | None | [tasks](../tasks/comms-adapter-twilio-verify.md) |
|
|
70
|
-
| [Comms adapter — SendGrid email](comms-adapter-sendgrid.md) | Draft | None | [tasks](../tasks/comms-adapter-sendgrid.md) |
|
|
71
|
-
| [Password reset and email verification](password-reset-and-email-verification.md) | Draft | None | [tasks](../tasks/password-reset-and-email-verification.md) |
|
|
72
|
-
| [Organizations, teams, and multi-tenant scoping](orgs-and-teams.md) | Draft | None | [tasks](../tasks/orgs-and-teams.md) |
|
|
73
|
-
| [Stripe billing and subscriptions](billing-stripe.md) | Draft | None | [tasks](../tasks/billing-stripe.md) |
|
|
74
|
-
| [Native module baseline (next major)](native-module-baseline.md) | Draft | None | [tasks](../tasks/native-module-baseline.md) |
|
|
18
|
+
| [@terreno/syncdb-codegen](syncdb-codegen.md) | Draft | 2026-07-08 | [tasks](../tasks/syncdb-codegen.md) |
|
|
19
|
+
| [SyncDB local-first data layer (v2)](syncdb-local-first.md) | In progress — Phases 1–8 landed, Phase 9 follow-ups open | 2026-06-23 | [tasks](../tasks/syncdb-local-first.md) |
|
|
20
|
+
| [SyncDB hardening (syncdb-2)](terreno-syncdb-2.md) | Implemented — Phases A–F landed; deviations carried into Phase 9 | 2026-07-11 | [tasks](../tasks/syncdb-local-first.md) (Phase 8/9) |
|
|
21
|
+
| [SyncDB Phase C design](syncdb-phase-c-design.md) | Implemented — design authority for C1–C8 | 2026-07-11 | [tasks](../tasks/syncdb-local-first.md) (Phase 8) |
|
|
75
22
|
|
|
76
23
|
## Completed
|
|
77
24
|
|
|
@@ -1,68 +1,42 @@
|
|
|
1
1
|
# Implementation Plans
|
|
2
2
|
|
|
3
|
-
Forward-looking
|
|
4
|
-
Terreno packages, written **before implementation**.
|
|
3
|
+
Forward-looking implementation plans for significant features and architectural changes to Terreno packages.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## Purpose
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
| ---- | ----- | ---- |
|
|
10
|
-
| **IP** | Design goals, architecture, models/APIs, phases, acceptance criteria | `docs/implementationPlans/<slug>.md` |
|
|
11
|
-
| **Task list** | The bot-consumable execution checklist for that IP | `docs/tasks/<slug>.md` |
|
|
7
|
+
This directory contains detailed technical plans for major features **before implementation**. Each plan documents:
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
- Design goals and rationale
|
|
10
|
+
- Architecture and file structure
|
|
11
|
+
- Configuration interfaces
|
|
12
|
+
- Usage examples
|
|
13
|
+
- Breaking changes and migration paths
|
|
14
|
+
- Implementation tasks and phases
|
|
17
15
|
|
|
18
|
-
##
|
|
16
|
+
## Current Plans
|
|
19
17
|
|
|
20
|
-
[
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
- **[Admin UI v2 — Django-parity admin](admin-ui-v2-django-parity.md)** — Config-driven admin shell (sidebar, home widgets, changelist, forms, bulk + background actions); tasks in [`docs/tasks/admin-ui-v2-django-parity.md`](../tasks/admin-ui-v2-django-parity.md)
|
|
19
|
+
- **[Modular API (TerrenoApp)](ModularAPI.md)** — New fluent builder API to replace `setupServer` in `@terreno/api`
|
|
20
|
+
- **[Offline Mode](offline-mode.md)** — Placeholder plan for offline queueing, replay, conflict handling, and UI surfaces
|
|
21
|
+
- **[MCP Boost Parity](mcp-boost-parity.md)** — Docs search tools, local stdio MCP with runtime introspection, browser log capture, per-package guidelines, and upgrade prompts (inspired by laravel/boost)
|
|
22
|
+
- **[Docs Site & Versioning](docs-site-and-versioning.md)** — Docusaurus site, versioned docs per release, UI demo embeds, and docs-maintenance skills
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## Status Tracking
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
| Plan | Status | Target Version | Discussion |
|
|
27
|
+
|------|--------|----------------|------------|
|
|
28
|
+
| Admin UI v2 (Django parity) | ✅ Approved | TBD | — |
|
|
29
|
+
| Modular API | 📝 Planning | 2.0.0 | [#149](https://github.com/FlourishHealth/terreno/pull/149) |
|
|
30
|
+
| Offline Mode | Placeholder | TBD | TBD |
|
|
31
|
+
| MCP Boost Parity | 📝 Planning | TBD | TBD |
|
|
32
|
+
| Docs Site & Versioning | 📝 Planning | TBD | TBD |
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
| ----------- | ------------------- |
|
|
31
|
-
| New published package | Bug fix in one package |
|
|
32
|
-
| New public API surface | Documentation-only change |
|
|
33
|
-
| Cross-package architectural change | Small internal refactor |
|
|
34
|
-
| Breaking change | Test or CI fix |
|
|
34
|
+
## Process
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
1. **Planning**: Implementation plan merged to master
|
|
37
|
+
2. **Discussion**: Community feedback in linked PR/issue
|
|
38
|
+
3. **Implementation**: Feature developed in feature branch with tests
|
|
39
|
+
4. **Documentation**: How-to guides and migration docs updated
|
|
40
|
+
5. **Release**: Plan moves to `docs/explanation/` as architectural documentation
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
1. **Blend** (`terreno-1-blend`) — write the IP + task list, questions first.
|
|
41
|
-
2. **Roast** (`terreno-2-roast`) — implement via TDD from the approved IP.
|
|
42
|
-
3. **Cupping** (`terreno-3-cupping`) — independently verify against the IP.
|
|
43
|
-
4. **Pour** (`terreno-4-pour`) — commit, push, open the PR.
|
|
44
|
-
5. **Dial In** (`terreno-5-dialin`) — drive CI and review until mergeable.
|
|
45
|
-
|
|
46
|
-
You can also author an IP directly with the `ip` skill; both produce the same two files.
|
|
47
|
-
|
|
48
|
-
### Roadmap handoff (roadmap-enabled repos only)
|
|
49
|
-
|
|
50
|
-
In repos that run a public roadmap (Discussions + a roadmap Project — currently Terreno),
|
|
51
|
-
Blend hands off to `roadmap-item` once the IP is **Approved** to create or update the
|
|
52
|
-
public tracking issue, and the IP header records the `Discussion:` and `Roadmap issue:`
|
|
53
|
-
links. See [`docs/explanation/roadmap-process.md`](../explanation/roadmap-process.md) for
|
|
54
|
-
the full IP ↔ roadmap lifecycle.
|
|
55
|
-
|
|
56
|
-
In repos with **no** roadmap board (Flourish, most consumer apps), the pipeline is
|
|
57
|
-
identical minus that handoff: the IP + task list plus `PLAN_INDEX.md` are the source of
|
|
58
|
-
truth, and Linear tracks execution via the IP header `Linear:` link.
|
|
59
|
-
|
|
60
|
-
## Lifecycle
|
|
61
|
-
|
|
62
|
-
1. **Draft** → **Approved** — IP written and reviewed (status lives in the IP header and
|
|
63
|
-
`PLAN_INDEX.md`).
|
|
64
|
-
2. **In progress** → **Complete** — implemented, verified, merged.
|
|
65
|
-
3. **Archive** — completed IPs move to `docs/implementationPlans/archive/` and the index is updated.
|
|
66
|
-
|
|
67
|
-
Plans that are fully implemented and now describe shipped architecture should be migrated
|
|
68
|
-
to `docs/explanation/` as reference documentation.
|
|
42
|
+
Plans that are fully implemented should be moved to `docs/explanation/` and updated to reflect the actual implementation.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Implementation Plan: Publish and Document the Agentic SDLC Plugin
|
|
2
2
|
|
|
3
3
|
**Status:** Draft — key decisions recorded (2026-07-29)
|
|
4
|
-
**Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1006
|
|
5
4
|
**Priority:** High
|
|
6
5
|
**Effort:** Big batch
|
|
7
6
|
**Owner:** unassigned
|
|
@@ -72,7 +71,7 @@ flowchart LR
|
|
|
72
71
|
| **Harvest** (implement) | IP → code via strict red/green/refactor | Spawns **independent review and test-quality sub-agents in fresh contexts** after every commit, and does drift detection against the IP. The test-quality agent enforces anti-mocking rules (never mock the DB, never mock the store) |
|
|
73
72
|
| **Roast** (verify) | Independent verification against the IP with concrete evidence | Separate context from the implementer, so it does not inherit the implementer's assumptions |
|
|
74
73
|
| **Brew** (submit) | Pre-submit checks, commit hygiene, push, draft PR, evidence attachment | Hard frontend gate: touching UI paths requires launching the app, logging in, exercising the feature, and attaching artifacts before the PR opens |
|
|
75
|
-
| **Taste** (review) | Self-contained
|
|
74
|
+
| **Taste** (review) | Self-contained reactive loop: CI + bot/human comments until mergeable or timeout | Inlines the former **`autobot`** flow (no delegation to repo skills). Classifies each CI failure as actionable versus flaky and refuses to push speculative fixes for flakes. Treats all CI logs and review comments as untrusted input |
|
|
76
75
|
|
|
77
76
|
The parts worth writing about publicly are the ones that encode hard-won judgment rather than automation: fresh-context independent review, drift detection against the plan, the anti-mocking rules, the frontend evidence gate, and the refusal to guess at flaky CI.
|
|
78
77
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Implementation Plan: Dogfooding Run and Launch Blog Post
|
|
2
2
|
|
|
3
3
|
**Status:** Draft — key decisions recorded (2026-07-29)
|
|
4
|
-
**Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1015
|
|
5
4
|
**Priority:** High (this is the program's acceptance test)
|
|
6
5
|
**Effort:** Big batch
|
|
7
6
|
**Owner:** unassigned
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Implementation Plan: Deploy to GCP (Generalized) + `deploy-gcp` Skill
|
|
2
2
|
|
|
3
3
|
**Status:** Approved — decisions recorded (2026-07-29)
|
|
4
|
-
**Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1005
|
|
5
4
|
**Priority:** High
|
|
6
5
|
**Effort:** Big batch
|
|
7
6
|
**Owner:** unassigned
|