@happyvertical/smrt-web 0.43.2 → 0.43.4
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 +30 -1
- package/README.md +84 -0
- package/dist/chunks/{src-CDdW9uYx.js → src-n14q6RHC.js} +754 -43
- package/dist/chunks/src-n14q6RHC.js.map +1 -0
- package/dist/index.d.ts +143 -3
- package/dist/index.js +2 -2
- package/dist/webmcp.d.ts +59 -2
- package/dist/webmcp.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/src-CDdW9uYx.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -38,9 +38,10 @@ module you are editing. This file keeps what holds in every module.
|
|
|
38
38
|
| `index.ts` hooks + `durable-store.ts` | the six capability hook points, hook error isolation, the no-op guarantee, and the shared durable-store namespacing/wipe registry | [agents/capability-seam.md](agents/capability-seam.md) |
|
|
39
39
|
| `offline/` | durable offline writes — config, sync-apply-only replay, idempotency, the shared namespace-keyed engine, and Web Locks leader election | [agents/offline-outbox.md](agents/offline-outbox.md) |
|
|
40
40
|
| `sse-client.ts` | the client half of live cache invalidation — the app-wide subscriber, the wire contract it consumes, and SSE-vs-polling behaviour | [agents/live-invalidation.md](agents/live-invalidation.md) |
|
|
41
|
-
| `webmcp.ts` | framework-agnostic WebMCP registrar;
|
|
41
|
+
| `webmcp.ts` | framework-agnostic WebMCP registrar; validates an optionally bounded/namespaced, effect-filtered prospective set atomically, keeps legacy list-backed tools on collection state, and executes canonical tool-only definitions directly through REST fetchers | — |
|
|
42
42
|
| `persistence/` + `update-state.ts` | the read-cache rehydrate capability and the framework-free `updateAvailable` primitive (bundle + contract signals) | [agents/version-persistence.md](agents/version-persistence.md) |
|
|
43
43
|
| `data-query.ts` | dependency-free browser mirror and defensive response normalizer for the canonical bounded data-query envelope (#2444) | — |
|
|
44
|
+
| `remote-query.ts` | query-shaped remote pages over a `SmrtWebCollection`, with keyed stale cache, execution modes, cancellation/latest-query-wins, and optional query-scoped live subscriptions (#2445) | — |
|
|
44
45
|
|
|
45
46
|
## The engine-absorption boundary (ratified conditions, #1761)
|
|
46
47
|
|
|
@@ -60,6 +61,34 @@ module you are editing. This file keeps what holds in every module.
|
|
|
60
61
|
|
|
61
62
|
## Conventions
|
|
62
63
|
|
|
64
|
+
- **WebMCP definition mirror** — `WebMcpToolDefinition` textually mirrors the
|
|
65
|
+
generated `@happyvertical/smrt-virt-web` / physical `@smrt/web` declaration.
|
|
66
|
+
It is transport-complete and does not imply that a list-materialized client
|
|
67
|
+
collection exists. Keep the mirror dependency-free. Register canonical tools
|
|
68
|
+
or legacy collection definitions for overlapping collections; when composing
|
|
69
|
+
the two forms, keep their names and collection/action identities disjoint.
|
|
70
|
+
Duplicates fail atomically before registration.
|
|
71
|
+
With no exposure policy, only `read` effects are selected; broader effects
|
|
72
|
+
require explicit opt-in, and undeclared custom actions are destructive.
|
|
73
|
+
Direct mutations invalidate their
|
|
74
|
+
own and relationship-derived collection names through the public
|
|
75
|
+
`invalidateSmrtWebCollections()` seam when the host supplies its shared
|
|
76
|
+
`SmrtWebClient`. Legacy `filter` callbacks receive complete collection
|
|
77
|
+
metadata; canonical definitions use `filterTool`. Supplying either filter for
|
|
78
|
+
definitions of the other kind fails closed rather than ignoring the predicate
|
|
79
|
+
or fabricating incomplete metadata for a policy decision. Filters and fetcher
|
|
80
|
+
resolvers receive isolated value snapshots, so integrations must key external
|
|
81
|
+
state by stable values such as collection/action rather than definition object
|
|
82
|
+
identity.
|
|
83
|
+
Canonical writes validate that shared client handle before registration, and
|
|
84
|
+
string or structured `{ error }` REST envelopes fail before cache
|
|
85
|
+
invalidation. The private `__smrt_options` GET sentinel is reserved only for
|
|
86
|
+
no-path single-options-bag actions; positional actions preserve a legitimate
|
|
87
|
+
parameter with that name.
|
|
88
|
+
This capability policy is not authorization:
|
|
89
|
+
the authenticated REST surface remains the auth, tenant, field-write, and
|
|
90
|
+
sensitive-data boundary.
|
|
91
|
+
|
|
63
92
|
- **No inter-smrt dependencies** — depends only on TanStack packages
|
|
64
93
|
(dependency-DAG guardrails). Definitions and fetchers arrive as arguments.
|
|
65
94
|
- **Data-query mirror** — `data-query.ts` mirrors the portable
|
package/README.md
CHANGED
|
@@ -9,6 +9,12 @@ Use it for browser-side collection state, shared request deduplication, offline
|
|
|
9
9
|
writes, persisted read caches, and live invalidation. Svelte bindings live in
|
|
10
10
|
[`@happyvertical/smrt-svelte/web`](../smrt-svelte/README.md).
|
|
11
11
|
|
|
12
|
+
Query-backed surfaces can use `createSmrtWebQuery(collection, transport)` to
|
|
13
|
+
fetch one canonical bounded page. Visible runs update state; `background`,
|
|
14
|
+
`prefetch`, and `silent` runs stay out of visible state. The controller keeps
|
|
15
|
+
stale rows available while refreshing, cancels superseded visible runs, and can
|
|
16
|
+
attach a query-scoped live subscription.
|
|
17
|
+
|
|
12
18
|
## Installation
|
|
13
19
|
|
|
14
20
|
```bash
|
|
@@ -119,6 +125,7 @@ core.
|
|
|
119
125
|
| Group | Main exports |
|
|
120
126
|
| --- | --- |
|
|
121
127
|
| Collections | `createSmrtCollection`, `createSmrtWebClient`, `newLocalId` |
|
|
128
|
+
| Remote queries | `createSmrtWebQuery`, `SmrtWebQueryTransport` |
|
|
122
129
|
| HTTP | `createDefinitionFetchers`, `unwrapListResult`, `unwrapItemResult` |
|
|
123
130
|
| Offline | `offlineOutbox`, `getOutboxHandle` |
|
|
124
131
|
| Persistence | `persistCollection`, `wipeDurableStore` |
|
|
@@ -126,6 +133,83 @@ core.
|
|
|
126
133
|
| Version awareness | `createUpdateState` |
|
|
127
134
|
| WebMCP | `registerWebMcpTools` |
|
|
128
135
|
|
|
136
|
+
## WebMCP capability exposure
|
|
137
|
+
|
|
138
|
+
`registerWebMcpTools()` is secure by default: omitting an exposure policy
|
|
139
|
+
registers only `read` tools. CRUD effects are fixed (`list`/`get` are `read`,
|
|
140
|
+
`create`/`update` are `write`, and `delete` is `destructive`). A custom action
|
|
141
|
+
without declared metadata is treated as destructive, non-idempotent, and open
|
|
142
|
+
world. Declare safer custom-action semantics in the route metadata only when
|
|
143
|
+
they are true:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
@smrt({
|
|
147
|
+
api: {
|
|
148
|
+
routes: {
|
|
149
|
+
preview: {
|
|
150
|
+
method: 'GET',
|
|
151
|
+
effect: 'read',
|
|
152
|
+
idempotent: true,
|
|
153
|
+
openWorld: false,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
class Report extends SmrtObject {}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Opt into broader capabilities explicitly. `namespace` prevents cross-surface
|
|
162
|
+
name collisions, an explicit `maxTools` bounds the selected set, and duplicate
|
|
163
|
+
names or stable collection/action identities reject the entire call before the
|
|
164
|
+
first browser registration. No implicit budget is applied to whole-manifest
|
|
165
|
+
read registration:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
registerWebMcpTools(definitions, {
|
|
169
|
+
effects: ['read', 'write', 'destructive'],
|
|
170
|
+
namespace: 'admin',
|
|
171
|
+
maxTools: 32,
|
|
172
|
+
filter: (collection, tool) => collection.fields.tenantId !== undefined,
|
|
173
|
+
filterTool: (tool) => tool.collection === 'reports',
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The returned disposer also exposes a `ready` promise. Await it when the host
|
|
178
|
+
must report browser-side registration rejection; any rejected tool aborts all
|
|
179
|
+
sibling registrations from that call before `ready` rejects.
|
|
180
|
+
|
|
181
|
+
`filter` receives legacy collection metadata; `filterTool` receives canonical
|
|
182
|
+
per-tool definitions. Configuring only one filter while registering definitions
|
|
183
|
+
for the other filter kind fails closed; canonical tools do not carry complete
|
|
184
|
+
collection field metadata, and legacy descriptors do not satisfy the canonical
|
|
185
|
+
filter contract. Policy callbacks and fetcher resolvers receive isolated value
|
|
186
|
+
snapshots; key host-side maps by stable values such as collection/action or tool
|
|
187
|
+
name, not definition object identity.
|
|
188
|
+
|
|
189
|
+
Do not concatenate complete legacy and canonical definition sets for the same
|
|
190
|
+
collections. Their duplicate tool names or collection/action identities reject
|
|
191
|
+
the registration atomically. Prefer the canonical set for complete generated
|
|
192
|
+
coverage, or compose only disjoint legacy and canonical subsets.
|
|
193
|
+
|
|
194
|
+
WebMCP policy controls which capabilities a page advertises; it is not an
|
|
195
|
+
authorization boundary. Execution still uses the page's authenticated REST
|
|
196
|
+
transport, whose auth, tenancy, writable-field, and sensitive-field guards must
|
|
197
|
+
remain enabled. All application-derived tool results are annotated as untrusted
|
|
198
|
+
content, including mutation responses.
|
|
199
|
+
|
|
200
|
+
Policy only narrows the actions already exposed by the generated API metadata.
|
|
201
|
+
Legacy descriptors outside their collection's `actions` set reject the whole
|
|
202
|
+
registration, and intrinsic CRUD effects cannot be relabeled by caller data.
|
|
203
|
+
|
|
204
|
+
Migration note: registrations that previously relied on every descriptor being
|
|
205
|
+
exposed must now pass `effects: ['read', 'write', 'destructive']`. Prefer a
|
|
206
|
+
narrower allowlist for each browser surface. Integrations that previously keyed
|
|
207
|
+
filter or resolver state by definition object identity must migrate to stable
|
|
208
|
+
name or collection/action keys. If both legacy and canonical definition arrays
|
|
209
|
+
are available, select one complete source or remove overlaps before combining
|
|
210
|
+
them. Set `maxTools` explicitly on surfaces that need a hard capability budget;
|
|
211
|
+
overflow rejects the complete registration rather than truncating it.
|
|
212
|
+
|
|
129
213
|
## Development
|
|
130
214
|
|
|
131
215
|
```bash
|