@terreno/mcp 57.3.0 → 57.4.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/README.md +7 -1
- package/dist/bootstrap.d.ts +0 -18
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +10 -2428
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/guidelines/admin-frontend/guidelines/core.md +5 -1
- package/dist/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +23 -10
- package/dist/docs/resources/syncdb.md +4 -1
- package/dist/docs/upgrades/57.4.0.md +140 -0
- package/dist/docs/versioned/next/README.md +3 -0
- package/dist/docs/versioned/next/explanation/README.md +4 -1
- package/dist/docs/versioned/next/explanation/admin-interface.md +20 -13
- package/dist/docs/versioned/next/explanation/charts.md +29 -0
- package/dist/docs/versioned/next/explanation/deployment-architecture-gcp.md +32 -0
- package/dist/docs/versioned/next/explanation/deployment-baseline.md +1 -1
- package/dist/docs/versioned/next/explanation/example-coverage.md +43 -0
- package/dist/docs/versioned/next/explanation/local-first-data.md +5 -2
- package/dist/docs/versioned/next/explanation/loop-engineering.md +9 -6
- package/dist/docs/versioned/next/explanation/model-router-actions.md +19 -2
- package/dist/docs/versioned/next/explanation/organizations.md +88 -0
- package/dist/docs/versioned/next/explanation/planning-plugins.md +114 -0
- package/dist/docs/versioned/next/explanation/positioning.md +3 -3
- package/dist/docs/versioned/next/explanation/repository-settings.md +6 -5
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +44 -34
- package/dist/docs/versioned/next/explanation/source-rules.md +1 -1
- package/dist/docs/versioned/next/explanation/static-analysis.md +76 -16
- package/dist/docs/versioned/next/how-to/README.md +10 -0
- package/dist/docs/versioned/next/how-to/add-gpt-chat-mascot.md +92 -0
- package/dist/docs/versioned/next/how-to/add-organizations.md +204 -0
- package/dist/docs/versioned/next/how-to/admin-add-model.md +9 -1
- package/dist/docs/versioned/next/how-to/admin-import-prebuilt.md +7 -1
- package/dist/docs/versioned/next/how-to/audit-log.md +85 -0
- package/dist/docs/versioned/next/how-to/background-jobs.md +296 -0
- package/dist/docs/versioned/next/how-to/build-admin-screens.md +42 -13
- package/dist/docs/versioned/next/how-to/charts-and-dashboards.md +37 -0
- package/dist/docs/versioned/next/how-to/circleci.md +136 -27
- package/dist/docs/versioned/next/how-to/compare-chart-rendered-snapshots.md +36 -0
- package/dist/docs/versioned/next/how-to/configure-better-auth.md +4 -0
- package/dist/docs/versioned/next/how-to/create-a-terreno-app.md +154 -0
- package/dist/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +2 -0
- package/dist/docs/versioned/next/how-to/github-actions-ci.md +4 -3
- package/dist/docs/versioned/next/how-to/github-issue-lifecycle.md +12 -8
- package/dist/docs/versioned/next/how-to/in-app-notifications.md +147 -0
- package/dist/docs/versioned/next/how-to/install-agent-skills.md +24 -12
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +19 -3
- package/dist/docs/versioned/next/how-to/product-announcements.md +155 -0
- package/dist/docs/versioned/next/how-to/run-mongodb-migrations.md +127 -0
- package/dist/docs/versioned/next/how-to/run-tests-locally.md +102 -0
- package/dist/docs/versioned/next/how-to/seed-a-database.md +7 -2
- package/dist/docs/versioned/next/implementationPlans/README.md +8 -5
- package/dist/docs/versioned/next/implementationPlans/admin-scripts-durable-jobs.md +44 -0
- package/dist/docs/versioned/next/implementationPlans/agent-ui-blocks.md +386 -0
- package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +11 -8
- package/dist/docs/versioned/next/implementationPlans/announcements-surfaces.md +231 -0
- package/dist/docs/versioned/next/implementationPlans/announcements.md +289 -0
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -1
- package/dist/docs/versioned/next/implementationPlans/charts-and-dashboards.md +246 -0
- package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +4 -3
- package/dist/docs/versioned/next/implementationPlans/create-terreno-app.md +177 -0
- package/dist/docs/versioned/next/implementationPlans/datatable-server-side-filtering.md +219 -0
- package/dist/docs/versioned/next/implementationPlans/examples-demo-coverage.md +17 -17
- package/dist/docs/versioned/next/implementationPlans/framework-audit-log.md +247 -0
- package/dist/docs/versioned/next/implementationPlans/gpt-chat-mascot.md +40 -0
- package/dist/docs/versioned/next/implementationPlans/job-queues.md +330 -0
- package/dist/docs/versioned/next/implementationPlans/knip-cleanup.md +136 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +210 -0
- package/dist/docs/versioned/next/implementationPlans/mongodb-migrations-tooling.md +254 -0
- package/dist/docs/versioned/next/implementationPlans/notification-center.md +185 -0
- package/dist/docs/versioned/next/implementationPlans/org-management-ui.md +8 -3
- package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/dist/docs/versioned/next/reference/README.md +4 -0
- package/dist/docs/versioned/next/reference/admin-backend.md +83 -5
- package/dist/docs/versioned/next/reference/admin-config.md +7 -0
- package/dist/docs/versioned/next/reference/admin-frontend.md +178 -5
- package/dist/docs/versioned/next/reference/admin-spa.md +18 -1
- package/dist/docs/versioned/next/reference/ai.md +2 -0
- package/dist/docs/versioned/next/reference/announcements.md +179 -0
- package/dist/docs/versioned/next/reference/api.md +343 -4
- package/dist/docs/versioned/next/reference/comms.md +33 -0
- package/dist/docs/versioned/next/reference/create-terreno-app.md +44 -0
- package/dist/docs/versioned/next/reference/environment-variables.md +29 -0
- package/dist/docs/versioned/next/reference/jobs.md +319 -0
- package/dist/docs/versioned/next/reference/legacy/rtk.md +5 -1
- package/dist/docs/versioned/next/reference/lifecycle-plugin.md +29 -11
- package/dist/docs/versioned/next/reference/mcp-server.md +2 -43
- package/dist/docs/versioned/next/reference/scan-plugin.md +169 -0
- package/dist/docs/versioned/next/reference/syncdb.md +38 -12
- package/dist/docs/versioned/next/reference/test.md +57 -6
- package/dist/docs/versioned/next/reference/ui-performance.md +2 -1
- package/dist/docs/versioned/next/reference/ui.md +257 -3
- package/dist/docs/versioned/next/tasks/admin-scripts-durable-jobs.md +10 -0
- package/dist/docs/versioned/next/tasks/agent-ui-blocks.md +114 -0
- package/dist/docs/versioned/next/tasks/announcements-surfaces.md +101 -0
- package/dist/docs/versioned/next/tasks/announcements.md +173 -0
- package/dist/docs/versioned/next/tasks/charts-and-dashboards.md +120 -0
- package/dist/docs/versioned/next/tasks/create-terreno-app.md +82 -0
- package/dist/docs/versioned/next/tasks/datatable-server-side-filtering.md +87 -0
- package/dist/docs/versioned/next/tasks/examples-demo-coverage.md +123 -17
- package/dist/docs/versioned/next/tasks/framework-audit-log.md +86 -0
- package/dist/docs/versioned/next/tasks/gpt-chat-mascot.md +13 -0
- package/dist/docs/versioned/next/tasks/job-queues.md +144 -0
- package/dist/docs/versioned/next/tasks/knip-cleanup.md +146 -0
- package/dist/docs/versioned/next/tasks/migrate-admin-to-syncdb.md +209 -0
- package/dist/docs/versioned/next/tasks/mongodb-migrations-tooling.md +107 -0
- package/dist/docs/versioned/next/tasks/notification-center.md +102 -0
- package/dist/docs/versioned/next/tasks/org-management-ui.md +14 -14
- package/dist/docs/versioned/next/tutorials/README.md +1 -1
- package/dist/docs/versioned/next/tutorials/getting-started.md +62 -22
- package/dist/help/excerpt.d.ts +2 -0
- package/dist/help/excerpt.d.ts.map +1 -0
- package/dist/help/excerpt.js +8 -0
- package/dist/help/excerpt.js.map +1 -0
- package/dist/help/updateNotes.d.ts +42 -0
- package/dist/help/updateNotes.d.ts.map +1 -0
- package/dist/help/updateNotes.js +235 -0
- package/dist/help/updateNotes.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/local/tools/databaseQuery.d.ts +1 -0
- package/dist/local/tools/databaseQuery.d.ts.map +1 -1
- package/dist/local/tools/databaseQuery.js +1 -0
- package/dist/local/tools/databaseQuery.js.map +1 -1
- package/dist/packageGuidelines.d.ts +2 -2
- package/dist/packageGuidelines.d.ts.map +1 -1
- package/dist/packageGuidelines.js +2 -8
- package/dist/packageGuidelines.js.map +1 -1
- package/dist/resources.d.ts +3 -0
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +3 -0
- package/dist/resources.js.map +1 -1
- package/dist/search/chunker.d.ts +1 -0
- package/dist/search/chunker.d.ts.map +1 -1
- package/dist/search/chunker.js +1 -0
- package/dist/search/chunker.js.map +1 -1
- package/dist/search/docIndex.d.ts +1 -5
- package/dist/search/docIndex.d.ts.map +1 -1
- package/dist/search/docIndex.js +1 -0
- package/dist/search/docIndex.js.map +1 -1
- package/dist/search/docVersion.d.ts +2 -1
- package/dist/search/docVersion.d.ts.map +1 -1
- package/dist/search/docVersion.js +3 -1
- package/dist/search/docVersion.js.map +1 -1
- package/dist/tools.d.ts +2 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +113 -2
- package/dist/tools.js.map +1 -1
- package/package.json +28 -27
- package/src/docs/guidelines/admin-frontend/guidelines/core.md +5 -1
- package/src/docs/guidelines/api/skills/mongoose-schema-safety/SKILL.md +23 -10
- package/src/docs/resources/syncdb.md +4 -1
- package/src/docs/upgrades/57.4.0.md +140 -0
- package/src/docs/versioned/next/README.md +3 -0
- package/src/docs/versioned/next/explanation/README.md +4 -1
- package/src/docs/versioned/next/explanation/admin-interface.md +20 -13
- package/src/docs/versioned/next/explanation/charts.md +29 -0
- package/src/docs/versioned/next/explanation/deployment-architecture-gcp.md +32 -0
- package/src/docs/versioned/next/explanation/deployment-baseline.md +1 -1
- package/src/docs/versioned/next/explanation/example-coverage.md +43 -0
- package/src/docs/versioned/next/explanation/local-first-data.md +5 -2
- package/src/docs/versioned/next/explanation/loop-engineering.md +9 -6
- package/src/docs/versioned/next/explanation/model-router-actions.md +19 -2
- package/src/docs/versioned/next/explanation/organizations.md +88 -0
- package/src/docs/versioned/next/explanation/planning-plugins.md +114 -0
- package/src/docs/versioned/next/explanation/positioning.md +3 -3
- package/src/docs/versioned/next/explanation/repository-settings.md +6 -5
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +44 -34
- package/src/docs/versioned/next/explanation/source-rules.md +1 -1
- package/src/docs/versioned/next/explanation/static-analysis.md +76 -16
- package/src/docs/versioned/next/how-to/README.md +10 -0
- package/src/docs/versioned/next/how-to/add-gpt-chat-mascot.md +92 -0
- package/src/docs/versioned/next/how-to/add-organizations.md +204 -0
- package/src/docs/versioned/next/how-to/admin-add-model.md +9 -1
- package/src/docs/versioned/next/how-to/admin-import-prebuilt.md +7 -1
- package/src/docs/versioned/next/how-to/audit-log.md +85 -0
- package/src/docs/versioned/next/how-to/background-jobs.md +296 -0
- package/src/docs/versioned/next/how-to/build-admin-screens.md +42 -13
- package/src/docs/versioned/next/how-to/charts-and-dashboards.md +37 -0
- package/src/docs/versioned/next/how-to/circleci.md +136 -27
- package/src/docs/versioned/next/how-to/compare-chart-rendered-snapshots.md +36 -0
- package/src/docs/versioned/next/how-to/configure-better-auth.md +4 -0
- package/src/docs/versioned/next/how-to/create-a-terreno-app.md +154 -0
- package/src/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +2 -0
- package/src/docs/versioned/next/how-to/github-actions-ci.md +4 -3
- package/src/docs/versioned/next/how-to/github-issue-lifecycle.md +12 -8
- package/src/docs/versioned/next/how-to/in-app-notifications.md +147 -0
- package/src/docs/versioned/next/how-to/install-agent-skills.md +24 -12
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +19 -3
- package/src/docs/versioned/next/how-to/product-announcements.md +155 -0
- package/src/docs/versioned/next/how-to/run-mongodb-migrations.md +127 -0
- package/src/docs/versioned/next/how-to/run-tests-locally.md +102 -0
- package/src/docs/versioned/next/how-to/seed-a-database.md +7 -2
- package/src/docs/versioned/next/implementationPlans/README.md +8 -5
- package/src/docs/versioned/next/implementationPlans/admin-scripts-durable-jobs.md +44 -0
- package/src/docs/versioned/next/implementationPlans/agent-ui-blocks.md +386 -0
- package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +11 -8
- package/src/docs/versioned/next/implementationPlans/announcements-surfaces.md +231 -0
- package/src/docs/versioned/next/implementationPlans/announcements.md +289 -0
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -1
- package/src/docs/versioned/next/implementationPlans/charts-and-dashboards.md +246 -0
- package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +4 -3
- package/src/docs/versioned/next/implementationPlans/create-terreno-app.md +177 -0
- package/src/docs/versioned/next/implementationPlans/datatable-server-side-filtering.md +219 -0
- package/src/docs/versioned/next/implementationPlans/examples-demo-coverage.md +17 -17
- package/src/docs/versioned/next/implementationPlans/framework-audit-log.md +247 -0
- package/src/docs/versioned/next/implementationPlans/gpt-chat-mascot.md +40 -0
- package/src/docs/versioned/next/implementationPlans/job-queues.md +330 -0
- package/src/docs/versioned/next/implementationPlans/knip-cleanup.md +136 -0
- package/src/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +210 -0
- package/src/docs/versioned/next/implementationPlans/mongodb-migrations-tooling.md +254 -0
- package/src/docs/versioned/next/implementationPlans/notification-center.md +185 -0
- package/src/docs/versioned/next/implementationPlans/org-management-ui.md +8 -3
- package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -1
- package/src/docs/versioned/next/reference/README.md +4 -0
- package/src/docs/versioned/next/reference/admin-backend.md +83 -5
- package/src/docs/versioned/next/reference/admin-config.md +7 -0
- package/src/docs/versioned/next/reference/admin-frontend.md +178 -5
- package/src/docs/versioned/next/reference/admin-spa.md +18 -1
- package/src/docs/versioned/next/reference/ai.md +2 -0
- package/src/docs/versioned/next/reference/announcements.md +179 -0
- package/src/docs/versioned/next/reference/api.md +343 -4
- package/src/docs/versioned/next/reference/comms.md +33 -0
- package/src/docs/versioned/next/reference/create-terreno-app.md +44 -0
- package/src/docs/versioned/next/reference/environment-variables.md +29 -0
- package/src/docs/versioned/next/reference/jobs.md +319 -0
- package/src/docs/versioned/next/reference/legacy/rtk.md +5 -1
- package/src/docs/versioned/next/reference/lifecycle-plugin.md +29 -11
- package/src/docs/versioned/next/reference/mcp-server.md +2 -43
- package/src/docs/versioned/next/reference/scan-plugin.md +169 -0
- package/src/docs/versioned/next/reference/syncdb.md +38 -12
- package/src/docs/versioned/next/reference/test.md +57 -6
- package/src/docs/versioned/next/reference/ui-performance.md +2 -1
- package/src/docs/versioned/next/reference/ui.md +257 -3
- package/src/docs/versioned/next/tasks/admin-scripts-durable-jobs.md +10 -0
- package/src/docs/versioned/next/tasks/agent-ui-blocks.md +114 -0
- package/src/docs/versioned/next/tasks/announcements-surfaces.md +101 -0
- package/src/docs/versioned/next/tasks/announcements.md +173 -0
- package/src/docs/versioned/next/tasks/charts-and-dashboards.md +120 -0
- package/src/docs/versioned/next/tasks/create-terreno-app.md +82 -0
- package/src/docs/versioned/next/tasks/datatable-server-side-filtering.md +87 -0
- package/src/docs/versioned/next/tasks/examples-demo-coverage.md +123 -17
- package/src/docs/versioned/next/tasks/framework-audit-log.md +86 -0
- package/src/docs/versioned/next/tasks/gpt-chat-mascot.md +13 -0
- package/src/docs/versioned/next/tasks/job-queues.md +144 -0
- package/src/docs/versioned/next/tasks/knip-cleanup.md +146 -0
- package/src/docs/versioned/next/tasks/migrate-admin-to-syncdb.md +209 -0
- package/src/docs/versioned/next/tasks/mongodb-migrations-tooling.md +107 -0
- package/src/docs/versioned/next/tasks/notification-center.md +102 -0
- package/src/docs/versioned/next/tasks/org-management-ui.md +14 -14
- package/src/docs/versioned/next/tutorials/README.md +1 -1
- package/src/docs/versioned/next/tutorials/getting-started.md +62 -22
|
@@ -11,6 +11,8 @@ flowchart TD
|
|
|
11
11
|
U["User<br/>iOS / Android / Web"]
|
|
12
12
|
CDN["Cloud CDN + GCS bucket<br/>expo export -p web output"]
|
|
13
13
|
CR["Cloud Run<br/>@terreno/api backend"]
|
|
14
|
+
CT["Cloud Tasks<br/>durable jobs push queue"]
|
|
15
|
+
JW["Cloud Run<br/>private jobs worker service"]
|
|
14
16
|
SM["Secret Manager<br/>auth secrets, MONGO_URI"]
|
|
15
17
|
AT["MongoDB Atlas<br/>replica set (change streams)"]
|
|
16
18
|
GCS["GCS bucket<br/>user file uploads"]
|
|
@@ -21,6 +23,9 @@ flowchart TD
|
|
|
21
23
|
CR --> SM
|
|
22
24
|
CR --> AT
|
|
23
25
|
CR --> GCS
|
|
26
|
+
CR -->|"enqueue"| CT
|
|
27
|
+
CT -->|"OIDC POST /jobs/execute"| JW
|
|
28
|
+
JW --> AT
|
|
24
29
|
AR --> CR
|
|
25
30
|
```
|
|
26
31
|
|
|
@@ -30,6 +35,8 @@ flowchart TD
|
|
|
30
35
|
|-----------|------|
|
|
31
36
|
| **Artifact Registry** | Stores versioned backend container images built from `example-backend/Dockerfile` |
|
|
32
37
|
| **Cloud Run** | Runs the long-lived `@terreno/api` process (HTTP + Socket.io) |
|
|
38
|
+
| **Cloud Tasks** | Dispatches persisted `@terreno/jobs` rows to an authenticated HTTP worker with queue-level concurrency limits |
|
|
39
|
+
| **Jobs worker service** | Runs the same example-backend image and job definitions; exposes only the Cloud Tasks execute callback through Cloud Run IAM |
|
|
33
40
|
| **Secret Manager** | Holds `MONGO_URI`, JWT secrets, and other credentials — mounted as env vars |
|
|
34
41
|
| **MongoDB Atlas** | Primary database; must be a replica set for change streams (realtime, feature flags) |
|
|
35
42
|
| **GCS (web bucket)** | Serves static web export; CDN caches at the edge |
|
|
@@ -59,6 +66,31 @@ flowchart TD
|
|
|
59
66
|
|
|
60
67
|
Native iOS and Android apps call Cloud Run directly; only the web client uses the CDN origin.
|
|
61
68
|
|
|
69
|
+
## Durable jobs and PR isolation
|
|
70
|
+
|
|
71
|
+
Cloud Tasks is a push service; it does not expose a pull-consumer API. Cloud Run worker
|
|
72
|
+
pools do not have HTTP ingress, so the example uses a private Cloud Run service as the
|
|
73
|
+
execution pool. Queue rate limits bound dispatch concurrency and Cloud Run scales the
|
|
74
|
+
worker instances.
|
|
75
|
+
|
|
76
|
+
Production and PR revisions share one queue safely because every task stores its complete
|
|
77
|
+
callback URL. A PR backend targets the matching `pr-<number>` worker tag and uses
|
|
78
|
+
`terreno-example-pr-<number>` as its Mongo database. Removing a preview removes both
|
|
79
|
+
service tags. An old callback then fails closed instead of reaching production or another
|
|
80
|
+
PR. A failed backend preview tag cannot stay on a not-Ready revision: CD rebuilds traffic
|
|
81
|
+
from Ready tags, deploys the new revision without `--tag`, then tags it.
|
|
82
|
+
|
|
83
|
+
Every example-frontend PR preview is paired with this isolated backend, including
|
|
84
|
+
frontend-only PRs. The exported Netlify bundle targets the matching `pr-<number>` Cloud
|
|
85
|
+
Run tag, whose CORS configuration trusts only that preview origin. Preview clients never
|
|
86
|
+
fall back to the production backend or production database.
|
|
87
|
+
|
|
88
|
+
Queue IAM grants `cloudtasks.enqueuer` and `iam.serviceAccountUser` on
|
|
89
|
+
`terreno-jobs-invoker` only to `terreno-backend-runtime`, the example API Cloud Run
|
|
90
|
+
identity. The project default Compute Engine SA (MCP and any other service that omits a
|
|
91
|
+
runtime identity) cannot create tasks that present that OIDC token. The worker remains
|
|
92
|
+
invokable only by `terreno-jobs-invoker`.
|
|
93
|
+
|
|
62
94
|
## Related
|
|
63
95
|
|
|
64
96
|
- [Deployment baseline](deployment-baseline.md) — seven requirements every host must satisfy
|
|
@@ -73,6 +73,6 @@ Three details consumers get wrong:
|
|
|
73
73
|
|
|
74
74
|
- **`PORT`** — Cloud Run and other platforms assign the listen port via `PORT`. Terreno reads `process.env.PORT` in `api/src/terrenoApp.ts` (default `9000` if unset).
|
|
75
75
|
- **Non-root** — Do not run the container as root in production.
|
|
76
|
-
- **Compile order** — Workspace packages (`@terreno/api`, `@terreno/test`, etc.) must compile before the example backend bundles.
|
|
76
|
+
- **Compile order** — Workspace packages (`@terreno/api`, `@terreno/jobs`, `@terreno/test`, etc.) must compile before the example backend bundles. Compile `@terreno/jobs` before `@terreno/admin-backend` — admin-backend imports jobs. The image `exports` point at `dist/`, so skipping a workspace compile fails `bun build --compile` with an unresolved `@terreno/*` import.
|
|
77
77
|
|
|
78
78
|
CI builds the image on every PR that touches backend paths (`.github/workflows/example-backend-docker.yml`).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Example app coverage
|
|
2
|
+
|
|
3
|
+
The `example-backend` and `example-frontend` apps are the living checklist for
|
|
4
|
+
framework capabilities. When you add a capability to `@terreno/*`, update this
|
|
5
|
+
matrix in the same slice.
|
|
6
|
+
|
|
7
|
+
Citations are paths from the repository root. A "yes" means a reader can follow
|
|
8
|
+
that file (and its imports) to a working example. Gaps stay explicit.
|
|
9
|
+
|
|
10
|
+
## Capability matrix
|
|
11
|
+
|
|
12
|
+
| Capability | example-backend | example-frontend | Notes |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| `modelRouter` CRUD | yes — `example-backend/src/api/todos.ts` | yes — `example-frontend/components/SyncTodosScreen.tsx` (syncdb hooks generated from the same collection) | Todos are synced; list/create/update/delete go through `@terreno/syncdb`, not RTK collection hooks. |
|
|
15
|
+
| Owner permissions | yes — `OwnerQueryFilter` + `Permissions.IsOwner` in `example-backend/src/api/todos.ts` | yes — the todos screen only shows the signed-in user's rows after sync scopes apply | Also gated by RBAC `access: {resource: "todo"}`. |
|
|
16
|
+
| Admin panel (embedded) | yes — Admin plugin registration in `example-backend/src/server.ts` | yes — `example-frontend/app/admin/` | Expo routes wrap `@terreno/admin-frontend` screens. |
|
|
17
|
+
| Admin SPA | yes — `AdminSpaServeApp` in `example-backend/src/server.ts` | n/a | Standalone SPA is served from the backend; not a frontend route. |
|
|
18
|
+
| AI streaming chat | yes — `example-backend/src/api/ai.ts` (`addGptRoutes`) | yes — `example-frontend/app/(tabs)/ai.tsx` (`GPTChat`, optional `mascot`) | Empty-chat mascot is consumer-owned; the example fox is not a framework default. |
|
|
19
|
+
| AI structured output | no | no | `@terreno/ai` supports structured generation; the example only streams chat. Recorded gap — not claimed by a current tutorial. |
|
|
20
|
+
| Feature flags + live updates | yes — `FeatureFlagsApp` in `example-backend/src/server.ts`, seed `example-backend/src/scripts/seed-feature-flags.ts` | yes — `useTerrenoFeatureFlags` in `example-frontend/app/_layout.tsx` | Socket-backed live updates share the realtime connection. |
|
|
21
|
+
| Websockets / realtime | yes — `RealtimeApp` in `example-backend/src/server.ts`, `example-backend/src/websockets.ts` | yes — `useSocketConnection` in `example-frontend/app/_layout.tsx` | Sync deltas also use the socket (`SyncApp` + `@terreno/syncdb`). |
|
|
22
|
+
| Consent forms | yes — `example-backend/src/consentDefinitions.ts`, seed scripts | yes — `example-frontend/app/(tabs)/consents.tsx`, admin `example-frontend/app/admin/consent-forms/` | First-login flow is covered by e2e (`example-frontend/e2e/consents.spec.ts`). |
|
|
23
|
+
| File upload / GCS | yes — `example-backend/src/api/settings.ts`, AI file routes in `example-backend/src/api/ai.ts` | yes — `example-frontend/app/(tabs)/files.tsx`, `example-frontend/app/gcs-settings.tsx` | |
|
|
24
|
+
| Better Auth | yes — `example-backend/src/utils/betterAuthConfig.ts`, `BetterAuthApp` in `example-backend/src/server.ts` | yes — `example-frontend/app/login.tsx`, `example-frontend/lib/betterAuth.ts` | Default `AUTH_PROVIDER` is `better-auth`. |
|
|
25
|
+
| syncdb local-first | yes — `SyncApp` in `example-backend/src/server.ts` | yes — `example-frontend/store/syncdb.ts`, `example-frontend/app/(tabs)/index.tsx` | PR #869 closed without merge; `@terreno/syncdb` shipped on the launch line and is the example todos path. |
|
|
26
|
+
| RBAC | yes — `example-backend/src/rbacRoles.ts`, `access.ts`, `access: {resource: "todo"}` on the todo router | yes — `example-frontend/app/admin/roles.tsx` | Shipped. The IP snapshot that marked RBAC "not shipped" is stale. Plan: [rbac-permissions.md](../implementationPlans/rbac-permissions.md). |
|
|
27
|
+
| Organizations | yes — `createAccess({organizations: true})`, `organizationSettingsSchema`, `orgScopedPlugin` on projects | yes — admin org directory/settings at `example-frontend/app/admin/orgs/` | Settings live on `Organization.settings`; example registers a nested timezone schema. |
|
|
28
|
+
| Background jobs | no | no | No generic job queue example. Admin maintenance scripts (`example-backend/src/adminScripts.ts`, script runner widget) are a related but different surface. Plan: [admin-script-runner.md](../implementationPlans/admin-script-runner.md). |
|
|
29
|
+
|
|
30
|
+
## Gaps
|
|
31
|
+
|
|
32
|
+
| Gap | Why it stays | Follow-up |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| AI structured output | Chat streaming already demonstrates the AI pillar; structured `generateObject`-style routes are unused by current tutorials | Track with [AI-first tutorials #1010](https://github.com/FlourishHealth/terreno/issues/1010) (`add-ai-features.md` requires one structured-output call). |
|
|
35
|
+
| Generic background jobs | Unshipped as a first-class example; do not invent a queue UI here | Track with [Durable background jobs #1188](https://github.com/FlourishHealth/terreno/issues/1188). Admin script runner is a related surface — [admin-script-runner.md](../implementationPlans/admin-script-runner.md). |
|
|
36
|
+
|
|
37
|
+
## Keeping the matrix true
|
|
38
|
+
|
|
39
|
+
When you add a framework capability:
|
|
40
|
+
|
|
41
|
+
1. Exercise it in `example-backend` and/or `example-frontend`.
|
|
42
|
+
2. Update this page (cite the file).
|
|
43
|
+
3. Mention the example in the PR.
|
|
@@ -27,7 +27,10 @@ Think **apply locally, then reconcile** instead of **request, wait, update cache
|
|
|
27
27
|
3. **Refetch orchestration** — `invalidatesTags`, `refetch()`, and list/detail cache coordination after mutations.
|
|
28
28
|
4. **Treating the network as the read path** — list screens blocked on `isLoading` for every navigation.
|
|
29
29
|
|
|
30
|
-
RTK Query remains appropriate for **non-synced** endpoints
|
|
30
|
+
RTK Query remains appropriate for **non-synced generated** endpoints such as
|
|
31
|
+
`/auth/me` and AI routes. Built-in admin RPC stays request/response through its
|
|
32
|
+
host-bound fetch client; ObjectId/API-only admin CRUD keeps RTK compatibility in
|
|
33
|
+
Terreno 57.
|
|
31
34
|
|
|
32
35
|
## What you start doing
|
|
33
36
|
|
|
@@ -35,7 +38,7 @@ RTK Query remains appropriate for **non-synced** endpoints: `/auth/me`, admin RP
|
|
|
35
38
|
2. **Sync-status UX** — Surface offline state, queued mutations, and drain progress with `useSyncStatus` (and optionally `SyncStatusBanner`).
|
|
36
39
|
3. **Encryption at rest (web)** — Web persistence uses AES-GCM via the default `createServerKeyProvider`; understand key fetch and `onDecryptFailure` for support flows.
|
|
37
40
|
4. **Key lifecycle on logout** — Call `syncDb.stop()` and consider `wipeLocalData` when the authenticated user changes so one account does not read another's local store.
|
|
38
|
-
5. **Backend sync registration** — Every synced collection needs `syncPlugin`, `isDeletedPlugin`, and a `sync` block on `modelRouter`, plus `SyncApp` and `RealtimeApp` on the server.
|
|
41
|
+
5. **Backend sync registration** — Every synced collection needs `syncPlugin`, `isDeletedPlugin`, and a `sync` block on `modelRouter`, plus `SyncApp` and `RealtimeApp` on the server. Optional `sync.adminBroadcast: true` also emits `sync:delta` to `{collection}|admin`. Admin clients subscribe with `mode: "window"` (`createSyncDb({windowCollections})`) so they do not snapshot or reconcile that collection; they call `hydrateWindow` (REST membership ids + `GET /sync/entities`). Pass the same `accessControl` into `SyncApp` that `AdminApp` uses so `{collection}|admin` requires `admin:access`. `AdminApp.register` also installs that model's admin list/read/`queryFilter` on the admin window so hydrate and live `|admin` deltas match `/admin` REST. Without RBAC, `user.admin` is enough for the shell gate. Live deltas on that stream apply only to ids already in the window; Refresh is a REST re-query plus `hydrateWindow`.
|
|
39
42
|
|
|
40
43
|
## Tradeoffs
|
|
41
44
|
|
|
@@ -49,8 +49,10 @@ the inner loop until the approved task list is done. Roast never invokes Pick. B
|
|
|
49
49
|
Taste additionally wait while async review bots are running, preferring provider CLI
|
|
50
50
|
watch hooks or harness event subscriptions over timer polling. Taste also waits in a
|
|
51
51
|
loop for product CI with `gh` or `circleci` until jobs are terminal or the wait times
|
|
52
|
-
out. Before any push it always pulls latest `master`, then
|
|
53
|
-
|
|
52
|
+
out. Before any push it always pulls latest `master`, then records last-run failed tests
|
|
53
|
+
and re-verifies them locally, then runs the repository's root
|
|
54
|
+
`prepush` package script in a no-context subagent when present (falling back to affected
|
|
55
|
+
package lint, typecheck, and tests), then pushes and watches CI.
|
|
54
56
|
|
|
55
57
|
Invocable outer loops in the plugin:
|
|
56
58
|
|
|
@@ -81,9 +83,10 @@ daemon. It waits until async review bots (Bugbot, CodeQL, and similar) on the cu
|
|
|
81
83
|
head have reported, then waits in a loop for product CI using GitHub CLI
|
|
82
84
|
(`gh pr checks --watch`, `gh run watch`) or CircleCI CLI (`circleci run watch`) until
|
|
83
85
|
jobs are terminal or the wait times out. Before any push it always pulls latest
|
|
84
|
-
`master`,
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
`master`, records last-run failed tests and re-verifies them locally, then runs root
|
|
87
|
+
`prepush` when present in a fresh subagent with no parent
|
|
88
|
+
conversation. If absent, it proves affected-package lint, typecheck, and tests instead.
|
|
89
|
+
It then pushes and watches CI, emits `PASS`, `FAIL`, `BLOCKED`, or `PENDING`, and exits.
|
|
87
90
|
|
|
88
91
|
Brew review-bot waits use only hooks targeted to the matched bot so ordinary CI cannot
|
|
89
92
|
extend Brew. Taste's product-CI wait uses unfiltered GitHub/CircleCI watches on purpose.
|
|
@@ -118,7 +121,7 @@ include:
|
|
|
118
121
|
| UI/app | `terreno-ui`, `building-terreno-apps`, `verify-ui-changes` |
|
|
119
122
|
| AI/prompts | `ai-prompt-governance` |
|
|
120
123
|
| Docs/submission | `update-docs`, Brew, `fix-conflicts` |
|
|
121
|
-
| GitHub issues | `create-github-issue`, `work-github-issues`, `implement-ready-for-dev` (Pick plan comment is the Roast contract) |
|
|
124
|
+
| GitHub issues | `create-github-issue`, `work-github-issues`, `implement-ready-for-dev` (Pick plan comment is the Roast contract; unattended Grow may also write an IP) |
|
|
122
125
|
| Deployment/runtime | `deploy-gcp`, Expo deployment/workflow skills |
|
|
123
126
|
|
|
124
127
|
This inventory is descriptive, not a plugin dependency list. Stages inspect the actual
|
|
@@ -6,18 +6,35 @@ CRUD **create, update, and delete** (not named actions) share one write pipeline
|
|
|
6
6
|
|
|
7
7
|
## When to use actions
|
|
8
8
|
|
|
9
|
+
Use `collectionActions` / `instanceActions` for every application GET or POST that is not
|
|
10
|
+
plain document CRUD. Do **not** register `app.get`, `app.post`, `router.get`, or
|
|
11
|
+
`router.post` for those endpoints.
|
|
12
|
+
|
|
9
13
|
Use actions when an endpoint performs an operation that is not a plain create/read/update/delete on the model document:
|
|
10
14
|
|
|
11
15
|
- **Collection scope** (`POST /todos/bulkComplete`) — operate on many documents or the collection as a whole.
|
|
12
16
|
- **Instance scope** (`POST /todos/:id/markComplete`) — operate on one loaded document.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
Leave Express `app.get` / `app.post` only for:
|
|
19
|
+
|
|
20
|
+
- Inbound webhooks (`WebhooksApp`)
|
|
21
|
+
- Static SPA / file serving
|
|
22
|
+
- Framework auth, health, and version-check plugins
|
|
23
|
+
- SSE or other streaming handlers that write the response themselves
|
|
24
|
+
- Tests and harnesses
|
|
25
|
+
|
|
26
|
+
PATCH and DELETE are CRUD (or a POST action that performs the same work). Do not add a
|
|
27
|
+
hand-rolled DELETE next to a modelRouter.
|
|
28
|
+
|
|
29
|
+
Use [custom routes with `createOpenApiBuilder`](./modular-api-design.md) only when the
|
|
30
|
+
URL cannot be `/{actionName}` or `/:id/{actionName}` **and** the exceptions above do not
|
|
31
|
+
apply.
|
|
15
32
|
|
|
16
33
|
## Example
|
|
17
34
|
|
|
18
35
|
```typescript
|
|
19
36
|
import {modelRouter, Permissions, z} from "@terreno/api";
|
|
20
|
-
import {Todo} from "../models";
|
|
37
|
+
import {Todo} from "../models/todo";
|
|
21
38
|
|
|
22
39
|
export const todoRouter = modelRouter("/todos", Todo, {
|
|
23
40
|
permissions: {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# How organization tenancy works
|
|
2
|
+
|
|
3
|
+
Terreno treats organizations as an optional framework primitive. Existing
|
|
4
|
+
single-tenant apps do not pay a migration or authorization cost; multi-tenant
|
|
5
|
+
apps opt in at the access, application, model, and admin layers. New apps
|
|
6
|
+
generated by `create-terreno-app` opt in by default.
|
|
7
|
+
|
|
8
|
+
## Identity and authorization layers
|
|
9
|
+
|
|
10
|
+
Platform and tenant authority are separate:
|
|
11
|
+
|
|
12
|
+
| Authority | Storage | Scope |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| `superadmin` | `User.roles` | Every framework permission |
|
|
15
|
+
| `operator` | `User.roles` | Organization directory and every organization |
|
|
16
|
+
| `org-admin` | `Membership.roleName` | One organization |
|
|
17
|
+
| `member` | `Membership.roleName` | One organization; app permissions decide actions |
|
|
18
|
+
|
|
19
|
+
`user.admin` does not imply operator access. `org-admin` is deliberately not a
|
|
20
|
+
global RBAC role: putting it on `User.roles` grants nothing. During an
|
|
21
|
+
organization request, `createAccess({organizations: true})` adds the current
|
|
22
|
+
active Membership grants to the normal role permissions.
|
|
23
|
+
|
|
24
|
+
## Request context
|
|
25
|
+
|
|
26
|
+
Tenant routes resolve `X-Organization-Id` after authentication. An operator or
|
|
27
|
+
superadmin may enter any organization but must choose one. An org-admin with
|
|
28
|
+
exactly one administered organization may omit the header; Terreno infers it.
|
|
29
|
+
Ambiguous or unauthorized context fails before model queries run.
|
|
30
|
+
|
|
31
|
+
The resolved organization and membership are stored in AsyncLocalStorage as
|
|
32
|
+
well as `req.organization` / `req.membership`. This lets `OrgQueryFilter` add
|
|
33
|
+
the server-owned organization id without trusting a client query parameter.
|
|
34
|
+
|
|
35
|
+
## Isolation boundaries
|
|
36
|
+
|
|
37
|
+
Tenant isolation uses multiple checks rather than one convention:
|
|
38
|
+
|
|
39
|
+
1. `orgContextMiddleware({required: true})` rejects missing or unauthorized context.
|
|
40
|
+
2. `OrgQueryFilter` ANDs the selected organization into list and search queries.
|
|
41
|
+
3. `Permissions.IsOrganizationMember` rejects cross-org object reads and writes.
|
|
42
|
+
4. Create hooks overwrite client-supplied organization ids.
|
|
43
|
+
5. `orgScopedPlugin` rejects any post-create change to `organizationId` (REST, admin, sync, direct save).
|
|
44
|
+
6. Sync scopes resolve active Membership rows and partition streams by organization.
|
|
45
|
+
|
|
46
|
+
`AdminApp({organizations: true})` applies these boundaries automatically to
|
|
47
|
+
admin models whose schema contains `organizationId`. Models without that path
|
|
48
|
+
remain platform-scoped.
|
|
49
|
+
|
|
50
|
+
## Disabled organizations
|
|
51
|
+
|
|
52
|
+
When `Organization.disabled` is `true`, tenant context and membership mutations
|
|
53
|
+
stop, but operators can still manage the organization record itself:
|
|
54
|
+
|
|
55
|
+
| Surface | Disabled org behavior |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `orgContextMiddleware` / inferred org context | 403 `Organization is disabled` |
|
|
58
|
+
| `GET /orgs/mine` | Disabled orgs omitted from the switcher list |
|
|
59
|
+
| `GET /orgs` (operator directory) | Disabled orgs still listed |
|
|
60
|
+
| `GET` / `PATCH /orgs/:id` | Allowed (operators use `PATCH` with `disabled: false` to re-enable) |
|
|
61
|
+
| `POST` / `PATCH` / `DELETE /orgs/:id/members` | 403 while disabled |
|
|
62
|
+
| Soft-deleted orgs | Still 404 everywhere |
|
|
63
|
+
|
|
64
|
+
Disabling or deleting an organization suspends its memberships. Re-enabling does
|
|
65
|
+
not automatically reactivate them.
|
|
66
|
+
|
|
67
|
+
## Why organizations are optional
|
|
68
|
+
|
|
69
|
+
Automatically registering routes, roles, or Mongoose models would change
|
|
70
|
+
existing apps merely because they upgraded `@terreno/api`. Instead:
|
|
71
|
+
|
|
72
|
+
- `createAccess` omits Membership grants and the `operator` seed unless
|
|
73
|
+
`organizations: true`;
|
|
74
|
+
- `TerrenoApp` does not mount `/orgs` unless organizations are enabled;
|
|
75
|
+
- `AdminApp` does not scope models unless organizations are enabled;
|
|
76
|
+
- Organization and Membership Mongoose models register lazily on first use.
|
|
77
|
+
Apps add fields to `Organization.settings` with `createOrganizationSettingsSchema`
|
|
78
|
+
and `registerOrganizationSettings`, not by replacing the Organization model.
|
|
79
|
+
|
|
80
|
+
This keeps upgrades backward compatible while letting bootstrap generate
|
|
81
|
+
multi-tenant-ready apps.
|
|
82
|
+
|
|
83
|
+
## Related
|
|
84
|
+
|
|
85
|
+
- [Add organizations](../how-to/add-organizations.md)
|
|
86
|
+
- [API reference](../reference/api.md#organizations)
|
|
87
|
+
- [Admin backend reference](../reference/admin-backend.md#organization-scoping)
|
|
88
|
+
- [Admin frontend reference](../reference/admin-frontend.md#orgdirectoryscreen)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Planning plugins
|
|
2
|
+
|
|
3
|
+
Terreno ships its agentic workflows as **two host plugins**. They divide along one line:
|
|
4
|
+
the lifecycle plugin knows *how to build one approved thing correctly*, and the scan
|
|
5
|
+
plugin knows *what is worth building next and whether it worked*.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
terreno-scan terreno (lifecycle)
|
|
9
|
+
------------ -------------------
|
|
10
|
+
Aim charter a measurable goal
|
|
11
|
+
Sweep shard + map the repository
|
|
12
|
+
Sift reduce to verified findings
|
|
13
|
+
Plot slice findings into briefs ───► Grow shape IP + tasks
|
|
14
|
+
Pick ⇄ Roast build and prove
|
|
15
|
+
Brew submit the PR
|
|
16
|
+
Taste react to CI and review
|
|
17
|
+
Track re-measure, close findings ◄─── (merged)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
A scan never edits product code. The lifecycle never decides what the repository should
|
|
21
|
+
become. Every slice crosses that boundary exactly once, as an approved IP and task list.
|
|
22
|
+
|
|
23
|
+
## terreno (lifecycle plugin)
|
|
24
|
+
|
|
25
|
+
Five bounded transitions plus three outer loops. Canonical source:
|
|
26
|
+
`plugins/terreno-planning/`; Claude Code consumes the generated `plugins/terreno-claude/`.
|
|
27
|
+
|
|
28
|
+
| Stage | Owns | PASS next |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Grow | Research, grilling, approved IP and dependency-aware task list, criterion → verification map | Pick |
|
|
31
|
+
| Pick | Implement one task, then Roast it, then take the next until the list is done | Roast, or Brew when done |
|
|
32
|
+
| Roast | Independently prove the current task against its criteria | Pick if tasks remain, else Brew |
|
|
33
|
+
| Brew | Final checks, commit, push, PR, evidence, CI trigger, wait for review bots | Taste |
|
|
34
|
+
| Taste | One reaction to the current head: bots, CI on every host, conflicts, comments | null or fresh Taste |
|
|
35
|
+
|
|
36
|
+
| Outer loop | Walks |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `pick-roast-loop` | An approved plan through every Pick/Roast retry, one ledger, stop only at completion or a genuine human gate |
|
|
39
|
+
| `planning-loop` | Grow/Pick/Brew/Taste, restrictable with `phases=` |
|
|
40
|
+
| `taste-sweep` | Every open PR of yours that is conflicting or failing, until each is mergeable |
|
|
41
|
+
|
|
42
|
+
Full contract: [lifecycle plugin reference](../reference/lifecycle-plugin.md) and
|
|
43
|
+
[loop engineering](loop-engineering.md).
|
|
44
|
+
|
|
45
|
+
## terreno-scan (scan plugin)
|
|
46
|
+
|
|
47
|
+
Five bounded transitions plus two outer loops. Canonical source: `plugins/terreno-scan/`;
|
|
48
|
+
Claude Code consumes the generated `plugins/terreno-scan-claude/`. It depends on the
|
|
49
|
+
lifecycle plugin — Plot hands every slice to Grow.
|
|
50
|
+
|
|
51
|
+
| Stage | Owns | PASS next |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Aim | Charter: metric with a command, measured baseline, dry-run detection rules, exclusions, validity rule, severity rubric, slice policy, review routing, budget | Sweep |
|
|
54
|
+
| Sweep | Run the rules, shard hits deterministically, map fresh workers into candidate findings | Sift |
|
|
55
|
+
| Sift | Dedupe, adversarially verify, drop what does not reproduce, rank, write the findings report | Plot, or Track when dry |
|
|
56
|
+
| Plot | Slice findings into PR-sized units with standalone Grow briefs | Track, handing off to Grow |
|
|
57
|
+
| Track | Re-measure the metric, close or reopen findings with evidence, record the round, choose the next move | Plot, Sweep, or null |
|
|
58
|
+
|
|
59
|
+
| Outer loop | Walks |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `campaign` | Bounded rounds: Aim → Sweep → Sift → Plot → lifecycle → Track. Stops at every gate. |
|
|
62
|
+
| `loop` | Resident session: the same rounds, plus a heartbeat over open campaign PRs — route, answer review through Taste, fix red CI, Track merges — refilling work up to `wipLimit`. |
|
|
63
|
+
|
|
64
|
+
Full contract: [scan plugin reference](../reference/scan-plugin.md).
|
|
65
|
+
|
|
66
|
+
## Which one to invoke
|
|
67
|
+
|
|
68
|
+
| Situation | Start with |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| You know what to build | `1-grow` |
|
|
71
|
+
| You have an approved plan and want it built | `pick-roast-loop` |
|
|
72
|
+
| A PR of yours is red or conflicting | `5-taste`, or `taste-sweep` for all of them |
|
|
73
|
+
| You know the outcome you want, not the work | `scan 1-aim` |
|
|
74
|
+
| You want that outcome pursued unattended | `scan loop` |
|
|
75
|
+
|
|
76
|
+
## What each plugin persists
|
|
77
|
+
|
|
78
|
+
| Artifact | Owner | Committed |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| IP and task list | Grow | yes |
|
|
81
|
+
| Execution state (`.terreno/pipeline/<slug>.json`) | Lifecycle outer loops | no |
|
|
82
|
+
| Charter (`docs/scans/<goal>/charter.md`) | Aim | yes |
|
|
83
|
+
| Findings report (`docs/scans/<goal>/round-<n>-findings.md`) | Sift | yes |
|
|
84
|
+
| Campaign state (`.terreno/scan/<goal>.json`) | Scan outer loops | no |
|
|
85
|
+
|
|
86
|
+
Both plugins emit the same shaped result — `v: 2`, `status` of `PASS` / `FAIL` /
|
|
87
|
+
`BLOCKED` / `PENDING`, a `next`, and a concrete `action` — in a collapsed details block,
|
|
88
|
+
with `status` / `next` / `action` as the visible lines. Neither persists
|
|
89
|
+
chain-of-thought.
|
|
90
|
+
|
|
91
|
+
## Why the split
|
|
92
|
+
|
|
93
|
+
Three properties fall out of keeping discovery and delivery in separate plugins:
|
|
94
|
+
|
|
95
|
+
- **A finding must earn its slice.** Sift drops anything that cannot be tied to the
|
|
96
|
+
goal metric, so the lifecycle only ever receives work with a stated payoff.
|
|
97
|
+
- **Delivery rules stay in one place.** Review response, CI waiting, the pre-push gate,
|
|
98
|
+
and documentation obligations live in the lifecycle, so a scan cannot invent a
|
|
99
|
+
shortcut around them.
|
|
100
|
+
- **Progress is measured, not asserted.** Track re-runs the metric command after the
|
|
101
|
+
work merges, so "we improved it" is always a number with its command output.
|
|
102
|
+
|
|
103
|
+
## Hosts
|
|
104
|
+
|
|
105
|
+
| Host | Lifecycle | Scan |
|
|
106
|
+
| --- | --- | --- |
|
|
107
|
+
| Cursor | `terreno-planning`, `/terreno-1-grow` | `terreno-scan`, `/terreno-scan-1-aim` |
|
|
108
|
+
| Codex | `terreno-planning`, `$terreno-1-grow` | `terreno-scan`, `$terreno-scan-1-aim` |
|
|
109
|
+
| Claude Code | `terreno`, `/terreno:1-grow` | `terreno-scan`, `/terreno-scan:1-aim` |
|
|
110
|
+
|
|
111
|
+
Install both from the marketplaces described in
|
|
112
|
+
[install agent skills](../how-to/install-agent-skills.md). Claude Code resolves a plugin
|
|
113
|
+
skill's command from its frontmatter `name`, which is why the two `*-claude/` trees are
|
|
114
|
+
generated with shortened names by `bun run skills:sync`.
|
|
@@ -103,8 +103,8 @@ your codebase is the 20% that is unique to your product.
|
|
|
103
103
|
|
|
104
104
|
The analogy earns two honest caveats. First, Terreno targets a document store
|
|
105
105
|
(MongoDB via Mongoose), not a relational ORM, and it has no migrations framework.
|
|
106
|
-
Second, it is younger — several Django/Rails staples (
|
|
107
|
-
|
|
106
|
+
Second, it is younger — several Django/Rails staples (server-side rendering,
|
|
107
|
+
role-based access control) are not shipped yet. The
|
|
108
108
|
comparison table below is deliberately straight about where the analogy holds and
|
|
109
109
|
where it does not; being honest about the gaps is what makes the analogy credible
|
|
110
110
|
rather than marketing.
|
|
@@ -125,7 +125,7 @@ shipped" row links the implementation plan or roadmap item that tracks it.
|
|
|
125
125
|
| Auth + permissions | Better Auth (`api/src/betterAuthApp.ts`) + `Permissions` (`api/src/permissions.ts`) | Fine-grained RBAC is in progress ([`rbac-permissions`](../implementationPlans/rbac-permissions.md)) |
|
|
126
126
|
| Templates / views | `@terreno/ui` components — one universal codebase for iOS, Android, and web | Server-side rendering for web is not shipped yet ([`web-ssr-and-admin-spa`](../implementationPlans/web-ssr-and-admin-spa.md)) |
|
|
127
127
|
| `manage.py` / generators | MCP server tools — the *tool* layer (`mcp-server/src/tools.ts`) + the `/terreno-*` SDLC pipeline — the *process* layer (`plugins/terreno-planning/skills/`) | Agent-driven rather than CLI-driven; the pipeline is not yet packaged for consumer apps ([`agentic-sdlc-plugin`](../implementationPlans/agentic-sdlc-plugin.md) Task 2.5) |
|
|
128
|
-
| Celery / ActiveJob (background jobs) |
|
|
128
|
+
| Celery / ActiveJob (background jobs) | `@terreno/jobs` `JobsApp` (`jobs/`) | [How-to](../how-to/background-jobs.md), [reference](../reference/jobs.md); optional GCP Cloud Tasks and Vercel Queues runners |
|
|
129
129
|
| Migrations | No migrations framework | Schema evolution is convention plus the published `mongoose-schema-safety` skill |
|
|
130
130
|
|
|
131
131
|
## Language rules
|
|
@@ -31,8 +31,9 @@ descriptions):
|
|
|
31
31
|
**Path:** Settings → Branches → Branch protection rules → `master`
|
|
32
32
|
|
|
33
33
|
- Require a pull request before merging
|
|
34
|
-
- Require status checks to pass (include
|
|
35
|
-
Rulesync Check jobs relevant to the change
|
|
34
|
+
- Require status checks to pass (include CircleCI `repo-policies`, package CI,
|
|
35
|
+
and Rulesync Check jobs relevant to the change — see the check name map in
|
|
36
|
+
[how-to/circleci.md](../how-to/circleci.md))
|
|
36
37
|
- Require branches to be up to date before merging
|
|
37
38
|
- Do not allow bypassing the above settings
|
|
38
39
|
|
|
@@ -50,9 +51,9 @@ as GitHub App checks; they are not CircleCI jobs.
|
|
|
50
51
|
|
|
51
52
|
**Path:** Settings → Environments
|
|
52
53
|
|
|
53
|
-
Same-repo PR jobs in `cd.yml` (`Terraform preview`, `
|
|
54
|
-
skip when `head.repo.full_name != github.repository`.
|
|
55
|
-
`gcp-cd-preview` environment (create it on first deploy if missing) with a
|
|
54
|
+
Same-repo PR jobs in `cd.yml` (`Terraform preview`, `Tasks deploy (preview)`,
|
|
55
|
+
`Backend deploy (preview)`) skip when `head.repo.full_name != github.repository`.
|
|
56
|
+
Also restrict the `gcp-cd-preview` environment (create it on first deploy if missing) with a
|
|
56
57
|
**deployment branch policy** or **required reviewers** so a fork that edits
|
|
57
58
|
`cd.yml` cannot mint a prod WIF token.
|
|
58
59
|
|
|
@@ -553,7 +553,9 @@ org-admins manage only the current org. Invites and billing are design-only plac
|
|
|
553
553
|
|
|
554
554
|
- **Implementation plan:** [org-management-ui.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/org-management-ui.md)
|
|
555
555
|
- **Tasks:** [org-management-ui.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/org-management-ui.md)
|
|
556
|
-
- **RTK flag:** Partial —
|
|
556
|
+
- **RTK flag:** Partial — custom non-synced routes use the generated SDK;
|
|
557
|
+
ObjectId admin compatibility may use `useAdminApi` in Terreno 57, while
|
|
558
|
+
eligible String-`_id` CRUD uses windowed syncdb
|
|
557
559
|
- **Depends on:** rbac-permissions
|
|
558
560
|
|
|
559
561
|
---
|
|
@@ -605,15 +607,15 @@ same binary. Manifest finalized 2026-08-09 (decisions D1/D3/D7); TenTap excluded
|
|
|
605
607
|
**Title:** `create-terreno-app scaffolding CLI`
|
|
606
608
|
|
|
607
609
|
**Labels:** `area:dx`, `type:feature`
|
|
608
|
-
**Project fields:** Area=`dx`, Target=`Next`, Impact=`Feature`, IP
|
|
610
|
+
**Project fields:** Area=`dx`, Target=`Next`, Impact=`Feature`, IP=`create-terreno-app`, Status=`In progress`
|
|
609
611
|
|
|
610
612
|
Today the MCP bootstrap tool returns markdown instructions and writes no files. This ships
|
|
611
613
|
a real `create-terreno-app` CLI (or template repo) that produces a running, deployable app
|
|
612
614
|
— backend, Expo app, env files, seeded auth — in one command, with the MCP bootstrap
|
|
613
615
|
delegating to it.
|
|
614
616
|
|
|
615
|
-
- **Implementation plan:**
|
|
616
|
-
- **Tasks:**
|
|
617
|
+
- **Implementation plan:** [create-terreno-app.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/create-terreno-app.md)
|
|
618
|
+
- **Tasks:** [create-terreno-app.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/create-terreno-app.md)
|
|
617
619
|
- **RTK flag:** Partial — scaffold output follows the syncdb + Better Auth direction
|
|
618
620
|
- **Depends on:** deployment-foundation
|
|
619
621
|
|
|
@@ -624,15 +626,14 @@ delegating to it.
|
|
|
624
626
|
**Title:** `Charts and dashboard primitives`
|
|
625
627
|
|
|
626
628
|
**Labels:** `area:ui`, `type:feature`
|
|
627
|
-
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP
|
|
629
|
+
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP=`charts-and-dashboards`, Status=`In progress`
|
|
628
630
|
|
|
629
|
-
`@terreno/ui`
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
layout, with demo stories and docs.
|
|
631
|
+
`@terreno/ui` ships themed `LineChart`, `BarChart`, `AreaChart`, `DonutChart` on owned
|
|
632
|
+
`react-native-svg` (not `victory-native`) plus `DashboardGrid`. Demo stories and Diátaxis
|
|
633
|
+
docs are the proof; comms admin stats consume these primitives later.
|
|
633
634
|
|
|
634
|
-
- **Implementation plan:**
|
|
635
|
-
- **Tasks:**
|
|
635
|
+
- **Implementation plan:** [charts-and-dashboards.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/charts-and-dashboards.md)
|
|
636
|
+
- **Tasks:** [charts-and-dashboards.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/charts-and-dashboards.md)
|
|
636
637
|
- **RTK flag:** None
|
|
637
638
|
- **Depends on:** —
|
|
638
639
|
|
|
@@ -662,14 +663,14 @@ root views and system chrome follow the scheme.
|
|
|
662
663
|
**Title:** `DataTable server-side filtering and search`
|
|
663
664
|
|
|
664
665
|
**Labels:** `area:ui`, `type:feature`
|
|
665
|
-
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP
|
|
666
|
+
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP=`datatable-server-side-filtering`, Status=`Planned`
|
|
666
667
|
|
|
667
668
|
DataTable sorts and paginates but has no filter UI. Adds per-column filter controls and a
|
|
668
669
|
search box that emit modelRouter-compatible query params (`queryFields`, `$and`/`$or`), so
|
|
669
670
|
list screens get server-side filtering without custom plumbing. Admin tables adopt it.
|
|
670
671
|
|
|
671
|
-
- **Implementation plan:**
|
|
672
|
-
- **Tasks:**
|
|
672
|
+
- **Implementation plan:** [datatable-server-side-filtering.md](../implementationPlans/datatable-server-side-filtering.md)
|
|
673
|
+
- **Tasks:** [datatable-server-side-filtering.md](../tasks/datatable-server-side-filtering.md)
|
|
673
674
|
- **RTK flag:** Partial — query wiring examples depend on the frontend data layer
|
|
674
675
|
- **Depends on:** —
|
|
675
676
|
|
|
@@ -699,14 +700,14 @@ native module baseline regardless, so this lands as a JS/OTA feature when schedu
|
|
|
699
700
|
**Title:** `In-app notification center`
|
|
700
701
|
|
|
701
702
|
**Labels:** `area:ui`, `type:feature`
|
|
702
|
-
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP
|
|
703
|
+
**Project fields:** Area=`ui`, Target=`Next`, Impact=`Feature`, IP=`notification-center` (Approved), Status=`Planned`
|
|
703
704
|
|
|
704
705
|
Adds a Notification model with per-user preferences, realtime delivery over the existing
|
|
705
706
|
change-stream socket layer, and a bell/inbox UI in `@terreno/ui` with read/unread state —
|
|
706
707
|
the in-app channel beside `@terreno/comms` mail/SMS/push.
|
|
707
708
|
|
|
708
|
-
- **Implementation plan:**
|
|
709
|
-
- **Tasks:**
|
|
709
|
+
- **Implementation plan:** [notification-center.md](../implementationPlans/notification-center.md)
|
|
710
|
+
- **Tasks:** [notification-center.md](../tasks/notification-center.md)
|
|
710
711
|
- **RTK flag:** Partial — inbox screens target the syncdb data layer where available
|
|
711
712
|
- **Depends on:** comms-abstraction
|
|
712
713
|
|
|
@@ -826,17 +827,20 @@ enforcement hooks in the permission layer.
|
|
|
826
827
|
**Title:** `Framework-level audit log`
|
|
827
828
|
|
|
828
829
|
**Labels:** `area:api`, `type:feature`
|
|
829
|
-
**Project fields:** Area=`api`, Target=`Next`, Impact=`Feature`, IP
|
|
830
|
+
**Project fields:** Area=`api`, Target=`Next`, Impact=`Feature`, IP=`framework-audit-log`, Status=`Planned`
|
|
830
831
|
|
|
831
832
|
Generalizes the admin/consent audit patterns into a first-class audit log: an AuditEvent
|
|
832
833
|
model, modelRouter hooks that record who changed what (with before/after diffs), org
|
|
833
834
|
scoping, retention policy, and an admin viewer — a hard requirement for compliance-minded
|
|
834
835
|
B2B customers.
|
|
835
836
|
|
|
836
|
-
|
|
837
|
-
|
|
837
|
+
Shipping this work **closes** https://github.com/FlourishHealth/terreno/issues/1186.
|
|
838
|
+
|
|
839
|
+
- **Implementation plan:** [framework-audit-log.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/framework-audit-log.md)
|
|
840
|
+
- **Tasks:** [framework-audit-log.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/framework-audit-log.md)
|
|
841
|
+
- **How-to:** [audit-log.md](../how-to/audit-log.md)
|
|
838
842
|
- **RTK flag:** None
|
|
839
|
-
- **Depends on:** org-management-ui
|
|
843
|
+
- **Depends on:** — (optional `organizationId` now; org-admin list filter waits on org-management-ui)
|
|
840
844
|
|
|
841
845
|
---
|
|
842
846
|
|
|
@@ -866,15 +870,19 @@ Shipping this work **closes** https://github.com/FlourishHealth/terreno/issues/1
|
|
|
866
870
|
**Title:** `Durable background jobs`
|
|
867
871
|
|
|
868
872
|
**Labels:** `area:api`, `type:feature`
|
|
869
|
-
**Project fields:** Area=`api`, Target=`
|
|
873
|
+
**Project fields:** Area=`api`, Target=`Released`, Impact=`Feature`, IP=`job-queues`, Status=`Shipped`
|
|
870
874
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
875
|
+
Adds `@terreno/jobs`: Mongo-recorded jobs with retries, schedules, dead-lettering, in-process or
|
|
876
|
+
standalone workers, and pluggable runners (Mongo, GCP Cloud Tasks, Vercel Queues, custom).
|
|
877
|
+
Email/webhook/billing consumers enqueue later; this item ships the queue.
|
|
874
878
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
- **
|
|
879
|
+
Shipping this work **closes** https://github.com/FlourishHealth/terreno/issues/1188.
|
|
880
|
+
|
|
881
|
+
- **Implementation plan:** [job-queues.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/job-queues.md)
|
|
882
|
+
- **Tasks:** [job-queues.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/job-queues.md)
|
|
883
|
+
- **How-to:** [background-jobs.md](../how-to/background-jobs.md)
|
|
884
|
+
- **Reference:** [jobs.md](../reference/jobs.md)
|
|
885
|
+
- **RTK flag:** Partial — admin screens use generated SDK
|
|
878
886
|
- **Depends on:** —
|
|
879
887
|
|
|
880
888
|
---
|
|
@@ -883,15 +891,17 @@ a Redis/BullMQ driver — so email sends, webhook retries, and billing sync surv
|
|
|
883
891
|
|
|
884
892
|
**Title:** `MongoDB migrations tooling`
|
|
885
893
|
|
|
886
|
-
**Labels:** `area:api`, `type:feature`
|
|
887
|
-
**Project fields:** Area=`api`, Target=`Future`, Impact=`Feature`, IP
|
|
894
|
+
**Labels:** `area:api`, `type:feature`
|
|
895
|
+
**Project fields:** Area=`api`, Target=`Future`, Impact=`Feature`, IP=`mongodb-migrations-tooling`, Status=`Planned`
|
|
888
896
|
|
|
889
897
|
A migrations runner for Terreno apps: versioned migration files, up/down with a lock
|
|
890
|
-
collection, CI checks,
|
|
891
|
-
ad-hoc backfill scripts.
|
|
898
|
+
collection, CI checks, CLI generate-from-schema-diff, optional boot apply, and an admin
|
|
899
|
+
Migrations page — replacing ad-hoc backfill scripts for once-per-environment schema changes.
|
|
892
900
|
|
|
893
|
-
|
|
894
|
-
|
|
901
|
+
Shipping this work **closes** https://github.com/FlourishHealth/terreno/issues/1189.
|
|
902
|
+
|
|
903
|
+
- **Implementation plan:** [mongodb-migrations-tooling.md](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/mongodb-migrations-tooling.md)
|
|
904
|
+
- **Tasks:** [mongodb-migrations-tooling.md](https://github.com/FlourishHealth/terreno/blob/master/docs/tasks/mongodb-migrations-tooling.md)
|
|
895
905
|
- **RTK flag:** None
|
|
896
906
|
- **Depends on:** —
|
|
897
907
|
|