@luckystack/server 0.10.0 → 0.10.2

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.
@@ -38,7 +38,7 @@ A custom-route registry sits in front of the static fallback. Both the legacy `c
38
38
  | `/livez` | GET | `handleLivezRoute` | `200 { status: 'live' }` | Always 200 when reachable |
39
39
  | `/readyz` | GET | `handleReadyzRoute` | `200 { status: 'ready', checks: {...} }` | `503 { status: 'not-ready', checks: {...} }` |
40
40
  | `/_health` | GET | `handleHealthRoute` | `200 { status: 'ok', bootUuid, envKey, synchronizedHashes }` | `503 { status: 'degraded', ... }` when boot UUID is missing |
41
- | `/_test/reset` | POST | `handleTestResetRoute` | `200 { status: 'success', cleared: string[] }` | `404 notFound` or `403 auth.forbidden` — see `security-defaults.md` |
41
+ | `/_test/reset` | POST | `handleTestResetRoute` | `200 { status: 'success', cleared: string[] }` | `404 notFound`, `403 auth.forbidden`, or `400 test.invalidResetTarget` (bad `?only=`) — see `security-defaults.md` |
42
42
  | `/uploads/*` | GET | `handleUploadsRoute` | Avatar bytes via `@luckystack/core` `serveAvatar` | `404` from `serveAvatar` when missing |
43
43
  | `/auth/api/email-code/request` | POST | `handleAuthEmailCodeRoute` | `200 { status: true }` (anti-enumeration: also for unknown addresses) | `200 { status:false, reason }`, `429` per-IP |
44
44
  | `/auth/api/email-code/verify` | POST | `handleAuthEmailCodeRoute` | Login envelope + session transport, or 2FA-challenge envelope | `200 { status:false, reason }`, `429` per-IP |
@@ -54,7 +54,7 @@ A custom-route registry sits in front of the static fallback. Both the legacy `c
54
54
 
55
55
  > `GET /auth/csrf` issues the token; state-changing requests send it using `getCsrfConfig().headerName` (default `x-csrf-token`). `registerCsrfConfig(...)` also controls the login-absent cookie name/options and token length.
56
56
  >
57
- > `/_test/reset` clears rate limits and only the framework's default Redis session/active-user namespaces. It does not clear application database rows or invoke a custom `SessionAdapter`; custom-storage tests own that cleanup.
57
+ > `/_test/reset` clears rate limits and only the framework's default Redis session/active-user namespaces; `?only=<target>[,<target>]` narrows it to the listed targets (so a logged-in test sweep can drain limiter buckets without deleting its own session). It does not clear application database rows or invoke a custom `SessionAdapter`; custom-storage tests own that cleanup.
58
58
 
59
59
  ## API Reference — handlers
60
60
 
@@ -122,9 +122,11 @@ x-test-reset-token: <value of TEST_RESET_TOKEN>
122
122
 
123
123
  **What the reset clears:**
124
124
 
125
+ Without `?only=` the default below runs. With `?only=<target>[,<target>]` exactly the listed targets run and nothing else; the valid targets are core's `TEST_RESET_TARGETS` (shared with `@luckystack/test-runner`, so the two sides cannot drift). An unknown or empty target returns `400 { status: 'error', errorCode: 'test.invalidResetTarget' }` — a typo must not silently reset nothing, or everything. The selector exists because the default also deletes the session an authenticated test sweep runs on; the runner therefore always sends `only=rateLimits`.
126
+
125
127
  | Step | Action |
126
128
  | --- | --- |
127
- | 1 | `clearAllRateLimits()` — purges in-memory + Redis rate-limit counters. Always reported in `cleared`. |
129
+ | 1 | `clearAllRateLimits()` — purges in-memory + Redis rate-limit counters. Reported in `cleared` whenever it runs. |
128
130
  | 2 | `redis SCAN` + `DEL` keys matching `<projectName>-session:*`. Reported as `'sessions'` when at least one key is deleted. |
129
131
  | 3 | `redis SCAN` + `DEL` keys matching `<projectName>-activeUsers:*`. Reported as `'activeUsers'` when at least one key is deleted. |
130
132
  | 4 (opt-in) | When `?include=hooks` is supplied, `clearAllHooks()` empties every framework hook registration. Reported as `'hooks'`. |
@@ -137,7 +139,7 @@ x-test-reset-token: <value of TEST_RESET_TOKEN>
137
139
 
138
140
  **Errors / edge cases:**
139
141
 
140
- - Malformed `req.url` is detected with `URL.canParse(rawUrl, base)`. When false, `?include=hooks` is treated as absent.
142
+ - Malformed `req.url` is detected with `URL.canParse(rawUrl, base)`. When false, the query is treated as empty: no `only`, no `?include=hooks` — the default reset runs.
141
143
  - Redis `SCAN`+`DEL` errors are swallowed per pattern — the cleared array simply omits the label.
142
144
  - The hook-clear is opt-in because clearing every hook also removes framework-internal registrations (e.g. presence's `postLogout`).
143
145
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luckystack/server",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -57,20 +57,20 @@
57
57
  "test": "vitest run"
58
58
  },
59
59
  "dependencies": {
60
- "@luckystack/api": "^0.10.0",
61
- "@luckystack/core": "^0.10.0"
60
+ "@luckystack/api": "^0.10.2",
61
+ "@luckystack/core": "^0.10.2"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@prisma/client": "^6.19.0",
65
65
  "socket.io": "^4.8.0",
66
- "@luckystack/cron": "^0.10.0",
67
- "@luckystack/devkit": "^0.10.0",
68
- "@luckystack/docs-ui": "^0.10.0",
69
- "@luckystack/email": "^0.10.0",
70
- "@luckystack/error-tracking": "^0.10.0",
71
- "@luckystack/login": "^0.10.0",
72
- "@luckystack/presence": "^0.10.0",
73
- "@luckystack/sync": "^0.10.0"
66
+ "@luckystack/cron": "^0.10.2",
67
+ "@luckystack/devkit": "^0.10.2",
68
+ "@luckystack/docs-ui": "^0.10.2",
69
+ "@luckystack/email": "^0.10.2",
70
+ "@luckystack/error-tracking": "^0.10.2",
71
+ "@luckystack/login": "^0.10.2",
72
+ "@luckystack/presence": "^0.10.2",
73
+ "@luckystack/sync": "^0.10.2"
74
74
  },
75
75
  "peerDependenciesMeta": {
76
76
  "@prisma/client": {