@stacksjs/defaults 0.75.451 → 0.75.457

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.
@@ -190,8 +190,11 @@ Do not assume every caller gets that allowlist when constructing config itself.
190
190
  First-party capturePageviews is separate from script injection and the remote
191
191
  driver gate. recordPageview(req) writes qualifying GET page requests to
192
192
  analytics_events; isPageviewRequest filters assets/API/internal paths and obvious
193
- bots/monitors. classifyAgent/referrerHost are coarse helpers, not unique visitor
194
- identification. Capture failures are swallowed so a statistic cannot break a
193
+ bots/monitors. The site's host is the first `X-Forwarded-Host` hop, else the
194
+ URL's host, and a referrer from that host is stored as null: behind rpx the URL
195
+ carries the upstream address, so comparing against it recorded every internal
196
+ click as a referral from the site itself. classifyAgent/referrerHost are coarse
197
+ helpers, not unique visitor identification. Capture failures are swallowed so a statistic cannot break a
195
198
  page. Apply the table/model migration before relying on the dashboard data.
196
199
 
197
200
  Source: `storage/framework/core/analytics/src/registry.ts`, capture.ts and
@@ -113,3 +113,13 @@ composables/useAuth.ts/useApi.ts/csrf.ts/request-error.ts and utils/fetch.ts.
113
113
  Tests: client-bundle-safety.test.ts, use-auth-refresh.test.ts (refresh, session
114
114
  resilience, burst expiry, authGuard, handoff code), auth.test.ts, csrf.test.ts,
115
115
  request-error.test.ts and api-url.test.ts under core/browser/tests.
116
+
117
+
118
+ ## Retry timing
119
+
120
+ `retry` and `calculateDelay` are available through the utilities entry. Retry
121
+ budgets must be finite non-negative safe integers; delays and backoff factors
122
+ must be finite non-negative numbers. Invalid options reject before invoking
123
+ work. Retry runs once plus the allowed retries, preserving the final error.
124
+ Backoff/jitter delays saturate at the platform timer maximum (2147483647 ms),
125
+ including numeric overflow. Large delays never fall through to one-ms timers.
@@ -25,14 +25,15 @@ console.log(preview.plan.create, preview.plan.keep, preview.plan.skip)
25
25
 
26
26
  desiredDnsRecords(domain, config) converts native config to provider records.
27
27
  planDnsSync(desired, current, { zone? }) returns create/keep/skip with reasons.
28
- syncDnsConfig(domain, config, { dryRun?, provider? }) reports created/kept/failed,
28
+ syncDnsConfig(domain, config, { dryRun?, provider?, resolver? }) reports created/kept/failed,
29
29
  failures/skipped/applied/provider. It only creates missing declared records;
30
30
  it never deletes or overwrites an existing value. Single-value A/AAAA/CNAME
31
31
  records are kept when present; TXT/MX can add distinct values. Editing config
32
32
  does not imply changing an already-present provider value.
33
33
 
34
34
  dryRun reads public DNS without provider credentials; that is not a complete
35
- zone export. Actual apply selects a ts-cloud DNS provider by domain/nameservers
35
+ zone export. It looks up the apex, `www` and every declared in-zone name, so a
36
+ live `_dmarc` or DKIM record reads as kept. Actual apply selects a ts-cloud DNS provider by domain/nameservers
36
37
  and credentials. A missing provider yields an unapplied plan, not fake success.
37
38
  The native sync interface supports Route53/Porkbun/GoDaddy/Cloudflare through
38
39
  the provider factory; retained request/planner tests are not live provider parity.
@@ -51,7 +52,11 @@ Private/loopback/placeholder addresses and out-of-zone records are skipped;
51
52
  TTL normalization applies the planner's current minimum. Resolve conflicts
52
53
  deliberately rather than interpreting keep as identical desired content.
53
54
 
54
- resolveLiveRecords(domain) reads public DNS. renderDnsConfig(domain, records)
55
+ resolveLiveRecords(domain, names?, resolver?) reads public DNS for the apex,
56
+ `www` and the in-zone `names`. A non-apex name with a CNAME is reported as
57
+ that CNAME alone, never as the addresses it resolves to, so `dns:pull` keeps
58
+ an alias an alias. The optional resolver replaces `node:dns` in tests.
59
+ renderDnsConfig(domain, records)
55
60
  renders source for review; dnsProviderForDomain(domain) resolves the mutable
56
61
  provider. Use buddy dns:* --help for pull/sync command flags and output paths.
57
62
 
@@ -154,6 +154,24 @@ For the web renderer, choose a primary content source:
154
154
  Only enable capabilities the product uses. Craft turns enabled capabilities
155
155
  into native bridge availability and required iOS privacy descriptions.
156
156
 
157
+ `capabilities.shakeGesture` arms the accelerometer while the app is in front,
158
+ on iOS and Android, and sends the page Craft's `shake` event (with its `force`
159
+ in g) once per deliberate shake. It needs craft-native 0.0.435 or later, and
160
+ the build refuses an older one rather than shipping a gesture that does
161
+ nothing.
162
+
163
+ `capabilities.wallet` lets a native screen add a pass through stx's
164
+ `craft.wallet`: `add({ data })` with a base64 `.pkpass` or `add({ url })` with
165
+ an https URL on iOS, an https Google Wallet save URL on Android. On iOS
166
+ `craft.wallet.has(serialNumber)` cannot find a pass yet: Craft adds no
167
+ pass-type entitlement, and iOS shows an app only the passes its entitlement
168
+ covers. `android.capabilities.healthServices` runs a native screen's
169
+ `craft.health.startWorkout()`, `pauseWorkout()`, `resumeWorkout()` and
170
+ `endWorkout()` through Health Services; it needs `android.minSdk` 30, which
171
+ Craft sets when the app leaves it unset. Native passkeys are not offered yet:
172
+ Craft's iOS host has them, and a native screen has nothing to call them with
173
+ until stx's native runtime does (stacksjs/stx#2151).
174
+
157
175
  The shell's behaviour around the page defaults to a native app's; set only
158
176
  what should differ: `swipeBack` (`'router'`, the stx router's interactive
159
177
  swipe, or `'webview'` for WebKit's history swipe), `keyboardAccessory` (off),
@@ -11,17 +11,17 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
11
11
  | Package | Task guidance | Source entry | Retained tests |
12
12
  |---|---|---|---|
13
13
  | `@stacksjs/action-runner` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/action-runner/src/index.ts) | 1 |
14
- | `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) | 96 |
14
+ | `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) | 100 |
15
15
  | `@stacksjs/ai` | [`stacks-ai`](../stacks-ai/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/index.ts) | 21 |
16
16
  | `@stacksjs/alias` | [`stacks-alias`](../stacks-alias/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/alias/src/index.ts) | 3 |
17
- | `@stacksjs/analytics` | [`stacks-analytics`](../stacks-analytics/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/index.ts) | 6 |
17
+ | `@stacksjs/analytics` | [`stacks-analytics`](../stacks-analytics/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/index.ts) | 7 |
18
18
  | `@stacksjs/api` | [`stacks-api`](../stacks-api/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/api/src/index.ts) | 12 |
19
19
  | `@stacksjs/arrays` | [`stacks-arrays`](../stacks-arrays/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/src/index.ts) | 12 |
20
20
  | `@stacksjs/audio` | [`stacks-audio`](../stacks-audio/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/audio/src/index.ts) | 3 |
21
21
  | `@stacksjs/auth` | [`stacks-auth`](../stacks-auth/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/index.ts) | 127 |
22
- | `@stacksjs/browser` | [`stacks-browser`](../stacks-browser/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/index.ts) | 8 |
22
+ | `@stacksjs/browser` | [`stacks-browser`](../stacks-browser/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/index.ts) | 9 |
23
23
  | `@stacksjs/browser-extension` | [`stacks-browser-extension`](../stacks-browser-extension/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser-extension/src/index.ts) | 9 |
24
- | `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 180 |
24
+ | `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 181 |
25
25
  | `@stacksjs/build` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/build/src/index.ts) | 6 |
26
26
  | `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) | 24 |
27
27
  | `@stacksjs/calendar-api` | [`stacks-calendar`](../stacks-calendar/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/calendar-api/src/index.ts) | 5 |
@@ -35,13 +35,13 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
35
35
  | `@stacksjs/composables` | [`stacks-composables`](../stacks-composables/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/composables/src/index.ts) | 18 |
36
36
  | `@stacksjs/config` | [`stacks-config`](../stacks-config/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/config/src/index.ts) | 16 |
37
37
  | `@stacksjs/cron` | [`stacks-cron`](../stacks-cron/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cron/src/index.ts) | 6 |
38
- | `@stacksjs/database` | [`stacks-database`](../stacks-database/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index.ts) | 138 |
38
+ | `@stacksjs/database` | [`stacks-database`](../stacks-database/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index.ts) | 139 |
39
39
  | `@stacksjs/datetime` | [`stacks-datetime`](../stacks-datetime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/index.ts) | 22 |
40
40
  | `@stacksjs/defaults` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/defaults/package.json) | 2 |
41
41
  | `@stacksjs/deploy` | [`stacks-deploy`](../stacks-deploy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/deploy/package.json) | 1 |
42
42
  | `@stacksjs/desktop-build` | [`stacks-desktop`](../stacks-desktop/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/index.ts) | 15 |
43
43
  | `@stacksjs/development` | [`stacks-development`](../stacks-development/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/development/package.json) | 1 |
44
- | `@stacksjs/dns` | [`stacks-dns`](../stacks-dns/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/index.ts) | 3 |
44
+ | `@stacksjs/dns` | [`stacks-dns`](../stacks-dns/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/index.ts) | 4 |
45
45
  | `@stacksjs/docs` | [`stacks-docs`](../stacks-docs/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/docs/src/index.ts) | 2 |
46
46
  | `@stacksjs/email` | [`stacks-email`](../stacks-email/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/index.ts) | 23 |
47
47
  | `@stacksjs/enums` | [`stacks-enums`](../stacks-enums/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/enums/src/index.ts) | 3 |
@@ -62,21 +62,21 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
62
62
  | `@stacksjs/logging` | [`stacks-logging`](../stacks-logging/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/logging/src/index.ts) | 14 |
63
63
  | `@stacksjs/mobile` | [`stacks-mobile`](../stacks-mobile/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/index.ts) | 23 |
64
64
  | `@stacksjs/model-meta` | [`stacks-models`](../stacks-models/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/model-meta/src/index.ts) | 1 |
65
- | `@stacksjs/newsletter` | [`stacks-newsletter`](../stacks-newsletter/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/index.ts) | 7 |
65
+ | `@stacksjs/newsletter` | [`stacks-newsletter`](../stacks-newsletter/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/index.ts) | 9 |
66
66
  | `@stacksjs/notifications` | [`stacks-notifications`](../stacks-notifications/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/notifications/src/index.ts) | 18 |
67
- | `@stacksjs/objects` | [`stacks-objects`](../stacks-objects/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/index.ts) | 8 |
67
+ | `@stacksjs/objects` | [`stacks-objects`](../stacks-objects/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/index.ts) | 10 |
68
68
  | `@stacksjs/orm` | [`stacks-orm`](../stacks-orm/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/index.ts) | 77 |
69
69
  | `@stacksjs/pagination` | [`stacks-pagination`](../stacks-pagination/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/pagination/src/index.ts) | 1 |
70
70
  | `@stacksjs/path` | [`stacks-path`](../stacks-path/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/path/src/index.ts) | 13 |
71
71
  | `@stacksjs/payments` | [`stacks-payments`](../stacks-payments/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/payments/src/index.ts) | 39 |
72
72
  | `@stacksjs/push` | [`stacks-push`](../stacks-push/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/push/src/index.ts) | 8 |
73
73
  | `@stacksjs/query-builder` | [`stacks-query-builder`](../stacks-query-builder/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/query-builder/src/index.ts) | 7 |
74
- | `@stacksjs/queue` | [`stacks-queue`](../stacks-queue/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/index.ts) | 52 |
75
- | `@stacksjs/realtime` | [`stacks-realtime`](../stacks-realtime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/index.ts) | 12 |
74
+ | `@stacksjs/queue` | [`stacks-queue`](../stacks-queue/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/index.ts) | 55 |
75
+ | `@stacksjs/realtime` | [`stacks-realtime`](../stacks-realtime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/index.ts) | 13 |
76
76
  | `@stacksjs/registry` | [`stacks-registry`](../stacks-registry/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/registry/src/index.ts) | 1 |
77
77
  | `@stacksjs/repl` | [`stacks-repl`](../stacks-repl/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/repl/src/index.ts) | 2 |
78
78
  | `@stacksjs/router` | [`stacks-router`](../stacks-router/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/router/src/index.ts) | 99 |
79
- | `@stacksjs/scheduler` | [`stacks-scheduler`](../stacks-scheduler/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/index.ts) | 17 |
79
+ | `@stacksjs/scheduler` | [`stacks-scheduler`](../stacks-scheduler/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/index.ts) | 19 |
80
80
  | `@stacksjs/search-engine` | [`stacks-search-engine`](../stacks-search-engine/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/search-engine/src/index.ts) | 11 |
81
81
  | `@stacksjs/security` | [`stacks-security`](../stacks-security/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/security/src/index.ts) | 12 |
82
82
  | `@stacksjs/server` | [`stacks-server`](../stacks-server/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/server/src/index.ts) | 28 |
@@ -86,14 +86,14 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
86
86
  | `@stacksjs/slug` | [`stacks-slug`](../stacks-slug/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/slug/src/index.ts) | 5 |
87
87
  | `@stacksjs/sms` | [`stacks-sms`](../stacks-sms/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/sms/src/index.ts) | 6 |
88
88
  | `@stacksjs/socials` | [`stacks-socials`](../stacks-socials/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/index.ts) | 18 |
89
- | `@stacksjs/storage` | [`stacks-storage`](../stacks-storage/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts) | 48 |
89
+ | `@stacksjs/storage` | [`stacks-storage`](../stacks-storage/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts) | 49 |
90
90
  | `@stacksjs/strings` | [`stacks-strings`](../stacks-strings/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/strings/src/index.ts) | 11 |
91
91
  | `@stacksjs/testing` | [`stacks-testing`](../stacks-testing/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/testing/src/index.ts) | 24 |
92
92
  | `@stacksjs/tinker` | [`stacks-repl`](../stacks-repl/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tinker/src/index.ts) | 1 |
93
93
  | `@stacksjs/tunnel` | [`stacks-tunnel`](../stacks-tunnel/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tunnel/src/index.ts) | 1 |
94
94
  | `@stacksjs/types` | [`stacks-types`](../stacks-types/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/index.ts) | 2 |
95
95
  | `@stacksjs/ui` | [`stacks-ui`](../stacks-ui/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/index.ts) | 6 |
96
- | `@stacksjs/utils` | [`stacks-utils`](../stacks-utils/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/index.ts) | 22 |
96
+ | `@stacksjs/utils` | [`stacks-utils`](../stacks-utils/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/index.ts) | 28 |
97
97
  | `@stacksjs/validation` | [`stacks-validation`](../stacks-validation/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/index.ts) | 25 |
98
98
  | `@stacksjs/video` | [`stacks-video`](../stacks-video/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/video/src/index.ts) | 3 |
99
99
  | `@stacksjs/whois` | [`stacks-whois`](../stacks-whois/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/whois/src/index.ts) | 5 |
@@ -119,7 +119,7 @@ Declared runtime exports: `BlogAdminError`, `DEFAULT_IOS_DEPENDENCIES`, `DEFAULT
119
119
 
120
120
  Local source modules: [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/action.ts), [src/add.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/add.ts), [src/blog-admin.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/blog-admin.ts), [src/build/ios-toolchain.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/ios-toolchain.ts), [src/build/macos-native.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/macos-native.ts), [src/commit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/commit.ts), [src/dev/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/dev/index.ts), [src/discover-packages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/discover-packages.ts), [src/generate/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/generate/index.ts), [src/github-release.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/github-release.ts), [src/helpers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/helpers/index.ts), [src/library/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/library/index.ts), [src/lint/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/lint.ts), [src/lint/stx-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/stx-gate.ts), [src/make-command.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-command.ts), [src/make-job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-job.ts), [src/make-policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-policy.ts), [src/make-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-resource.ts), [src/make.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make.ts), [src/publication-preflight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/publication-preflight.ts), [src/release-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/release-evidence.ts), [src/scaffold-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/scaffold-crud.ts), [src/setup/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/setup/index.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stacks.ts), [src/stx-source.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stx-source.ts), [src/upgrade/package-project.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/package-project.ts), [src/upgrade/route-actions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/route-actions.ts).
121
121
 
122
- Evidence directory: [96 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
122
+ Evidence directory: [100 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
123
123
 
124
124
  ### @stacksjs/ai
125
125
 
@@ -149,7 +149,7 @@ Declared runtime exports: `classifyAgent`, `isPageviewRequest`, `recordPageview`
149
149
 
150
150
  Local source modules: [src/capture.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/capture.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/drivers/index.ts), [src/registry.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/registry.ts).
151
151
 
152
- Evidence directory: [6 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
152
+ Evidence directory: [7 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
153
153
 
154
154
  ### @stacksjs/api
155
155
 
@@ -199,7 +199,7 @@ Declared runtime exports: `BrowserQueryBuilder`, `BrowserQueryError`, `browserAu
199
199
 
200
200
  Local source modules: [src/auto-init.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/auto-init.ts), [src/composables/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/composables/index.ts), [src/model-loader.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/model-loader.ts), [src/types/globals.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/types/globals.ts), [src/utils/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/utils/index.ts).
201
201
 
202
- Evidence directory: [8 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
202
+ Evidence directory: [9 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
203
203
 
204
204
  ### @stacksjs/browser-extension
205
205
 
@@ -219,7 +219,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
219
219
 
220
220
  Local source modules: [src/commands/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/commands/index.ts).
221
221
 
222
- Evidence directory: [180 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
222
+ Evidence directory: [181 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
223
223
 
224
224
  ### @stacksjs/build
225
225
 
@@ -357,7 +357,7 @@ Declared runtime exports: `Database`, `EntityQueryBuilder`, `__flushAfterCommitN
357
357
 
358
358
  Local source modules: [src/affected-rows.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/affected-rows.ts), [src/auth-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/auth-tables.ts), [src/custom/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/custom/index.ts), [src/database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/database.ts), [src/datetime-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/datetime-columns.ts), [src/ddl-constraints.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ddl-constraints.ts), [src/defaults.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/defaults.ts), [src/dialect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/dialect.ts), [src/driver-config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/driver-config.ts), [src/drivers/dynamodb.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/drivers/dynamodb.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/drivers/index.ts), [src/ensure-database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ensure-database.ts), [src/erd.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/erd.ts), [src/fk-audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/fk-audit.ts), [src/framework-renames.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/framework-renames.ts), [src/framework-route-admission.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/framework-route-admission.ts), [src/hand-written-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/hand-written-migrations.ts), [src/ignored-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ignored-migrations.ts), [src/index-shape.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index-shape.ts), [src/managed-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/managed-columns.ts), [src/migration-dialect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-dialect.ts), [src/migration-ledger.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-ledger.ts), [src/migration-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-names.ts), [src/migration-path.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-path.ts), [src/migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migrations.ts), [src/model-sources.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/model-sources.ts), [src/notification-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/notification-tables.ts), [src/package-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/package-migrations.ts), [src/package-models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/package-models.ts), [src/query-logger.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/query-logger.ts), [src/rbac-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/rbac-tables.ts), [src/relation-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/relation-columns.ts), [src/replicas.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/replicas.ts), [src/row-lease.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/row-lease.ts), [src/row-lock.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/row-lock.ts), [src/safe-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/safe-migrations.ts), [src/schema-align.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/schema-align.ts), [src/schema-drift.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/schema-drift.ts), [src/seeder.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/seeder.ts), [src/shadowed-models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/shadowed-models.ts), [src/sql-helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/sql-helpers.ts), [src/trait-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/trait-tables.ts), [src/transaction-context.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/transaction-context.ts), [src/transaction-options.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/transaction-options.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/types.ts), [src/unique-audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/unique-audit.ts), [src/utc-defaults.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/utc-defaults.ts), [src/utils.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/utils.ts), [src/uuid-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/uuid-columns.ts), [src/vschema.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/vschema.ts).
359
359
 
360
- Evidence directory: [138 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
360
+ Evidence directory: [139 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
361
361
 
362
362
  ### @stacksjs/datetime
363
363
 
@@ -411,7 +411,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
411
411
 
412
412
  Local source modules: [src/drivers/aws.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/drivers/aws.ts), [src/sync.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/sync.ts).
413
413
 
414
- Evidence directory: [3 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
414
+ Evidence directory: [4 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
415
415
 
416
416
  ### @stacksjs/docs
417
417
 
@@ -611,7 +611,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
611
611
 
612
612
  Local source modules: [src/campaigns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/campaigns.ts), [src/delivery.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/delivery.ts), [src/headers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/headers.ts), [src/lists.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/lists.ts), [src/newsletter.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/newsletter.ts), [src/subscriptions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/subscriptions.ts), [src/sync.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/sync.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/types.ts), [src/usage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/usage.ts).
613
613
 
614
- Evidence directory: [7 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
614
+ Evidence directory: [9 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
615
615
 
616
616
  ### @stacksjs/notifications
617
617
 
@@ -631,13 +631,13 @@ Declared runtime exports: `clearUndefined`, `deepMerge`, `hasOwnProperty`, `isKe
631
631
 
632
632
  Local source modules: [src/transform.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/transform.ts).
633
633
 
634
- Evidence directory: [8 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
634
+ Evidence directory: [10 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
635
635
 
636
636
  ### @stacksjs/orm
637
637
 
638
638
  Guidance: [`stacks-orm`](../stacks-orm/SKILL.md). Source: [storage/framework/core/orm/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/index.ts).
639
639
 
640
- Declared runtime exports: `Activity`, `AnalyticsEvent`, `Auction`, `AuctionItem`, `Author`, `Automation`, `AutomationRun`, `BILLABLE_INSTANCE_METHODS`, `Bid`, `Board`, `BoardColumn`, `Campaign`, `CampaignSend`, `CampaignVariant`, `Card`, `CardAttachment`, `CardComment`, `Cart`, `CartItem`, `Categorizable`, `Category`, `Comment`, `CommunicationSuppression`, `ConsentEvent`, `Coupon`, `Courier`, `CourierPing`, `Customer`, `DeliveryRoute`, `DeliveryStop`, `Deployment`, `DigitalDelivery`, `EmailIdempotency`, `EmailList`, `EmailListSubscriber`, `EmailSuppression`, `EmailWebhookEvent`, `ErrorModel`, `FailedJob`, `FeedbackToken`, `Form`, `FormField`, `FormSubmission`, `GdprRequest`, `GiftCard`, `Job`, `Label`, `LicenseKey`, `Log`, `LoyaltyPoint`, `LoyaltyReward`, `MagicLinkToken`, `MailPreference`, `Manufacturer`, `Menu`, `MenuItem`, `Notification`, `NotificationDelivery`, `Order`, `OrderIdempotency`, `OrderItem`, `Page`, `PageRevision`, `Payment`, `PaymentMethod`, `PaymentProduct`, `PaymentTransaction`, `PaymentWebhookEvent`, `PersonalAccessToken`, `Pledge`, `Post`, `PrintDevice`, `Product`, `ProductUnit`, `ProductVariant`, `QueryLog`, `Receipt`, `Redirect`, `Referral`, `ReferralCode`, `Release`, `Request`, `Review`, `SenderDomain`, `ShippingMethod`, `ShippingRate`, `ShippingZone`, `Site`, `SiteDomain`, `SmsOptOut`, `SocialAccount`, `SocialPost`, `StorageItem`, `StorageItemTask`, `Subscriber`, `SubscriberEmail`, `Subscription`, `SubscriptionNotOwnedError`, `Tag`, `TaxRate`, `Team`, `TeamInvitation`, `TeamMember`, `Transaction`, `UsageEvent`, `User`, `WaitlistProduct`, `WaitlistRestaurant`, `Websocket`, `buildDatabaseSchema`, `collectEncryptedAttributes`, `createAuditMethods`, `createCategorizableMethods`, `createCommentableMethods`, `createLikeableMethods`, `createTaggableMethods`, `customerOwnership`, `decryptValue`, `encryptValue`, `enrichPaginatorUrls`, `filterFillable`, `getWritableFields`, `isBillable`, `isCursorPaginator`, `isEncrypted`, `isPaginator`, `isSimplePaginator`, `isUniqueViolation`, `mapWriteError`, `modelGlobalNames`, `ormReady`, `parentOwnership`, `parseCursor`, `renderDatabaseTypeFile`, `resolveCursorArgs`, `resolvePageArgs`, `selfOwnership`, `setAuditUser`, `siteOwnership`, `teamMembershipOwnership`, `toCursorPaginator`, `toPaginator`, `toSimplePaginator`, `toSnakeCaseKeys`.
640
+ Declared runtime exports: `Activity`, `AnalyticsEvent`, `Auction`, `AuctionItem`, `Author`, `Automation`, `AutomationRun`, `BILLABLE_INSTANCE_METHODS`, `Bid`, `Board`, `BoardColumn`, `Campaign`, `CampaignSend`, `CampaignVariant`, `Card`, `CardAttachment`, `CardComment`, `Cart`, `CartItem`, `Categorizable`, `Category`, `Comment`, `CommunicationSuppression`, `ConsentEvent`, `Coupon`, `Courier`, `CourierPing`, `Customer`, `DeliveryRoute`, `DeliveryStop`, `Deployment`, `DigitalDelivery`, `EmailIdempotency`, `EmailList`, `EmailListSubscriber`, `EmailSuppression`, `EmailWebhookEvent`, `ErrorModel`, `FailedJob`, `FeedbackToken`, `Form`, `FormField`, `FormSubmission`, `GdprRequest`, `GiftCard`, `Job`, `Label`, `LicenseKey`, `Log`, `LoyaltyPoint`, `LoyaltyReward`, `MagicLinkToken`, `MailPreference`, `Manufacturer`, `Menu`, `MenuItem`, `Notification`, `NotificationDelivery`, `Order`, `OrderIdempotency`, `OrderItem`, `Page`, `PageRevision`, `Payment`, `PaymentMethod`, `PaymentProduct`, `PaymentTransaction`, `PaymentWebhookEvent`, `PersonalAccessToken`, `Pledge`, `Post`, `PrintDevice`, `Product`, `ProductUnit`, `ProductVariant`, `QueryLog`, `Receipt`, `Redirect`, `Referral`, `ReferralCode`, `Release`, `Request`, `Review`, `SenderDomain`, `ShippingMethod`, `ShippingRate`, `ShippingZone`, `Site`, `SiteDomain`, `SmsOptOut`, `SocialAccount`, `SocialPost`, `StorageItem`, `StorageItemTask`, `Subscriber`, `SubscriberEmail`, `Subscription`, `SubscriptionNotOwnedError`, `Tag`, `TaxRate`, `Team`, `TeamInvitation`, `TeamMember`, `Transaction`, `UsageEvent`, `User`, `WaitlistProduct`, `WaitlistRestaurant`, `Websocket`, `buildDatabaseSchema`, `collectEncryptedAttributes`, `createAuditMethods`, `createCategorizableMethods`, `createCommentableMethods`, `createLikeableMethods`, `createTaggableMethods`, `customerOwnership`, `decryptValue`, `encryptValue`, `enrichPaginatorUrls`, `filterFillable`, `frameworkModelFeature`, `getWritableFields`, `isBillable`, `isCursorPaginator`, `isEncrypted`, `isPaginator`, `isSimplePaginator`, `isUniqueViolation`, `mapWriteError`, `modelGlobalNames`, `ormReady`, `parentOwnership`, `parseCursor`, `renderDatabaseTypeFile`, `resolveCursorArgs`, `resolvePageArgs`, `selfOwnership`, `setAuditUser`, `siteOwnership`, `teamMembershipOwnership`, `toCursorPaginator`, `toPaginator`, `toSimplePaginator`, `toSnakeCaseKeys`.
641
641
 
642
642
  Local source modules: [src/auto-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/auto-crud.ts), [src/batch-loader.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/batch-loader.ts), [src/db.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/db.ts), [src/define-model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/define-model.ts), [src/extend-model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/extend-model.ts), [src/gdpr/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/gdpr/index.ts), [src/generate-database-schema.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/generate-database-schema.ts), [src/locked-row.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/locked-row.ts), [src/messaging.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/messaging.ts), [src/model-types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/model-types.ts), [src/ownership.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/ownership.ts), [src/paginator-request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/paginator-request.ts), [src/row-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/row-token.ts), [src/subquery.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/subquery.ts), [src/traits/audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/audit.ts), [src/traits/billable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/billable.ts), [src/traits/categorizable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/categorizable.ts), [src/traits/commentable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/commentable.ts), [src/traits/likeable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/likeable.ts), [src/traits/taggable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/taggable.ts), [src/transaction.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/transaction.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/types.ts), [src/utils/encrypted.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/utils/encrypted.ts), [src/utils/prunable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/utils/prunable.ts).
643
643
 
@@ -699,7 +699,7 @@ Declared runtime exports: `Batch`, `DispatchedBatch`, `FailedJobNotifier`, `JOB_
699
699
 
700
700
  Local source modules: [src/action-runner.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/action-runner.ts), [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/action.ts), [src/batch.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/batch.ts), [src/bun-queue.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/bun-queue.ts), [src/circuit-breaker.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/circuit-breaker.ts), [src/dead-letter.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/dead-letter.ts), [src/discovery.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/discovery.ts), [src/driver.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/driver.ts), [src/drivers/redis.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/drivers/redis.ts), [src/envelope.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/envelope.ts), [src/events.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/events.ts), [src/health.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/health.ts), [src/idempotency.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/idempotency.ts), [src/job-progress.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/job-progress.ts), [src/job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/job.ts), [src/notifications.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/notifications.ts), [src/poison.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/poison.ts), [src/scheduler.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/scheduler.ts), [src/testing.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/testing.ts), [src/worker.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/src/worker.ts).
701
701
 
702
- Evidence directory: [52 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
702
+ Evidence directory: [55 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/queue/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
703
703
 
704
704
  ### @stacksjs/realtime
705
705
 
@@ -709,7 +709,7 @@ Declared runtime exports: `LegacyBroadcast`, `StacksChannel`, `channel`, `create
709
709
 
710
710
  Local source modules: [src/broadcast.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/broadcast.ts), [src/channel.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/channel.ts), [src/emit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/emit.ts), [src/replay-buffer.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/replay-buffer.ts), [src/server-instance.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/server-instance.ts), [src/stream.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/stream.ts), [src/ws.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/src/ws.ts).
711
711
 
712
- Evidence directory: [12 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
712
+ Evidence directory: [13 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/realtime/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
713
713
 
714
714
  ### @stacksjs/registry
715
715
 
@@ -745,7 +745,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
745
745
 
746
746
  Local source modules: [src/run.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/run.ts), [src/schedule.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/schedule.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/src/types.ts).
747
747
 
748
- Evidence directory: [17 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
748
+ Evidence directory: [19 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/scheduler/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
749
749
 
750
750
  ### @stacksjs/search-engine
751
751
 
@@ -843,7 +843,7 @@ Declared runtime exports: `PathSanitizeError`, `Storage`, `StorageManager`, `Upl
843
843
 
844
844
  Local source modules: [src/adapters/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/adapters/index.ts), [src/bounded-text-file.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/bounded-text-file.ts), [src/completed-artifact-directory.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/completed-artifact-directory.ts), [src/copy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/copy.ts), [src/delete.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/delete.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/drivers/index.ts), [src/facade.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/facade.ts), [src/file-info.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/file-info.ts), [src/files.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/files.ts), [src/folders.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/folders.ts), [src/fs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/fs.ts), [src/glob.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/glob.ts), [src/hash.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/hash.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/helpers.ts), [src/mime-verify.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/mime-verify.ts), [src/path-sanitize.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/path-sanitize.ts), [src/provision.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/provision.ts), [src/s3-presigned-post.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/s3-presigned-post.ts), [src/signed-url.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/signed-url.ts), [src/static-serve.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/static-serve.ts), [src/storage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/storage.ts), [src/temporary-workspaces.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/temporary-workspaces.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/types.ts), [src/types/filesystem.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/types/filesystem.ts), [src/uploaded-file.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/uploaded-file.ts), [src/zip.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/zip.ts).
845
845
 
846
- Evidence directory: [48 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
846
+ Evidence directory: [49 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
847
847
 
848
848
  ### @stacksjs/strings
849
849
 
@@ -911,7 +911,7 @@ Declared runtime exports: `browserUtils`, `clamp`, `notNullish`, `retry`, `useOn
911
911
 
912
912
  Local source modules: [src/bytes.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/bytes.ts), [src/clean.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/clean.ts), [src/colors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/colors.ts), [src/config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/config.ts), [src/debounce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/debounce.ts), [src/detect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/detect.ts), [src/equal.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/equal.ts), [src/errors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/errors.ts), [src/export-size.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/export-size.ts), [src/find.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/find.ts), [src/git.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/git.ts), [src/hash.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/hash.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/helpers.ts), [src/macroable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/macroable.ts), [src/markdown.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/markdown.ts), [src/merge.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/merge.ts), [src/observer.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/observer.ts), [src/pipe.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/pipe.ts), [src/pipeline.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/pipeline.ts), [src/safe-json.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/safe-json.ts), [src/size.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/size.ts), [src/versions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/versions.ts).
913
913
 
914
- Evidence directory: [22 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
914
+ Evidence directory: [28 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
915
915
 
916
916
  ### @stacksjs/validation
917
917
 
@@ -19,6 +19,13 @@ subscriber updates. Preserve one-click unsubscribe headers and suppression.
19
19
  List/campaign helpers own their schema and state transitions; direct column
20
20
  writes can bypass transition guards or schedule/idempotency behavior.
21
21
 
22
+ An address is one person whatever its case: subscribe() stores it trimmed and
23
+ lowercased (normalizeEmail), and subscribe(), unsubscribeAll() and
24
+ syncListSubscribers() find rows case-insensitively, so rows stored with capitals
25
+ before that still match. A sync skips an address whose row on the list is
26
+ unsubscribed under any spelling. subscriberIdsForEmail(email) and
27
+ listStatusForEmail(email, listId) are the lookups they share.
28
+
22
29
  Campaign delivery snapshots, dispatch keys and state conflict errors protect
23
30
  retries and concurrent queue requests. Scheduled work uses the package's actual
24
31
  transition and readiness checks. DeliveryVariant allocation and
@@ -26,7 +26,7 @@ additional transforms re-exported from transform.ts.
26
26
  function objectMap<K extends string, V, NK extends PropertyKey = K, NV = V>(
27
27
  obj: Record<K, V>,
28
28
  fn: (key: K, value: V) => [NK, NV] | undefined,
29
- ): Record<NK, NV>
29
+ ): Partial<Record<NK, NV>>
30
30
  ```
31
31
 
32
32
  The callback receives `(key, value)` and must return either:
@@ -61,7 +61,7 @@ function deepMerge<T extends object = object, S extends object = T>(
61
61
  ): DeepMerge<T, S>
62
62
  ```
63
63
 
64
- Recursively merges source objects into target. Handles multiple sources via recursive spread.
64
+ Recursively merges source objects into target, overlaying sources from left to right.
65
65
 
66
66
  Key behaviors:
67
67
  - Only merges "mergeable objects" (objects that are not arrays, checked via `isObject()` and `!Array.isArray()`)
@@ -86,6 +86,11 @@ built-in instance values while merging record keys recursively. A replaced Date
86
86
  target no longer exposes Date methods. The authoritative type is in
87
87
  `core/types/src/utils.ts`; verify consumers against built declarations.
88
88
 
89
+ Plain-record graph merges track source nodes per overlay. Self/mutual cycles
90
+ and shared nodes terminate and reuse the first destination for that source node.
91
+ Arrays and non-plain values remain atomic; later source overlays use fresh graph
92
+ tracking while updating the same target.
93
+
89
94
  ### objectPick -- Pick Properties by Key
90
95
  ```typescript
91
96
  function objectPick<O extends object, T extends keyof O>(
@@ -198,6 +203,10 @@ parser. `getPath(source, path, fallback?)` reads a nested value;
198
203
  `mapValues` preserves optional properties and omits symbol keys in its result type,
199
204
  matching its enumerable string-key traversal. The pure `@stacksjs/objects/transform`
200
205
  entry ships both JavaScript and declarations.
206
+ `omit` normalizes numeric exclusions to string property keys, as JavaScript does.
207
+ `objectMap` returns a partial record: a callback may omit entries, so narrow a
208
+ result value before assuming it exists.
209
+
201
210
  `setPath(source, path, value)` performs a persistent update by copying containers
202
211
  along the path and sharing unaffected siblings. Treat paths as application-owned
203
212
  inputs; this helper is not a path authorization boundary. Array `length` updates
@@ -225,3 +234,9 @@ Retained evidence: `core/objects/tests/transform.test.ts`.
225
234
  - `hasOwnProperty` accepts `null`/`undefined` objects without throwing.
226
235
  - `objectPick` with `omitUndefined=false` (default) includes keys even if their values are `undefined`, as long as the key exists in the object.
227
236
  - `@stacksjs/utils` does not re-export these. Its `merge` / `defu` is a separate merge that builds a new object.
237
+
238
+ Path inference normalizes numeric/string aliases and distributes finite union
239
+ steps. Broad string/number/template steps and open index-signature object sources
240
+ return `unknown`; narrow before using them. Length changes drop fixed tuple index
241
+ guarantees, and generic array results include possible holes. Numeric-looking
242
+ named siblings such as `-1` and `1.5` retain their own value types.
@@ -234,7 +234,7 @@ import { replaySince, setReplayBuffer } from '@stacksjs/realtime'
234
234
  setReplayBuffer({ channels: ['orders.*'], maxPerChannel: 100, ttlMs: 5 * 60_000 })
235
235
  ```
236
236
 
237
- Every broadcast on a matching channel, from any API, is recorded and reaches clients as `{ event, channel, data, seq }`. Patterns match with or without the `private-`/`presence-` prefix (`orders.*` covers `private-orders.1`); `replaySince()` takes the full name. The client keeps the last `seq` per channel and sends it back after reconnecting (through a route of the app's), which answers with `replaySince('private-orders.1', seq)`. The buffer and its numbering are per process.
237
+ Every broadcast on a matching channel, from any API, is recorded and reaches clients as `{ event, channel, data, seq }`. Patterns match with or without the `private-`/`presence-` prefix (`orders.*` covers `private-orders.1`); `replaySince()` takes the full name. The client keeps the last `seq` per channel and sends it back after reconnecting (through a route of the app's), which answers with `replaySince('private-orders.1', seq)`. The buffer and its numbering are per process. A channel's `seq` rises by one per message and keeps rising across a restart (each channel starts from the clock, never below a number already issued), so messages sent after a restart are still newer than the `seq` a reconnecting client holds. Do not assume it starts at 1. When the first replayed `seq` is not the client's `seq + 1`, messages were lost: evicted, expired, or sent before a restart.
238
238
 
239
239
  ---
240
240
 
@@ -143,6 +143,17 @@ lock, and a DB-unavailable fallback warns rather than promising cluster
143
143
  coordination. Use the same task name on all participating hosts. Names are
144
144
  sanitized and hashed for lock paths.
145
145
 
146
+ The advisory lock is released when a run ends, so on its own it only stops
147
+ two runs at once. `onOneServer()` therefore also claims the slot: each tick
148
+ inserts `(task, slot)` into a `scheduler_claims` table with a unique key, and
149
+ only the server whose row went in first runs it (`scheduler-claims.ts`,
150
+ stacksjs/stacks#3152). The slot is the cron time the tick woke for; for
151
+ `everySecond()` it is the wall-clock second, and interval timers are not
152
+ aligned across servers, so ticks that straddle a boundary both run. The table
153
+ is created on first use with CREATE TABLE IF NOT EXISTS, and claims older than
154
+ a day are pruned. `Schedule.runNow()` and `buddy schedule:run-one` have no
155
+ slot and always run. SQLite and the DB-unavailable fallback claim nothing.
156
+
146
157
  ### Background Execution
147
158
 
148
159
  When `runInBackground()` is called, each run starts `buddy schedule:run-one <name> --in-process` as a detached child in the project directory. That process registers the app's schedule the way `schedule:run` does and runs the one task there, taking any `withoutOverlapping()` / `onOneServer()` lock itself. The child is `unref()`'d so it does not keep the parent alive, and a non-zero exit is logged under the task's name. The task needs a name (`schedule.job/action/command` have one; a callback needs `.withName()`), or registration fails.
@@ -362,7 +373,7 @@ export default {
362
373
  - A task's default timezone is the app's (`config.app.timezone`, which `config/app.ts` ships as `'America/Los_Angeles'`), not a fixed zone; UTC when the app sets none
363
374
  - `everySecond()` uses `setInterval`, not cron -- it sets `intervalMs = 1000` and bypasses the cron parser entirely
364
375
  - The `Queue` class in `schedule.ts` is just an empty subclass of `Schedule` (`export class Queue extends Schedule {}`) -- it adds no functionality
365
- - `withoutOverlapping()` provides local file locking. `onOneServer()` adds PostgreSQL/MySQL advisory coordination where available
376
+ - `withoutOverlapping()` provides local file locking. `onOneServer()` adds a PostgreSQL/MySQL advisory lock and a per-slot claim in `scheduler_claims`, created on first use
366
377
  - SQLite/Turso and DB-unavailable fallback cannot provide cluster-wide scheduler coordination; read scheduler-lock.ts and its warning
367
378
  - `runInBackground()` runs the task by name in a `buddy schedule:run-one <name> --in-process` child, so the task must be registered under that name by the app's scheduler file, and an unnamed callback is refused
368
379
  - There are TWO scheduler systems: `@stacksjs/scheduler` (fluent API in `schedule.ts`) and the queue-level scheduler in `@stacksjs/queue` (`queue/src/scheduler.ts`). The former runs tasks in-process; the latter dispatches to the queue
@@ -383,8 +394,13 @@ six-field forms: all-wildcard intervals in seconds dividing 60, or leading zero
383
394
  seconds with a five-field schedule. Unsupported specific-second forms throw.
384
395
  `dailyAt(time)`, `weekdays()` and `onQueue(name)` are native methods.
385
396
  `sendOutputTo(path)` and `appendOutputTo(path)` capture supported command
386
- output. `runMissed({ since, max? })` performs bounded catch-up; read its
387
- window/overlap behavior before using it for non-idempotent tasks.
397
+ output. `runMissed({ since, max? })` performs bounded catch-up: each missed
398
+ slot runs in this process, awaited, through the live guards. A paused task
399
+ runs none, only slots inside `between()` run, and a slot is skipped while the
400
+ task holds its `withoutOverlapping()` or `onOneServer()` lock. An
401
+ `onOneServer()` task also claims each slot it replays, so two servers that
402
+ boot together run each missed slot once.
403
+
388
404
 
389
405
  `schedule.notification(recipient, payload, channels?, options?)` schedules
390
406
  native notify fan-out and fails the task if any channel result failed.
@@ -610,6 +610,13 @@ const files = getFiles('dir/', ['node_modules']) // with exclusions
610
610
  deleteFiles('dir/', ['keep.txt']) // delete all except exclusions
611
611
  ```
612
612
 
613
+ Recursive deletion unlinks symlinks, including an explicit symlink root, without
614
+ traversing their targets. Listing skips root and descendant symlink entries and cycles. Symlink ancestors
615
+ below the longest cwd/temp anchor reject; platform aliases above it are accepted.
616
+ Exclusions protect paths.
617
+ Config updates copy own enumerable entries and preserve `__proto__` as data;
618
+ inherited fields/getters are not read.
619
+
613
620
  ### Config File Helper
614
621
 
615
622
  ```typescript
@@ -221,6 +221,8 @@ Pipeline.send('hello')
221
221
  ```
222
222
 
223
223
  Internally uses `reduceRight` so pipes execute in order (first pipe wraps outermost).
224
+ `through()` snapshots its readonly input array. Builder-local `pipe()` calls and
225
+ later edits to the caller array do not change other pipelines.
224
226
 
225
227
  ## Markdown Tables (`markdown.ts`)
226
228
 
@@ -231,6 +233,7 @@ interface MarkdownTableOptions {
231
233
  delimiter?: string // default: '|'
232
234
  delimiterStart?: boolean // default: true
233
235
  delimiterEnd?: boolean // default: true
236
+ escapeCells?: boolean // default: true; false accepts preformatted cells
234
237
  alignDelimiter?: string // default: '-'
235
238
  }
236
239
 
@@ -265,6 +268,11 @@ loadYaml(content) // alias for parseYaml
265
268
  dumpYaml(object) // Bun.YAML.stringify(content), falls back to JSON.stringify
266
269
  ```
267
270
 
271
+ Tables normalize headers and data rows to the same column count. Text cells
272
+ escape literal backslashes and pipes and replace CR/LF with `<br>`, keeping one
273
+ cell from creating columns or rows. `escapeCells: false` preserves caller-owned
274
+ Markdown escaping. This is table structure handling, not an HTML sanitizer.
275
+
268
276
  ## Macroable (`macroable.ts`)
269
277
 
270
278
  Laravel-inspired dynamic method registration on classes.
@@ -298,6 +306,13 @@ Enhanced.macro('newMethod', fn)
298
306
 
299
307
  Static methods: `macro(name, fn, replace?)`, `mixin(obj, replace?)`, `hasMacro(name)`, `flushMacros()`, `getMacros()`.
300
308
 
309
+ Registrations belong to the receiving constructor in all three APIs. Descendants
310
+ see effective inherited macros; sibling mutations are isolated. Flush removes
311
+ only own registrations, restoring original descriptors and revealing inherited
312
+ methods again. Existing native methods need explicit `replace: true` (the third
313
+ argument); `constructor` is reserved. Failed installation publishes no registry
314
+ entry. `getMacros` includes effective inherited macro names.
315
+
301
316
  ## ResizeObserver (`observer.ts`)
302
317
 
303
318
  ```typescript
@@ -314,7 +329,12 @@ const stop = observeElementSize(element, (entry) => {
314
329
  stop() // stop observing
315
330
  ```
316
331
 
317
- The polyfill uses `requestAnimationFrame` (or `setTimeout` fallback) to poll element sizes via `getBoundingClientRect()`.
332
+ The polyfill polls bounding-box width/height with `requestAnimationFrame` (or a
333
+ 16-ms timeout). It delivers initial measurements and size changes, not position
334
+ changes or every frame. Callback errors still reach host error reporting while
335
+ monitoring continues. Unobserve/disconnect discard measurements and pending work;
336
+ reobserving starts with a new initial delivery. This simple fallback does not
337
+ implement native content/border/device-pixel box measurement distinctions.
318
338
 
319
339
  ## Deep Equality (`equal.ts`)
320
340
 
@@ -468,6 +488,16 @@ two corresponding holes compare equal. Host objects and Errors remain identity
468
488
  comparisons. Read retained equal tests for a non-plain object rather than
469
489
  assuming every object with similar printable fields is equal.
470
490
 
491
+ `retry` (re-exported from the browser package) validates a finite non-negative
492
+ safe-integer retry count before work starts. It runs once plus that retry budget.
493
+ Delay and factor must be finite non-negative numbers. `calculateDelay` saturates
494
+ exponential/jitter output at 2147483647 ms, preventing platform timeout overflow
495
+ from turning long backoffs into rapid retries.
496
+
497
+ `setEnvValue` preserves literal dollar replacement sequences for existing and
498
+ appended keys. Unknown-error helpers guard accessors/proxies and return safe
499
+ fallbacks instead of replacing the original error during extraction.
500
+
471
501
  ## Gotchas
472
502
  - `merge()` concatenates arrays instead of replacing them -- this differs from spread/Object.assign behavior
473
503
  - `mergeDefaults()`/`defu()` gives precedence to the FIRST argument (the object), not the defaults
@@ -480,4 +510,7 @@ assuming every object with similar printable fields is equal.
480
510
  - `detectIndent` in utils (`detect.ts`) is a different, simpler implementation than the one in strings (`detect-indent.ts`)
481
511
  - `isDeepEqual` uses `getTypeName` from `@stacksjs/types` for type checking
482
512
  - Version comparison uses `Bun.semver.order()` which returns -1, 0, or 1
483
- - `cleanProject()` uses `Bun.$` shell -- destructive operation that removes lock files, node_modules, and dist
513
+ - `cleanProject()` removes lock files and generated artifacts using native filesystem
514
+ operations, including nested framework `dist` and `node_modules` directories.
515
+ Symlink entries may be unlinked as artifacts, but aliased parents and external
516
+ targets are never traversed.
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'bun:test'
2
2
  import { activityStatus } from './DashboardActivityAction'
3
- import { formatDashboardStat } from './DashboardStatsAction'
3
+ import { collectDashboardStats, formatDashboardStat } from './DashboardStatsAction'
4
4
 
5
5
  describe('legacy dashboard API projections', () => {
6
6
  it('formats persisted totals without inventing trends', () => {
@@ -24,6 +24,25 @@ describe('legacy dashboard API projections', () => {
24
24
  ).value).toBe('Unavailable')
25
25
  })
26
26
 
27
+ it('settles a count that throws before returning a promise as that card\'s failure', async () => {
28
+ // A query on a model whose feature is off throws on first touch, which is
29
+ // what took /api/dashboard/stats down with commerce off.
30
+ const { shown, results } = await collectDashboardStats([
31
+ { title: 'Users', icon: 'users', iconBg: 'primary', count: async () => 3 },
32
+ { title: 'Orders', icon: 'orders', iconBg: 'success', count: () => { throw new Error('commerce is off') } },
33
+ ])
34
+ expect(shown.map(card => card.title)).toEqual(['Users', 'Orders'])
35
+ expect(results.map(result => result.status)).toEqual(['fulfilled', 'rejected'])
36
+ })
37
+
38
+ it('leaves out a card whose model is not available', async () => {
39
+ const { shown } = await collectDashboardStats([
40
+ { title: 'Users', icon: 'users', iconBg: 'primary', count: async () => 3 },
41
+ { title: 'Customers', icon: 'customers', iconBg: 'warning', count: async () => 1, available: () => false },
42
+ ])
43
+ expect(shown.map(card => card.title)).toEqual(['Users'])
44
+ })
45
+
27
46
  it('derives activity severity from persisted event types', () => {
28
47
  expect(activityStatus('order.completed')).toBe('success')
29
48
  expect(activityStatus('login.failed')).toBe('warning')
@@ -7,6 +7,29 @@ interface DashboardStatDefinition {
7
7
  icon: string
8
8
  iconBg: string
9
9
  count: () => Promise<number>
10
+ /** False when the model's feature is off, so the card is left out. */
11
+ available?: () => boolean
12
+ }
13
+
14
+ /** A model whose feature is off answers `getDefinition` with nothing. */
15
+ function loaded(model: unknown): boolean {
16
+ return Boolean((model as { getDefinition?: () => unknown } | undefined)?.getDefinition?.())
17
+ }
18
+
19
+ /**
20
+ * Settle every available card's count, each on its own.
21
+ *
22
+ * A count runs inside a promise, so one that throws before it returns one -
23
+ * a query on a model whose feature is off throws the moment it is touched -
24
+ * becomes that card's failure, not the request's. It used to be called
25
+ * straight from a map, so with commerce off (the default since #2488) the
26
+ * first Order card threw out of the action and the whole endpoint answered
27
+ * 500.
28
+ */
29
+ export async function collectDashboardStats(definitions: DashboardStatDefinition[]) {
30
+ const shown = definitions.filter(definition => definition.available?.() ?? true)
31
+ const results = await Promise.allSettled(shown.map(definition => Promise.resolve().then(definition.count)))
32
+ return { shown, results }
10
33
  }
11
34
 
12
35
  export function formatDashboardStat(
@@ -39,24 +62,27 @@ export default new Action({
39
62
  icon: 'i-hugeicons-shopping-cart-02',
40
63
  iconBg: 'success',
41
64
  count: () => Order.where('status', '!=', 'cancelled').count(),
65
+ available: () => loaded(Order),
42
66
  },
43
67
  {
44
68
  title: 'Blog Posts',
45
69
  icon: 'i-hugeicons-document-validation',
46
70
  iconBg: 'info',
47
71
  count: () => Post.count(),
72
+ available: () => loaded(Post),
48
73
  },
49
74
  {
50
75
  title: 'Customers',
51
76
  icon: 'i-hugeicons-user-multiple',
52
77
  iconBg: 'warning',
53
78
  count: () => Customer.count(),
79
+ available: () => loaded(Customer),
54
80
  },
55
81
  ]
56
82
 
57
- const results = await Promise.allSettled(definitions.map(definition => definition.count()))
58
- const stats = definitions.map((definition, index) => {
59
- const { count: _count, ...metadata } = definition
83
+ const { shown, results } = await collectDashboardStats(definitions)
84
+ const stats = shown.map((definition, index) => {
85
+ const { count: _count, available: _available, ...metadata } = definition
60
86
  // allSettled returns one result per input, but indexed access is typed
61
87
  // as possibly missing; a rejected placeholder keeps the shape honest.
62
88
  const result = results[index] ?? { status: 'rejected' as const, reason: new Error('missing result') }
@@ -64,11 +90,11 @@ export default new Action({
64
90
  })
65
91
  const issues = results.flatMap((result, index) => result.status === 'rejected'
66
92
  ? [{
67
- source: definitions[index]?.title ?? 'Unknown',
93
+ source: shown[index]?.title ?? 'Unknown',
68
94
  message: dashboardOperationalIssue(
69
95
  result.reason,
70
- `${definitions[index]?.title ?? 'Dashboard'} data could not be loaded.`,
71
- `DashboardStatsAction.${(definitions[index]?.title ?? 'unknown').toLowerCase().replaceAll(' ', '-')}`,
96
+ `${shown[index]?.title ?? 'Dashboard'} data could not be loaded.`,
97
+ `DashboardStatsAction.${(shown[index]?.title ?? 'unknown').toLowerCase().replaceAll(' ', '-')}`,
72
98
  ),
73
99
  }]
74
100
  : [])
@@ -118,6 +118,22 @@ function typeForColumn(column: string, values: unknown[]): ColumnMeta['type'] {
118
118
  return inferType(values)
119
119
  }
120
120
 
121
+ /**
122
+ * The columns a global search matches with LIKE: the ones the page is told
123
+ * are text, by the same rule.
124
+ *
125
+ * It used to take every column whose sampled value was a string. PostgreSQL
126
+ * answers BIGINT as a string, so `id` and every `*_id` qualified, and the
127
+ * search failed with `operator does not exist: bigint ~~ unknown` on any
128
+ * table with a row in it: `/models/team?q=PrimeSoft` answered 503.
129
+ */
130
+ export function searchColumnsFor(columns: Iterable<string>, sample: unknown): string[] {
131
+ return [...columns].filter((column) => {
132
+ const value = safeGet(sample, column, null)
133
+ return typeof value === 'string' && typeForColumn(column, [value]) === 'text'
134
+ })
135
+ }
136
+
121
137
  function queryValue(request: RequestInstance, key: string, fallback = ''): string {
122
138
  const value = request.get<unknown>(key, fallback)
123
139
  if (Array.isArray(value))
@@ -244,7 +260,7 @@ export default new Action({
244
260
  ? requestedSort
245
261
  : (allowed.has('id') ? 'id' : (response.columns[0] ?? ''))
246
262
  response.sort = sort
247
- const searchColumns = [...allowed].filter(c => typeof safeGet(first, c, null) === 'string')
263
+ const searchColumns = searchColumnsFor(allowed, first)
248
264
 
249
265
  const build = () => {
250
266
  let chain = Model.query() as any
@@ -71,8 +71,10 @@ fi
71
71
  PIPE_DIR="$(mktemp -d "\${TMPDIR:-/tmp}/stacks-install.XXXXXX")" || exit 1
72
72
  PIPE="$PIPE_DIR/setup.pipe"
73
73
  SETUP_PID=""
74
+ LOGGER_PID=""
74
75
  cleanup() {
75
- if [ -n "$SETUP_PID" ]; then kill -TERM -- "-$SETUP_PID" 2>/dev/null; fi
76
+ if [ -n "$SETUP_PID" ]; then kill -TERM -- "-$SETUP_PID" 2>/dev/null; wait "$SETUP_PID" 2>/dev/null; fi
77
+ if [ -n "$LOGGER_PID" ]; then kill -TERM -- "-$LOGGER_PID" 2>/dev/null; wait "$LOGGER_PID" 2>/dev/null; fi
76
78
  rm -rf "$PIPE_DIR"
77
79
  }
78
80
  trap cleanup EXIT
@@ -85,17 +87,22 @@ mkfifo "$PIPE" || exit 1
85
87
  # process group (job control) so an interrupted run can stop all of it, and
86
88
  # pipefail keeps the setup's own exit status rather than tee's.
87
89
  set -m
90
+ # Keep the reader in its own group too. Bash defers a trap while waiting for a
91
+ # foreground timestamp command; waiting for background jobs is interruptible.
92
+ ( while IFS= read -r line; do echo "$(date '+[%Y-%m-%d %H:%M:%S]') $line"; done < "$PIPE" >> "$LOG_PATH" ) &
93
+ LOGGER_PID=$!
88
94
  ( set -o pipefail; bun "$CLI_PATH" setup | tee "$PIPE" ) &
89
95
  SETUP_PID=$!
90
96
  set +m
91
97
 
92
- # Read from the pipe, add timestamps, and append to the file
93
- while IFS= read -r line; do echo "$(date '+[%Y-%m-%d %H:%M:%S]') $line"; done < "$PIPE" >> "$LOG_PATH"
94
-
95
98
  # Report the setup's exit status, not the cleanup's
96
99
  wait "$SETUP_PID"
97
100
  STATUS=$?
98
101
  SETUP_PID=""
102
+ wait "$LOGGER_PID"
103
+ LOGGER_STATUS=$?
104
+ LOGGER_PID=""
105
+ if [ "$STATUS" -eq 0 ]; then STATUS=$LOGGER_STATUS; fi
99
106
  exit "$STATUS"
100
107
  `
101
108
 
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.451",
5
+ "version": "0.75.457",
6
6
  "description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.451",
5
+ "version": "0.75.457",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -45,7 +45,7 @@
45
45
  "dependencies": {
46
46
  "@iconify-json/f7": "^1.2.2",
47
47
  "@iconify-json/hugeicons": "^1.2.35",
48
- "@stacksjs/mobile": "0.75.451",
48
+ "@stacksjs/mobile": "0.75.457",
49
49
  "@stacksjs/sanitizer": "0.2.794",
50
50
  "@stacksjs/stx": "0.2.794",
51
51
  "@xterm/addon-fit": "^0.11.0",