@happyvertical/smrt-template-sveltekit 0.38.26 → 0.39.1

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/AGENTS.md CHANGED
@@ -1,31 +1,50 @@
1
1
  # template-sveltekit
2
2
 
3
- Base SvelteKit project template used by `smrt init`. Scaffolds a full-stack, multi-tenant app with SMRT integration.
3
+ Minimal SvelteKit project template used by `smrt gnode create --template=sveltekit`.
4
+ It is the ground-up alternative to `smrt-saas-starter`.
4
5
 
5
6
  ## Exports
6
7
 
7
- - `getTemplatePath()` returns path to template directory
8
- - `copyTemplate(destination, options)` copies template files with project name substitution. Skips internal-only directories (e.g. `.svelte-kit/` tsconfig stub).
9
- - `templateInfo` — metadata (SvelteKit 2.x, Svelte 5, REST API, SMRT CLI, SQLite, multi-tenant)
10
-
11
- ## Template Contents
12
-
13
- - `template/src/hooks.server.ts` — pre-wires `enableTenancy()`, `createSessionHandler({ enterTenantContext: true })`, and a subdomain → tenantId handle, sequenced in that order
14
- - `template/src/lib/server/tenancy.ts` — pluggable tenant resolver (`subdomainStrategy`, `pathPrefixStrategy`, `headerStrategy`, `createTenantResolver`)
15
- - `template/src/lib/server/smrt.ts` centralized SmrtClassOptions / collection factory; imports the plugin-generated `smrt-register.js` (guarded the file is gitignored and regenerated on every dev/build run) and seeds `.smrt/manifest.json` so server runtimes get package-qualified registrations + scanned field metadata (without them, writes silently drop domain columns)
16
- - `template/vite.config.ts` smrtPlugin() + smrtConsumer(), plus explicit `oxc: { decorator: { legacy: true } }` (Vite 8's oxc transform does not reliably honor `experimentalDecorators` through the SvelteKit tsconfig `extends` chain)
17
- - `template/src/lib/objects/Item.ts` example `@smrt()` object
18
- - `template/src/routes/+page.server.ts` + `+page.svelte` reference SSR data loading: server load queries collections directly (opt-in read cache via `cache: { ttl }`), declares `depends('smrt:items')`, and a form action + `invalidate('smrt:items')` demonstrates post-mutation refresh
19
- - `template/src/app.d.ts` `App.Locals` extends `SessionLocals` from `@happyvertical/smrt-users/sveltekit`
20
-
21
- ## Test Infrastructure
22
-
23
- - Tests live in `__tests__/` at the package root — **not** inside `template/` — because `cpSync` would otherwise scaffold them into consumer projects.
24
- - The template's `template/tsconfig.json` extends `./.svelte-kit/tsconfig.json` (per SvelteKit convention). To let the package run its tests without first running `svelte-kit sync`, a vitest `globalSetup` hook at `__tests__/setup/svelte-kit-stub.ts` writes a minimal stub at test startup and removes it at teardown. The stub directory is gitignored AND `copyTemplate()` filters it out as defense-in-depth.
25
-
26
- ## Key Patterns
27
-
28
- - **SSR data loading convention**: reference pages load collection data in `+page.server.ts` (serialized into the HTML, hydrated without a duplicate client fetch). Loads declare `depends('smrt:<collection>')` (REST route segment naming: `/api/items` → `smrt:items`); mutations call `invalidate('smrt:<collection>')` to re-run them.
29
- - **Pluggable tenant resolver**: `tenancy.ts` exports strategy functions + a `createTenantResolver()` factory. Consumers swap strategies by editing one line.
30
- - **File copying with placeholder substitution**: project name is replaced in template files during generation.
31
- - **No template-internal test pollution**: `__tests__/` and the `.svelte-kit/` stub are package-level and excluded from `copyTemplate` output.
8
+ - `getTemplatePath()` returns the template directory.
9
+ - `copyTemplate(destination, options)` copies authored files, substitutes the
10
+ project package name, and skips `.svelte-kit` plus test-fixture directories.
11
+ - `templateInfo` describes the SvelteKit, SQLite, generated-interface, session,
12
+ tenancy, and permission foundation.
13
+
14
+ ## Current generated-project contract
15
+
16
+ - Node `>=24.18.0`; pnpm `10.34.4` via `packageManager` and `engines`.
17
+ - Directly used `@happyvertical/smrt-*` packages share one current release range.
18
+ - `@happyvertical/smrt-cli` is a direct dev dependency because scripts/docs use
19
+ its binary. `@happyvertical/smrt-web` stays opt-in until a page imports it.
20
+ - `smrtConsumer()` explicitly consumes profiles, tenancy, and users manifests;
21
+ `smrtPlugin()` scans `src/lib/objects`, generates Vite virtual definitions,
22
+ SvelteKit routes, runtime registration, and knowledge artifacts.
23
+ - `pnpm db:migrate` builds first to refresh generated artifacts, then runs the
24
+ current manifest-driven migration command. Do not restore deprecated
25
+ `smrt db:setup` documentation.
26
+
27
+ ## Application patterns
28
+
29
+ - `src/hooks.server.ts` stores a URL-selected tenant candidate separately, then
30
+ lets `createSessionHandler({ enterTenantContext: true })` establish the only
31
+ authorized tenant context. Never turn an untrusted header into authority.
32
+ - `src/lib/server/smrt.ts` imports generated local registrations, loads the
33
+ generated manifest metadata, and uses the public users request-scoped DB API.
34
+ - `Item` is the single example object and demonstrates optional tenant scope,
35
+ a REST writable allowlist, shared CRUD action metadata, and the explicit
36
+ collection registration required by generated CLI/MCP runtime commands.
37
+ - Initial data comes from `+page.server.ts`; loads declare
38
+ `depends('smrt:items')`, mutations call `invalidate('smrt:items')`, and
39
+ hand-written writes call `assertOperationPermission()` with the session's
40
+ exact permission snapshot.
41
+ - The root layout uses Provider, the current smrt-ui ThemeProvider, AdminShell,
42
+ and a small explicit TenantNav. Generated REST routes do not imply page routes.
43
+ - WebMCP and live browser data examples are opt-in per page and must seed live
44
+ collections from SSR `initialData` to avoid a duplicate first request.
45
+
46
+ ## Tests
47
+
48
+ Tests live in package-level `__tests__/`, never under `template/`. Vitest's
49
+ global setup creates a temporary `.svelte-kit/tsconfig.json` stub and removes it
50
+ afterward; `copyTemplate()` filters the directory as defense in depth.
package/README.md CHANGED
@@ -1,113 +1,151 @@
1
1
  # @happyvertical/smrt-template-sveltekit
2
2
 
3
- SvelteKit project template with SMRT framework integration. Scaffolds a full-stack app with auto-generated REST API routes, TypeScript, and SQLite.
3
+ The minimal “learn and build from the ground up” SvelteKit template for
4
+ s-m-r-t 0.38.25. The package exports `copyTemplate()`, `getTemplatePath()`, and
5
+ `templateInfo` and is the `sveltekit` template used by `smrt gnode create`.
4
6
 
5
- ## What This Template Provides
7
+ ## 1. Install and run
6
8
 
7
- - SvelteKit 2.x with Svelte 5 and TypeScript
8
- - `smrtPlugin()` Vite integration for automatic REST API route generation
9
- - Example `@smrt()` object (`Item.ts`) with barrel export
10
- - Reference SSR data loading: `+page.server.ts` server load with the `depends('smrt:<collection>')` / `invalidate('smrt:<collection>')` refresh convention and opt-in collection read caching
11
- - Server-side SMRT initialization (`src/lib/server/smrt.ts`)
12
- - `smrt.config.ts` with SQLite database and optional AI provider
13
- - `.env.example` with starter environment variables
14
- - **Multi-tenancy pre-wired**: `src/hooks.server.ts` registers the tenancy interceptor, loads sessions via `createSessionHandler({ enterTenantContext: true })`, and resolves the tenant from a leading subdomain (`acme.demo.local` → `tenantId='acme'`). Strategy is swappable in `src/lib/server/tenancy.ts` — see the template's own README for path-prefix / header-based variants.
15
-
16
- ## Prerequisites
17
-
18
- - Node.js 18+
19
- - pnpm (recommended) or npm
20
-
21
- ## Usage
22
-
23
- ### With smrt CLI (recommended)
9
+ Scaffold through the public CLI:
24
10
 
25
11
  ```bash
26
- smrt gnode create my-app --template sveltekit
12
+ node --input-type=module -e "import { copyTemplate } from './packages/template-sveltekit/index.js'; copyTemplate('./my-app', { name: 'my-app' })"
27
13
  cd my-app
28
- npm install
29
- npm run dev
14
+ pnpm install
15
+ cp .env.example .env
16
+ pnpm db:migrate
17
+ pnpm check
18
+ pnpm build
19
+ pnpm dev
30
20
  ```
31
21
 
32
- ### Programmatic usage
22
+ Run the copy command from the monorepo root. The public 0.38.25 CLI advertises
23
+ `gnode create`, but its command dispatcher currently rejects `gnode`; this
24
+ package's tested `copyTemplate()` export is the working scaffold path.
33
25
 
34
- ```javascript
26
+ Generated projects require Node.js 24.18.0 or newer and pnpm 10.34.4. They pin
27
+ all directly used `@happyvertical/smrt-*` packages to 0.38.25.
28
+
29
+ For programmatic scaffolding:
30
+
31
+ ```js
35
32
  import { copyTemplate } from '@happyvertical/smrt-template-sveltekit';
36
33
 
37
- copyTemplate('./my-new-project', {
34
+ copyTemplate('/absolute/path/to/my-app', {
38
35
  name: 'my-app',
39
36
  overwrite: false,
40
37
  });
41
38
  ```
42
39
 
43
- ## Getting Started (after scaffolding)
40
+ `copyTemplate()` substitutes the package name and excludes package-internal
41
+ `.svelte-kit` and test fixtures.
42
+
43
+ ## 2. Understand the generated files
44
+
45
+ The checked-in template contains authored objects, hooks, server helpers,
46
+ pages, and configuration. Vite generates `.smrt/manifest.json`,
47
+ `.smrt/smrt-knowledge.json`, `.smrt/register.js`,
48
+ `src/lib/server/smrt-register.ts`, `src/lib/types/smrt-generated/`, and
49
+ `src/routes/api/**/+server.ts`. All are ignored and excluded from scaffold
50
+ fixtures.
51
+
52
+ `smrtPlugin()` scans the local object directory and generates local routes and
53
+ types. `smrtConsumer()` explicitly consumes the profiles, tenancy, and users
54
+ package manifests. `@happyvertical/smrt-cli` is a direct dev dependency because
55
+ the generated package scripts and README invoke its `smrt` binary.
56
+
57
+ ## 3. Define the first object
58
+
59
+ The generated `src/lib/objects/Item.ts` is one optional-tenant object with
60
+ title, description, and status fields. Its small explicit `ItemCollection`
61
+ constructor keeps generated CLI/MCP runtime commands constructible. Its
62
+ `@smrt()` configuration exposes CRUD to REST, MCP, WebMCP definitions, and CLI
63
+ while using an API writable allowlist.
64
+
65
+ Add objects beside Item and export them from `src/lib/objects/index.ts`.
66
+ `vite.config.ts` already scans that directory.
67
+
68
+ ## 4. Initialize or migrate the database
69
+
70
+ Generated projects use SQLite at `./app.db` by default:
44
71
 
45
72
  ```bash
46
- cd my-app
47
- npm install
48
- cp .env.example .env # Edit with your values
49
- npm run dev # Start dev server at http://localhost:5173
73
+ pnpm db:migrate
50
74
  ```
51
75
 
52
- ## Environment Variables
76
+ The script builds first to refresh manifests, registrations, types, and API
77
+ routes, then runs `smrt db:migrate`. The deprecated `smrt db:setup` command is
78
+ not documented or shipped.
53
79
 
54
- Defined in `.env.example`:
80
+ ## 5. Understand tenant context
55
81
 
56
- | Variable | Required | Description |
57
- |----------|----------|-------------|
58
- | `DATABASE_URL` | Yes | Database path (default: `./data/app.db`) |
59
- | `DATABASE_TYPE` | Yes | Database engine (default: `sqlite`) |
60
- | `PUBLIC_SITE_NAME` | No | Display name for the site |
61
- | `PUBLIC_SITE_URL` | No | Public URL (default: `http://localhost:5173`) |
62
- | `OPENAI_API_KEY` | No | OpenAI API key for AI features |
63
- | `ANTHROPIC_API_KEY` | No | Anthropic API key (alternative AI provider) |
82
+ The template resolves a URL tenant candidate into separate
83
+ `selectedTenantId`/`selectedTenantSlug` locals. It does not establish query
84
+ context from that selection. The session hook runs afterward and only its
85
+ membership-authorized tenant enters the s-m-r-t tenancy context.
64
86
 
65
- ## Template Structure
87
+ Untrusted tenant headers are ignored. Applications may replace
88
+ `src/lib/server/tenancy.ts` with a path, signed-cookie, or trusted-gateway
89
+ selector, but selection must remain separate from authorization and session
90
+ switches must use `switchSessionTenant()`.
66
91
 
67
- ```
68
- template/
69
- ├── .env.example # Environment variable defaults
70
- ├── .gitignore
71
- ├── package.json # Dependencies (smrt-core, SvelteKit)
72
- ├── smrt.config.ts # SMRT configuration (DB, AI, schema migration)
73
- ├── svelte.config.js # SvelteKit config (adapter-auto)
74
- ├── tsconfig.json
75
- ├── vite.config.ts # Vite + smrtPlugin() for API route generation
76
- └── src/
77
- ├── app.d.ts # SvelteKit type declarations (extends SessionLocals)
78
- ├── app.html # HTML shell
79
- ├── hooks.server.ts # Pre-wired auth + tenancy
80
- ├── lib/
81
- │ ├── objects/
82
- │ │ ├── index.ts # Barrel export
83
- │ │ └── Item.ts # Example @smrt() object
84
- │ └── server/
85
- │ ├── smrt.ts # Server-side SMRT initialization + manifest seeding
86
- │ ├── smrt-register.ts # Object registration (generated by smrtPlugin, gitignored)
87
- │ └── tenancy.ts # Pluggable tenant resolver
88
- └── routes/
89
- ├── +page.server.ts # Home page server load + demo mutation (reference pattern)
90
- └── +page.svelte # Home page
91
- ```
92
+ ## 6. Understand users, profiles, memberships, roles, and permissions
93
+
94
+ The generated project consumes the current profiles and users manifests and
95
+ wires `createSessionHandler({ enterTenantContext: true })`. A User is the auth
96
+ identity, Profile is person-facing metadata, Membership joins a User to a
97
+ Tenant and Role, Role maps to Permission records, and Session publishes the
98
+ resolved permission snapshot.
92
99
 
93
- ## Exports
100
+ The home-page form action calls `assertOperationPermission()` with that exact
101
+ snapshot. Provider-specific login and provisioning remain app-owned extension
102
+ points.
94
103
 
95
- This package exposes three things for programmatic use:
104
+ ## 7. Load data into a SvelteKit page
96
105
 
97
- - `getTemplatePath()` -- returns the absolute path to the `template/` directory
98
- - `copyTemplate(destination, options)` -- copies template files with project name substitution in `package.json`
99
- - `templateInfo` -- metadata object describing the template
106
+ The home page loads Item rows in `+page.server.ts`, returns plain serialized
107
+ data, and declares `depends('smrt:items')`. The Svelte 5 page reads hydrated
108
+ `$props()` data and calls `invalidate('smrt:items')` after a successful form
109
+ mutation. It does not fetch initial data in `onMount` or `$effect`.
100
110
 
101
- ## Placeholder Substitution
111
+ ## 8. Use generated REST, MCP, WebMCP, and CLI interfaces
102
112
 
103
- During `smrt gnode create`, these placeholders are replaced in template files:
113
+ REST routes are generated under `src/routes/api`. MCP and WebMCP descriptors
114
+ come from the same action metadata. CLI commands are available through the
115
+ declared dev dependency:
116
+
117
+ ```bash
118
+ pnpm smrt objects
119
+ pnpm smrt schema Item
120
+ pnpm smrt generate-mcp --no-config --no-readme
121
+ ```
122
+
123
+ WebMCP registration is documented as an opt-in, per-page integration using
124
+ `collectionDefinitions` from `@happyvertical/smrt-virt-web` and
125
+ `registerWebMcpTools()` from `@happyvertical/smrt-web`. CRUD is wired in
126
+ 0.38.25; custom action execution is not yet wired and is documented as such.
127
+ The CLI's manifest-only `objects` and `schema` commands work in this
128
+ source-first template. Local-object CRUD execution through the generic CLI
129
+ additionally requires a compiled JavaScript project entry point.
130
+
131
+ ## 9. Add optional live browser data
132
+
133
+ `@happyvertical/smrt-web` is intentionally not a base direct dependency. A
134
+ consumer adds it only when a page imports the live collection or WebMCP runtime:
135
+
136
+ ```bash
137
+ pnpm add @happyvertical/smrt-web@0.38.25
138
+ ```
104
139
 
105
- | Placeholder | Value |
106
- |-------------|-------|
107
- | `{{PROJECT_NAME}}` | Project name from CLI |
108
- | `{{PACKAGE_NAME}}` | Lowercase, hyphenated package name |
140
+ The generated-project README shows the current hydration pattern:
141
+ `createSmrtCollection(getCollectionDefinition('items'), { initialData,
142
+ basePath: '/api' })` followed by `liveCollection()`. The root layout does not
143
+ load the browser engine.
109
144
 
110
- ## Related
145
+ ## 10. Graduate to smrt-saas-starter
111
146
 
112
- - [SMRT Framework](https://github.com/happyvertical/smrt)
113
- - [SvelteKit](https://kit.svelte.dev/)
147
+ Use this template for learning and focused, ground-up applications. Choose
148
+ `smrt-saas-starter` when the baseline should already contain production-shaped
149
+ onboarding, billing/subscriptions, workers, provider configuration, deployment
150
+ infrastructure, and mobile applications. This package intentionally avoids
151
+ becoming a second SaaS starter.
package/index.js CHANGED
@@ -22,7 +22,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
22
22
  * vendored `.svelte-kit/tsconfig.json` stub that lets the template's own
23
23
  * tests typecheck without first running `svelte-kit sync`).
24
24
  */
25
- const COPY_SKIP = new Set(['.svelte-kit']);
25
+ const COPY_SKIP = new Set(['.svelte-kit', '__tests__', 'test', 'tests']);
26
26
 
27
27
  /**
28
28
  * Get the path to the template directory
@@ -81,14 +81,14 @@ export function copyTemplate(destination, options = {}) {
81
81
  */
82
82
  export const templateInfo = {
83
83
  name: 'sveltekit',
84
- description: 'SvelteKit project with SMRT framework integration',
84
+ description: 'Minimal SvelteKit project with s-m-r-t framework integration',
85
85
  features: [
86
86
  'SvelteKit 2.x with Svelte 5',
87
87
  'Auto-generated REST API routes',
88
- 'SMRT CLI integration',
88
+ 's-m-r-t CLI integration',
89
89
  'TypeScript support',
90
90
  'SQLite database (configurable)',
91
- 'Multi-tenant ready (session + subdomain tenant resolution wired)',
91
+ 'Session-authorized tenancy with separate subdomain selection',
92
92
  ],
93
93
  };
94
94
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-template-sveltekit",
3
- "version": "0.38.26",
4
- "description": "SvelteKit project template with SMRT framework integration",
3
+ "version": "0.39.1",
4
+ "description": "Minimal SvelteKit project template with s-m-r-t framework integration",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "exports": {
@@ -29,10 +29,12 @@
29
29
  "directory": "packages/template-sveltekit"
30
30
  },
31
31
  "peerDependencies": {
32
- "@happyvertical/smrt-core": "0.38.26"
32
+ "@happyvertical/smrt-core": "0.39.1"
33
33
  },
34
34
  "devDependencies": {
35
- "vitest": "^4.1.9"
35
+ "vitest": "^4.1.9",
36
+ "@happyvertical/smrt-tenancy": "0.39.1",
37
+ "@happyvertical/smrt-users": "0.39.1"
36
38
  },
37
39
  "publishConfig": {
38
40
  "registry": "https://registry.npmjs.org",
@@ -1,11 +1,7 @@
1
1
  # Database
2
- DATABASE_URL=./data/app.db
2
+ DATABASE_URL=./app.db
3
3
  DATABASE_TYPE=sqlite
4
4
 
5
- # AI Provider (optional)
6
- OPENAI_API_KEY=
7
- # ANTHROPIC_API_KEY=
8
-
9
- # Site
10
- PUBLIC_SITE_NAME=My SMRT App
11
- PUBLIC_SITE_URL=http://localhost:5173
5
+ # Optional apex used for subdomain tenant selection.
6
+ # The value selects a tenant candidate; session membership still authorizes it.
7
+ TENANT_BASE_DOMAIN=demo.local
@@ -1,34 +1,35 @@
1
- # SMRT SvelteKit App
1
+ # s-m-r-t SvelteKit app
2
2
 
3
- This project uses SMRT objects to generate REST routes, CLI commands, MCP
4
- tools, and agent/developer knowledge artifacts.
3
+ This project uses s-m-r-t objects to generate REST routes, CLI commands, MCP
4
+ tools, WebMCP definitions, and agent/developer knowledge artifacts.
5
5
 
6
- ## Agent Workflow
6
+ ## Agent workflow
7
7
 
8
- - Treat `.smrt/smrt-knowledge.json` as generated local context.
9
- - Regenerate knowledge by running the app build or dev server with
10
- `smrtPlugin()` enabled.
11
- - Use `smrt knowledge:review-context --format markdown` or the
12
- `build-domain-review-context` MCP tool before reviewing SMRT object changes.
13
- - Use `smrt knowledge:architecture-context --format markdown` or the
14
- `build-domain-architecture-context` MCP tool when planning new SMRT objects.
8
+ - Treat `.smrt/`, `src/routes/api/**/+server.ts`,
9
+ `src/lib/server/smrt-register.ts`, and
10
+ `src/lib/types/smrt-generated/` as generated.
11
+ - Regenerate them with `pnpm build` or `pnpm dev`; run `pnpm db:migrate` after
12
+ object schema changes.
15
13
  - Keep `CLAUDE.md` as the one-line `@AGENTS.md` shim.
16
14
 
17
- ## Package Guidance
15
+ ## Data and authorization
18
16
 
19
- - Load page data in `+page.server.ts` server loads that query collections
20
- directly (see `src/routes/+page.server.ts`); never fetch `/api/*` from
21
- `$effect`/`onMount` for initial page data.
22
- - Declare `depends('smrt:<collection>')` in loads (route segment naming:
23
- `/api/items` `smrt:items`) and call `invalidate('smrt:<collection>')`
24
- after mutations to refresh in place.
25
- - Opt read-heavy SSR reads into the collection cache with
26
- `list({ cache: { ttl } })`; skip it for per-user data and admin editors
27
- (see README "Data loading").
28
- - Keep SMRT object relationship metadata close to the `@smrt()` decorator.
29
- - Use `knowledge: false` only for objects that should stay out of authored
30
- agent context while remaining in the runtime manifest.
31
- - Use `knowledge: { tags, summary, risks }` for domain objects with important
32
- review or architecture constraints.
33
- - Do not enable `/__smrt/knowledge` HTTP routes in production without explicit
34
- admin auth.
17
+ - Load initial page data in `+page.server.ts`, return plain serializable rows,
18
+ and never fetch initial `/api/*` data from `onMount` or `$effect`.
19
+ - Declare `depends('smrt:<collection>')` in loads and call
20
+ `invalidate('smrt:<collection>')` after mutations.
21
+ - URL tenant selection lives in `selectedTenantId`/`selectedTenantSlug`; it is
22
+ not authorization. Only the session-authorized `tenantId` may scope queries.
23
+ - Ignore untrusted tenant headers. Use `switchSessionTenant()` for
24
+ membership-gated browser tenant changes.
25
+ - Use `assertOperationPermission()` for hand-written server mutations and pass
26
+ the exact session permission snapshot when available.
27
+
28
+ ## Extension rules
29
+
30
+ - Keep object relationship metadata close to `@smrt()`.
31
+ - Add human-facing routes explicitly; generated REST routes do not create nav
32
+ pages.
33
+ - Add `@happyvertical/smrt-web` only when a dedicated page imports live browser
34
+ data or registers WebMCP tools. Seed live collections with SSR `initialData`.
35
+ - Do not enable knowledge HTTP routes in production without explicit admin auth.