@terreno/mcp 57.0.0-beta.1 → 57.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +381 -191
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
- package/dist/docs/resources/overview.md +6 -1
- package/dist/docs/resources/rtk.md +3 -1
- package/dist/docs/resources/syncdb.md +43 -0
- package/dist/docs/upgrades/56.0.0-beta.2.md +34 -0
- package/dist/docs/upgrades/57.0.0.md +49 -0
- package/dist/docs/upgrades/57.1.0.md +126 -0
- package/dist/docs/versioned/next/README.md +15 -3
- package/dist/docs/versioned/next/explanation/README.md +3 -0
- package/dist/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
- package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
- package/dist/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
- package/dist/docs/versioned/next/explanation/authentication.md +51 -58
- package/dist/docs/versioned/next/explanation/local-first-data.md +52 -0
- package/dist/docs/versioned/next/explanation/loop-engineering.md +117 -0
- package/dist/docs/versioned/next/explanation/repository-settings.md +8 -0
- package/dist/docs/versioned/next/explanation/roadmap-process.md +22 -9
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
- package/dist/docs/versioned/next/how-to/README.md +3 -0
- package/dist/docs/versioned/next/how-to/admin-add-model.md +41 -0
- package/dist/docs/versioned/next/how-to/admin-custom-home.md +31 -0
- package/dist/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
- package/dist/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
- package/dist/docs/versioned/next/how-to/circleci.md +173 -0
- package/dist/docs/versioned/next/how-to/configure-better-auth.md +13 -10
- package/dist/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
- package/dist/docs/versioned/next/how-to/install-agent-skills.md +46 -0
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
- package/dist/docs/versioned/next/how-to/websocket-integration.md +2 -1
- package/dist/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/README.md +31 -17
- package/dist/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
- package/dist/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
- package/dist/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/admin-only.md +3 -1
- package/dist/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
- package/dist/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
- package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
- package/dist/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
- package/dist/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
- package/dist/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
- package/dist/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
- package/dist/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
- package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
- package/dist/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
- package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
- package/dist/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
- package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
- package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
- package/dist/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
- package/dist/docs/versioned/next/reference/README.md +6 -1
- package/dist/docs/versioned/next/reference/admin-config.md +51 -0
- package/dist/docs/versioned/next/reference/ai.md +15 -1
- package/dist/docs/versioned/next/reference/api.md +18 -0
- package/dist/docs/versioned/next/reference/comms.md +88 -7
- package/dist/docs/versioned/next/reference/environment-variables.md +9 -1
- package/dist/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
- package/dist/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
- package/dist/docs/versioned/next/reference/mcp-server.md +7 -0
- package/dist/docs/versioned/next/reference/syncdb.md +30 -3
- package/dist/docs/versioned/next/tasks/README.md +21 -10
- package/dist/docs/versioned/next/tasks/admin-improvements.md +189 -353
- package/dist/docs/versioned/next/tasks/admin-only.md +2 -0
- package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
- package/dist/docs/versioned/next/tasks/comms-abstraction.md +30 -24
- package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
- package/dist/docs/versioned/next/tasks/consent-forms.md +2 -0
- package/dist/docs/versioned/next/tasks/feature-flags.md +2 -0
- package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
- package/dist/docs/versioned/next/tasks/model-router-actions.md +2 -0
- package/dist/docs/versioned/next/tasks/model-router-mcp.md +27 -27
- package/dist/docs/versioned/next/tasks/offline-mode.md +2 -0
- package/dist/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
- package/dist/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
- package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
- package/dist/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
- package/dist/docs/versioned/next/tasks/upgrade-banner.md +2 -0
- package/dist/index.js +24 -55
- package/dist/index.js.map +1 -1
- package/dist/local/localServer.d.ts.map +1 -1
- package/dist/local/localServer.js +9 -8
- package/dist/local/localServer.js.map +1 -1
- package/dist/local/localTools.d.ts +1 -1
- package/dist/local/localTools.d.ts.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +44 -45
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +9 -2
- package/dist/resources.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -2
- package/dist/tools.js.map +1 -1
- package/package.json +7 -3
- package/src/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +8 -0
- package/src/docs/resources/overview.md +6 -1
- package/src/docs/resources/rtk.md +3 -1
- package/src/docs/resources/syncdb.md +43 -0
- package/src/docs/upgrades/56.0.0-beta.2.md +34 -0
- package/src/docs/upgrades/57.0.0.md +49 -0
- package/src/docs/upgrades/57.1.0.md +126 -0
- package/src/docs/versioned/next/README.md +15 -3
- package/src/docs/versioned/next/explanation/README.md +3 -0
- package/src/docs/versioned/next/explanation/admin-consent-migration.md +15 -0
- package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +12 -0
- package/src/docs/versioned/next/explanation/announcements/rtk-deprecation.md +29 -0
- package/src/docs/versioned/next/explanation/authentication.md +51 -58
- package/src/docs/versioned/next/explanation/local-first-data.md +52 -0
- package/src/docs/versioned/next/explanation/loop-engineering.md +117 -0
- package/src/docs/versioned/next/explanation/repository-settings.md +8 -0
- package/src/docs/versioned/next/explanation/roadmap-process.md +22 -9
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +39 -0
- package/src/docs/versioned/next/how-to/README.md +3 -0
- package/src/docs/versioned/next/how-to/admin-add-model.md +41 -0
- package/src/docs/versioned/next/how-to/admin-custom-home.md +31 -0
- package/src/docs/versioned/next/how-to/admin-custom-widget.md +42 -0
- package/src/docs/versioned/next/how-to/admin-import-prebuilt.md +25 -0
- package/src/docs/versioned/next/how-to/circleci.md +173 -0
- package/src/docs/versioned/next/how-to/configure-better-auth.md +13 -10
- package/src/docs/versioned/next/how-to/expose-mcp-tools.md +194 -0
- package/src/docs/versioned/next/how-to/install-agent-skills.md +46 -0
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +26 -1
- package/src/docs/versioned/next/how-to/websocket-integration.md +2 -1
- package/src/docs/versioned/next/implementationPlans/ModularAPI.md +1 -0
- package/src/docs/versioned/next/implementationPlans/README.md +31 -17
- package/src/docs/versioned/next/implementationPlans/admin-improvements-research.md +136 -0
- package/src/docs/versioned/next/implementationPlans/admin-improvements.md +157 -527
- package/src/docs/versioned/next/implementationPlans/admin-only-research.md +4 -0
- package/src/docs/versioned/next/implementationPlans/admin-only.md +3 -1
- package/src/docs/versioned/next/implementationPlans/admin-script-runner.md +1 -0
- package/src/docs/versioned/next/implementationPlans/admin-ui-v2-django-parity.md +1 -0
- package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +160 -130
- package/src/docs/versioned/next/implementationPlans/apierror-standard-error-redesign.md +1 -0
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +5 -4
- package/src/docs/versioned/next/implementationPlans/comms-abstraction-research.md +48 -0
- package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +152 -62
- package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +9 -9
- package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +1 -1
- package/src/docs/versioned/next/implementationPlans/consent-forms.md +4 -0
- package/src/docs/versioned/next/implementationPlans/design-blend-skill.md +1 -0
- package/src/docs/versioned/next/implementationPlans/docs-site-and-versioning.md +1 -0
- package/src/docs/versioned/next/implementationPlans/feature-flags-openfeature.md +1 -0
- package/src/docs/versioned/next/implementationPlans/feature-flags.md +4 -0
- package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +1 -0
- package/src/docs/versioned/next/implementationPlans/infra-mcp.md +3 -3
- package/src/docs/versioned/next/implementationPlans/mcp-boost-parity.md +1 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +1 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +2 -2
- package/src/docs/versioned/next/implementationPlans/model-router-actions.md +4 -0
- package/src/docs/versioned/next/implementationPlans/model-router-mcp.md +5 -4
- package/src/docs/versioned/next/implementationPlans/offline-mode.md +3 -1
- package/src/docs/versioned/next/implementationPlans/oss-launch-program.md +11 -2
- package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite-research.md +150 -0
- package/src/docs/versioned/next/implementationPlans/pluggable-database-sqlite.md +247 -0
- package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +2 -2
- package/src/docs/versioned/next/implementationPlans/rbac-permissions.md +52 -15
- package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +13 -12
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen-research.md +137 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +63 -59
- package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +1 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +1 -0
- package/src/docs/versioned/next/implementationPlans/terreno-langfuse-integration.md +1 -0
- package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +1 -0
- package/src/docs/versioned/next/implementationPlans/upgrade-banner.md +4 -0
- package/src/docs/versioned/next/reference/README.md +6 -1
- package/src/docs/versioned/next/reference/admin-config.md +51 -0
- package/src/docs/versioned/next/reference/ai.md +15 -1
- package/src/docs/versioned/next/reference/api.md +18 -0
- package/src/docs/versioned/next/reference/comms.md +88 -7
- package/src/docs/versioned/next/reference/environment-variables.md +9 -1
- package/src/docs/versioned/next/reference/{rtk.md → legacy/rtk.md} +11 -7
- package/src/docs/versioned/next/reference/lifecycle-plugin.md +54 -0
- package/src/docs/versioned/next/reference/mcp-server.md +7 -0
- package/src/docs/versioned/next/reference/syncdb.md +30 -3
- package/src/docs/versioned/next/tasks/README.md +21 -10
- package/src/docs/versioned/next/tasks/admin-improvements.md +189 -353
- package/src/docs/versioned/next/tasks/admin-only.md +2 -0
- package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +54 -160
- package/src/docs/versioned/next/tasks/comms-abstraction.md +30 -24
- package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +4 -4
- package/src/docs/versioned/next/tasks/consent-forms.md +2 -0
- package/src/docs/versioned/next/tasks/feature-flags.md +2 -0
- package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +14 -10
- package/src/docs/versioned/next/tasks/model-router-actions.md +2 -0
- package/src/docs/versioned/next/tasks/model-router-mcp.md +27 -27
- package/src/docs/versioned/next/tasks/offline-mode.md +2 -0
- package/src/docs/versioned/next/tasks/pluggable-database-sqlite.md +44 -0
- package/src/docs/versioned/next/tasks/public-roadmap-github.md +1 -1
- package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +15 -15
- package/src/docs/versioned/next/tasks/syncdb-codegen.md +37 -31
- package/src/docs/versioned/next/tasks/upgrade-banner.md +2 -0
- package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
- package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
- package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +0 -73
- package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +0 -303
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# CircleCI (Terreno)
|
|
2
|
+
|
|
3
|
+
Dual-run migration from GitHub Actions. See
|
|
4
|
+
[`docs/implementationPlans/migrate-cicd-to-circleci.md`](../implementationPlans/migrate-cicd-to-circleci.md).
|
|
5
|
+
|
|
6
|
+
**Status (2026-08-20):** CircleCI is **disabled**. GitHub Actions is the CI of
|
|
7
|
+
record. Setup/path-filtering is parked in `.circleci/config.setup.yml`;
|
|
8
|
+
`.circleci/config.yml` is a no-op (`workflows.disabled.when: false`). Real jobs
|
|
9
|
+
remain in `.circleci/continue-config.yml`. To re-enable, copy `config.setup.yml`
|
|
10
|
+
over `config.yml`.
|
|
11
|
+
|
|
12
|
+
**Parked (2026-08-17):** Phase 1–3 config is in-repo (package CI, repo policy, Playwright
|
|
13
|
+
e2e). **Deploys are not ported yet** (Netlify, GCP CD, EAS, npm publish). GHA remains
|
|
14
|
+
required until CircleCI twins are trusted.
|
|
15
|
+
|
|
16
|
+
## Project setup (maintainers)
|
|
17
|
+
|
|
18
|
+
1. Link `FlourishHealth/terreno` in CircleCI (GitHub App).
|
|
19
|
+
2. Default branch: `master`.
|
|
20
|
+
3. Enable **dynamic config** / setup workflows for the project (required for
|
|
21
|
+
`.circleci/config.yml` `setup: true`).
|
|
22
|
+
4. Build forked PRs if you want DCO + rulesync on forks.
|
|
23
|
+
|
|
24
|
+
Org/project slug: _(record after Phase 0.1 — e.g. `flourishhealth/terreno`)_.
|
|
25
|
+
|
|
26
|
+
## Config layout
|
|
27
|
+
|
|
28
|
+
| File | Role |
|
|
29
|
+
|------|------|
|
|
30
|
+
| `.circleci/config.yml` | Active CircleCI config (currently a disabled no-op) |
|
|
31
|
+
| `.circleci/config.setup.yml` | Parked setup workflow + `path-filtering` (copy over `config.yml` to re-enable) |
|
|
32
|
+
| `.circleci/continue-config.yml` | Real jobs/workflows gated by those params |
|
|
33
|
+
|
|
34
|
+
Smoke job `config-ok` always runs on continuation.
|
|
35
|
+
|
|
36
|
+
`.circleci/**` sets `run-circleci-config`, which starts the `circleci-config`
|
|
37
|
+
workflow: one job from each ported family (package CI, policy, example apps,
|
|
38
|
+
`e2e` with `spec: login`, admin-spa). `comms/**` also sets
|
|
39
|
+
`run-example-backend` and `run-example-backend-script`, matching the GitHub
|
|
40
|
+
Actions twins.
|
|
41
|
+
|
|
42
|
+
## Contexts (create empty shells, then fill)
|
|
43
|
+
|
|
44
|
+
Do **not** paste secret values into the repo. Create these CircleCI Contexts and restrict
|
|
45
|
+
`terreno-release` to tag/release pipelines when publish is ported.
|
|
46
|
+
|
|
47
|
+
| Context | Maps from GHA | Used by (planned / current) |
|
|
48
|
+
|---------|---------------|------------------------------|
|
|
49
|
+
| `terreno-npm` | `NPM_TOKEN` | publish (deferred) |
|
|
50
|
+
| `terreno-netlify` | `NETLIFY_*` | deploys (deferred) |
|
|
51
|
+
| `terreno-expo` | `EXPO_TOKEN` | EAS (deferred) |
|
|
52
|
+
| `terreno-gcp` | OIDC / WIF (no long-lived key for CD) | GCP CD (deferred) |
|
|
53
|
+
| `terreno-e2e` | `E2E_TOKEN_SECRET`, `E2E_REFRESH_TOKEN_SECRET`, `E2E_SESSION_SECRET` | `e2e`, `admin-spa-integration` |
|
|
54
|
+
| `terreno-release` | `REPO_ADMIN_TOKEN`, Zoom webhooks | publish (deferred) |
|
|
55
|
+
| `terreno-agentic` | `CURSOR_API_KEY` | agentic replacements (deferred) |
|
|
56
|
+
| `terreno-github-api` | PAT (`pull-requests`, `contents`, …) | `dco`, PR comments later |
|
|
57
|
+
|
|
58
|
+
Until contexts exist, e2e jobs may use **project env vars for `E2E_*` secrets only**
|
|
59
|
+
(or the in-job `ci-e2e-*-secret` fallbacks). **Do not** put `GITHUB_TOKEN` (or any
|
|
60
|
+
GitHub PAT) in project env vars — those are injected into every job, including
|
|
61
|
+
`bun` scripts from the PR. Create `terreno-github-api`, restrict it to this
|
|
62
|
+
project, leave fork-PR secret passing off, and attach that context **only** to
|
|
63
|
+
`dco` (and later comment jobs). DCO skips if `GITHUB_TOKEN` is unset.
|
|
64
|
+
|
|
65
|
+
After contexts exist, attach them on the matching jobs in
|
|
66
|
+
`.circleci/continue-config.yml` (see comments in the `workflows:` section).
|
|
67
|
+
|
|
68
|
+
## Check name map (GHA → CircleCI)
|
|
69
|
+
|
|
70
|
+
Branch protection still requires **GitHub Actions** names during dual-run. CircleCI
|
|
71
|
+
checks appear as CircleCI job names in the GitHub Checks UI.
|
|
72
|
+
|
|
73
|
+
| GHA job `name:` / workflow | CircleCI job |
|
|
74
|
+
|----------------------------|--------------|
|
|
75
|
+
| Repository policies / No barrel imports | `no-barrel-imports` |
|
|
76
|
+
| Explicit any baseline | `explicit-any` |
|
|
77
|
+
| License coverage | `license-coverage` |
|
|
78
|
+
| Verify rules are in sync | `rulesync-check` |
|
|
79
|
+
| `dco` | `dco` |
|
|
80
|
+
| Run all tests (API CI) | `api-ci` |
|
|
81
|
+
| Run all tests (AI CI) | `ai-ci` |
|
|
82
|
+
| RTK Lint and Build | `rtk-ci` |
|
|
83
|
+
| UI Lint, Build, Types, and Tests | `ui-ci` |
|
|
84
|
+
| Demo TypeScript Check (UI dependency) | `ui-demo-typecheck` |
|
|
85
|
+
| Demo Lint and TypeScript Check | `ui-demo-ci` |
|
|
86
|
+
| Lint, compile, and test communications | `comms-ci` |
|
|
87
|
+
| Lint, Build, and Test (MCP) | `mcp-server-ci` |
|
|
88
|
+
| Build Docker Image (MCP) | `mcp-server-docker` |
|
|
89
|
+
| Example Frontend Lint and Test | `example-frontend-ci` |
|
|
90
|
+
| Example Backend Lint, Build, and Test | `example-backend-ci` |
|
|
91
|
+
| Run admin script CLI | `example-backend-script-runner` |
|
|
92
|
+
| Build backend Docker image | `example-backend-docker` |
|
|
93
|
+
| Admin SPA Build and E2E | `admin-spa-ci` |
|
|
94
|
+
| E2E · `<spec>` | `e2e` (matrix `spec`) |
|
|
95
|
+
| E2E Load · syncdb-loadlab | `e2e-load` (trigger-gated, see below) |
|
|
96
|
+
| Admin SPA Backend Integration E2E | `admin-spa-integration` |
|
|
97
|
+
| _(new)_ CircleCI path-filter parity | `circleci-parity` |
|
|
98
|
+
| _(smoke)_ | `config-ok` |
|
|
99
|
+
|
|
100
|
+
Deferred phases keep their GHA checks for now; these are the planned CircleCI job
|
|
101
|
+
names so branch protection can be remapped in one pass later:
|
|
102
|
+
|
|
103
|
+
| GHA job `name:` / workflow (not yet ported) | Planned CircleCI job |
|
|
104
|
+
|---------------------------------------------|----------------------|
|
|
105
|
+
| Fingerprint gate (`fingerprint-gate.yml`) | `fingerprint-gate` (Phase 5) |
|
|
106
|
+
| EAS PR update/build (`eas-pr.yml`) | `eas-pr` (Phase 5) |
|
|
107
|
+
| EAS dev build (`eas-dev-build.yml`) | `eas-dev-build`, manual pipeline (Phase 5) |
|
|
108
|
+
| CD terraform preview/apply (`cd.yml`) | `cd-terraform`, `cd-deploy` (Phase 6) |
|
|
109
|
+
| Preview cleanup (`preview-cleanup.yml`) | `preview-cleanup` (Phase 6) |
|
|
110
|
+
| Netlify demo / frontend / docs deploys | `deploy-demo`, `deploy-example-frontend`, `deploy-docs` (Phase 4) |
|
|
111
|
+
| Publish on tag (`publish-on-tag.yml`) | `publish-npm` (Phase 7, single-writer cutover) |
|
|
112
|
+
| Appium / Maestro | `appium-android`, `appium-ios`, `maestro` (Phase 8) |
|
|
113
|
+
|
|
114
|
+
## Path-filter parity guard
|
|
115
|
+
|
|
116
|
+
`bun run check:circleci-parity` fails when a GHA `paths:` entry has no mapping to
|
|
117
|
+
its CircleCI parameter — otherwise the twin silently never runs. It runs as the
|
|
118
|
+
`circleci-parity` job (CircleCI) and the **CircleCI path-filter parity** job
|
|
119
|
+
(GitHub Actions `repo-policies`). Add new packages/paths to the mapping in
|
|
120
|
+
`.circleci/config.setup.yml` (or `config.yml` when enabled) and to `WORKFLOW_PARAMETERS` in
|
|
121
|
+
`scripts/check-circleci-parity/lib.ts`.
|
|
122
|
+
|
|
123
|
+
## Config-only changes
|
|
124
|
+
|
|
125
|
+
When CircleCI is enabled, `.circleci/config.yml` / `continue-config.yml` /
|
|
126
|
+
`example-frontend/playwright.circleci.config.ts` edits set `run-circleci-config`,
|
|
127
|
+
which runs a representative slice (`api-ci`, `ui-ci`, `example-backend-ci`,
|
|
128
|
+
`no-barrel-imports`, `e2e` spec `login`) so config changes are actually exercised
|
|
129
|
+
instead of only hitting the always-on smoke jobs. While disabled, keep the mapping
|
|
130
|
+
in `config.setup.yml` in sync; `check:circleci-parity` reads that file first. CircleCI e2e
|
|
131
|
+
pre-starts a static `bun expo export` on `:8082` (`NODE_OPTIONS=--max-old-space-size=3072`
|
|
132
|
+
for the export only) and reuses it (60s test timeout, `large` Docker). Keeping Metro
|
|
133
|
+
alive next to Chromium gets SIGKILL on 8GB. `xlarge` is not on this project's plan.
|
|
134
|
+
|
|
135
|
+
## Nightly load test
|
|
136
|
+
|
|
137
|
+
`e2e-load` (syncdb-loadlab) is never PR-blocking. Trigger the **setup** pipeline
|
|
138
|
+
with `run-e2e-load`. Setup skips path-filtering and continues with a differently
|
|
139
|
+
named continuation parameter (`e2e-load`) so CircleCI does not report conflicting
|
|
140
|
+
pipeline parameters.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{"run-e2e-load": true}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This replaces the GHA cron / `workflow_dispatch` / `load-test` label triggers in
|
|
147
|
+
`e2e-load-nightly.yml`.
|
|
148
|
+
|
|
149
|
+
## Local validation
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
circleci config validate .circleci/config.yml
|
|
153
|
+
circleci config validate .circleci/continue-config.yml
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Dual-run drift
|
|
157
|
+
|
|
158
|
+
While both systems run, keep these in sync when editing a GHA workflow:
|
|
159
|
+
|
|
160
|
+
1. `paths:` → mapping in `.circleci/config.setup.yml` (or `config.yml` when enabled; enforced by `check:circleci-parity`)
|
|
161
|
+
2. e2e `spec:` matrix → `e2e` workflow matrix in `continue-config.yml`
|
|
162
|
+
3. New package CI workflow → new param + job + `WORKFLOW_PARAMETERS` entry
|
|
163
|
+
|
|
164
|
+
## Not in this phase
|
|
165
|
+
|
|
166
|
+
- Netlify / docs / demo / example-frontend **deploys**
|
|
167
|
+
- GCP `cd.yml`, preview-cleanup, OIDC
|
|
168
|
+
- EAS / fingerprint
|
|
169
|
+
- npm publish-on-tag
|
|
170
|
+
- Appium / Maestro
|
|
171
|
+
- CodeQL, Dependabot auto-merge, triage, gh-aw agentics
|
|
172
|
+
|
|
173
|
+
Keep matching `.github/workflows/*` until dual-run cutover deletes them per phase.
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
# Configure Better Auth
|
|
2
2
|
|
|
3
|
-
Set up Better Auth as
|
|
3
|
+
Set up Better Auth as the **default** authentication provider for new Terreno apps — session-based auth with built-in social OAuth and first-class `@terreno/syncdb` integration.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Better Auth is
|
|
7
|
+
Better Auth is the recommended authentication system for new Terreno frontends. Register `BetterAuthApp` on the backend, set `AUTH_PROVIDER=better-auth`, and wire `createBetterAuthClient` + `generateBetterAuthSlice` on the client. Pair with `betterAuthAdapter` when using `@terreno/syncdb`.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
JWT/Passport remains available for legacy deployments (`AUTH_PROVIDER=jwt`). Both can run in parallel during migration.
|
|
10
|
+
|
|
11
|
+
**Choose Better Auth for:**
|
|
12
|
+
- New apps and greenfield screens
|
|
10
13
|
- Social login (Google, GitHub, Apple)
|
|
11
|
-
- Session-based authentication
|
|
12
|
-
-
|
|
14
|
+
- Session-based authentication with `@terreno/syncdb`
|
|
15
|
+
- Socket.io sync via `RealtimeApp` bearer sessions
|
|
13
16
|
|
|
14
|
-
**
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
17
|
+
**Stay on JWT only when:**
|
|
18
|
+
- You have an existing JWT deployment and are mid-migration
|
|
19
|
+
- You require a fully stateless token contract with no session cookies
|
|
20
|
+
- You have custom JWT payload requirements Better Auth cannot satisfy
|
|
18
21
|
|
|
19
22
|
## Backend Setup
|
|
20
23
|
|
|
@@ -292,5 +295,5 @@ Better Auth runs **in parallel** with JWT auth. You don't need to migrate existi
|
|
|
292
295
|
|
|
293
296
|
- [Authentication Architecture](../explanation/authentication.md)
|
|
294
297
|
- [@terreno/api Reference](../reference/api.md#better-auth)
|
|
295
|
-
- [@terreno/rtk Reference](../reference/rtk.md#better-auth)
|
|
298
|
+
- [@terreno/rtk Reference (legacy)](../reference/legacy/rtk.md#better-auth)
|
|
296
299
|
- [Better Auth Documentation](https://better-auth.com/)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Expose Model Context Protocol Tools
|
|
2
|
+
|
|
3
|
+
Turn a `modelRouter` model into Model Context Protocol (MCP) tools that an LLM can call, reusing the permissions, query filters, population, and lifecycle hooks you already declared for REST.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- A working Terreno backend using `TerrenoApp`
|
|
8
|
+
- At least one model registered with `modelRouter`
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
### 1. Add an `mcp` config to a model router
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import {modelRouter, OwnerQueryFilter, Permissions} from "@terreno/api";
|
|
16
|
+
|
|
17
|
+
export const todoRouter = modelRouter("/todos", Todo, {
|
|
18
|
+
mcp: {
|
|
19
|
+
excludeFields: ["internalNote"],
|
|
20
|
+
maxLimit: 25,
|
|
21
|
+
methods: ["list", "read", "create", "update", "delete"],
|
|
22
|
+
},
|
|
23
|
+
permissions: {
|
|
24
|
+
create: [Permissions.IsAuthenticated],
|
|
25
|
+
delete: [Permissions.IsOwner],
|
|
26
|
+
list: [Permissions.IsAuthenticated],
|
|
27
|
+
read: [Permissions.IsOwner],
|
|
28
|
+
update: [Permissions.IsOwner],
|
|
29
|
+
},
|
|
30
|
+
queryFields: ["completed", "title"],
|
|
31
|
+
queryFilter: OwnerQueryFilter,
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`methods` defaults to `["list", "read"]`, and `maxLimit` defaults to 50. A method whose `permissions` array is empty is never exposed as a tool, so REST and MCP cannot drift apart.
|
|
36
|
+
|
|
37
|
+
### 2. Start the server
|
|
38
|
+
|
|
39
|
+
`TerrenoApp` mounts `POST /mcp` automatically as soon as any model has an `mcp` config. Every other verb on `/mcp` returns a JSON-RPC 405. No extra registration is needed.
|
|
40
|
+
|
|
41
|
+
Tools are named `{prefix}_{method}` — `todos_list`, `todos_read`, and so on.
|
|
42
|
+
|
|
43
|
+
The endpoint speaks the `2026-07-28` MCP revision through the TypeScript SDK v2
|
|
44
|
+
`createMcpHandler`. It is stateless: every request carries its protocol version,
|
|
45
|
+
client identity, and capabilities, so requests can land on any backend instance.
|
|
46
|
+
The SDK's stateless legacy fallback remains enabled, so 2025-era clients continue
|
|
47
|
+
to work while clients migrate.
|
|
48
|
+
|
|
49
|
+
### 3. Call the tools
|
|
50
|
+
|
|
51
|
+
Point any MCP client at `POST /mcp` with the user's `Authorization: Bearer <token>` header. Both JWT and Better Auth sessions are accepted; the resolved user is what the permission checks run against, so an LLM can never see more than that user could see over REST.
|
|
52
|
+
|
|
53
|
+
Authentication is required by default, matching REST. A tool call with no resolvable user is refused before any permission check unless the model router sets `allowAnonymous: true` — the same flag REST passes to `authenticateMiddleware`. That matters for read-only helpers like `IsAuthenticatedOrReadOnly`, which would otherwise pass for an anonymous `list`. Disabled accounts are refused too, as they are over HTTP.
|
|
54
|
+
|
|
55
|
+
To run the same tools in-process (for example inside a chat route), use `getMCPTools`:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import {getMCPTools} from "@terreno/ai";
|
|
59
|
+
|
|
60
|
+
const tools = getMCPTools(req.user);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`useMCPTools()` from `@terreno/rtk` uses the official MCP v2 client with automatic
|
|
64
|
+
version negotiation. It no longer constructs JSON-RPC or parses SSE responses by
|
|
65
|
+
hand; the SDK supplies the `2026-07-28` `_meta` envelope and required
|
|
66
|
+
`Mcp-Method` / `Mcp-Name` routing headers.
|
|
67
|
+
|
|
68
|
+
## Naming tools
|
|
69
|
+
|
|
70
|
+
The default prefix is the lowercase model name run through a simple pluralizer: `Todo` → `todos`, `Category` → `categories`, `Status` → `statuses`. Irregular nouns need an explicit prefix:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
mcp: {toolPrefix: "people"} // person_list -> people_list
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Filtering list results
|
|
77
|
+
|
|
78
|
+
Only fields listed in `queryFields` can be filtered, exactly as in REST. A filter value may be an exact value or an operator object:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{"completed": false, "title": {"$in": ["Buy milk", "Walk dog"]}}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Allowed operators are `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$all`, `$size`, `$exists`, and `$regex` (with `$options`). Operators that can execute code or ignore indexes — `$where`, `$expr`, `$function`, `$accumulator`, `$jsonSchema`, `$text` — are rejected with an error rather than silently dropped, so the model can correct itself.
|
|
85
|
+
|
|
86
|
+
Filters can be combined with top-level `$and` / `$or`, whose branches are validated against `queryFields` too:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{"$or": [{"completed": true}, {"title": {"$regex": "^Urgent"}}]}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`queryFilter` still runs after the filter is built, so an `OwnerQueryFilter` keeps scoping results to the calling user no matter what the LLM sends.
|
|
93
|
+
|
|
94
|
+
## Populating references
|
|
95
|
+
|
|
96
|
+
Population comes from the model router's `populatePaths`, exactly as it does over REST. A tool may pass `populate` to request a **subset** of those declared paths — it can never introduce a new one, so the `fields` allowlist on each declared path always applies and a caller cannot pull back a whole referenced document:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
populatePaths: [{fields: ["name", "email"], path: "ownerId"}],
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`{"populate": "ownerId"}` is accepted; anything undeclared is refused with an error listing the allowed paths. Models with no `populatePaths` don't get a `populate` parameter at all.
|
|
103
|
+
|
|
104
|
+
## Hiding fields
|
|
105
|
+
|
|
106
|
+
`excludeFields` removes fields from both the generated tool schemas and the responses:
|
|
107
|
+
|
|
108
|
+
- A bare name (`"hash"`) is removed at **every depth**, including inside arrays and populated refs, so a redacted name cannot leak through a nested document.
|
|
109
|
+
- A dot path (`"metadata.secretKey"`) removes exactly that location, following arrays of subdocuments element-wise.
|
|
110
|
+
|
|
111
|
+
## Customizing responses
|
|
112
|
+
|
|
113
|
+
`mcpResponseHandler` shapes MCP responses independently of the REST `responseHandler`, which is useful for returning compact summaries to an LLM:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
mcp: {
|
|
117
|
+
mcpResponseHandler: async (value, method) => {
|
|
118
|
+
if (Array.isArray(value)) {
|
|
119
|
+
return value.map((todo) => ({id: String(todo._id), title: todo.title}));
|
|
120
|
+
}
|
|
121
|
+
return {id: String(value._id), title: value.title};
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`excludeFields` is applied after your handler runs.
|
|
127
|
+
|
|
128
|
+
## Lifecycle hooks
|
|
129
|
+
|
|
130
|
+
`preCreate`, `postCreate`, `preUpdate`, `postUpdate`, `preDelete`, and `postDelete` all run for MCP calls. An MCP tool call is JSON-RPC rather than HTTP, so `createMCPRequest` builds a stub Express-shaped `request` (`MCPRequest`):
|
|
131
|
+
|
|
132
|
+
- `user` — the authenticated MCP user
|
|
133
|
+
- `body` — the hook-stage payload after write denylist + transform, not the raw tool args (on delete, `id` is in `body`, not `params`)
|
|
134
|
+
- `headers` / `query` / `params` — always `{}` (MCP does not forward HTTP headers)
|
|
135
|
+
- `isMCPRequest` — `true`
|
|
136
|
+
|
|
137
|
+
REST `responseHandler` gets the same stub with an empty `body`.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import type {MCPRequest} from "@terreno/api";
|
|
141
|
+
|
|
142
|
+
preCreate: (body, req) => {
|
|
143
|
+
if ((req as unknown as MCPRequest).isMCPRequest) {
|
|
144
|
+
// e.g. tag records created by an assistant
|
|
145
|
+
return {...body, source: "assistant"};
|
|
146
|
+
}
|
|
147
|
+
return body;
|
|
148
|
+
},
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
A hook that reads `req.headers` or `req.query` gets an empty object instead of a crash, but anything genuinely HTTP-specific (cookies, IP address) is unavailable — branch on `isMCPRequest` when that matters.
|
|
152
|
+
|
|
153
|
+
## Logging and error reporting
|
|
154
|
+
|
|
155
|
+
Every generated tool call emits a structured backend audit log with stable
|
|
156
|
+
`mcpTool`, `mcpMethod`, and `mcpModel` labels plus the active Terreno request
|
|
157
|
+
context (`requestId`, `userId`, and trace fields when present):
|
|
158
|
+
|
|
159
|
+
- successful calls log at `info` with `durationMs`
|
|
160
|
+
- expected refusals (permissions, not found, invalid filters) log at `warn`
|
|
161
|
+
- caught database, transform, and lifecycle-hook failures log at `error`
|
|
162
|
+
|
|
163
|
+
When `USE_SENTRY_LOGGING=true`, expected failures are mirrored as Sentry logs.
|
|
164
|
+
Unexpected exceptions and caught internal causes are also captured with
|
|
165
|
+
`Sentry.captureException`, preserving their original stack. The client still
|
|
166
|
+
receives the stable MCP error text — internal exceptions and stack traces stay
|
|
167
|
+
server-side. Tool arguments are not logged.
|
|
168
|
+
|
|
169
|
+
## Custom tools
|
|
170
|
+
|
|
171
|
+
CRUD tools cover one model at a time. For a query that spans models, register a custom tool with `registerMCPTool`. It shows up on `POST /mcp` and in `getMCPTools` next to the generated CRUD tools:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import {registerMCPTool} from "@terreno/api";
|
|
175
|
+
import {z} from "zod";
|
|
176
|
+
|
|
177
|
+
registerMCPTool({
|
|
178
|
+
name: "users_todo_statuses",
|
|
179
|
+
description: "List every user with each of their todos and completed status. Admin only.",
|
|
180
|
+
zodSchema: z.object({}).strict(),
|
|
181
|
+
handler: async (_args, user) => {
|
|
182
|
+
if (!user?.admin) {
|
|
183
|
+
return {
|
|
184
|
+
content: [{type: "text", text: JSON.stringify({error: "Permission denied: admin required"})}],
|
|
185
|
+
isError: true,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// load users + todos and return JSON text
|
|
189
|
+
return {content: [{type: "text", text: JSON.stringify({users: []})}]};
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The example backend registers this as `users_todo_statuses` from `example-backend/src/api/usersTodoStatus.ts`.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Install agent skills
|
|
2
|
+
|
|
3
|
+
Install Terreno's agent skills into another repo or agent with the skills CLI.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx skills add FlourishHealth/terreno
|
|
7
|
+
npx skills add FlourishHealth/terreno --skill terreno-1-grow
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
That copies the committed `skills/` tree: lifecycle stages (Grow, Pick, Roast, Brew,
|
|
11
|
+
Taste), repository skills, and published package skills.
|
|
12
|
+
|
|
13
|
+
## What you get
|
|
14
|
+
|
|
15
|
+
| Group | Skills |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| Lifecycle | `terreno-1-grow` … `terreno-5-taste` |
|
|
18
|
+
| Terreno apps | backend, UI, data, schema, SDK |
|
|
19
|
+
| Docs | `update-docs`, `update-agent-docs`, architecture skills |
|
|
20
|
+
| GitHub | commit, PR, review, verify, release, deploy |
|
|
21
|
+
|
|
22
|
+
`skills.sh.json` at the repo root groups those names on [skills.sh](https://skills.sh).
|
|
23
|
+
|
|
24
|
+
## Keep copies in sync (Terreno maintainers)
|
|
25
|
+
|
|
26
|
+
Canonical sources:
|
|
27
|
+
|
|
28
|
+
1. `.rulesync/skills/` — repository skills (`bun run rules` generates agent copies)
|
|
29
|
+
2. `plugins/terreno-planning/skills/` — portable lifecycle stages
|
|
30
|
+
3. `<package>/.ai/skills/` — published package skills; these overlay the repo copies
|
|
31
|
+
|
|
32
|
+
Regenerate the installable tree:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bun run skills:sync
|
|
36
|
+
bun run check:lifecycle-skills
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Do not hand-edit `skills/`.
|
|
40
|
+
|
|
41
|
+
## Write human docs with the skills
|
|
42
|
+
|
|
43
|
+
Skills read architecture docs before changing code. After a user-visible or architectural
|
|
44
|
+
change, update `docs/` in the same slice using `update-docs`. See
|
|
45
|
+
[lifecycle plugin](../reference/lifecycle-plugin.md) and the
|
|
46
|
+
[documentation contract](https://github.com/FlourishHealth/terreno/blob/master/plugins/terreno-planning/references/documentation-contract.md).
|
|
@@ -21,6 +21,8 @@ This guide is **AI-context-first**: it is written for an agent (or human) perfor
|
|
|
21
21
|
|
|
22
22
|
The example app completed both steps; todos are syncdb-only while profile/admin still use generated RTK hooks.
|
|
23
23
|
|
|
24
|
+
**Validation (Task 3.5):** The profile screen (`example-frontend/app/(tabs)/profile.tsx`) was reviewed against this guide. `useGetMeQuery` / `usePatchMeMutation` are **non-synced** custom SDK routes — the guide §8 explicitly says to keep them on RTK. No profile migration is required; the guide is sufficient for that case.
|
|
25
|
+
|
|
24
26
|
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
27
|
|
|
26
28
|
## 2. Install and configure
|
|
@@ -318,6 +320,18 @@ Required for Better Auth socket sessions. Legacy JWT sockets continue to work wi
|
|
|
318
320
|
|
|
319
321
|
## 8. Codegen
|
|
320
322
|
|
|
323
|
+
Synced collections use `bun run sync-sdk`, which runs `terreno-syncdb-codegen` from
|
|
324
|
+
`@terreno/syncdb`. It reads `/openapi.json`, finds list operations tagged
|
|
325
|
+
`x-terreno-sync`, and writes `store/syncDbSdk.ts` (`SYNC_COLLECTIONS` plus friendly
|
|
326
|
+
hooks such as `useTodos` / `useTodo` / `useCreateTodo`). Do not edit that file.
|
|
327
|
+
Custom collections call `createCollectionHooks` in a sibling file. Names are chosen
|
|
328
|
+
so they do not collide with RTK `openApiSdk.ts` during dual-stack migration.
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Backend running on port 4000
|
|
332
|
+
cd example-frontend && bun run sync-sdk
|
|
333
|
+
```
|
|
334
|
+
|
|
321
335
|
### Does `bun run sdk` still work?
|
|
322
336
|
|
|
323
337
|
**Yes.** `example-frontend/package.json` still defines:
|
|
@@ -332,7 +346,7 @@ It runs `@rtk-query/codegen-openapi` against `openapi-config.ts` and writes `sto
|
|
|
332
346
|
|
|
333
347
|
| Still generated | Stop using for migrated collections |
|
|
334
348
|
|-----------------|-------------------------------------|
|
|
335
|
-
| Auth routes, `GET /auth/me`, admin, AI explorer, version config, feature flags |
|
|
349
|
+
| Auth routes, `GET /auth/me`, admin, AI explorer, version config, feature flags | Collection CRUD — import from `store/syncDbSdk.ts` instead |
|
|
336
350
|
| Custom REST / RPC endpoints | Todo `realtimeList` / `realtimeDocument` wiring in `store/sdk.ts` |
|
|
337
351
|
|
|
338
352
|
Keep running `bun run sdk` after backend route changes — non-synced screens still import from `store/sdk.ts`.
|
|
@@ -342,8 +356,19 @@ Workflow:
|
|
|
342
356
|
```bash
|
|
343
357
|
# Backend running on port 4000
|
|
344
358
|
cd example-frontend && bun run sdk
|
|
359
|
+
cd example-frontend && bun run sync-sdk
|
|
345
360
|
```
|
|
346
361
|
|
|
362
|
+
### Syncdb hooks codegen
|
|
363
|
+
|
|
364
|
+
For collections with `sync` enabled on the backend, generate local-first hooks from the same OpenAPI spec:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
cd example-frontend && bun run sync-sdk
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
This writes `store/syncDbSdk.ts` with friendly hooks (`useTodos`, `useCreateTodo`, …) that intentionally differ from RTK names so both SDKs can coexist during migration. Import synced screens from `@/store/syncDbSdk`, not `store/sdk.ts`.
|
|
371
|
+
|
|
347
372
|
## 9. Feature flags
|
|
348
373
|
|
|
349
374
|
Post-migration, feature flags stay on `@terreno/rtk` + OpenFeature — **not** on syncdb.
|
|
@@ -411,6 +411,7 @@ This logs:
|
|
|
411
411
|
|
|
412
412
|
## Related Documentation
|
|
413
413
|
|
|
414
|
-
- [@terreno/
|
|
414
|
+
- [@terreno/syncdb Reference](../reference/syncdb.md) — Local-first data layer (replaces RTK for synced collections)
|
|
415
|
+
- [@terreno/rtk Reference (legacy)](../reference/legacy/rtk.md) — RTK Query utilities during the support window
|
|
415
416
|
- [Authentication Architecture](../explanation/authentication.md) — JWT system deep-dive
|
|
416
417
|
- [Socket.io Documentation](https://socket.io/docs/v4/) — Official Socket.io docs
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Modular API Implementation Plan
|
|
2
2
|
|
|
3
|
+
**Roadmap issue:** https://github.com/FlourishHealth/terreno/issues/1084
|
|
3
4
|
## Overview
|
|
4
5
|
|
|
5
6
|
This document outlines the implementation plan for a new modular API design in `@terreno/api`. The goal is to create a `TerrenoApp` class that provides a cleaner, more flexible interface for building APIs while maintaining backward compatibility with the existing `setupServer` function.
|
|
@@ -7,7 +7,7 @@ An implementation plan (IP) is one half of a two-file pair:
|
|
|
7
7
|
|
|
8
8
|
| File | Holds | Path |
|
|
9
9
|
| ---- | ----- | ---- |
|
|
10
|
-
| **IP** | Design goals, architecture, models/APIs, phases, acceptance criteria | `docs/implementationPlans/<slug>.md` |
|
|
10
|
+
| **IP** | Design goals, architecture, models/APIs, testing decisions, phases, acceptance criteria | `docs/implementationPlans/<slug>.md` |
|
|
11
11
|
| **Task list** | The bot-consumable execution checklist for that IP | `docs/tasks/<slug>.md` |
|
|
12
12
|
|
|
13
13
|
The IP is the source of truth for *what and why*; the task list is the source of truth
|
|
@@ -15,11 +15,12 @@ for *the concrete steps*. External trackers (a GitHub roadmap issue, a Linear is
|
|
|
15
15
|
discussion thread) link **to** these files — they never replace them. See
|
|
16
16
|
[`docs/tasks/README.md`](../tasks/README.md) for the task-file shape.
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Status lives on each IP
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
There is no shared `PLAN_INDEX.md`. That file caused merge conflicts the same way a
|
|
21
|
+
shared changelog Unreleased section did. Status is the `**Status:**` line in each
|
|
22
|
+
`docs/implementationPlans/<slug>.md` (and in `archive/` after close). List those
|
|
23
|
+
directories to see what exists; this README explains the process.
|
|
23
24
|
|
|
24
25
|
## When to write an IP
|
|
25
26
|
|
|
@@ -35,34 +36,47 @@ Substantial work is planned before coding. Quick rule (full table in
|
|
|
35
36
|
|
|
36
37
|
## How a plan gets written and built
|
|
37
38
|
|
|
38
|
-
The [`terreno-planning` plugin](../../plugins/README.md) drives the pipeline
|
|
39
|
+
The [`terreno-planning` plugin](../../plugins/README.md) drives the pipeline.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
**Grow** interviews in grilling rounds (one frontier of decisions per message, recommended
|
|
42
|
+
answers, then wait). After the user confirms shared understanding it writes the two files
|
|
43
|
+
and ends with a **15-line verify table** — destination, in/out, tracer, task graph, test
|
|
44
|
+
seam — so a human can check the plan without rereading the IP.
|
|
45
|
+
|
|
46
|
+
For a small feature, an outer loop may use the plugin's **feature profile**: a compact
|
|
47
|
+
approved task contract, one fresh Pick invocation per frontier task, independent Roast,
|
|
48
|
+
then Brew and bounded Taste iterations. This preserves the former Grind behavior without
|
|
49
|
+
putting orchestration inside a lifecycle skill.
|
|
50
|
+
|
|
51
|
+
1. **Grow** (`terreno-1-grow`) — grill, then write the IP + tracer-bullet task list; end with the 15-line verify table.
|
|
52
|
+
2. **Pick** (`terreno-2-pick`) — implement one approved slice via TDD.
|
|
53
|
+
3. **Roast** (`terreno-3-roast`) — independently verify the implementation against the IP.
|
|
54
|
+
4. **Brew** (`terreno-4-brew`) — commit, push, open the PR.
|
|
55
|
+
5. **Taste** (`terreno-5-taste`) — react once to current CI, mergeability, and review state.
|
|
56
|
+
|
|
57
|
+
The outer loop owns stage selection, execution-state persistence, waiting, retries, and
|
|
58
|
+
human/external escalation. Each stage emits the common machine-readable result described
|
|
59
|
+
in [`plugins/terreno-planning/references/lifecycle-contract.md`](../../plugins/terreno-planning/references/lifecycle-contract.md).
|
|
45
60
|
|
|
46
61
|
You can also author an IP directly with the `ip` skill; both produce the same two files.
|
|
47
62
|
|
|
48
63
|
### Roadmap handoff (roadmap-enabled repos only)
|
|
49
64
|
|
|
50
65
|
In repos that run a public roadmap (Discussions + a roadmap Project — currently Terreno),
|
|
51
|
-
|
|
66
|
+
Grow hands off to `roadmap-item` once the IP is **Approved** to create or update the
|
|
52
67
|
public tracking issue, and the IP header records the `Discussion:` and `Roadmap issue:`
|
|
53
68
|
links. See [`docs/explanation/roadmap-process.md`](../explanation/roadmap-process.md) for
|
|
54
69
|
the full IP ↔ roadmap lifecycle.
|
|
55
70
|
|
|
56
71
|
In repos with **no** roadmap board (Flourish, most consumer apps), the pipeline is
|
|
57
|
-
identical minus that handoff: the IP + task list
|
|
58
|
-
|
|
72
|
+
identical minus that handoff: the IP + task list are the source of truth, and Linear
|
|
73
|
+
tracks execution via the IP header `Linear:` link.
|
|
59
74
|
|
|
60
75
|
## Lifecycle
|
|
61
76
|
|
|
62
|
-
1. **Draft** → **Approved** — IP written and reviewed (status lives in the IP header
|
|
63
|
-
`PLAN_INDEX.md`).
|
|
77
|
+
1. **Draft** → **Approved** — IP written and reviewed (status lives in the IP header).
|
|
64
78
|
2. **In progress** → **Complete** — implemented, verified, merged.
|
|
65
|
-
3. **Archive** — completed IPs move to `docs/implementationPlans/archive
|
|
79
|
+
3. **Archive** — completed IPs move to `docs/implementationPlans/archive/`.
|
|
66
80
|
|
|
67
81
|
Plans that are fully implemented and now describe shipped architecture should be migrated
|
|
68
82
|
to `docs/explanation/` as reference documentation.
|