kmcom-nuxt-layers 2.6.3 → 2.7.0

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 (114) hide show
  1. package/docs/ARCHITECTURE.md +21 -17
  2. package/docs/FEEDS.md +42 -34
  3. package/docs/IMPROVE-AUDIT-README.md +9 -10
  4. package/docs/IMPROVE-AUDIT-RESULTS.md +16 -17
  5. package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +29 -29
  6. package/docs/LAYERS-FIXES.md +1 -0
  7. package/docs/LAYOUT.md +91 -86
  8. package/docs/MIGRATION.md +93 -60
  9. package/docs/UPAGE-GRID-INTEGRATION.md +12 -10
  10. package/docs/USAGE.md +29 -38
  11. package/layers/animations/app/utils/pointerMotion.ts +1 -4
  12. package/layers/baseline/app/components/BaselineStatus.vue +13 -13
  13. package/layers/baseline/app/plugins/baseline-status.client.ts +4 -1
  14. package/layers/canvas/app/composables/useRendererCapabilities.ts +2 -2
  15. package/layers/content/app/components/Blog/Card.vue +1 -0
  16. package/layers/content/app/components/Gallery/Card.vue +1 -1
  17. package/layers/content/app/components/Gallery/Detail.vue +8 -1
  18. package/layers/content/app/components/Portfolio/Card.vue +1 -0
  19. package/layers/content/app/components/Portfolio/ColorPalette.vue +8 -1
  20. package/layers/content/app/components/Portfolio/Typography.vue +12 -2
  21. package/layers/content/app/composables/useGalleryItems.ts +3 -2
  22. package/layers/content/app/composables/usePortfolioItems.ts +3 -2
  23. package/layers/core/app/components/DiagnosticsPage.vue +15 -3
  24. package/layers/core/app/utils/featureClasses.test.ts +1 -3
  25. package/layers/core/app/utils/featureClasses.ts +1 -3
  26. package/layers/core/app/utils/helpers.test.ts +6 -2
  27. package/layers/core/nuxt.config.ts +2 -0
  28. package/layers/feeds/app/assets/css/feeds.css +3 -2
  29. package/layers/feeds/app/components/Feeds/Index.vue +36 -6
  30. package/layers/feeds/app/components/Feeds/RouteCard.vue +1 -3
  31. package/layers/feeds/app/plugins/feed-head.ts +2 -2
  32. package/layers/feeds/package.json +1 -1
  33. package/layers/feeds/public/feed/style.css +9 -9
  34. package/layers/feeds/server/utils/content-adapter.test.ts +3 -4
  35. package/layers/feeds/server/utils/content-adapter.ts +1 -1
  36. package/layers/feeds/server/utils/feed-author.test.ts +3 -3
  37. package/layers/feeds/server/utils/feed-config.test.ts +28 -6
  38. package/layers/feeds/server/utils/feed-config.ts +1 -4
  39. package/layers/feeds/server/utils/feed-service.ts +1 -1
  40. package/layers/feeds/server/utils/formats/rss.ts +1 -1
  41. package/layers/feeds/server/utils/formats.test.ts +1 -1
  42. package/layers/forms/app/utils/fieldProps.ts +1 -2
  43. package/layers/forms/server/api/contact.post.ts +4 -1
  44. package/layers/layout/app/assets/css/layout/grids.css +12 -3
  45. package/layers/layout/app/assets/css/layout/modes/fluid.css +9 -0
  46. package/layers/layout/app/components/Layout/Section/Sidebar.vue +11 -4
  47. package/layers/layout/app/utils/gridPlacementStyle.test.ts +3 -9
  48. package/layers/layout/app/utils/gridPlacementStyle.ts +10 -7
  49. package/layers/mailer/server/utils/email.ts +4 -3
  50. package/layers/mailer/server/utils/hooks.ts +1 -1
  51. package/layers/metadata/app/composables/useMetadataItem.ts +6 -2
  52. package/layers/metadata/app/composables/useMetadataSearch.ts +6 -2
  53. package/layers/metadata/providers/comicvine/server/utils/metadata-comicvine/client.ts +5 -5
  54. package/layers/metadata/providers/comicvine/server/utils/metadata-comicvine/provider.ts +11 -3
  55. package/layers/metadata/providers/google-books/server/utils/metadata-google-books/client.ts +9 -6
  56. package/layers/metadata/providers/google-books/server/utils/metadata-google-books/provider.ts +6 -3
  57. package/layers/metadata/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +3 -1
  58. package/layers/metadata/providers/openlibrary/server/utils/metadata-openlibrary/provider.ts +4 -2
  59. package/layers/metadata/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +1 -3
  60. package/layers/metadata/providers/themoviedb/server/utils/metadata-tmdb/provider.ts +3 -1
  61. package/layers/metadata/server/api/metadata/status.get.ts +13 -18
  62. package/layers/metadata/server/utils/metadata/provider-registry.test.ts +1 -1
  63. package/layers/metadata/server/utils/metadata/search.test.ts +18 -18
  64. package/layers/metadata/server/utils/metadata/search.ts +16 -8
  65. package/layers/navigation/app/utils/site.test.ts +1 -3
  66. package/layers/scroll/app/components/Motion/PinnedSection.vue +11 -1
  67. package/layers/scroll/app/composables/useSectionProgress.ts +1 -1
  68. package/layers/scroll/app/plugins/locomotive-scroll.client.ts +6 -0
  69. package/layers/scroll/app/utils/scroll.ts +5 -1
  70. package/layers/seo/app/utils/seoConfig.test.ts +1 -1
  71. package/layers/shader/app/assets/css/shader.css +1 -1
  72. package/layers/shader/app/components/Material/AmbientAurora.client.vue +16 -4
  73. package/layers/shader/app/components/Material/AmbientFlow.client.vue +21 -5
  74. package/layers/shader/app/components/Material/AmbientGradientMesh.client.vue +21 -5
  75. package/layers/shader/app/components/Material/AmbientNebula.client.vue +21 -5
  76. package/layers/shader/app/components/Material/AmbientOcean.client.vue +16 -4
  77. package/layers/shader/app/components/Material/Gradient.client.vue +1 -1
  78. package/layers/shader/app/components/Material/Image.client.vue +1 -1
  79. package/layers/shader/app/components/Material/Noise.client.vue +11 -3
  80. package/layers/shader/app/composables/useAmbientMaterials.ts +0 -1
  81. package/layers/shader/app/shaders/common/blend.ts +5 -1
  82. package/layers/shader/app/shaders/common/grain.ts +5 -1
  83. package/layers/shader/app/shaders/common/lighting.ts +1 -6
  84. package/layers/shader/app/shaders/common/noise.ts +3 -1
  85. package/layers/shader/app/shaders/common/patterns.ts +1 -1
  86. package/layers/shader/app/shaders/common/shapes.ts +5 -1
  87. package/layers/shader/app/shaders/common/uv.ts +19 -2
  88. package/layers/shader/app/shaders/createMaterial.ts +11 -6
  89. package/layers/shader/app/shaders/layers/shaderGradient.ts +2 -12
  90. package/layers/shader/app/shaders/types.ts +1 -1
  91. package/layers/shader/app/types/uniforms.ts +1 -0
  92. package/layers/shader/app/utils/tsl/animation.ts +34 -36
  93. package/layers/starter/app/components/StarterDesignSystem.vue +120 -120
  94. package/layers/starter/app/components/StarterHome.vue +233 -208
  95. package/layers/theme/app/assets/css/theme.css +1 -1
  96. package/layers/theme/server/utils/accent-css.test.ts +17 -2
  97. package/layers/theme/server/utils/fouc-config.test.ts +7 -3
  98. package/layers/theme/server/utils/fouc-config.ts +24 -12
  99. package/layers/transitions/app/assets/css/transitions.css +6 -0
  100. package/layers/typography/app/assets/css/typography.css +313 -0
  101. package/layers/typography/app/components/Typography/Headline.vue +23 -14
  102. package/layers/typography/app/components/Typography/HeadlineScreen.vue +5 -12
  103. package/layers/typography/app/components/Typography/index.vue +4 -0
  104. package/layers/typography/app/composables/typography.ts +45 -5
  105. package/layers/typography/app/types/typography.ts +36 -7
  106. package/layers/typography/nuxt.config.ts +2 -0
  107. package/layers/visual/app/app.config.ts +1 -1
  108. package/layers/visual/app/assets/css/visual.css +1 -1
  109. package/layers/visual/app/composables/accent.ts +1 -2
  110. package/layers/visual/app/composables/tint.ts +1 -2
  111. package/layers/visual/app/types/media.ts +2 -2
  112. package/layers/visual/app/utils/gradientStyle.test.ts +1 -2
  113. package/layers/visual/app/utils/responsiveSizes.ts +0 -1
  114. package/package.json +33 -13
@@ -94,6 +94,7 @@ pnpm dev
94
94
  ```
95
95
 
96
96
  The `resolveExtendedLayers()` function:
97
+
97
98
  1. Parses `PLAYGROUND_LAYERS` as a comma-separated list
98
99
  2. Auto-includes each layer's dependencies (defined in `LAYER_DEPENDENCIES`)
99
100
  3. Returns paths in correct order (dependencies first, following `AVAILABLE_LAYERS` order)
@@ -117,11 +118,13 @@ Nuxt auto-discovers components from all extended layers' `app/components/` direc
117
118
  The shader layer uses explicit component registration with `global: true` for its WebGPU components:
118
119
 
119
120
  ```ts
120
- components: [{
121
- path: './app/components',
122
- pathPrefix: false,
123
- global: true,
124
- }]
121
+ components: [
122
+ {
123
+ path: './app/components',
124
+ pathPrefix: false,
125
+ global: true,
126
+ },
127
+ ]
125
128
  ```
126
129
 
127
130
  ## app.config.ts
@@ -129,6 +132,7 @@ components: [{
129
132
  Each layer provides typed runtime configuration via `app.config.ts` with sensible defaults. Consumers can override any value in their own `app.config.ts`.
130
133
 
131
134
  Key config namespaces:
135
+
132
136
  - `coreLayer` — loading screen, error handling, scroll guard, 404 page
133
137
  - `motion` — Lenis smooth scroll, GSAP ScrollTrigger integration
134
138
  - `themeLayer` — accent colors, default accent
@@ -186,15 +190,15 @@ Some layers (ui, content) support standalone mode via environment variables (`UI
186
190
 
187
191
  ## Layer Details
188
192
 
189
- | Layer | Description |
190
- |-------|-------------|
191
- | **core** | Foundation layer. Nuxt UI, VueUse, device detection, Pinia, loading screen, error handler, scroll guard, feature detection, PWA support (production only). |
192
- | **ui** | Design system primitives. Typography components (Headline, CodeBlock, QuoteBlock), color system, media/picture component, site branding, breakpoint types. |
193
- | **layout** | Page structure. Grid systems, containers, spacing, layout compositions with breakpoint-based responsiveness. |
194
- | **motion** | Animation layer. GSAP with ScrollTrigger, Locomotive Scroll (Lenis) smooth scrolling, motion composables. Transpiles GSAP for SSR. |
195
- | **shader** | WebGPU/WebGL layer. Three.js + TresJS integration, TSL shader support, post-processing. Includes custom shader utilities and auto-imported shader modules. |
196
- | **forms** | Form validation layer. Zod schema-based validation, form composables, typed form components. |
197
- | **database** | Database infrastructure. Drizzle ORM + Neon Postgres via HTTP driver. Exposes `useSql()` and `useDrizzle(schema)` server utilities. App-owned schema and migrations; env: `NUXT_DATABASE_LAYER_URL`. |
198
- | **auth** | Authentication layer. nuxt-auth-utils + GitHub OAuth handler, sealed-cookie sessions. Opt-in `auth` route middleware; no user table (app's responsibility). Env: `NUXT_SESSION_PASSWORD`, `NUXT_OAUTH_GITHUB_CLIENT_ID/SECRET`. |
199
- | **theme** | Theming layer. Color mode switching, accent color palette, theme plugin, CSS custom properties for dynamic theming. |
200
- | **content** | Content management layer. @nuxt/content integration, better-sqlite3 for local content DB, optional Nuxt Studio support. |
193
+ | Layer | Description |
194
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
195
+ | **core** | Foundation layer. Nuxt UI, VueUse, device detection, Pinia, loading screen, error handler, scroll guard, feature detection, PWA support (production only). |
196
+ | **ui** | Design system primitives. Typography components (Headline, CodeBlock, QuoteBlock), color system, media/picture component, site branding, breakpoint types. |
197
+ | **layout** | Page structure. Grid systems, containers, spacing, layout compositions with breakpoint-based responsiveness. |
198
+ | **motion** | Animation layer. GSAP with ScrollTrigger, Locomotive Scroll (Lenis) smooth scrolling, motion composables. Transpiles GSAP for SSR. |
199
+ | **shader** | WebGPU/WebGL layer. Three.js + TresJS integration, TSL shader support, post-processing. Includes custom shader utilities and auto-imported shader modules. |
200
+ | **forms** | Form validation layer. Zod schema-based validation, form composables, typed form components. |
201
+ | **database** | Database infrastructure. Drizzle ORM + Neon Postgres via HTTP driver. Exposes `useSql()` and `useDrizzle(schema)` server utilities. App-owned schema and migrations; env: `NUXT_DATABASE_LAYER_URL`. |
202
+ | **auth** | Authentication layer. nuxt-auth-utils + GitHub OAuth handler, sealed-cookie sessions. Opt-in `auth` route middleware; no user table (app's responsibility). Env: `NUXT_SESSION_PASSWORD`, `NUXT_OAUTH_GITHUB_CLIENT_ID/SECRET`. |
203
+ | **theme** | Theming layer. Color mode switching, accent color palette, theme plugin, CSS custom properties for dynamic theming. |
204
+ | **content** | Content management layer. @nuxt/content integration, better-sqlite3 for local content DB, optional Nuxt Studio support. |
package/docs/FEEDS.md CHANGED
@@ -42,7 +42,7 @@ export default defineNuxtConfig({
42
42
  **Resolver-style (like the playground):**
43
43
 
44
44
  ```ts
45
- const AVAILABLE_LAYERS = [/* ...existing... */, 'content', 'feeds'] as const
45
+ const AVAILABLE_LAYERS = [, /* ...existing... */ 'content', 'feeds'] as const
46
46
 
47
47
  const LAYER_PATHS = {
48
48
  /* ... */
@@ -69,24 +69,24 @@ export default defineAppConfig({
69
69
  site: {
70
70
  title: 'My Site',
71
71
  description: 'What the site is about',
72
- url: 'https://example.com', // canonical origin, no trailing slash
72
+ url: 'https://example.com', // canonical origin, no trailing slash
73
73
  author: { name: 'Jane', email: 'jane@example.com' },
74
74
  },
75
75
  feedsLayer: {
76
76
  feed: {
77
- limit: 30, // max items per feed
77
+ limit: 30, // max items per feed
78
78
  collections: ['blog', 'portfolio'], // every collection to expose
79
- defaultCollection: 'blog', // backs the /feed/rss shorthand routes
79
+ defaultCollection: 'blog', // backs the /feed/rss shorthand routes
80
80
  },
81
81
  },
82
82
  })
83
83
  ```
84
84
 
85
- | Option | Default | Meaning |
86
- |--------|---------|---------|
87
- | `limit` | `30` | Max items included in each feed |
88
- | `collections` | `['blog']` | Collection names to expose as feeds |
89
- | `defaultCollection` | `'blog'` | Collection served by the shorthand `/feed/rss` routes |
85
+ | Option | Default | Meaning |
86
+ | ------------------- | ---------- | ----------------------------------------------------- |
87
+ | `limit` | `30` | Max items included in each feed |
88
+ | `collections` | `['blog']` | Collection names to expose as feeds |
89
+ | `defaultCollection` | `'blog'` | Collection served by the shorthand `/feed/rss` routes |
90
90
 
91
91
  ---
92
92
 
@@ -94,19 +94,19 @@ export default defineAppConfig({
94
94
 
95
95
  Every configured collection serves:
96
96
 
97
- | URL | Format |
98
- |-----|--------|
99
- | `/feed/:collection/rss` | RSS 2.0 |
100
- | `/feed/:collection/atom` | Atom 1.0 |
97
+ | URL | Format |
98
+ | ------------------------ | ------------- |
99
+ | `/feed/:collection/rss` | RSS 2.0 |
100
+ | `/feed/:collection/atom` | Atom 1.0 |
101
101
  | `/feed/:collection/json` | JSON Feed 1.1 |
102
102
 
103
103
  Plus site-wide shorthand and index routes:
104
104
 
105
- | URL | Purpose |
106
- |-----|---------|
107
- | `/feed/rss`, `/feed/atom`, `/feed/json` | Shorthand → serves `defaultCollection` |
108
- | `/feed` | JSON index of all configured feeds |
109
- | `/feed/style.xsl` | Browser stylesheet (applied automatically) |
105
+ | URL | Purpose |
106
+ | --------------------------------------- | ------------------------------------------ |
107
+ | `/feed/rss`, `/feed/atom`, `/feed/json` | Shorthand → serves `defaultCollection` |
108
+ | `/feed` | JSON index of all configured feeds |
109
+ | `/feed/style.xsl` | Browser stylesheet (applied automatically) |
110
110
 
111
111
  Opening any feed URL in a browser shows a styled page thanks to the XSLT stylesheet — no app work required.
112
112
 
@@ -146,11 +146,11 @@ The `feed-head.ts` plugin injects `<link rel="alternate">` tags so RSS readers a
146
146
  - **Every page** gets the 3 main site feeds (shorthand routes → `defaultCollection`).
147
147
  - A page whose first path segment matches a **non-default** collection (e.g. `/portfolio/...`) **also** gets that collection's 3 specific feeds.
148
148
 
149
- | Page | Links injected |
150
- |------|----------------|
151
- | `/`, `/about`, any non-collection page | 3 main site feeds |
152
- | `/blog`, `/blog/hello` (when `blog` is the default) | 3 main site feeds (already point to blog) |
153
- | `/portfolio`, `/portfolio/project` (non-default collection) | 3 main + 3 portfolio feeds |
149
+ | Page | Links injected |
150
+ | ----------------------------------------------------------- | ----------------------------------------- |
151
+ | `/`, `/about`, any non-collection page | 3 main site feeds |
152
+ | `/blog`, `/blog/hello` (when `blog` is the default) | 3 main site feeds (already point to blog) |
153
+ | `/portfolio`, `/portfolio/project` (non-default collection) | 3 main + 3 portfolio feeds |
154
154
 
155
155
  **Do nothing.** Don't hand-add `<link rel="alternate">` tags — you'll duplicate them.
156
156
 
@@ -162,10 +162,18 @@ If you've aliased a collection (e.g. reused the portfolio schema as `works` via
162
162
 
163
163
  ```ts
164
164
  // app.config.ts
165
- feedsLayer: { feed: { collections: ['blog', 'works'] } }
165
+ feedsLayer: {
166
+ feed: {
167
+ collections: ['blog', 'works']
168
+ }
169
+ }
166
170
 
167
171
  // nuxt.config.ts
168
- nitro: { prerender: { routes: ['/feed/works/rss', '/feed/works/atom', '/feed/works/json'] } }
172
+ nitro: {
173
+ prerender: {
174
+ routes: ['/feed/works/rss', '/feed/works/atom', '/feed/works/json']
175
+ }
176
+ }
169
177
  ```
170
178
 
171
179
  See `MIGRATION.md` → "Collection Aliases" for how to define the alias itself.
@@ -185,12 +193,12 @@ See `MIGRATION.md` → "Collection Aliases" for how to define the alias itself.
185
193
 
186
194
  ## Quick reference
187
195
 
188
- | Goal | Action |
189
- |------|--------|
190
- | Turn on feeds | Register `core` + `content` + `feeds` layers |
191
- | Expose a collection | Add its name to `feedsLayer.feed.collections` |
192
- | Set the shorthand target | `feedsLayer.feed.defaultCollection` |
193
- | Cap items per feed | `feedsLayer.feed.limit` |
194
- | Static hosting | Add `/feed/<collection>/{rss,atom,json}` to `nitro.prerender.routes` |
195
- | Autodiscovery in `<head>` | Automatic — nothing to do |
196
- | Feed channel metadata | Top-level `site` config in `app.config.ts` |
196
+ | Goal | Action |
197
+ | ------------------------- | -------------------------------------------------------------------- |
198
+ | Turn on feeds | Register `core` + `content` + `feeds` layers |
199
+ | Expose a collection | Add its name to `feedsLayer.feed.collections` |
200
+ | Set the shorthand target | `feedsLayer.feed.defaultCollection` |
201
+ | Cap items per feed | `feedsLayer.feed.limit` |
202
+ | Static hosting | Add `/feed/<collection>/{rss,atom,json}` to `nitro.prerender.routes` |
203
+ | Autodiscovery in `<head>` | Automatic — nothing to do |
204
+ | Feed channel metadata | Top-level `site` config in `app.config.ts` |
@@ -4,8 +4,8 @@ Audit written against commit `a2805da`.
4
4
 
5
5
  ## Files
6
6
 
7
- | File | Purpose |
8
- | --- | --- |
7
+ | File | Purpose |
8
+ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
9
9
  | [IMPROVE-AUDIT-RESULTS.md](./IMPROVE-AUDIT-RESULTS.md) | Vetted improve audit findings, direction options, verification results, and recommended planning order. |
10
10
 
11
11
  ## Recommended Next Work
@@ -20,11 +20,10 @@ Recommended first implementation set:
20
20
 
21
21
  ## Dependency Order
22
22
 
23
- | Order | Finding | Depends On | Status |
24
- | --- | --- | --- | --- |
25
- | 1 | Current feeds lint failure | None | TODO |
26
- | 2 | Server route typecheck coverage | Feeds lint fix recommended first | TODO |
27
- | 3 | Public forms status endpoint leaks email addresses | Server route typecheck coverage recommended first | TODO |
28
- | 4 | Wrong mailer env var docs in forms demo | None | TODO |
29
- | 5 | Missing behavior tests | Typecheck/lint baseline | TODO |
30
-
23
+ | Order | Finding | Depends On | Status |
24
+ | ----- | -------------------------------------------------- | ------------------------------------------------- | ------ |
25
+ | 1 | Current feeds lint failure | None | TODO |
26
+ | 2 | Server route typecheck coverage | Feeds lint fix recommended first | TODO |
27
+ | 3 | Public forms status endpoint leaks email addresses | Server route typecheck coverage recommended first | TODO |
28
+ | 4 | Wrong mailer env var docs in forms demo | None | TODO |
29
+ | 5 | Missing behavior tests | Typecheck/lint baseline | TODO |
@@ -10,25 +10,25 @@ This pass did not audit ignored generated folders, local `.env`, or every Vue de
10
10
 
11
11
  ## Verification
12
12
 
13
- | Command | Result | Notes |
14
- | --- | --- | --- |
15
- | `pnpm typecheck` | PASS | Uses `vue-tsc --noEmit -p tsconfig.typecheck.json`. |
16
- | `pnpm lint` | FAIL | Fails in `kmcom-layer-feeds` on `layers/feeds/server/utils/content-adapter.ts:25`. |
17
- | `pnpm -F kmcom-layer-feeds typecheck` | PASS | Passes even though feeds server files are outside the root typecheck include. |
18
- | `pnpm audit --audit-level high --prod` | FAIL | Reports high advisories for `esbuild` and `ws`. |
13
+ | Command | Result | Notes |
14
+ | -------------------------------------- | ------ | ---------------------------------------------------------------------------------- |
15
+ | `pnpm typecheck` | PASS | Uses `vue-tsc --noEmit -p tsconfig.typecheck.json`. |
16
+ | `pnpm lint` | FAIL | Fails in `kmcom-layer-feeds` on `layers/feeds/server/utils/content-adapter.ts:25`. |
17
+ | `pnpm -F kmcom-layer-feeds typecheck` | PASS | Passes even though feeds server files are outside the root typecheck include. |
18
+ | `pnpm audit --audit-level high --prod` | FAIL | Reports high advisories for `esbuild` and `ws`. |
19
19
 
20
20
  ## Findings
21
21
 
22
- | # | Finding | Category | Impact | Effort | Risk | Confidence | Evidence |
23
- | --- | --- | --- | --- | --- | --- | --- | --- |
24
- | 1 | `pnpm lint` currently fails on feeds server code | DX / Tooling | The main local quality gate is red, so CI cannot safely adopt it yet. | S | LOW | HIGH | `layers/feeds/server/utils/content-adapter.ts:25` |
25
- | 2 | Published server routes are excluded from root typecheck and type-aware lint | Correctness / DX | Feed/form/mailer server code ships in npm but can pass `pnpm typecheck` with type errors hiding there. | M | MED | HIGH | `tsconfig.typecheck.json:25`, `eslint.config.mjs:387`, `package.json:37` |
26
- | 3 | Public forms status endpoint exposes configured email addresses | Security | Any visitor can read `emailFrom` and `emailTo`, leaking operational inboxes and increasing spam targeting. | S | LOW | HIGH | `layers/forms/server/api/forms/status.get.ts:4`, `layers/forms/server/api/forms/status.get.ts:7` |
27
- | 4 | Forms demo documents the wrong mailer env var namespace | Correctness / Docs | Users following the UI instructions set `NUXT_FORMS_LAYER_*`, but runtime config reads `NUXT_MAILER_LAYER_*`, leaving email unconfigured. | S | LOW | HIGH | `apps/playground/app/pages/forms.vue:732`, `layers/mailer/nuxt.config.ts:16` |
28
- | 5 | Contact email endpoint has no server-side abuse controls | Security | The public POST path can be used to burn Resend quota or spam the configured recipient. | M | MED | HIGH | `layers/forms/server/api/contact.post.ts:11`, `layers/mailer/server/utils/email.ts:17` |
29
- | 6 | Lockfile still contains high-advisory `esbuild` and `ws` versions | Security / Dependencies | Build/tooling and Nuxt Content dependency paths remain vulnerable per `pnpm audit --prod`. | S/M | MED | HIGH | `pnpm-lock.yaml:6770`, `pnpm-lock.yaml:12275` |
30
- | 7 | No automated behavior tests exist for the published layers | Test Coverage | Feed serialization, contact email, routing governance, and content composables have no regression harness. | M/L | LOW | HIGH | `package.json:41`, `package.json:246` |
31
- | 8 | Feed generation fetches whole collections before filtering/limiting | Performance | Large content collections make each feed request do avoidable in-memory filtering, sorting, and slicing. | M | MED | HIGH | `layers/feeds/server/utils/content-adapter.ts:61`, `layers/feeds/server/utils/feed-service.ts:16` |
22
+ | # | Finding | Category | Impact | Effort | Risk | Confidence | Evidence |
23
+ | --- | ---------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- | ---------- | ------------------------------------------------------------------------------------------------- |
24
+ | 1 | `pnpm lint` currently fails on feeds server code | DX / Tooling | The main local quality gate is red, so CI cannot safely adopt it yet. | S | LOW | HIGH | `layers/feeds/server/utils/content-adapter.ts:25` |
25
+ | 2 | Published server routes are excluded from root typecheck and type-aware lint | Correctness / DX | Feed/form/mailer server code ships in npm but can pass `pnpm typecheck` with type errors hiding there. | M | MED | HIGH | `tsconfig.typecheck.json:25`, `eslint.config.mjs:387`, `package.json:37` |
26
+ | 3 | Public forms status endpoint exposes configured email addresses | Security | Any visitor can read `emailFrom` and `emailTo`, leaking operational inboxes and increasing spam targeting. | S | LOW | HIGH | `layers/forms/server/api/forms/status.get.ts:4`, `layers/forms/server/api/forms/status.get.ts:7` |
27
+ | 4 | Forms demo documents the wrong mailer env var namespace | Correctness / Docs | Users following the UI instructions set `NUXT_FORMS_LAYER_*`, but runtime config reads `NUXT_MAILER_LAYER_*`, leaving email unconfigured. | S | LOW | HIGH | `apps/playground/app/pages/forms.vue:732`, `layers/mailer/nuxt.config.ts:16` |
28
+ | 5 | Contact email endpoint has no server-side abuse controls | Security | The public POST path can be used to burn Resend quota or spam the configured recipient. | M | MED | HIGH | `layers/forms/server/api/contact.post.ts:11`, `layers/mailer/server/utils/email.ts:17` |
29
+ | 6 | Lockfile still contains high-advisory `esbuild` and `ws` versions | Security / Dependencies | Build/tooling and Nuxt Content dependency paths remain vulnerable per `pnpm audit --prod`. | S/M | MED | HIGH | `pnpm-lock.yaml:6770`, `pnpm-lock.yaml:12275` |
30
+ | 7 | No automated behavior tests exist for the published layers | Test Coverage | Feed serialization, contact email, routing governance, and content composables have no regression harness. | M/L | LOW | HIGH | `package.json:41`, `package.json:246` |
31
+ | 8 | Feed generation fetches whole collections before filtering/limiting | Performance | Large content collections make each feed request do avoidable in-memory filtering, sorting, and slicing. | M | MED | HIGH | `layers/feeds/server/utils/content-adapter.ts:61`, `layers/feeds/server/utils/feed-service.ts:16` |
32
32
 
33
33
  ## Direction Options
34
34
 
@@ -49,4 +49,3 @@ This pass did not audit ignored generated folders, local `.env`, or every Vue de
49
49
  3. Fix findings 3 and 4 while the server route coverage is fresh.
50
50
  4. Add focused tests for the same paths before larger refactors.
51
51
  5. Address dependency advisories and feed query performance after the baseline is stable.
52
-
@@ -10,38 +10,38 @@ This pass stayed read-only for source code. It did not read `.env` files. It did
10
10
 
11
11
  ## Verification Summary
12
12
 
13
- | Command | Result | Notes |
14
- | --- | --- | --- |
15
- | `pnpm typecheck` | PASS | Root `vue-tsc --noEmit -p tsconfig.typecheck.json` passed. |
16
- | `pnpm -r --if-present --workspace-concurrency=1 --no-bail typecheck` | PASS | Recursive package typecheck completed successfully across workspace packages. |
17
- | `pnpm -r --if-present --workspace-concurrency=1 --no-bail lint` | FAIL | 23 packages passed, `kmcom-layer-feeds` failed on one ESLint error. The run also reported 63 warnings. |
18
- | `pnpm format:check` | FAIL | Reports unknown `ignorePath` config option and 309 formatting failures, including local `.agents` content. |
19
- | `git ls-files '*.css' \| xargs pnpm exec stylelint --allow-empty-input` | FAIL | Tracked CSS only: 96 problems, 84 errors and 12 warnings. |
20
- | `pnpm audit --audit-level high --prod --json` | FAIL | 2 high advisories: `esbuild` and `ws`. Metadata also reports 1 low and 1 moderate advisory. |
21
- | `fallow health --hotspots --targets --format json --quiet` | COMPLETE | 651 files, 2825 functions, 147 functions above Fallow thresholds. |
22
- | `fallow dupes --top 20 --format json --quiet` | COMPLETE | 467 files, 147 with clones, 5593 duplicated lines in the top clone set, 9.18% duplication. |
23
- | `fallow dead-code --unused-deps --unused-files --unused-exports --format json --quiet` | COMPLETE | 260 cleanup candidates: 43 files, 190 exports, 27 dependencies. Treat as trace-required leads. |
24
- | `fallow flags --format json --quiet` | COMPLETE | No feature flags detected by Fallow, despite routing runtime flags being hand-implemented. |
25
- | `fallow security --surface --format json --quiet` | COMPLETE | One low-severity weak-hash candidate in feed ETag generation. |
13
+ | Command | Result | Notes |
14
+ | -------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
15
+ | `pnpm typecheck` | PASS | Root `vue-tsc --noEmit -p tsconfig.typecheck.json` passed. |
16
+ | `pnpm -r --if-present --workspace-concurrency=1 --no-bail typecheck` | PASS | Recursive package typecheck completed successfully across workspace packages. |
17
+ | `pnpm -r --if-present --workspace-concurrency=1 --no-bail lint` | FAIL | 23 packages passed, `kmcom-layer-feeds` failed on one ESLint error. The run also reported 63 warnings. |
18
+ | `pnpm format:check` | FAIL | Reports unknown `ignorePath` config option and 309 formatting failures, including local `.agents` content. |
19
+ | `git ls-files '*.css' \| xargs pnpm exec stylelint --allow-empty-input` | FAIL | Tracked CSS only: 96 problems, 84 errors and 12 warnings. |
20
+ | `pnpm audit --audit-level high --prod --json` | FAIL | 2 high advisories: `esbuild` and `ws`. Metadata also reports 1 low and 1 moderate advisory. |
21
+ | `fallow health --hotspots --targets --format json --quiet` | COMPLETE | 651 files, 2825 functions, 147 functions above Fallow thresholds. |
22
+ | `fallow dupes --top 20 --format json --quiet` | COMPLETE | 467 files, 147 with clones, 5593 duplicated lines in the top clone set, 9.18% duplication. |
23
+ | `fallow dead-code --unused-deps --unused-files --unused-exports --format json --quiet` | COMPLETE | 260 cleanup candidates: 43 files, 190 exports, 27 dependencies. Treat as trace-required leads. |
24
+ | `fallow flags --format json --quiet` | COMPLETE | No feature flags detected by Fallow, despite routing runtime flags being hand-implemented. |
25
+ | `fallow security --surface --format json --quiet` | COMPLETE | One low-severity weak-hash candidate in feed ETag generation. |
26
26
 
27
27
  ## Confirmed Findings
28
28
 
29
- | Priority | Finding | Impact | Effort | Confidence | Evidence |
30
- | --- | --- | --- | --- | --- | --- |
31
- | P0 | Public forms status endpoint exposes configured email addresses. | Any visitor can read operational sender and recipient addresses, increasing spam and metadata exposure. | S | HIGH | `layers/forms/server/api/forms/status.get.ts:4`, `layers/forms/server/api/forms/status.get.ts:7`, `apps/playground/app/pages/forms.vue:662`, `apps/playground/app/pages/forms.vue:675` |
32
- | P0 | Contact email endpoint has no server-side abuse controls. | The public POST path can burn Resend quota, spam the configured recipient, and create noisy hooks. | M | HIGH | `layers/forms/server/api/contact.post.ts:11`, `layers/forms/server/api/contact.post.ts:22`, `layers/mailer/server/utils/email.ts:17` |
33
- | P0 | Production dependency audit has high advisories. | `pnpm audit` reports high-severity `esbuild` and `ws` paths in production dependency graphs. | S/M | HIGH | `pnpm-lock.yaml:6770`, `pnpm-lock.yaml:6775`, `pnpm-lock.yaml:12275`, `package.json:106`, `package.json:112`, `package.json:115` |
34
- | P1 | Content list composables reuse cache keys while accepting different query options. | Calls with different `tags`, `limit`, `featured`, or `excludeDrafts` can share or cancel the wrong `useAsyncData` payload. | S/M | HIGH | `layers/content/app/composables/useContentData.ts:1`, `layers/content/app/composables/useBlogPosts.ts:3`, `layers/content/app/composables/useBlogPosts.ts:6`, `layers/content/app/composables/useGalleryItems.ts:3`, `layers/content/app/composables/usePortfolioItems.ts:3`, `layers/content/app/composables/createPortfolioComposables.ts:20` |
35
- | P1 | Published server files are outside root typecheck and type-aware lint. | `layers/*/server/**` ships in the package but is excluded from root typechecking and has type-aware ESLint disabled. | M | HIGH | `package.json:37`, `tsconfig.typecheck.json:25`, `eslint.config.mjs:387`, `eslint.config.mjs:390` |
36
- | P1 | Main lint baseline is red. | Recursive lint has one hard error, so CI or pre-commit adoption cannot rely on lint yet. | S | HIGH | `layers/feeds/server/utils/content-adapter.ts:25`, recursive lint summary: 1 fail, 23 pass |
37
- | P1 | Format baseline is noisy and includes local agent assets. | `pnpm format:check` fails on 309 files and warns that `ignorePath` is not a valid config option. The ignore file does not exclude `.agents/` or `.claude/`. | S | HIGH | `prettier.config.cjs:46`, `.prettierignore:1`, `.prettierignore:85` |
38
- | P1 | No tracked behavior tests exist. | Feed serialization, forms/mailer, routing governance, content composables, and shader utilities rely on manual checks plus lint/typecheck. | M/L | HIGH | `package.json:41`, `package.json:246`; `git ls-files` found no `*.test.*`, `*.spec.*`, `tests`, or `__tests__` paths. |
39
- | P2 | Feed dynamic collection routes accept arbitrary collection names. | `/feed/:collection/:format` passes unvalidated path segments into `queryCollection(event, collection)`, so invalid collections become uncontrolled content-query failures instead of 404s. | S | HIGH | `layers/feeds/server/routes/feed/[collection]/rss.get.ts:2`, `layers/feeds/server/utils/content-adapter.ts:28`, `layers/feeds/app/app.config.ts:5`, `layers/feeds/server/routes/feed/discovery.get.ts:20` |
40
- | P2 | Feed generation fetches whole collections before filtering and limiting. | Large collections make every feed request filter, sort, and slice in memory instead of pushing draft/date/limit work into the Nuxt Content query. | M | HIGH | `layers/feeds/server/utils/content-adapter.ts:61`, `layers/feeds/server/utils/content-adapter.ts:63`, `layers/feeds/server/utils/feed-service.ts:16` |
41
- | P2 | Feed date handling can turn bad frontmatter into runtime feed failures. | `new Date(...)` is not validated before `toISOString()`. Invalid dates can crash JSON or Atom serialization. | S | MED | `layers/feeds/server/utils/content-adapter.ts:50`, `layers/feeds/server/utils/formats/json.ts:16`, `layers/feeds/server/utils/formats/atom.ts:13`, `layers/feeds/server/utils/formats/atom.ts:22` |
42
- | P2 | CSS lint rules are configured but tracked CSS fails them. | Stylelint reports 84 errors and 12 warnings against tracked CSS only, mostly token fallback hex colors, import ordering, keyframe casing, and deprecated properties. | M | HIGH | `stylelint.config.mjs:48`, `stylelint.config.mjs:123`, `layers/core/app/assets/css/core.css:6`, `layers/feeds/public/feed/style.css:15`, `layers/feeds/app/assets/css/feeds.css:20` |
43
- | P2 | Routing runtime flags have a client fetch contract but no shipped endpoint. | Product and enterprise presets enable `runtimeFlags`, and the client fetches `/api/feature-flags`; the layer does not provide that server route. Consumers need an explicit contract or optional route. | S/M | HIGH | `layers/routing/app/plugins/feature-flags.client.ts:8`, `layers/routing/app/plugins/feature-flags.client.ts:12`, `layers/routing/app/types/routing.ts:47`, `layers/routing/app/types/routing.ts:56` |
44
- | P3 | Feed ETag generation uses MD5. | This is not password/signature crypto, but modern cache fingerprints should use SHA-256 to avoid weak-crypto findings. | S | HIGH | `layers/feeds/server/utils/cache.ts:5` |
29
+ | Priority | Finding | Impact | Effort | Confidence | Evidence |
30
+ | -------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31
+ | P0 | Public forms status endpoint exposes configured email addresses. | Any visitor can read operational sender and recipient addresses, increasing spam and metadata exposure. | S | HIGH | `layers/forms/server/api/forms/status.get.ts:4`, `layers/forms/server/api/forms/status.get.ts:7`, `apps/playground/app/pages/forms.vue:662`, `apps/playground/app/pages/forms.vue:675` |
32
+ | P0 | Contact email endpoint has no server-side abuse controls. | The public POST path can burn Resend quota, spam the configured recipient, and create noisy hooks. | M | HIGH | `layers/forms/server/api/contact.post.ts:11`, `layers/forms/server/api/contact.post.ts:22`, `layers/mailer/server/utils/email.ts:17` |
33
+ | P0 | Production dependency audit has high advisories. | `pnpm audit` reports high-severity `esbuild` and `ws` paths in production dependency graphs. | S/M | HIGH | `pnpm-lock.yaml:6770`, `pnpm-lock.yaml:6775`, `pnpm-lock.yaml:12275`, `package.json:106`, `package.json:112`, `package.json:115` |
34
+ | P1 | Content list composables reuse cache keys while accepting different query options. | Calls with different `tags`, `limit`, `featured`, or `excludeDrafts` can share or cancel the wrong `useAsyncData` payload. | S/M | HIGH | `layers/content/app/composables/useContentData.ts:1`, `layers/content/app/composables/useBlogPosts.ts:3`, `layers/content/app/composables/useBlogPosts.ts:6`, `layers/content/app/composables/useGalleryItems.ts:3`, `layers/content/app/composables/usePortfolioItems.ts:3`, `layers/content/app/composables/createPortfolioComposables.ts:20` |
35
+ | P1 | Published server files are outside root typecheck and type-aware lint. | `layers/*/server/**` ships in the package but is excluded from root typechecking and has type-aware ESLint disabled. | M | HIGH | `package.json:37`, `tsconfig.typecheck.json:25`, `eslint.config.mjs:387`, `eslint.config.mjs:390` |
36
+ | P1 | Main lint baseline is red. | Recursive lint has one hard error, so CI or pre-commit adoption cannot rely on lint yet. | S | HIGH | `layers/feeds/server/utils/content-adapter.ts:25`, recursive lint summary: 1 fail, 23 pass |
37
+ | P1 | Format baseline is noisy and includes local agent assets. | `pnpm format:check` fails on 309 files and warns that `ignorePath` is not a valid config option. The ignore file does not exclude `.agents/` or `.claude/`. | S | HIGH | `prettier.config.cjs:46`, `.prettierignore:1`, `.prettierignore:85` |
38
+ | P1 | No tracked behavior tests exist. | Feed serialization, forms/mailer, routing governance, content composables, and shader utilities rely on manual checks plus lint/typecheck. | M/L | HIGH | `package.json:41`, `package.json:246`; `git ls-files` found no `*.test.*`, `*.spec.*`, `tests`, or `__tests__` paths. |
39
+ | P2 | Feed dynamic collection routes accept arbitrary collection names. | `/feed/:collection/:format` passes unvalidated path segments into `queryCollection(event, collection)`, so invalid collections become uncontrolled content-query failures instead of 404s. | S | HIGH | `layers/feeds/server/routes/feed/[collection]/rss.get.ts:2`, `layers/feeds/server/utils/content-adapter.ts:28`, `layers/feeds/app/app.config.ts:5`, `layers/feeds/server/routes/feed/discovery.get.ts:20` |
40
+ | P2 | Feed generation fetches whole collections before filtering and limiting. | Large collections make every feed request filter, sort, and slice in memory instead of pushing draft/date/limit work into the Nuxt Content query. | M | HIGH | `layers/feeds/server/utils/content-adapter.ts:61`, `layers/feeds/server/utils/content-adapter.ts:63`, `layers/feeds/server/utils/feed-service.ts:16` |
41
+ | P2 | Feed date handling can turn bad frontmatter into runtime feed failures. | `new Date(...)` is not validated before `toISOString()`. Invalid dates can crash JSON or Atom serialization. | S | MED | `layers/feeds/server/utils/content-adapter.ts:50`, `layers/feeds/server/utils/formats/json.ts:16`, `layers/feeds/server/utils/formats/atom.ts:13`, `layers/feeds/server/utils/formats/atom.ts:22` |
42
+ | P2 | CSS lint rules are configured but tracked CSS fails them. | Stylelint reports 84 errors and 12 warnings against tracked CSS only, mostly token fallback hex colors, import ordering, keyframe casing, and deprecated properties. | M | HIGH | `stylelint.config.mjs:48`, `stylelint.config.mjs:123`, `layers/core/app/assets/css/core.css:6`, `layers/feeds/public/feed/style.css:15`, `layers/feeds/app/assets/css/feeds.css:20` |
43
+ | P2 | Routing runtime flags have a client fetch contract but no shipped endpoint. | Product and enterprise presets enable `runtimeFlags`, and the client fetches `/api/feature-flags`; the layer does not provide that server route. Consumers need an explicit contract or optional route. | S/M | HIGH | `layers/routing/app/plugins/feature-flags.client.ts:8`, `layers/routing/app/plugins/feature-flags.client.ts:12`, `layers/routing/app/types/routing.ts:47`, `layers/routing/app/types/routing.ts:56` |
44
+ | P3 | Feed ETag generation uses MD5. | This is not password/signature crypto, but modern cache fingerprints should use SHA-256 to avoid weak-crypto findings. | S | HIGH | `layers/feeds/server/utils/cache.ts:5` |
45
45
 
46
46
  ## Structural Findings
47
47
 
@@ -95,6 +95,7 @@ pnpm dev
95
95
  ```
96
96
 
97
97
  Then visit:
98
+
98
99
  - `/feed/rss` — styled RSS XML, blog items present
99
100
  - `/feed/blog/json` — JSON Feed 1.1 with items
100
101
  - `/feed` — index listing the blog collection