@proveanything/smartlinks 1.8.5 → 1.8.7

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.
@@ -199,6 +199,26 @@ await SL.appConfiguration.setConfig({
199
199
  });
200
200
  ```
201
201
 
202
+ Important visibility rule for app settings:
203
+
204
+ - `admin: true` means the SDK uses the admin endpoint.
205
+ - It does not make every root field private.
206
+ - If a value should only be visible to admins, put it under `config.admin`.
207
+
208
+ ```typescript
209
+ await SL.appConfiguration.setConfig({
210
+ collectionId,
211
+ appId,
212
+ admin: true,
213
+ config: {
214
+ enableNotifications: true,
215
+ admin: {
216
+ apiToken: 'secret-token'
217
+ }
218
+ }
219
+ })
220
+ ```
221
+
202
222
  ---
203
223
 
204
224
  ## Metrics & Analytics
@@ -228,6 +248,7 @@ await SL.appConfiguration.setConfig({
228
248
  | Issue | Cause | Fix |
229
249
  | --------------------- | -------------------------- | ----------------------------------------------------- |
230
250
  | Config save fails | Missing `admin: true` flag | Always include `admin: true` for admin operations |
251
+ | Secret visible publicly | Saved secret at root level | Put confidential values under the top-level `admin` object |
231
252
  | Widget doesn't render | Missing required props | Ensure `collectionId`, `appId`, and `SL` are provided |
232
253
  | Import skips rows | Invalid `productId` | Verify product IDs exist in the collection |
233
254
  | Theme not applied | Missing `?theme=` param | Check URL parameters or postMessage setup |
@@ -2,6 +2,27 @@
2
2
 
3
3
  The SmartLinks platform provides two distinct types of data storage for apps:
4
4
 
5
+ ## Choose the Right Model First
6
+
7
+ There are now two different families of flexible app data in SmartLinks, and they solve different problems:
8
+
9
+ | Need | Best Fit | Why |
10
+ |------|----------|-----|
11
+ | One settings blob per scope | `appConfiguration.getConfig` / `setConfig` | Simple app setup and feature flags |
12
+ | A few keyed scoped documents by ID | `appConfiguration.getData` / `setDataItem` | Lightweight, direct, minimal overhead |
13
+ | Rich app-owned entities with filtering, visibility, ownership, or lifecycle | `app.records` | Better default for real domain objects |
14
+ | Workflow items that move through resolution | `app.cases` | Status, priority, assignment, history |
15
+ | Discussions, comments, reply chains | `app.threads` | Built around replies and conversation flow |
16
+
17
+ ### Rule of Thumb
18
+
19
+ - Use `appConfiguration` when the thing you are storing is basically config or a small keyed document.
20
+ - Use `app.records` when the thing you are storing is a real object in your app.
21
+ - Use `app.cases` when the object represents work to resolve.
22
+ - Use `app.threads` when the object is conversational.
23
+
24
+ This matters for AI-generated apps too: if the documentation only mentions `setDataItem`, builders will overuse it. In most non-trivial app flows, `app.records` is usually the stronger default.
25
+
5
26
  ## 1. User-Specific Data (Global per User+App)
6
27
 
7
28
  **Use the `userAppData` namespace for all user-specific data.**
@@ -77,16 +98,62 @@ await userAppData.remove('garden-planner', 'bed-1');
77
98
 
78
99
  ## 2. Collection/Product-Scoped Data (Admin Configuration)
79
100
 
80
- **Use the `appConfiguration` namespace for collection/product-scoped data.**
101
+ **Use the `appConfiguration` namespace for collection/product-scoped config and simple keyed documents.**
81
102
 
82
103
  This data is scoped to specific collections, products, variants, or batches. It's typically configured by collection admins/owners and applies to all users viewing that collection/product.
83
104
 
105
+ If you need richer app-owned entities with querying, lifecycle, access zones, parent-child relationships, or workflow semantics, use [app-objects.md](app-objects.md) instead of forcing everything through `setDataItem`.
106
+
107
+ ### Critical: `admin: true` Controls the Endpoint, Not Field Privacy
108
+
109
+ This is the part that often gets misunderstood by apps and AI tools:
110
+
111
+ - `admin: true` means "call the admin endpoint".
112
+ - It does **not** mean "everything I wrote is now admin-only".
113
+ - For app config and collection settings, root-level fields are usually part of the public payload.
114
+ - If you need confidential values, store them under a top-level `admin` object.
115
+ - Public reads omit that `admin` block; admin reads include it.
116
+
117
+ Example for app config:
118
+
119
+ ```typescript
120
+ await appConfiguration.setConfig({
121
+ appId: 'warranty-portal',
122
+ collectionId: 'my-collection',
123
+ admin: true,
124
+ config: {
125
+ theme: 'gold',
126
+ supportEmail: 'support@example.com',
127
+ admin: {
128
+ accessToken: 'secret-token',
129
+ webhookSecret: 'top-secret'
130
+ }
131
+ }
132
+ })
133
+
134
+ const publicView = await appConfiguration.getConfig({
135
+ appId: 'warranty-portal',
136
+ collectionId: 'my-collection'
137
+ })
138
+ // { theme: 'gold', supportEmail: 'support@example.com' }
139
+
140
+ const adminView = await appConfiguration.getConfig({
141
+ appId: 'warranty-portal',
142
+ collectionId: 'my-collection',
143
+ admin: true
144
+ })
145
+ // { theme: 'gold', supportEmail: 'support@example.com', admin: { ... } }
146
+ ```
147
+
148
+ The same visibility pattern applies to collection settings via `collection.getSettings()` / `collection.updateSettings()`.
149
+
84
150
  ### Use Cases
85
151
  - App-specific settings for a collection
86
152
  - Product-level configuration
87
153
  - Feature flags and toggles
88
154
  - Theme and branding settings
89
155
  - Public content that all users see
156
+ - Small keyed content entries such as FAQs, menu items, or quick lookup documents
90
157
 
91
158
  ### API Endpoints
92
159
  ```
@@ -146,15 +213,37 @@ await appConfiguration.setDataItem({
146
213
 
147
214
  ## Comparison Table
148
215
 
149
- | Feature | User Data | Collection/Product Data |
150
- |---------|-----------|------------------------|
151
- | **Namespace** | `userAppData` | `appConfiguration` |
152
- | **Scope** | User + App (global) | Collection/Product/Variant/Batch |
153
- | **Set by** | Individual users | Collection admins/owners |
154
- | **Shared across collections?** | ✅ Yes | ❌ No |
155
- | **Requires auth?** | ✅ Yes (user token) | ✅ Yes (admin token for write) |
156
- | **Function signature** | Simple: `set(appId, data)` | Options object: `setDataItem({ appId, collectionId, data })` |
157
- | **Admin write required?** | No | Yes (for write operations) |
216
+ | Feature | User Data | Scoped Config/Data | App Objects |
217
+ |---------|-----------|--------------------|-------------|
218
+ | **Namespace** | `userAppData` | `appConfiguration` | `app.records` / `app.cases` / `app.threads` |
219
+ | **Scope** | User + App (global) | Collection/Product/Variant/Batch | Collection + App |
220
+ | **Best for** | Personal preferences and user-owned items | Config blobs and small keyed documents | Rich entities and workflows |
221
+ | **Shared across collections?** | ✅ Yes | ❌ No | ❌ No |
222
+ | **Requires auth?** | ✅ Yes (user token) | ✅ Yes (admin token for write) | Depends on public/admin endpoint and visibility |
223
+ | **Querying / filtering** | Minimal | Minimal | Strong |
224
+ | **Access control zones** | User-scoped only | Root fields + reserved `admin` block for settings/config | `data` / `owner` / `admin` zones |
225
+ | **Admin write required?** | ❌ No | ✅ Yes (for write operations) | Only for admin endpoints / admin fields |
226
+
227
+ ---
228
+
229
+ ## When `setDataItem` Is Still the Right Answer
230
+
231
+ `setDataItem` is still valuable and should not be treated as deprecated. It is the right fit when:
232
+
233
+ - You need a handful of documents attached to a collection or product
234
+ - Each item has a stable known ID
235
+ - You mostly fetch by exact ID or list all items
236
+ - You do not need rich lifecycle fields, reply chains, assignment, or advanced querying
237
+
238
+ Examples:
239
+
240
+ - Product FAQs
241
+ - Menu definitions
242
+ - Marketing content blocks
243
+ - Widget registry entries
244
+ - Static lookup tables for an app
245
+
246
+ If the object starts needing richer semantics, migrate that use case to `app.records`, `app.cases`, or `app.threads` rather than stretching scoped data items too far.
158
247
 
159
248
  ---
160
249
 
@@ -140,15 +140,47 @@ await SL.appConfiguration.setConfig({ collectionId, appId, config: myConfig, adm
140
140
 
141
141
  This applies to all write operations: `setConfig`, `setDataItem`, `updateDataItem`, etc.
142
142
 
143
+ ### Endpoint Auth vs Data Visibility
144
+
145
+ `admin: true` is an endpoint selector, not a privacy marker.
146
+
147
+ - It tells the SDK to call the admin endpoint.
148
+ - It allows writes and admin reads.
149
+ - It does **not** mean every root-level field you save becomes admin-only.
150
+
151
+ For `appConfiguration` config blobs and `collection.getSettings()` groups, root-level fields are typically the public-facing settings. If you need private values such as tokens or secrets, store them inside a top-level `admin` object:
152
+
153
+ ```typescript
154
+ await SL.appConfiguration.setConfig({
155
+ collectionId,
156
+ appId,
157
+ admin: true,
158
+ config: {
159
+ publicLabel: 'Warranty Portal',
160
+ color: '#B68C2A',
161
+ admin: {
162
+ accessToken: 'secret-token'
163
+ }
164
+ }
165
+ })
166
+ ```
167
+
168
+ Public reads omit the `admin` block. Admin reads include it.
169
+
143
170
  ### Config vs Data
144
171
 
145
172
  | Storage Type | Function | Use Case |
146
173
  |-------------|---------|---------|
147
174
  | **Config** (`getConfig`/`setConfig`) | Single JSON document | App settings, feature flags, global options |
148
175
  | **Data** (`getData`/`setDataItem`) | Array of documents with IDs | Lists of items, records, entries |
176
+ | **App Objects** (`app.records` / `app.cases` / `app.threads`) | Queryable domain objects | Real app entities, workflows, conversations, richer access control |
149
177
 
150
178
  Both can be scoped to **collection level** or **product level** by including `productId`.
151
179
 
180
+ For config/settings visibility, remember: root fields are the normal shared payload, while a reserved top-level `admin` object is the place for admin-only values.
181
+
182
+ Prefer `app.records` over `setDataItem` when the data is becoming a real entity that needs lifecycle, ownership, visibility, relationships, or filtering. Keep `setDataItem` for simple keyed scoped documents and config-adjacent content.
183
+
152
184
  ### Attestations (Proof-level data)
153
185
 
154
186
  For data attached to specific proof instances, use `SL.attestation.create()` and `SL.attestation.list()`.
package/dist/openapi.yaml CHANGED
@@ -79,7 +79,7 @@ paths:
79
79
  post:
80
80
  tags:
81
81
  - collection
82
- summary: Update a specific settings group for a collection (admin endpoint).
82
+ summary: Create a new collection (admin only).
83
83
  operationId: collection_create
84
84
  security:
85
85
  - bearerAuth: []
@@ -5446,7 +5446,7 @@ paths:
5446
5446
  post:
5447
5447
  tags:
5448
5448
  - collection
5449
- summary: Retrieve all configured app module definitions for a collection (public endpoint).
5449
+ summary: Update a specific settings group for a collection (admin endpoint).
5450
5450
  operationId: collection_updateSettings
5451
5451
  security:
5452
5452
  - bearerAuth: []
@@ -7080,7 +7080,7 @@ paths:
7080
7080
  get:
7081
7081
  tags:
7082
7082
  - collection
7083
- summary: Retrieve a specific settings group for a collection (public endpoint).
7083
+ summary: Retrieve all configured app module definitions for a collection (public endpoint).
7084
7084
  operationId: collection_getAppsConfig
7085
7085
  security: []
7086
7086
  parameters: