davaux 0.8.0 → 0.8.1

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.
Files changed (90) hide show
  1. package/package.json +6 -2
  2. package/BASELINE.md +0 -169
  3. package/CLAUDE.md +0 -518
  4. package/ROADMAP.md +0 -198
  5. package/build.mjs +0 -101
  6. package/client/control.ts +0 -247
  7. package/client/hydrate.ts +0 -37
  8. package/client/index.ts +0 -19
  9. package/client/jsx-runtime.ts +0 -209
  10. package/client/resource.ts +0 -122
  11. package/client/signal.ts +0 -211
  12. package/client/store.ts +0 -110
  13. package/client/useHead.ts +0 -63
  14. package/pka.config.json +0 -32
  15. package/src/build/config.ts +0 -42
  16. package/src/build/index.ts +0 -6
  17. package/src/build/plugins.ts +0 -118
  18. package/src/cli.ts +0 -502
  19. package/src/config.ts +0 -197
  20. package/src/create-multisite.ts +0 -310
  21. package/src/create.ts +0 -194
  22. package/src/dev/blueprints.ts +0 -75
  23. package/src/dev/components.ts +0 -108
  24. package/src/dev/insert.ts +0 -221
  25. package/src/dev/remove.ts +0 -677
  26. package/src/dev/watch.ts +0 -3098
  27. package/src/errors.ts +0 -64
  28. package/src/generate.ts +0 -228
  29. package/src/index.ts +0 -67
  30. package/src/island.ts +0 -47
  31. package/src/jsx-runtime.d.ts +0 -408
  32. package/src/jsx-runtime.d.ts.map +0 -1
  33. package/src/jsx-runtime.ts +0 -536
  34. package/src/link.ts +0 -49
  35. package/src/oml/fragment.ts +0 -54
  36. package/src/oml/index.ts +0 -21
  37. package/src/oml/jsx-runtime.ts +0 -121
  38. package/src/oml/jsx.ts +0 -151
  39. package/src/oml/page.ts +0 -13
  40. package/src/oml/render.ts +0 -181
  41. package/src/oml/types.ts +0 -159
  42. package/src/router/handler.ts +0 -515
  43. package/src/router/matcher.ts +0 -52
  44. package/src/router/scanner.ts +0 -272
  45. package/src/server/index.ts +0 -49
  46. package/src/signal.ts +0 -39
  47. package/src/ssg.ts +0 -253
  48. package/src/test/actions.test.ts +0 -40
  49. package/src/test/body-limits.test.ts +0 -83
  50. package/src/test/errors.test.ts +0 -53
  51. package/src/test/fixtures/routes/[id].page.ts +0 -3
  52. package/src/test/fixtures/routes/_error.ts +0 -6
  53. package/src/test/fixtures/routes/_global.ts +0 -8
  54. package/src/test/fixtures/routes/_layout-template.ts +0 -7
  55. package/src/test/fixtures/routes/_layout.ts +0 -7
  56. package/src/test/fixtures/routes/_layout_scripts.ts +0 -8
  57. package/src/test/fixtures/routes/_middleware.ts +0 -8
  58. package/src/test/fixtures/routes/_redirect301_mw.ts +0 -5
  59. package/src/test/fixtures/routes/_redirect_mw.ts +0 -5
  60. package/src/test/fixtures/routes/about.page.ts +0 -6
  61. package/src/test/fixtures/routes/action.page.ts +0 -11
  62. package/src/test/fixtures/routes/api/form-all.post.ts +0 -5
  63. package/src/test/fixtures/routes/api/form-limited.post.ts +0 -6
  64. package/src/test/fixtures/routes/api/response-obj.get.ts +0 -17
  65. package/src/test/fixtures/routes/api/upload.post.ts +0 -14
  66. package/src/test/fixtures/routes/api/users.get.ts +0 -3
  67. package/src/test/fixtures/routes/api/xml.get.ts +0 -5
  68. package/src/test/fixtures/routes/auth/_middleware.ts +0 -11
  69. package/src/test/fixtures/routes/auth/protected.page.ts +0 -3
  70. package/src/test/fixtures/routes/index.page.ts +0 -3
  71. package/src/test/fixtures/routes/oml.page.ts +0 -7
  72. package/src/test/fixtures/routes/redirect.page.ts +0 -3
  73. package/src/test/fixtures/routes/ssg/[slug].page.ts +0 -8
  74. package/src/test/fixtures/routes/ssg/server.page.ts +0 -5
  75. package/src/test/fixtures/routes/state.page.ts +0 -4
  76. package/src/test/fixtures/routes/throw.page.ts +0 -5
  77. package/src/test/fixtures/routes/wiki/[...slug].page.ts +0 -3
  78. package/src/test/helpers.ts +0 -132
  79. package/src/test/layouts.test.ts +0 -76
  80. package/src/test/middleware.test.ts +0 -69
  81. package/src/test/multipart.test.ts +0 -91
  82. package/src/test/oml-routing.test.ts +0 -59
  83. package/src/test/oml.test.ts +0 -429
  84. package/src/test/redirects.test.ts +0 -32
  85. package/src/test/routing.test.ts +0 -118
  86. package/src/test/ssg.test.ts +0 -273
  87. package/src/test/web-response.test.ts +0 -33
  88. package/src/types.ts +0 -670
  89. package/tsconfig.client.json +0 -17
  90. package/tsconfig.json +0 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davaux",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "SSR-first JSX framework with file-based routing and signals",
5
5
  "type": "module",
6
6
  "author": "David L Dyess II",
@@ -13,6 +13,10 @@
13
13
  "url": "https://codeberg.org/davaux/davaux/issues"
14
14
  },
15
15
  "homepage": "https://codeberg.org/davaux/davaux#readme",
16
+ "files": [
17
+ "dist",
18
+ "src/env.d.ts"
19
+ ],
16
20
  "exports": {
17
21
  ".": {
18
22
  "import": "./dist/index.js",
@@ -100,4 +104,4 @@
100
104
  "tsx": "^4.19.2",
101
105
  "typescript": "^6.0.3"
102
106
  }
103
- }
107
+ }
package/BASELINE.md DELETED
@@ -1,169 +0,0 @@
1
- # Davaux — Security Review
2
-
3
- Findings from a full audit of the framework and all `@davaux/*` packages. Grouped by severity. Each entry tracks the file, the issue, the fix, and current status.
4
-
5
- ---
6
-
7
- ## High
8
-
9
- ### H1 — Rate Limiter: Unconditional Trust of `X-Forwarded-For` ✅ fixed
10
-
11
- **File:** `packages/rate-limit/src/index.ts`
12
-
13
- The default key function reads `X-Forwarded-For` without any trust model. Any client can set this header to an arbitrary value — including `127.0.0.1` or a legitimate user's IP — bypassing rate limiting entirely.
14
-
15
- **Fix:** Default to `req.socket.remoteAddress`. Add a `trustProxy?: boolean | number` option that, when enabled, extracts the correct leftmost-untrusted IP from the `X-Forwarded-For` chain. Document that `trustProxy` should only be enabled when the app runs behind a trusted reverse proxy.
16
-
17
- ---
18
-
19
- ### H2 — CSRF: `multipart/form-data` Token Not Read from Form Fields ✅ fixed
20
-
21
- **File:** `packages/csrf/src/index.ts`
22
-
23
- `resolveSubmitted()` only reads the CSRF token from `application/x-www-form-urlencoded` body fields. For `multipart/form-data` requests, it falls back to the `X-CSRF-Token` header only — which browsers cannot set on a standard form submit. A developer building a file-upload form who embeds the token as a hidden field will find it silently not enforced, and may remove the middleware believing it is broken.
24
-
25
- **Fix:** Add a `multipart/form-data` branch in `resolveSubmitted()` that calls `ctx.multipart()` and reads `fields[field]`.
26
-
27
- ---
28
-
29
- ## Medium
30
-
31
- ### M1 — Island Serialization: `<` and `>` Not Escaped in `data-props` ✅ fixed
32
-
33
- **File:** `packages/davaux/src/island.ts`
34
-
35
- ```ts
36
- const serialized = JSON.stringify(props).replace(/'/g, '&#39;')
37
- return `<div data-island="${id}" data-props='${serialized}'>${rendered}</div>`
38
- ```
39
-
40
- `JSON.stringify` does not escape `<`, `>`, or `&`. A prop value containing `</div>` produces unescaped angle brackets inside the HTML attribute. Single-quote breakout is prevented, but the unescaped characters break HTML parsers and become exploitable if the context ever changes (e.g., inside a `<script>` or `<template>` element).
41
-
42
- **Fix:** Use Unicode escapes to keep the JSON parseable while making it safe in any HTML context:
43
-
44
- ```ts
45
- const serialized = JSON.stringify(props)
46
- .replace(/&/g, '\\u0026')
47
- .replace(/</g, '\\u003c')
48
- .replace(/>/g, '\\u003e')
49
- .replace(/'/g, '\\u0027')
50
- ```
51
-
52
- ---
53
-
54
- ### M2 — Swagger CDN Assets Served Without Subresource Integrity ✅ fixed
55
-
56
- **File:** `packages/swagger/src/index.ts`
57
-
58
- The Swagger UI CSS and JS bundle are loaded from `cdn.jsdelivr.net/npm/swagger-ui-dist@5` with no `integrity` or `crossorigin` attributes. A CDN compromise or supply-chain attack on the `swagger-ui-dist` package would serve malicious JavaScript to anyone visiting `/docs`. The `@5` semver range means any `5.x` release is automatically served.
59
-
60
- **Fix:** Pin to a specific version and add SRI `integrity` hashes. Regenerate hashes on upgrade.
61
-
62
- ---
63
-
64
- ### M3 — Session: No Minimum Secret Length Enforcement ✅ fixed
65
-
66
- **File:** `packages/session/src/index.ts`
67
-
68
- Only empty strings are rejected. A single-character secret like `"x"` passes through silently. Short secrets dramatically reduce the brute-force search space for forging signed session cookies.
69
-
70
- **Fix:** Emit a `console.warn` when any secret is shorter than 32 characters. A throw is acceptable during development (`NODE_ENV !== 'production'`).
71
-
72
- ---
73
-
74
- ### M4 — Static File Serving: No Explicit Path Traversal Guard in `runStart` and Dev Server ✅ fixed
75
-
76
- **Files:** `packages/davaux/src/cli.ts` (`runStart`), `packages/davaux/src/dev/watch.ts` (`serveStatic`)
77
-
78
- Both rely solely on `new URL(req.url, 'http://x').pathname` to normalize request paths before `join(dir, pathname)`. This is correct in current Node.js, but is a single point of failure — no belt-and-suspenders check exists. `runPreview` already has the correct explicit guard:
79
-
80
- ```ts
81
- if (!safePath.startsWith(`${outDir}/`) && safePath !== outDir) {
82
- res.writeHead(403, ...); return
83
- }
84
- ```
85
-
86
- **Fix:** Apply the same `startsWith` guard to the public-directory handler in `runStart` and to `serveStatic` in `watch.ts`.
87
-
88
- ---
89
-
90
- ## Low
91
-
92
- ### L1 — Swagger: HTML `<title>` Inserted Without Escaping ✅ fixed
93
-
94
- **File:** `packages/swagger/src/index.ts`
95
-
96
- `options.info?.title` is inserted directly into `<title>${title}</title>` with no HTML escaping. If the title originates from a database or environment variable, a value like `</title><script>alert(1)</script>` produces reflected XSS on the `/docs` page.
97
-
98
- **Fix:** HTML-escape the title before insertion. `specPath` is already handled correctly via `JSON.stringify`.
99
-
100
- ---
101
-
102
- ### L2 — `CookieJar`: `path` and `domain` Options Not Sanitized ✅ fixed
103
-
104
- **File:** `packages/davaux/src/types.ts`
105
-
106
- `name` and `value` are correctly URI-encoded, but `path` and `domain` are inserted into the `Set-Cookie` header without sanitization. Node.js rejects CRLF characters (blocking header splitting), but a semicolon in `path` or `domain` injects additional cookie attributes:
107
-
108
- ```ts
109
- ctx.cookies.set('session', value, { path: '/; SameSite=None' })
110
- // → Set-Cookie: session=value; Path=/; SameSite=None
111
- ```
112
-
113
- Values come from developer configuration rather than user input directly, but the API makes it easy to pass user-controlled values through accidentally.
114
-
115
- **Fix:** Strip semicolons, carriage returns, and newlines from `path` and `domain` before constructing the header value.
116
-
117
- ---
118
-
119
- ## Informational
120
-
121
- ### I1 — CORS: No Error on `credentials: true` + `origin: '*'` ✅ fixed
122
-
123
- **File:** `packages/cors/src/index.ts`
124
-
125
- Browsers reject credentialed responses with a wildcard origin by spec, so no credentials actually leak. However, the middleware silently accepts this misconfiguration rather than throwing, leading to hard-to-debug CORS failures.
126
-
127
- **Fix:** Throw at middleware creation time:
128
- ```ts
129
- if (options.credentials && options.origin === '*') {
130
- throw new Error('@davaux/cors: credentials:true requires a specific origin, not "*"')
131
- }
132
- ```
133
-
134
- ---
135
-
136
- ### I2 — Body Cache: First-Read `maxBytes` Applies to All Subsequent Reads ℹ️ by design
137
-
138
- **File:** `packages/davaux/src/types.ts`
139
-
140
- The body is read and cached on the first call to `ctx.form()`, `ctx.json()`, or `ctx.multipart()`. The `maxBytes` limit from the first call is the effective limit for all subsequent calls, regardless of what later callers specify. A middleware reading the body at the global default could allow more data than a per-route limit intended — or less.
141
-
142
- This is a documented tradeoff (the body stream can only be read once), not a bug. Worth noting in the API docs.
143
-
144
- ---
145
-
146
- ### I3 — `redirect()`: No Guard Against Open Redirects ℹ️ doc needed
147
-
148
- **File:** `packages/davaux/src/types.ts`
149
-
150
- `redirect(url)` passes the URL directly to the `Location` header with no validation. If a developer passes unvalidated user input (e.g., `redirect(ctx.query.get('next'))`), this is an open redirect. The framework cannot prevent this without breaking legitimate uses.
151
-
152
- **Fix:** Add a JSDoc warning that user-supplied URLs must be validated before passing to `redirect()`.
153
-
154
- ---
155
-
156
- ## What Was Reviewed and Found Correct
157
-
158
- - **JSX runtime `escapeHtml`** — escapes `&`, `<`, `>`, `"`, `'`. Applied to all string children and attribute values. `dangerouslySetInnerHTML` correctly bypasses escaping as intended.
159
- - **Session HMAC signing** — `createHmac('sha256')`, `timingSafeEqual` for verification, `base64url` encoding, `lastIndexOf('.')` split. Correct and complete.
160
- - **CSRF token generation** — `randomBytes(32).toString('hex')`, 256 bits of entropy.
161
- - **CSRF timing-safe comparison** — `timingSafeEqual` used after length check.
162
- - **Session cookie flags** — `httpOnly: true`, `sameSite: 'Lax'` by default.
163
- - **Path traversal in `runPreview`** — explicit `startsWith` guard present and correct.
164
- - **URL normalization** — `new URL(req.url, 'http://x').pathname` correctly resolves `..` sequences. `/%2e%2e/` is resolved before `join`.
165
- - **CORS origin reflection** — no unintended origin reflection when origin is not in allowlist.
166
- - **SSE injection** — `JSON.stringify` escapes newlines, preventing event injection via error payloads.
167
- - **Scanner dynamic imports** — no user input flows into import targets.
168
- - **Prototype pollution** — `Object.assign(ctx.params, result.params)` assigns string values only; `JSON.parse` does not pollute `Object.prototype` in this usage.
169
- - **Multipart parser** — boundary used as a literal buffer, not a regex. Body size limit enforced before parsing.