@happyvertical/smrt-template-sveltekit 0.53.3 → 0.54.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/AGENTS.md +60 -27
- package/README.md +23 -16
- package/mcp-apps-template/package.dependencies.json +2 -2
- package/mcp-apps-template/src/routes/.well-known/oauth-protected-resource/api/mcp/+server.ts +10 -6
- package/mcp-apps-template/src/routes/api/mcp/+server.ts +68 -12
- package/package.json +19 -15
- package/template/AGENTS.md +20 -5
- package/template/Dockerfile +0 -1
- package/template/INSTALL_PROMPT.md +2 -2
- package/template/README.md +86 -40
- package/template/compose.yaml +2 -2
- package/template/package.json +28 -27
- package/template/smrt.config.ts +16 -34
- package/template/src/app.d.ts +4 -11
- package/template/src/hooks.server.ts +10 -51
- package/template/src/lib/server/smrt.ts +22 -98
- package/template/src/routes/+layout.server.ts +4 -12
- package/template/src/routes/+layout.svelte +27 -99
- package/template/src/routes/+page.server.ts +4 -4
- package/template/src/routes/api/_runtime/diagnostics/+server.ts +17 -3
- package/template/src/routes/api/_runtime/health/+server.ts +4 -28
- package/template/src/routes/settings/+page.svelte +3 -34
- package/template/src/routes/setup/+page.server.ts +7 -94
- package/template/src/routes/setup/+page.svelte +3 -23
- package/template/vite.config.ts +5 -43
- package/template.config.js +11 -11
- package/mcp-apps-template/src/lib/McpAppsBridge.svelte +0 -37
- package/mcp-apps-template/src/lib/server/mcp-hosted-principal.ts +0 -12
- package/mcp-apps-template/src/lib/server/mcp-hosted.ts +0 -28
- package/mcp-apps-template/src/lib/server/mcp.ts +0 -85
- package/template/scripts/smrt-app.mjs +0 -885
- package/template/scripts/smrt-mcp-apps.mjs +0 -18
- package/template/scripts/smrt-operation-lock.mjs +0 -102
- package/template/scripts/smrt-portability-assets.mjs +0 -707
- package/template/scripts/smrt-portability.mjs +0 -470
- package/template/scripts/smrt-prepare-migration.mjs +0 -93
- package/template/scripts/smrt-process.mjs +0 -82
- package/template/scripts/smrt-provider-readiness.mjs +0 -33
- package/template/scripts/smrt-runtime-identity.mjs +0 -245
- package/template/scripts/smrt-vite.mjs +0 -45
- package/template/scripts/smrt-web.mjs +0 -10
- package/template/scripts/smrt-worker.mjs +0 -100
- package/template/scripts/smrt-writer-lease.mjs +0 -199
- package/template/src/lib/RuntimeDiagnosticsWebMcp.svelte +0 -11
- package/template/src/lib/runtime-diagnostics-webmcp.ts +0 -108
- package/template/src/lib/server/application-runtime.ts +0 -262
- package/template/src/lib/server/runtime-diagnostics.ts +0 -114
- package/template/src/lib/server/tenancy.ts +0 -114
- package/template/src/smrt-webmcp.d.ts +0 -6
package/AGENTS.md
CHANGED
|
@@ -17,6 +17,22 @@ It is the ground-up alternative to `smrt-saas-starter`.
|
|
|
17
17
|
images ship no Corepack, so the Dockerfile installs a pinned copy.
|
|
18
18
|
- `runtime.profile` is the canonical infrastructure selector. Generated apps
|
|
19
19
|
expose deterministic `app:*` operations and keep runtime state outside source.
|
|
20
|
+
- Every lifecycle script is a `smrt app <operation>` one-liner
|
|
21
|
+
(`packages/cli/agents/app-commands.md`); the template ships no `scripts/`.
|
|
22
|
+
Never reintroduce copied operator scripts: fix the CLI command instead.
|
|
23
|
+
- Server composition is `createSmrtSvelteKitRuntime()` from
|
|
24
|
+
`@happyvertical/smrt-app-runtime/sveltekit`, built once in
|
|
25
|
+
`src/lib/server/smrt.ts`, which holds only `runtime` and its options
|
|
26
|
+
(provider readiness via `createProviderReadinessProbe`), so the web process
|
|
27
|
+
never imports the CLI. The runtime takes the local writer lease by default,
|
|
28
|
+
the `smrt()` plugin injects the generated registration, and each generated
|
|
29
|
+
route embeds a prelude that imports `$lib/server/smrt` and resolves
|
|
30
|
+
collections through its exported `runtime.getCollection()` (#3416). A legacy
|
|
31
|
+
`getCollection`/`getSmrtConfig` export would take precedence (deprecated,
|
|
32
|
+
honoured for one release): never re-add one, a register import, guard, or
|
|
33
|
+
manifest hydration.
|
|
34
|
+
Health, diagnostics, layout session, and owner setup routes mount that
|
|
35
|
+
package's handlers.
|
|
20
36
|
- The production baseline uses adapter-node with separate web, task-worker, and
|
|
21
37
|
schedule-worker processes. Workers import the build-compiled
|
|
22
38
|
`.smrt/runtime/register.js` (#3117) before creating runners so app-defined
|
|
@@ -37,8 +53,9 @@ It is the ground-up alternative to `smrt-saas-starter`.
|
|
|
37
53
|
different or stale server is never accepted as this app. Deployed health
|
|
38
54
|
responses expose only generic status and profile.
|
|
39
55
|
- Directly used `@happyvertical/smrt-*` packages share one current release range.
|
|
40
|
-
- `@happyvertical/smrt-cli` is a direct dev dependency because
|
|
41
|
-
its binary
|
|
56
|
+
- `@happyvertical/smrt-cli` is a direct dev dependency because every
|
|
57
|
+
lifecycle script runs its binary; the runtime image keeps dev dependencies so
|
|
58
|
+
workers and operator commands can. The template includes `@happyvertical/smrt-web` because the root
|
|
42
59
|
Provider wires the generated read-only WebMCP definitions for every page.
|
|
43
60
|
- The generated MCP server resolves its imports from the scaffolded app, not
|
|
44
61
|
from the CLI, so every specifier `generate-mcp` emits must be declared here.
|
|
@@ -49,9 +66,10 @@ It is the ground-up alternative to `smrt-saas-starter`.
|
|
|
49
66
|
for the default worker and tenant surfaces. Do not assume pnpm exposes the
|
|
50
67
|
CLI's or core's transitive dependencies to the app root — its strict layout
|
|
51
68
|
does not (#2297).
|
|
52
|
-
- `
|
|
53
|
-
`
|
|
54
|
-
|
|
69
|
+
- `vite.config.ts` is `[sveltekit(), smrt()]`. The preset consumes exactly the
|
|
70
|
+
packages in `smrt.config.ts` `consumer.packages` (profiles, tenancy, users),
|
|
71
|
+
scans `src/lib/objects`, and generates Vite virtual definitions, SvelteKit
|
|
72
|
+
routes, runtime registration, and knowledge artifacts.
|
|
55
73
|
- `pnpm db:migrate` builds first to refresh generated artifacts, then the
|
|
56
74
|
migration wrapper holds the shared operation/writer exclusion for the full
|
|
57
75
|
manifest-driven migration command. Do not restore deprecated `smrt db:setup`
|
|
@@ -59,11 +77,11 @@ It is the ground-up alternative to `smrt-saas-starter`.
|
|
|
59
77
|
|
|
60
78
|
## Application patterns
|
|
61
79
|
|
|
62
|
-
- `src/hooks.server.ts`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
80
|
+
- `src/hooks.server.ts` re-exports the runtime's `handle`/`init`: URL tenant
|
|
81
|
+
selection stays a separate candidate and only the verified session
|
|
82
|
+
establishes tenant context. Never turn an untrusted header into authority.
|
|
83
|
+
- App code uses `runtime.getCollection()`/`runtime.classOptions()`, which are
|
|
84
|
+
request-scoped (RLS transaction) and must never be retained.
|
|
67
85
|
- `Item` is the single example object and demonstrates optional tenant scope,
|
|
68
86
|
a REST writable allowlist, shared CRUD action metadata, and the explicit
|
|
69
87
|
collection registration required by generated CLI/MCP runtime commands.
|
|
@@ -71,18 +89,27 @@ It is the ground-up alternative to `smrt-saas-starter`.
|
|
|
71
89
|
`depends('smrt:items')`, mutations call `invalidate('smrt:items')`, and
|
|
72
90
|
hand-written writes call `assertOperationPermission()` with the session's
|
|
73
91
|
exact permission snapshot.
|
|
74
|
-
- The root layout
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
page
|
|
92
|
+
- The root layout is `AppShell` from `@happyvertical/smrt-svelte/app` with a
|
|
93
|
+
small explicit `nav`; `/setup` and `/settings` mount that package's
|
|
94
|
+
`OwnerSetupForm` and `ShellSettingsPage`. Generated REST routes do not imply
|
|
95
|
+
page routes.
|
|
96
|
+
- AppShell's Provider registers generated WebMCP read tools with the
|
|
97
|
+
authenticated page session. Write/destructive effects require an explicit
|
|
98
|
+
page-owned policy.
|
|
78
99
|
Live browser collections remain opt-in per page and must seed from SSR
|
|
79
100
|
`initialData` to avoid a duplicate first request.
|
|
80
|
-
- `
|
|
81
|
-
`smrt.runtime.diagnostics.read
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
owner role or
|
|
85
|
-
|
|
101
|
+
- AppShell's `runtimeDiagnostics` (on for signed-in sessions) owns exactly one
|
|
102
|
+
additional read-only tool, `smrt.runtime.diagnostics.read`, which fetches the
|
|
103
|
+
mounted `/api/_runtime/diagnostics` route as the page user. That route
|
|
104
|
+
(`createRuntimeDiagnosticsHandler`) requires a direct active tenant membership
|
|
105
|
+
plus the owner role or `runtime_diagnostics.read` before any projection or
|
|
106
|
+
probe; it never calls principal-bound server tools.
|
|
107
|
+
- The opt-in `mcp-apps-template/` overlay is one `mountMcpAppRoute()` route
|
|
108
|
+
and the protected-resource metadata route, both using
|
|
109
|
+
`createHostedMcpResourceAuth({ profile, runtime })` (local owner tokens,
|
|
110
|
+
hosted membership-backed principals); `pnpm typecheck` checks it against
|
|
111
|
+
the template. `__tests__/localMcpToken.test.ts` proves mint → real
|
|
112
|
+
`smrt-mcp-bridge` stdio → route against the real runtime.
|
|
86
113
|
|
|
87
114
|
## Tests
|
|
88
115
|
|
|
@@ -126,11 +153,13 @@ own. Never add a mocked REST handler, an in-memory database, or DOM automation
|
|
|
126
153
|
presented as WebMCP execution.
|
|
127
154
|
|
|
128
155
|
- `@happyvertical/smrt-cli` is a devDependency **because the gate needs it**:
|
|
129
|
-
the app's `app
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
156
|
+
the harness runs the app's own `smrt app setup` and `smrt app dev` from the
|
|
157
|
+
linked CLI, and setup's `pnpm build` is `smrt app build`. The copied app
|
|
158
|
+
deliberately never runs `pnpm install`, so `smrt` has to arrive through the
|
|
159
|
+
linked `node_modules`. The harness pins the app's own `.bin` ahead of `PATH`
|
|
160
|
+
and fails with a named error if the binary is missing, so a host-global
|
|
161
|
+
`smrt` cannot make a local run pass where CI fails. Identity and state-root
|
|
162
|
+
values it checks come from `@happyvertical/smrt-app-runtime`.
|
|
134
163
|
- `pnpm test:e2e` runs the browser half.
|
|
135
164
|
- `pnpm test:m5` runs the whole aggregate gate through
|
|
136
165
|
`e2e/support/gate.mjs`, which requires a PostgreSQL service and fails when a
|
|
@@ -145,8 +174,12 @@ presented as WebMCP execution.
|
|
|
145
174
|
from `testInfo.project.outputDir` and asserts it is outside the repository.
|
|
146
175
|
The harness gives the copied app a real `node_modules` directory of
|
|
147
176
|
individually symlinked entries rather than one symlink to this package's, so
|
|
148
|
-
the served app's `node_modules/.vite` cache cannot land in the checkout
|
|
149
|
-
|
|
177
|
+
the served app's `node_modules/.vite` cache cannot land in the checkout.
|
|
178
|
+
Scope directories (`@happyvertical/`) and `.bin/` are real directories of
|
|
179
|
+
per-entry links too: the copy ships `pnpm-workspace.yaml` and setup runs
|
|
180
|
+
`pnpm build` in it, so anything pnpm relinks must land in the copy, never in
|
|
181
|
+
this package's `node_modules`. Never replace either loop with a
|
|
182
|
+
whole-directory symlink.
|
|
150
183
|
- `e2e/` is outside `biome.json`'s include globs, as every package's `e2e/` is,
|
|
151
184
|
so a green `Lint` job says nothing about this tree. `pnpm typecheck` covers
|
|
152
185
|
the `.ts` files (`tsconfig.fixture.json` includes `e2e/**/*.ts`) but NOT
|
package/README.md
CHANGED
|
@@ -52,17 +52,21 @@ fixtures.
|
|
|
52
52
|
|
|
53
53
|
## 2. Understand the generated files
|
|
54
54
|
|
|
55
|
-
The checked-in template contains authored objects,
|
|
56
|
-
|
|
55
|
+
The checked-in template contains authored objects, one server module
|
|
56
|
+
(`src/lib/server/smrt.ts`, the runtime and its options), thin hooks and
|
|
57
|
+
routes that mount package handlers, pages, and configuration. It ships no
|
|
58
|
+
operator scripts. Vite generates `.smrt/manifest.json`,
|
|
57
59
|
`.smrt/smrt-knowledge.json`, `.smrt/register.js`,
|
|
58
60
|
`src/lib/server/smrt-register.ts`, `src/lib/types/smrt-generated/`, and
|
|
59
61
|
`src/routes/api/**/+server.ts`. All are ignored and excluded from scaffold
|
|
60
62
|
fixtures.
|
|
61
63
|
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
`vite.config.ts` is `plugins: [sveltekit(), smrt()]`: the
|
|
65
|
+
`@happyvertical/smrt-core/vite` preset applies the decorator transform, scans
|
|
66
|
+
the local object directory, generates local routes and types, and consumes the
|
|
67
|
+
packages `smrt.config.ts` lists under `consumer.packages` (profiles, tenancy,
|
|
68
|
+
users). `@happyvertical/smrt-cli` is a direct dev dependency because every
|
|
69
|
+
lifecycle script is `smrt app <operation>`.
|
|
66
70
|
|
|
67
71
|
## 3. Define the first object
|
|
68
72
|
|
|
@@ -85,25 +89,28 @@ pnpm db:migrate
|
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
The script builds first to refresh manifests, registrations, types, and API
|
|
88
|
-
routes, then runs `smrt
|
|
92
|
+
routes, then runs `smrt app migrate`, which holds the operation lock and runs
|
|
93
|
+
`smrt db:migrate`. The deprecated `smrt db:setup` command is
|
|
89
94
|
not documented or shipped.
|
|
90
95
|
|
|
91
96
|
## 5. Understand tenant context
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
`src/hooks.server.ts` mounts `createSmrtSvelteKitRuntime()` from
|
|
99
|
+
`@happyvertical/smrt-app-runtime/sveltekit`. It resolves a URL tenant candidate
|
|
100
|
+
into separate `selectedTenantId`/`selectedTenantSlug` locals and does not
|
|
101
|
+
establish query context from that selection. The session step runs afterward
|
|
102
|
+
and only its membership-authorized tenant enters the s-m-r-t tenancy context.
|
|
97
103
|
|
|
98
|
-
Untrusted tenant headers are ignored. Applications may
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
Untrusted tenant headers are ignored. Applications may pass `selectTenant` for
|
|
105
|
+
a path, signed-cookie, or trusted-gateway selector, but selection must remain
|
|
106
|
+
separate from authorization and session switches must use
|
|
107
|
+
`switchSessionTenant()`.
|
|
102
108
|
|
|
103
109
|
## 6. Understand users, profiles, memberships, roles, and permissions
|
|
104
110
|
|
|
105
111
|
The generated project consumes the current profiles and users manifests and
|
|
106
|
-
|
|
112
|
+
loads the signed session through the runtime, which enters tenant context only
|
|
113
|
+
for a verified active membership. A User is the auth
|
|
107
114
|
identity, Profile is person-facing metadata, Membership joins a User to a
|
|
108
115
|
Tenant and Role, Role maps to Permission records, and Session publishes the
|
|
109
116
|
resolved permission snapshot.
|
package/mcp-apps-template/src/routes/.well-known/oauth-protected-resource/api/mcp/+server.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHostedMcpResourceAuth } from '@happyvertical/smrt-app-mcp/auth';
|
|
2
|
+
import { mountMcpProtectedResourceMetadataRoute } from '@happyvertical/smrt-app-mcp/sveltekit';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import { runtime } from '$lib/server/smrt';
|
|
5
|
+
|
|
6
|
+
const { profile } = await runtime.resolvedRuntime();
|
|
7
|
+
|
|
8
|
+
/** RFC 9728 metadata at exactly the URL hosted bearer challenges advertise (404 locally). */
|
|
9
|
+
export const GET = mountMcpProtectedResourceMetadataRoute(
|
|
10
|
+
createHostedMcpResourceAuth({ profile, runtime }),
|
|
11
|
+
);
|
|
@@ -1,15 +1,71 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { McpWorkflowToolDefinition } from '@happyvertical/smrt-app-mcp';
|
|
2
|
+
import { createHostedMcpResourceAuth } from '@happyvertical/smrt-app-mcp/auth';
|
|
3
|
+
import { mountMcpAppRoute } from '@happyvertical/smrt-app-mcp/sveltekit';
|
|
4
|
+
import { openAiDisplayMetadata, withOpenAiEntrypoints } from '@happyvertical/smrt-mcp-openai';
|
|
2
5
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
6
|
+
import { Item } from '$lib/objects/Item';
|
|
7
|
+
import { runtime } from '$lib/server/smrt';
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
const
|
|
9
|
+
const ITEM_RESOURCE_URI = 'ui://smrt-app/v1/items.html';
|
|
10
|
+
const itemResourceHtml = `<!doctype html><html lang="en"><head><title>Items</title></head><body><main tabindex="-1"><h1>Items</h1><p>Use the host controls to review your authorized items.</p></main></body></html>`;
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const itemsOverview: McpWorkflowToolDefinition = withOpenAiEntrypoints(
|
|
13
|
+
{
|
|
14
|
+
name: 'items_overview',
|
|
15
|
+
description: 'Open the authorized item overview.',
|
|
16
|
+
title: 'Items',
|
|
17
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
18
|
+
outputSchema: {
|
|
19
|
+
type: 'object',
|
|
20
|
+
properties: { state: { type: 'string' } },
|
|
21
|
+
required: ['state'],
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
},
|
|
24
|
+
effect: 'read',
|
|
25
|
+
idempotent: true,
|
|
26
|
+
openWorld: false,
|
|
27
|
+
ui: { resourceUri: ITEM_RESOURCE_URI },
|
|
28
|
+
async execute() {
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: 'text', text: 'Item overview is ready.' }],
|
|
31
|
+
structuredContent: { state: 'ready' },
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
['global'],
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const { profile } = await runtime.resolvedRuntime();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Stateless SDK-v2 Streamable HTTP MCP endpoint for this app's own `Item`.
|
|
42
|
+
* Locally the principal is the signed session (user, authorized tenant, and
|
|
43
|
+
* permission slugs), or an owner-minted bearer token from `smrt app token`
|
|
44
|
+
* for a local MCP client such as the `smrt-mcp-bridge` stdio bridge. Hosted
|
|
45
|
+
* profiles verify a bearer access token and map it through the runtime's
|
|
46
|
+
* membership-backed `resolveMcpPrincipal` (pass `resolvePrincipal` to
|
|
47
|
+
* override it). A bearer principal is bound into the request permission
|
|
48
|
+
* context (under `database-rls`, its own RLS transaction) with its scopes
|
|
49
|
+
* capped to live permissions. Every principal needs `items.read`, so only
|
|
50
|
+
* read-only tools are published until per-operation authorization exists;
|
|
51
|
+
* browser requests from a foreign `Origin` are refused.
|
|
52
|
+
*/
|
|
53
|
+
export const POST = mountMcpAppRoute({
|
|
54
|
+
models: [Item],
|
|
55
|
+
requiredScopes: ['items.read'],
|
|
56
|
+
effects: ['read'],
|
|
57
|
+
smrtOptions: () => ({ db: runtime.databaseConfig() }),
|
|
58
|
+
auth: createHostedMcpResourceAuth({ profile, runtime }),
|
|
59
|
+
bindPrincipal: runtime.runAsPrincipal,
|
|
60
|
+
workflowTools: [itemsOverview],
|
|
61
|
+
resources: [
|
|
62
|
+
{
|
|
63
|
+
uri: ITEM_RESOURCE_URI,
|
|
64
|
+
version: 'v1',
|
|
65
|
+
name: 'Items',
|
|
66
|
+
html: itemResourceHtml,
|
|
67
|
+
csp: {},
|
|
68
|
+
metadata: openAiDisplayMetadata({ availableDisplayModes: ['inline'] }),
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-template-sveltekit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "Minimal SvelteKit project template with s-m-r-t framework integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -32,23 +32,27 @@
|
|
|
32
32
|
"directory": "packages/template-sveltekit"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@happyvertical/smrt-core": "0.
|
|
35
|
+
"@happyvertical/smrt-core": "0.54.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@happyvertical/smrt-app-
|
|
39
|
-
"@happyvertical/smrt-
|
|
40
|
-
"@happyvertical/smrt-
|
|
41
|
-
"@happyvertical/smrt-
|
|
42
|
-
"@happyvertical/smrt-
|
|
43
|
-
"@happyvertical/smrt-
|
|
44
|
-
"@happyvertical/smrt-
|
|
45
|
-
"@happyvertical/smrt-
|
|
46
|
-
"@happyvertical/smrt-
|
|
47
|
-
"@happyvertical/smrt-
|
|
48
|
-
"@happyvertical/smrt-
|
|
49
|
-
"@happyvertical/smrt-
|
|
50
|
-
"@happyvertical/smrt-
|
|
38
|
+
"@happyvertical/smrt-app-cli": "0.54.0",
|
|
39
|
+
"@happyvertical/smrt-app-mcp": "0.54.0",
|
|
40
|
+
"@happyvertical/smrt-app-runtime": "0.54.0",
|
|
41
|
+
"@happyvertical/smrt-assets": "0.54.0",
|
|
42
|
+
"@happyvertical/smrt-cli": "0.54.0",
|
|
43
|
+
"@happyvertical/smrt-config": "0.54.0",
|
|
44
|
+
"@happyvertical/smrt-jobs": "0.54.0",
|
|
45
|
+
"@happyvertical/smrt-mcp-openai": "0.54.0",
|
|
46
|
+
"@happyvertical/smrt-playbooks": "0.54.0",
|
|
47
|
+
"@happyvertical/smrt-profiles": "0.54.0",
|
|
48
|
+
"@happyvertical/smrt-scanner": "0.54.0",
|
|
49
|
+
"@happyvertical/smrt-svelte": "0.54.0",
|
|
50
|
+
"@happyvertical/smrt-tenancy": "0.54.0",
|
|
51
|
+
"@happyvertical/smrt-ui": "0.54.0",
|
|
52
|
+
"@happyvertical/smrt-users": "0.54.0",
|
|
53
|
+
"@happyvertical/smrt-web": "0.54.0",
|
|
51
54
|
"@happyvertical/sql": "^0.89.12",
|
|
55
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
52
56
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
53
57
|
"@playwright/test": "^1.63.0",
|
|
54
58
|
"@sveltejs/adapter-node": "^5.5.7",
|
package/template/AGENTS.md
CHANGED
|
@@ -18,7 +18,20 @@ tools, WebMCP definitions, and agent/developer knowledge artifacts.
|
|
|
18
18
|
return only the schema-versioned allowlist; never expose private runtime
|
|
19
19
|
objects, identity fields, paths, URLs, secrets, PII, raw errors, or logs.
|
|
20
20
|
- Never improvise setup internals. Run `pnpm app:install`; use individual
|
|
21
|
-
`app:*` commands only for recovery or explicit operator control.
|
|
21
|
+
`app:*` commands only for recovery or explicit operator control. They call
|
|
22
|
+
`smrt app <operation>` from `@happyvertical/smrt-cli`; do not copy operator
|
|
23
|
+
scripts into this app.
|
|
24
|
+
- Server composition (profile, storage custody, owner bootstrap, tenant
|
|
25
|
+
selection, session, health, diagnostics) comes from
|
|
26
|
+
`@happyvertical/smrt-app-runtime/sveltekit`, configured once in
|
|
27
|
+
`src/lib/server/smrt.ts`, which holds only `runtime` and its options. Pass
|
|
28
|
+
app-specific behaviour as options (`selectTenant`, `classOverrides`,
|
|
29
|
+
`session`, `prepareDatabase`); do not reimplement hooks, re-add the
|
|
30
|
+
`smrt-register` import (the `smrt()` plugin injects it), or export
|
|
31
|
+
`getCollection` (generated routes import this module and use its
|
|
32
|
+
`runtime.getCollection()`; a legacy export would win, deprecated).
|
|
33
|
+
`runtime.getCollection()`/`runtime.classOptions()` are request-scoped: never
|
|
34
|
+
keep their result beyond the request.
|
|
22
35
|
- Recover an interrupted unclaimed owner invitation with `pnpm app:stop`, then
|
|
23
36
|
`pnpm app:recover`, `pnpm app:start`, and `pnpm app:open`; never print or copy
|
|
24
37
|
its token.
|
|
@@ -48,8 +61,9 @@ tools, WebMCP definitions, and agent/developer knowledge artifacts.
|
|
|
48
61
|
- Keep object relationship metadata close to `@smrt()`.
|
|
49
62
|
- Add human-facing routes explicitly; generated REST routes do not create nav
|
|
50
63
|
pages.
|
|
51
|
-
- The root layout
|
|
52
|
-
|
|
64
|
+
- The root layout is `AppShell` from `@happyvertical/smrt-svelte/app`; it
|
|
65
|
+
includes `@happyvertical/smrt-web` and registers generated WebMCP read tools
|
|
66
|
+
through its Provider when the browser exposes `modelContext`.
|
|
53
67
|
Keep the guard in place for SSR and seed live collections with SSR
|
|
54
68
|
`initialData`.
|
|
55
69
|
- Do not enable knowledge HTTP routes in production without explicit admin auth.
|
|
@@ -57,8 +71,9 @@ tools, WebMCP definitions, and agent/developer knowledge artifacts.
|
|
|
57
71
|
imports `.smrt/runtime/register.js` (compiled by `pnpm build`) before any
|
|
58
72
|
runner starts, so jobs can target this app's own `@smrt()` objects; keep that
|
|
59
73
|
import ahead of runner creation and keep domain objects free of SvelteKit
|
|
60
|
-
virtual modules (`$env/*`, `$app/*`), which a worker cannot load.
|
|
61
|
-
portability adapter
|
|
74
|
+
virtual modules (`$env/*`, `$app/*`), which a worker cannot load. Add a
|
|
75
|
+
`scripts/smrt-portability.mjs` adapter (it overrides the CLI's built-in one)
|
|
76
|
+
instead of converting database files. Deployed provider
|
|
62
77
|
readiness must come from installed modules that probe the real backing
|
|
63
78
|
services; environment booleans are not readiness evidence.
|
|
64
79
|
- Every supported local web entry point (`app:start` or `pnpm dev`) holds the
|
package/template/Dockerfile
CHANGED
|
@@ -17,7 +17,6 @@ ENV NODE_ENV=production
|
|
|
17
17
|
ENV SMRT_RUNTIME_PROFILE=self-hosted
|
|
18
18
|
COPY --from=build /app/build ./build
|
|
19
19
|
COPY --from=build /app/.smrt ./.smrt
|
|
20
|
-
COPY --from=build /app/scripts ./scripts
|
|
21
20
|
COPY --from=build /app/smrt.config.ts ./smrt.config.ts
|
|
22
21
|
RUN chown -R node:node /app
|
|
23
22
|
USER node
|
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
> `pnpm app:doctor`, show me its secret-free recovery findings, and ask before
|
|
8
8
|
> changing provider configuration.
|
|
9
9
|
|
|
10
|
-
The prompt is intentionally thin. `
|
|
11
|
-
recovery.
|
|
10
|
+
The prompt is intentionally thin. `smrt app` (from `@happyvertical/smrt-cli`)
|
|
11
|
+
owns operations and recovery.
|