@proveanything/smartlinks 1.15.5 → 1.15.8

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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.15.5 | Generated: 2026-07-18T14:07:37.915Z
3
+ Version: 1.15.8 | Generated: 2026-07-19T09:55:23.623Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -1447,7 +1447,6 @@ interface AppConfigSettings {
1447
1447
  addOns?: string[]
1448
1448
  requestedBasePlanId?: string
1449
1449
  itemRecordMode?: 'registered' | 'owned' | null
1450
- virtualItemsEnabled?: boolean
1451
1450
  system?: SystemBlock
1452
1451
  }
1453
1452
  ```
@@ -3698,8 +3697,6 @@ interface Collection {
3698
3697
  secondaryColor?: string
3699
3698
  portalUrl?: string // URL for the collection's portal (if applicable)
3700
3699
  allowAutoGenerateClaims?: boolean
3701
- variants: boolean // does this collection support variants?
3702
- batches: boolean // does this collection support batches?
3703
3700
  defaultAuthKitId: string // default auth kit for this collection, used for auth
3704
3701
  }
3705
3702
  ```
@@ -36,7 +36,6 @@ export interface AppConfigSettings {
36
36
 
37
37
  /** How the account handles individual physical items. */
38
38
  itemRecordMode?: 'registered' | 'owned' | null;
39
- virtualItemsEnabled?: boolean;
40
39
 
41
40
  // ── SYSTEM-OWNED, PUBLIC (reconcile writes; client read-only) ─────
42
41
  /** Resolved entitlement truth. Read this to gate features. */
@@ -220,26 +219,50 @@ Resolution rule (see `resolveFeature()` / `isFeatureEnabled()`, §6.0):
220
219
  | `false` (explicit) | **off** | off |
221
220
  | absent | **on** (enterprise default) | off (standard default) |
222
221
 
223
- This is why reading `cfg.system.features.custom_domain` directly is wrong
222
+ This is why reading `cfg.system.features.customDomain` directly is wrong
224
223
  for enterprise accounts — an absent key there does NOT mean disabled:
225
224
 
226
225
  ```ts
227
226
  // ❌ WRONG for enterprise accounts — absent key silently reads as "off"
228
- if (cfg.system.features.custom_domain) enableCustomDomainUI();
227
+ if (cfg.system.features.customDomain) enableCustomDomainUI();
229
228
 
230
229
  // ✅ CORRECT — applies the enterprise default
231
- if (await appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')) {
230
+ if (await appConfiguration.isFeatureEnabled(collectionId, 'customDomain')) {
232
231
  enableCustomDomainUI();
233
232
  }
234
233
  ```
235
234
 
236
- Feature flag naming: bare snake_case, no `feature_` prefix.
235
+ Feature flag naming: camelCase, no `feature`/`is`/`has` prefix (e.g.
236
+ `customDomain`, not `feature_custom_domain` or `isCustomDomainEnabled`).
237
+ Flags belonging to the same topic/module may use a dotted grouping prefix,
238
+ e.g. `crm.broadcasts`, `crm.segments` — this is a plain string key in
239
+ `features`, not a nested object, so resolve it the same way:
240
+ `isFeatureEnabled(collectionId, 'crm.broadcasts')`.
237
241
 
238
242
  Always resolve flags through `appConfiguration.isFeatureEnabled(collectionId, flag)`
239
243
  / `isFeatureEnabledSync()` (§6.0), or `appConfiguration.resolveFeature(cfg.system, flag)`
240
244
  if you already have a `system` block from elsewhere — never read
241
245
  `cfg.system.features[flag]` directly.
242
246
 
247
+ #### 4.4.1 Common feature flags
248
+
249
+ `features` is an open map — any microapp can define its own key — but
250
+ these are the major, cross-cutting flags most integrations will care
251
+ about:
252
+
253
+ | Flag | Gates |
254
+ | -------------- | ---------------------------------------------------------------------- |
255
+ | `analytics` | Analytics surfaces (dashboards, reporting, event exploration). |
256
+ | `crm` | Customer interaction / CRM — contact records, broadcasts, segments. Sub-features hang off the `crm.*` dotted prefix, e.g. `crm.broadcasts`, `crm.segments`. |
257
+ | `hub` | The Hub module. |
258
+ | `portal` | QR code scan portals. |
259
+ | `virtualItems` | Virtual items — algorithmic per-item IDs with no persistent row (battery serials, scan-to-collect points, bulk QR sheets). Replaces the old root-level `virtualItemsEnabled` boolean, which has been removed (§8) — resolve this like any other feature flag, not as a separate config key. Independent of `itemRecordMode`. |
260
+ | `batches` | Batch support. Used to be the `Collection.batches` boolean; that field has been removed — this flag is now the only source of truth. |
261
+ | `variants` | Variant support. Used to be the `Collection.variants` boolean; that field has been removed — this flag is now the only source of truth. |
262
+
263
+ Same resolution rule as any flag (§4.4) — don't read these off
264
+ `cfg.system.features` directly, always go through `isFeatureEnabled()`.
265
+
243
266
  ### 4.5 `meters`
244
267
 
245
268
  Map keyed by add-on key. Apps reporting usage should call the
@@ -308,7 +331,7 @@ every subsequent call — so calling it once per component, or once per
308
331
  render, doesn't cause repeat network requests.
309
332
 
310
333
  ```ts
311
- if (await SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')) {
334
+ if (await SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain')) {
312
335
  enableCustomDomainUI();
313
336
  }
314
337
  ```
@@ -321,11 +344,11 @@ cache once during app init and use the sync variant afterwards:
321
344
  ```ts
322
345
  // Once, e.g. in a top-level effect or before first render:
323
346
  useEffect(() => {
324
- SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')
347
+ SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain')
325
348
  }, [collectionId]);
326
349
 
327
350
  // Anywhere else, read synchronously — no await:
328
- const enabled = SL.appConfiguration.isFeatureEnabledSync(collectionId, 'custom_domain');
351
+ const enabled = SL.appConfiguration.isFeatureEnabledSync(collectionId, 'customDomain');
329
352
  if (enabled === undefined) {
330
353
  // not warmed yet this page load — treat as "not yet known", not "off"
331
354
  }
@@ -341,7 +364,7 @@ to bypass it — e.g. immediately after your own code calls
341
364
  `entitlements-reconcile` and the flags may have changed:
342
365
 
343
366
  ```ts
344
- await SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain', { force: true });
367
+ await SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain', { force: true });
345
368
  ```
346
369
 
347
370
  ### 6.1 Reading the raw config
@@ -402,18 +425,14 @@ with a stale local copy.
402
425
  Clients MUST NOT write directly to `system` or `systemPrivate`.
403
426
  `entitlements-reconcile` merges user-owned fields through untouched.
404
427
 
405
- ## 8. Item handling (`itemRecordMode`, `virtualItemsEnabled`)
428
+ ## 8. Item handling (`itemRecordMode`)
406
429
 
407
- Two **independent** root-level, user-owned keys describing how the
408
- account treats individual physical items. Reconcile never touches
409
- them.
430
+ A root-level, user-owned key describing how the account treats
431
+ individual physical items. Reconcile never touches it.
410
432
 
411
- Three axes (do NOT conflate):
433
+ Two axes (do NOT conflate):
412
434
 
413
- 1. **Virtual items** — `virtualItemsEnabled: boolean`. Algorithmic
414
- IDs, no per-item row. Battery serials, scan-to-collect points,
415
- bulk QR sheets. Can be on with `itemRecordMode` off.
416
- 2. **Item records** — `itemRecordMode`. Materialise a persistent row
435
+ 1. **Item records** — `itemRecordMode`. Materialise a persistent row
417
436
  per physical item. `null` / missing = **disabled** (no separate
418
437
  `"none"` enum — reads collapse to `mode === "off"` via the
419
438
  `useItemRecordMode()` hook).
@@ -421,7 +440,15 @@ Three axes (do NOT conflate):
421
440
  provenance without a customer relationship.
422
441
  - `"owned"` — tag row + owner + interaction history. Requires
423
442
  `basePlanId >= "engage"`. Enables claim / transfer / CRM.
424
- 3. **CRM** — downstream consequence of `owned`; not a peer flag.
443
+ 2. **CRM** — downstream consequence of `owned`; not a peer flag.
444
+
445
+ **Virtual items are not part of this key.** Algorithmic IDs with no
446
+ per-item row (battery serials, scan-to-collect points, bulk QR sheets)
447
+ used to be a separate root-level `virtualItemsEnabled: boolean` — that
448
+ field has been removed. Virtual items are now gated by the `virtualItems`
449
+ feature flag under `system.features` (§4.4.1), same as every other
450
+ feature — resolve it with `isFeatureEnabled(collectionId, 'virtualItems')`.
451
+ It's independent of `itemRecordMode` and can be on with item records off.
425
452
 
426
453
  **Billing:** the usage ledger stamps `tier` at event time from
427
454
  `itemRecordMode`. Writes with `mode === null` MUST be rejected. Mode
@@ -442,42 +469,3 @@ CRM visibility), not just a capability flag.
442
469
  features yet.
443
470
  - `systemOverrides` (old root-level key) → `systemPrivate.overrides`.
444
471
  One-off backfill moves the block and re-runs reconcile.
445
-
446
- ## 10. Change log
447
-
448
- - **2026-07-17**: Initial contract published; `appConfig.system` becomes
449
- canonical entitlements source of truth. `entitlements` group deprecated.
450
- - **2026-07-17**: Added `systemOverrides` for additive comps; reconcile
451
- records `system.appliedOverrides`.
452
- - **2026-07-18**: Renamed `systemOverrides` → `systemPrivate.overrides`
453
- and formalised the three-tier access model (user / system /
454
- systemPrivate). API strips `systemPrivate` for non-admin readers.
455
- Added `system.accountType` derived from
456
- `systemPrivate.overrides.accountType`. Added top-of-doc TypeScript
457
- definition.
458
- - **2026-07-18**: Added SDK helpers `appConfiguration.getAppConfig()`
459
- (typed + cached), `isFeatureEnabled()` (async, cache-backed feature
460
- gate), and `isFeatureEnabledSync()` (cache-only, for callers that can't
461
- await). Renamed the exported TypeScript type to `AppConfigSettings`
462
- to avoid a name collision with the existing per-module `AppConfig`
463
- type in `src/types/collection.ts`.
464
- - **2026-07-18**: `/public/collection/:id/app/config` (`collection.getAppsConfig()`)
465
- now returns the `appConfig` entitlements data (`system`, `addOns`,
466
- `requestedBasePlanId`, `itemRecordMode`, `virtualItemsEnabled`) merged
467
- alongside its existing app-catalog `apps[]`. `appConfiguration.getAppConfig()`
468
- was repointed at this endpoint (dropping its `admin` option — this endpoint
469
- is public-only); the settings-group endpoint (`appConfiguration.getConfig({ appId: 'appConfig' })`)
470
- is still the only way to reach `systemPrivate`. See §3.1 for why the two
471
- endpoints' `apps[]` fields are shaped differently and shouldn't be conflated.
472
- - **2026-07-18**: `system.features` changed from "only truthy flags appear"
473
- to explicit `Record<string, boolean>` overrides. Added the `accountType`
474
- default rule (§4.4): enterprise accounts default every flag to on unless
475
- explicitly `false`; standard accounts default off unless explicitly `true`.
476
- Added `appConfiguration.resolveFeature(system, flag)` — the pure resolver
477
- behind `isFeatureEnabled()`/`isFeatureEnabledSync()`, exposed only for the
478
- rare case of already holding a `system` block from somewhere other than
479
- `getAppConfig()`. There is no separate admin feature-check path — `system`
480
- is public data on every read, so admin surfaces should call
481
- `isFeatureEnabled()` like everything else. Reading `cfg.system.features[flag]`
482
- directly is no longer correct for enterprise accounts — always resolve
483
- through one of these three.
package/dist/openapi.yaml CHANGED
@@ -15719,8 +15719,6 @@ components:
15719
15719
  enum:
15720
15720
  - registered
15721
15721
  - owned
15722
- virtualItemsEnabled:
15723
- type: boolean
15724
15722
  system:
15725
15723
  $ref: "#/components/schemas/SystemBlock"
15726
15724
  required:
@@ -19309,10 +19307,6 @@ components:
19309
19307
  type: string
19310
19308
  allowAutoGenerateClaims:
19311
19309
  type: boolean
19312
- variants:
19313
- type: boolean
19314
- batches:
19315
- type: boolean
19316
19310
  defaultAuthKitId:
19317
19311
  type: string
19318
19312
  required:
@@ -19328,8 +19322,6 @@ components:
19328
19322
  - supported
19329
19323
  - roles
19330
19324
  - shortId
19331
- - variants
19332
- - batches
19333
19325
  - defaultAuthKitId
19334
19326
  HubAvailabilityResponse:
19335
19327
  type: object
@@ -112,7 +112,6 @@ export interface AppConfigSettings {
112
112
  requestedBasePlanId?: string;
113
113
  /** How the account handles individual physical items. */
114
114
  itemRecordMode?: 'registered' | 'owned' | null;
115
- virtualItemsEnabled?: boolean;
116
115
  /** Resolved entitlement truth. Read this to gate features. */
117
116
  system?: SystemBlock;
118
117
  }
@@ -57,8 +57,6 @@ export interface Collection {
57
57
  portalUrl?: string;
58
58
  /** Allow users to claim products without providing a proof ID (auto-generates serial on-demand) */
59
59
  allowAutoGenerateClaims?: boolean;
60
- variants: boolean;
61
- batches: boolean;
62
60
  defaultAuthKitId: string;
63
61
  }
64
62
  export type CollectionResponse = Collection;
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.15.5 | Generated: 2026-07-18T14:07:37.915Z
3
+ Version: 1.15.8 | Generated: 2026-07-19T09:55:23.623Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -1447,7 +1447,6 @@ interface AppConfigSettings {
1447
1447
  addOns?: string[]
1448
1448
  requestedBasePlanId?: string
1449
1449
  itemRecordMode?: 'registered' | 'owned' | null
1450
- virtualItemsEnabled?: boolean
1451
1450
  system?: SystemBlock
1452
1451
  }
1453
1452
  ```
@@ -3698,8 +3697,6 @@ interface Collection {
3698
3697
  secondaryColor?: string
3699
3698
  portalUrl?: string // URL for the collection's portal (if applicable)
3700
3699
  allowAutoGenerateClaims?: boolean
3701
- variants: boolean // does this collection support variants?
3702
- batches: boolean // does this collection support batches?
3703
3700
  defaultAuthKitId: string // default auth kit for this collection, used for auth
3704
3701
  }
3705
3702
  ```
package/docs/appConfig.md CHANGED
@@ -36,7 +36,6 @@ export interface AppConfigSettings {
36
36
 
37
37
  /** How the account handles individual physical items. */
38
38
  itemRecordMode?: 'registered' | 'owned' | null;
39
- virtualItemsEnabled?: boolean;
40
39
 
41
40
  // ── SYSTEM-OWNED, PUBLIC (reconcile writes; client read-only) ─────
42
41
  /** Resolved entitlement truth. Read this to gate features. */
@@ -220,26 +219,50 @@ Resolution rule (see `resolveFeature()` / `isFeatureEnabled()`, §6.0):
220
219
  | `false` (explicit) | **off** | off |
221
220
  | absent | **on** (enterprise default) | off (standard default) |
222
221
 
223
- This is why reading `cfg.system.features.custom_domain` directly is wrong
222
+ This is why reading `cfg.system.features.customDomain` directly is wrong
224
223
  for enterprise accounts — an absent key there does NOT mean disabled:
225
224
 
226
225
  ```ts
227
226
  // ❌ WRONG for enterprise accounts — absent key silently reads as "off"
228
- if (cfg.system.features.custom_domain) enableCustomDomainUI();
227
+ if (cfg.system.features.customDomain) enableCustomDomainUI();
229
228
 
230
229
  // ✅ CORRECT — applies the enterprise default
231
- if (await appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')) {
230
+ if (await appConfiguration.isFeatureEnabled(collectionId, 'customDomain')) {
232
231
  enableCustomDomainUI();
233
232
  }
234
233
  ```
235
234
 
236
- Feature flag naming: bare snake_case, no `feature_` prefix.
235
+ Feature flag naming: camelCase, no `feature`/`is`/`has` prefix (e.g.
236
+ `customDomain`, not `feature_custom_domain` or `isCustomDomainEnabled`).
237
+ Flags belonging to the same topic/module may use a dotted grouping prefix,
238
+ e.g. `crm.broadcasts`, `crm.segments` — this is a plain string key in
239
+ `features`, not a nested object, so resolve it the same way:
240
+ `isFeatureEnabled(collectionId, 'crm.broadcasts')`.
237
241
 
238
242
  Always resolve flags through `appConfiguration.isFeatureEnabled(collectionId, flag)`
239
243
  / `isFeatureEnabledSync()` (§6.0), or `appConfiguration.resolveFeature(cfg.system, flag)`
240
244
  if you already have a `system` block from elsewhere — never read
241
245
  `cfg.system.features[flag]` directly.
242
246
 
247
+ #### 4.4.1 Common feature flags
248
+
249
+ `features` is an open map — any microapp can define its own key — but
250
+ these are the major, cross-cutting flags most integrations will care
251
+ about:
252
+
253
+ | Flag | Gates |
254
+ | -------------- | ---------------------------------------------------------------------- |
255
+ | `analytics` | Analytics surfaces (dashboards, reporting, event exploration). |
256
+ | `crm` | Customer interaction / CRM — contact records, broadcasts, segments. Sub-features hang off the `crm.*` dotted prefix, e.g. `crm.broadcasts`, `crm.segments`. |
257
+ | `hub` | The Hub module. |
258
+ | `portal` | QR code scan portals. |
259
+ | `virtualItems` | Virtual items — algorithmic per-item IDs with no persistent row (battery serials, scan-to-collect points, bulk QR sheets). Replaces the old root-level `virtualItemsEnabled` boolean, which has been removed (§8) — resolve this like any other feature flag, not as a separate config key. Independent of `itemRecordMode`. |
260
+ | `batches` | Batch support. Used to be the `Collection.batches` boolean; that field has been removed — this flag is now the only source of truth. |
261
+ | `variants` | Variant support. Used to be the `Collection.variants` boolean; that field has been removed — this flag is now the only source of truth. |
262
+
263
+ Same resolution rule as any flag (§4.4) — don't read these off
264
+ `cfg.system.features` directly, always go through `isFeatureEnabled()`.
265
+
243
266
  ### 4.5 `meters`
244
267
 
245
268
  Map keyed by add-on key. Apps reporting usage should call the
@@ -308,7 +331,7 @@ every subsequent call — so calling it once per component, or once per
308
331
  render, doesn't cause repeat network requests.
309
332
 
310
333
  ```ts
311
- if (await SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')) {
334
+ if (await SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain')) {
312
335
  enableCustomDomainUI();
313
336
  }
314
337
  ```
@@ -321,11 +344,11 @@ cache once during app init and use the sync variant afterwards:
321
344
  ```ts
322
345
  // Once, e.g. in a top-level effect or before first render:
323
346
  useEffect(() => {
324
- SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain')
347
+ SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain')
325
348
  }, [collectionId]);
326
349
 
327
350
  // Anywhere else, read synchronously — no await:
328
- const enabled = SL.appConfiguration.isFeatureEnabledSync(collectionId, 'custom_domain');
351
+ const enabled = SL.appConfiguration.isFeatureEnabledSync(collectionId, 'customDomain');
329
352
  if (enabled === undefined) {
330
353
  // not warmed yet this page load — treat as "not yet known", not "off"
331
354
  }
@@ -341,7 +364,7 @@ to bypass it — e.g. immediately after your own code calls
341
364
  `entitlements-reconcile` and the flags may have changed:
342
365
 
343
366
  ```ts
344
- await SL.appConfiguration.isFeatureEnabled(collectionId, 'custom_domain', { force: true });
367
+ await SL.appConfiguration.isFeatureEnabled(collectionId, 'customDomain', { force: true });
345
368
  ```
346
369
 
347
370
  ### 6.1 Reading the raw config
@@ -402,18 +425,14 @@ with a stale local copy.
402
425
  Clients MUST NOT write directly to `system` or `systemPrivate`.
403
426
  `entitlements-reconcile` merges user-owned fields through untouched.
404
427
 
405
- ## 8. Item handling (`itemRecordMode`, `virtualItemsEnabled`)
428
+ ## 8. Item handling (`itemRecordMode`)
406
429
 
407
- Two **independent** root-level, user-owned keys describing how the
408
- account treats individual physical items. Reconcile never touches
409
- them.
430
+ A root-level, user-owned key describing how the account treats
431
+ individual physical items. Reconcile never touches it.
410
432
 
411
- Three axes (do NOT conflate):
433
+ Two axes (do NOT conflate):
412
434
 
413
- 1. **Virtual items** — `virtualItemsEnabled: boolean`. Algorithmic
414
- IDs, no per-item row. Battery serials, scan-to-collect points,
415
- bulk QR sheets. Can be on with `itemRecordMode` off.
416
- 2. **Item records** — `itemRecordMode`. Materialise a persistent row
435
+ 1. **Item records** — `itemRecordMode`. Materialise a persistent row
417
436
  per physical item. `null` / missing = **disabled** (no separate
418
437
  `"none"` enum — reads collapse to `mode === "off"` via the
419
438
  `useItemRecordMode()` hook).
@@ -421,7 +440,15 @@ Three axes (do NOT conflate):
421
440
  provenance without a customer relationship.
422
441
  - `"owned"` — tag row + owner + interaction history. Requires
423
442
  `basePlanId >= "engage"`. Enables claim / transfer / CRM.
424
- 3. **CRM** — downstream consequence of `owned`; not a peer flag.
443
+ 2. **CRM** — downstream consequence of `owned`; not a peer flag.
444
+
445
+ **Virtual items are not part of this key.** Algorithmic IDs with no
446
+ per-item row (battery serials, scan-to-collect points, bulk QR sheets)
447
+ used to be a separate root-level `virtualItemsEnabled: boolean` — that
448
+ field has been removed. Virtual items are now gated by the `virtualItems`
449
+ feature flag under `system.features` (§4.4.1), same as every other
450
+ feature — resolve it with `isFeatureEnabled(collectionId, 'virtualItems')`.
451
+ It's independent of `itemRecordMode` and can be on with item records off.
425
452
 
426
453
  **Billing:** the usage ledger stamps `tier` at event time from
427
454
  `itemRecordMode`. Writes with `mode === null` MUST be rejected. Mode
@@ -442,42 +469,3 @@ CRM visibility), not just a capability flag.
442
469
  features yet.
443
470
  - `systemOverrides` (old root-level key) → `systemPrivate.overrides`.
444
471
  One-off backfill moves the block and re-runs reconcile.
445
-
446
- ## 10. Change log
447
-
448
- - **2026-07-17**: Initial contract published; `appConfig.system` becomes
449
- canonical entitlements source of truth. `entitlements` group deprecated.
450
- - **2026-07-17**: Added `systemOverrides` for additive comps; reconcile
451
- records `system.appliedOverrides`.
452
- - **2026-07-18**: Renamed `systemOverrides` → `systemPrivate.overrides`
453
- and formalised the three-tier access model (user / system /
454
- systemPrivate). API strips `systemPrivate` for non-admin readers.
455
- Added `system.accountType` derived from
456
- `systemPrivate.overrides.accountType`. Added top-of-doc TypeScript
457
- definition.
458
- - **2026-07-18**: Added SDK helpers `appConfiguration.getAppConfig()`
459
- (typed + cached), `isFeatureEnabled()` (async, cache-backed feature
460
- gate), and `isFeatureEnabledSync()` (cache-only, for callers that can't
461
- await). Renamed the exported TypeScript type to `AppConfigSettings`
462
- to avoid a name collision with the existing per-module `AppConfig`
463
- type in `src/types/collection.ts`.
464
- - **2026-07-18**: `/public/collection/:id/app/config` (`collection.getAppsConfig()`)
465
- now returns the `appConfig` entitlements data (`system`, `addOns`,
466
- `requestedBasePlanId`, `itemRecordMode`, `virtualItemsEnabled`) merged
467
- alongside its existing app-catalog `apps[]`. `appConfiguration.getAppConfig()`
468
- was repointed at this endpoint (dropping its `admin` option — this endpoint
469
- is public-only); the settings-group endpoint (`appConfiguration.getConfig({ appId: 'appConfig' })`)
470
- is still the only way to reach `systemPrivate`. See §3.1 for why the two
471
- endpoints' `apps[]` fields are shaped differently and shouldn't be conflated.
472
- - **2026-07-18**: `system.features` changed from "only truthy flags appear"
473
- to explicit `Record<string, boolean>` overrides. Added the `accountType`
474
- default rule (§4.4): enterprise accounts default every flag to on unless
475
- explicitly `false`; standard accounts default off unless explicitly `true`.
476
- Added `appConfiguration.resolveFeature(system, flag)` — the pure resolver
477
- behind `isFeatureEnabled()`/`isFeatureEnabledSync()`, exposed only for the
478
- rare case of already holding a `system` block from somewhere other than
479
- `getAppConfig()`. There is no separate admin feature-check path — `system`
480
- is public data on every read, so admin surfaces should call
481
- `isFeatureEnabled()` like everything else. Reading `cfg.system.features[flag]`
482
- directly is no longer correct for enterprise accounts — always resolve
483
- through one of these three.
package/openapi.yaml CHANGED
@@ -15719,8 +15719,6 @@ components:
15719
15719
  enum:
15720
15720
  - registered
15721
15721
  - owned
15722
- virtualItemsEnabled:
15723
- type: boolean
15724
15722
  system:
15725
15723
  $ref: "#/components/schemas/SystemBlock"
15726
15724
  required:
@@ -19309,10 +19307,6 @@ components:
19309
19307
  type: string
19310
19308
  allowAutoGenerateClaims:
19311
19309
  type: boolean
19312
- variants:
19313
- type: boolean
19314
- batches:
19315
- type: boolean
19316
19310
  defaultAuthKitId:
19317
19311
  type: string
19318
19312
  required:
@@ -19328,8 +19322,6 @@ components:
19328
19322
  - supported
19329
19323
  - roles
19330
19324
  - shortId
19331
- - variants
19332
- - batches
19333
19325
  - defaultAuthKitId
19334
19326
  HubAvailabilityResponse:
19335
19327
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.15.5",
3
+ "version": "1.15.8",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",