@stacksjs/defaults 0.70.365 → 0.70.366
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/skills/stacks-dashboard/SKILL.md +23 -14
- package/app/Actions/Auth/LoginAction.ts +11 -2
- package/app/Actions/Auth/RefreshTokenAction.ts +6 -2
- package/app/Actions/Auth/RegisterAction.ts +6 -2
- package/app/Actions/Auth/VerifyTwoFactorLoginAction.ts +6 -2
- package/ide/vscode/package.json +1 -1
- package/package.json +1 -1
- package/resources/components/Dashboard/Auth/ForgotPasswordDashboard.stx +0 -2
- package/resources/components/Dashboard/Auth/LoginDashboard.stx +1 -1
- package/resources/components/Dashboard/Auth/RegisterDashboard.stx +1 -3
- package/resources/components/Dashboard/Kanban/KanbanBoardDashboard.stx +9 -435
- package/resources/components/Dashboard/Kanban/KanbanCardDialog.stx +416 -0
- package/resources/components/Dashboard/Modals/BaseModal.stx +13 -36
- package/resources/components/Dashboard/Modals/Popups/Alert.stx +18 -44
- package/resources/components/Dashboard/UI/Modal.stx +11 -7
- package/resources/components/Dashboard/UI/Table.stx +30 -25
- package/views/dashboard/AUDIT.md +21 -16
|
@@ -354,20 +354,19 @@ drawers must use the shared `dashboard-modal-layer` class so their interactive
|
|
|
354
354
|
surface starts beside that sidebar and returns to `left: 0` on mobile and in
|
|
355
355
|
the Craft native-sidebar shell.
|
|
356
356
|
|
|
357
|
-
Use
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
sidebar-aware root.
|
|
357
|
+
Use `Dashboard/UI/Modal`, `Dashboard/UI/Drawer`, and
|
|
358
|
+
`Dashboard/UI/ConfirmDialog` for page dialogs, inspectors, forms, and
|
|
359
|
+
confirmations. They own native `<dialog>` behavior, scroll locking, focus
|
|
360
|
+
restoration, Escape and backdrop handling, accessibility labels, and the
|
|
361
|
+
sidebar-aware boundary. `Dashboard/Modals/BaseModal` and
|
|
362
|
+
`Dashboard/Modals/Popups/Alert` are compatibility wrappers over that same
|
|
363
|
+
primitive, not alternate overlay implementations.
|
|
364
|
+
|
|
365
|
+
Do not add a page-owned `fixed inset-0` overlay. A purpose-built application
|
|
366
|
+
surface such as the global command palette or mobile navigation may own a
|
|
367
|
+
custom layer only when the shared dialog or drawer semantics do not fit. It
|
|
368
|
+
must still use `dashboard-modal-layer` and provide complete keyboard, focus,
|
|
369
|
+
and ARIA behavior. Do not solve sidebar overlap by increasing z-index alone.
|
|
371
370
|
|
|
372
371
|
### Live dashboard audit
|
|
373
372
|
|
|
@@ -378,6 +377,9 @@ the project root:
|
|
|
378
377
|
bun storage/framework/defaults/ai/skills/stacks-dashboard/scripts/audit.ts
|
|
379
378
|
# Or target a non-default origin:
|
|
380
379
|
bun storage/framework/defaults/ai/skills/stacks-dashboard/scripts/audit.ts --base-url http://127.0.0.1:3002
|
|
380
|
+
|
|
381
|
+
# Exercise hydrated navigation, console errors, failed requests, and layout:
|
|
382
|
+
bun storage/framework/defaults/ai/skills/stacks-browse/scripts/browse.ts crawl http://localhost:3002/ --max 500 --settle 350 --summary
|
|
381
383
|
```
|
|
382
384
|
|
|
383
385
|
Pass a base URL as the first argument when the dashboard is not on
|
|
@@ -388,6 +390,13 @@ dashboard API. It fails on missing page renders, invalid fragment contracts,
|
|
|
388
390
|
empty or non-HTML pages, unresolved component tags, 5xx or method-mismatch
|
|
389
391
|
APIs, HTML API fallbacks, invalid JSON, and HTTP-200 error payloads.
|
|
390
392
|
|
|
393
|
+
The dependency-free browser crawl follows the rendered link graph in a real
|
|
394
|
+
browser and fails on non-200 pages, console errors, failed subrequests, or
|
|
395
|
+
horizontal overflow. Seed source-only routes with repeated `--path` flags,
|
|
396
|
+
including optional or parameterized pages that the current data set does not
|
|
397
|
+
link. The HTTP audit and browser crawl cover different boundaries, so run both
|
|
398
|
+
for exhaustive dashboard work.
|
|
399
|
+
|
|
391
400
|
Run this after dashboard route, Action, STX, model, migration, or dev-server
|
|
392
401
|
changes. Record provider-backed or destructive success paths as explicit
|
|
393
402
|
environment boundaries. Never replace a failed live contract with sample data
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
|
-
import { Auth, createTwoFactorChallenge, getTwoFactorState } from '@stacksjs/auth'
|
|
2
|
+
import { Auth, authCookie, createTwoFactorChallenge, getTwoFactorState } from '@stacksjs/auth'
|
|
3
3
|
import { User } from '@stacksjs/orm'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
5
|
import { schema } from '@stacksjs/validation'
|
|
@@ -66,6 +66,15 @@ export default new Action({
|
|
|
66
66
|
// The legacy `token` field is kept for backward compatibility
|
|
67
67
|
// with clients that haven't been updated yet — it shadows
|
|
68
68
|
// `access_token` and will be removed in a future major.
|
|
69
|
+
//
|
|
70
|
+
// The same token also goes out as an httpOnly cookie, matching
|
|
71
|
+
// SocialCallbackAction. Without it, how a browser ends up signed in
|
|
72
|
+
// depended on which way it signed in: OAuth left a cookie, email+password
|
|
73
|
+
// left only JSON, and a server-rendered page cannot read JSON — it posts a
|
|
74
|
+
// form, follows a redirect, and comes back carrying nothing but cookies.
|
|
75
|
+
// So the first authenticated document render had no way to identify the
|
|
76
|
+
// user (#2306). The body is unchanged, so an API client that ignores the
|
|
77
|
+
// cookie behaves exactly as before.
|
|
69
78
|
return response.json({
|
|
70
79
|
access_token: result.token,
|
|
71
80
|
refresh_token: result.refreshToken,
|
|
@@ -77,6 +86,6 @@ export default new Action({
|
|
|
77
86
|
email: user?.email,
|
|
78
87
|
name: user?.name,
|
|
79
88
|
},
|
|
80
|
-
})
|
|
89
|
+
}, { headers: { 'Set-Cookie': authCookie(result.token) } })
|
|
81
90
|
},
|
|
82
91
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
|
-
import { refreshToken } from '@stacksjs/auth'
|
|
2
|
+
import { authCookie, refreshToken } from '@stacksjs/auth'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
4
|
import { schema } from '@stacksjs/validation'
|
|
5
5
|
|
|
@@ -25,12 +25,16 @@ export default new Action({
|
|
|
25
25
|
refreshExpiresInDays: 30, // 30 day refresh token
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
+
// Rotation invalidates the token the cookie was carrying, so a cookie
|
|
29
|
+
// left untouched here would go stale at the exact moment the session was
|
|
30
|
+
// meant to be extended: the browser keeps presenting a revoked token
|
|
31
|
+
// while the JSON body holds a live one it cannot read (#2306).
|
|
28
32
|
return response.json({
|
|
29
33
|
access_token: result.plainTextToken,
|
|
30
34
|
refresh_token: result.refreshToken,
|
|
31
35
|
token_type: 'Bearer',
|
|
32
36
|
expires_in: result.expiresIn,
|
|
33
|
-
})
|
|
37
|
+
}, { headers: { 'Set-Cookie': authCookie(result.plainTextToken) } })
|
|
34
38
|
}
|
|
35
39
|
catch (error: any) {
|
|
36
40
|
return response.unauthorized(error.message || 'Invalid or expired refresh token')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
|
-
import { Auth, register } from '@stacksjs/auth'
|
|
2
|
+
import { Auth, authCookie, register } from '@stacksjs/auth'
|
|
3
3
|
import { dispatch } from '@stacksjs/events'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
5
|
import { schema } from '@stacksjs/validation'
|
|
@@ -53,6 +53,10 @@ export default new Action({
|
|
|
53
53
|
// were signed out an hour into their first session while every other
|
|
54
54
|
// user refreshed normally (stacksjs/stacks#2212). The legacy `token`
|
|
55
55
|
// alias stays for backward compatibility.
|
|
56
|
+
// Registering signs the account in, so it is a session-issuing path like
|
|
57
|
+
// the other three and carries the cookie for the same reason: the very
|
|
58
|
+
// next thing a server-rendered app does is redirect to an authenticated
|
|
59
|
+
// page (#2306).
|
|
56
60
|
return response.json({
|
|
57
61
|
access_token: result.token,
|
|
58
62
|
refresh_token: result.refreshToken,
|
|
@@ -64,7 +68,7 @@ export default new Action({
|
|
|
64
68
|
email: user?.email,
|
|
65
69
|
name: user?.name,
|
|
66
70
|
},
|
|
67
|
-
})
|
|
71
|
+
}, { headers: { 'Set-Cookie': authCookie(result.token) } })
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
return response.error('Registration failed')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
|
-
import { Auth, consumeTwoFactorChallenge, verifyTwoFactorLoginCode } from '@stacksjs/auth'
|
|
2
|
+
import { Auth, authCookie, consumeTwoFactorChallenge, verifyTwoFactorLoginCode } from '@stacksjs/auth'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
4
|
import { schema } from '@stacksjs/validation'
|
|
5
5
|
|
|
@@ -41,6 +41,10 @@ export default new Action({
|
|
|
41
41
|
|
|
42
42
|
const user = result.user
|
|
43
43
|
|
|
44
|
+
// This is where a 2FA account's session actually begins — LoginAction
|
|
45
|
+
// deliberately mints nothing for these users until the code is verified —
|
|
46
|
+
// so the cookie belongs here too. Setting it only on LoginAction would
|
|
47
|
+
// have left every 2FA account exactly where it started (#2306).
|
|
44
48
|
return response.json({
|
|
45
49
|
access_token: result.token,
|
|
46
50
|
refresh_token: result.refreshToken,
|
|
@@ -52,6 +56,6 @@ export default new Action({
|
|
|
52
56
|
email: user?.email,
|
|
53
57
|
name: user?.name,
|
|
54
58
|
},
|
|
55
|
-
})
|
|
59
|
+
}, { headers: { 'Set-Cookie': authCookie(result.token) } })
|
|
56
60
|
},
|
|
57
61
|
})
|
package/ide/vscode/package.json
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.366",
|
|
6
6
|
"description": "The complete managed Stacks application scaffold, including runtime defaults, AI guidance, editor metadata, and npm-backed project support files.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"license": "MIT",
|
|
@@ -27,7 +27,7 @@ async function handleLogin(credentials) {
|
|
|
27
27
|
navigate(safeRedirect())
|
|
28
28
|
}
|
|
29
29
|
catch (err) {
|
|
30
|
-
error.set(err.message
|
|
30
|
+
error.set(err instanceof Error ? err.message : 'An error occurred during login')
|
|
31
31
|
}
|
|
32
32
|
finally {
|
|
33
33
|
isLoading.set(false)
|
|
@@ -27,9 +27,7 @@ async function handleRegister(credentials) {
|
|
|
27
27
|
navigate(safeRedirect())
|
|
28
28
|
}
|
|
29
29
|
catch (err) {
|
|
30
|
-
error.set(err.message
|
|
31
|
-
// eslint-disable-next-line no-console
|
|
32
|
-
console.error(err)
|
|
30
|
+
error.set(err instanceof Error ? err.message : 'An error occurred during registration')
|
|
33
31
|
}
|
|
34
32
|
finally {
|
|
35
33
|
isLoading.set(false)
|