webspresso 0.0.95 → 0.0.97

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 (94) hide show
  1. package/.agents/ADMIN.md +225 -0
  2. package/.agents/AGENTS.md +72 -0
  3. package/.agents/ARCHITECTURE.md +119 -0
  4. package/.agents/AUTH.md +103 -0
  5. package/.agents/CLI.md +115 -0
  6. package/.agents/COMPRESSION.md +59 -0
  7. package/.agents/CONVENTIONS.md +46 -0
  8. package/.agents/EMAIL.md +141 -0
  9. package/.agents/ERRORS.md +201 -0
  10. package/.agents/MCP.md +103 -0
  11. package/.agents/ORM.md +230 -0
  12. package/.agents/PLUGINS.md +419 -0
  13. package/.agents/QUEUE.md +113 -0
  14. package/.agents/REALTIME.md +213 -0
  15. package/.agents/ROUTING.md +292 -0
  16. package/.agents/SERVICES.md +341 -0
  17. package/.agents/SHUTDOWN.md +67 -0
  18. package/.agents/STREAMING.md +73 -0
  19. package/.agents/WORKFLOW.md +27 -0
  20. package/.agents/internal/DOCUMENTATION_REVIEW.md +485 -0
  21. package/.agents/internal/TECHNICAL_REVIEW.md +428 -0
  22. package/.agents/skills/webspresso-admin-and-plugins/SKILL.md +122 -0
  23. package/.agents/skills/webspresso-framework/SKILL.md +56 -0
  24. package/.agents/skills/webspresso-orm-and-database/SKILL.md +119 -0
  25. package/.agents/skills/webspresso-routing-and-api/SKILL.md +114 -0
  26. package/.agents/skills/webspresso-services/SKILL.md +101 -0
  27. package/.cursorrules +14 -0
  28. package/AGENTS.md +175 -0
  29. package/CLAUDE.md +54 -0
  30. package/README.md +18 -14
  31. package/bin/commands/admin-password.js +2 -1
  32. package/bin/commands/admin-setup.js +1 -1
  33. package/bin/commands/agents-init.js +209 -0
  34. package/bin/commands/api.js +114 -48
  35. package/bin/commands/audit-prune.js +1 -1
  36. package/bin/commands/doctor.js +35 -0
  37. package/bin/commands/favicon-generate.js +1 -1
  38. package/bin/commands/new.js +13 -2
  39. package/bin/commands/orm-map.js +5 -4
  40. package/bin/commands/page.js +75 -89
  41. package/bin/commands/polar-migrate.js +1 -1
  42. package/bin/commands/seed.js +1 -1
  43. package/bin/commands/service.js +77 -0
  44. package/bin/webspresso.js +2 -2
  45. package/core/auth/hash.js +10 -5
  46. package/core/compileSchema.js +1 -1
  47. package/core/errors/middleware.js +22 -2
  48. package/core/errors/normalize.js +29 -2
  49. package/{utils/schemaCache.js → core/schema-cache.js} +2 -3
  50. package/index.d.ts +306 -0
  51. package/index.js +35 -1
  52. package/package.json +36 -14
  53. package/plugins/admin-panel/app.js +10 -9
  54. package/plugins/admin-panel/client/parts/05-rich-text-file-helpers.js +22 -1
  55. package/plugins/admin-panel/core/api-extensions.js +4 -0
  56. package/plugins/basic-auth/index.js +3 -1
  57. package/plugins/content/client/inline-edit.js +12 -12
  58. package/plugins/cors.js +6 -7
  59. package/plugins/csrf/index.js +3 -2
  60. package/plugins/csv/engine.js +447 -0
  61. package/plugins/csv/index.js +94 -0
  62. package/plugins/csv/middleware.js +80 -0
  63. package/plugins/csv/services.js +138 -0
  64. package/plugins/file-manager/admin-component.js +613 -0
  65. package/plugins/file-manager/api-handlers.js +261 -0
  66. package/plugins/file-manager/core.js +601 -0
  67. package/plugins/file-manager/index.js +139 -0
  68. package/plugins/file-manager/security.js +217 -0
  69. package/plugins/index.js +45 -79
  70. package/plugins/mcp/transports/sse.js +4 -2
  71. package/plugins/site-analytics/admin-component.js +7 -8
  72. package/plugins/xlsx/engine.js +397 -0
  73. package/plugins/xlsx/index.js +91 -0
  74. package/plugins/xlsx/middleware.js +87 -0
  75. package/plugins/xlsx/services.js +118 -0
  76. package/src/api/api-loader.js +233 -0
  77. package/src/api/define-api.js +35 -0
  78. package/src/discovery/file-route-parser.js +201 -0
  79. package/src/discovery/scan-routes.js +265 -0
  80. package/src/file-router.js +9 -1
  81. package/src/modules/define-module.js +99 -0
  82. package/src/modules/module-discovery.js +117 -0
  83. package/src/pages/define-page.js +36 -0
  84. package/src/pages/page-loader.js +214 -0
  85. package/src/routing/mount-discovered-routes.js +78 -0
  86. package/src/routing/route-table.js +191 -0
  87. package/src/server.js +112 -15
  88. package/src/services/builtins/file-manager.js +178 -0
  89. package/src/services/discovery.js +6 -1
  90. package/src/services/index.js +6 -11
  91. package/bin/commands/skill.js +0 -187
  92. package/templates/skills/webspresso-usage/REFERENCE-framework.md +0 -289
  93. package/templates/skills/webspresso-usage/REFERENCE-kernel.md +0 -93
  94. package/templates/skills/webspresso-usage/SKILL.md +0 -48
@@ -0,0 +1,428 @@
1
+ # Webspresso – Technical Status & Phased Stabilization Report
2
+
3
+ ```text
4
+ Project: Webspresso
5
+ Review date: 2026-08-28
6
+ Current version: 0.0.91
7
+ Repository state / commit: e027fc7ba47635f6d8013fed5f207f54db602122 (branch: current)
8
+ Review scope: Complete codebase analysis (core, src, plugins, bin, utils, tests, templates)
9
+ Overall status: Healthy & passing (176 test files, 2,109 unit/integration/security tests passing), with stabilized architecture, unified validation core, isolated experimental kernel, and formal request context containers.
10
+ ```
11
+
12
+ ---
13
+
14
+ ## 1. Executive Summary
15
+
16
+ Webspresso is a feature-rich web framework for Node.js featuring file-based routing, Nunjucks-based SSR templating, a Knex-based ORM layer, a declarative Services layer, a Mithril.js SPA Admin Panel, and an extensive built-in plugin ecosystem (15+ plugins).
17
+
18
+ The current test suite (`vitest`) runs at **100% pass rate across 176 test files and 2,109 tests**. Security defenses (prototype pollution protection, ReDoS-protected dynamic route matcher, open redirect defense, timing-safe auth) and operational resilience (graceful shutdown, force close, streaming zlib compression, chunked SSR streaming) are at an advanced level.
19
+
20
+ Key architectural aspects and historical areas of duality addressed during stabilization:
21
+
22
+ 1. **Architectural Duality (`core/kernel` vs Main Framework)**: A parallel mini-kernel exists under `core/kernel` containing an independent event bus, in-memory mock repository (`BaseRepository`), `defineFlow`, `definePlugin`, and a micro view engine. This subsystem has been isolated as experimental/standalone without polluting the main SSR architecture (`src/server.js`, `src/services`, `core/orm`).
23
+ 2. **Implicit Global State Reduction (`src/app-context.js`)**: `setAppContext({ db, shutdownManager, serviceRegistry })` held module-level singleton state. The framework has been refactored to pass state through Express `req.context` / `ctx` containers, keeping `app-context.js` strictly as a backward-compatible fallback.
24
+ 3. **Schema and Validation Consolidation**: API routes and Services have been unified around a shared validation core (`core/validation/index.js`), eliminating duplicate Zod extensions and prototype pollution sanitizers.
25
+ 4. **Express & Node.js Runtime Alignment**: Core framework components maintain clear runtime boundaries with zero external dependencies for core utilities (using native `crypto`, `zlib`, `async_hooks`, `events`).
26
+
27
+ This report provides a comprehensive technical inventory, risk register, and completed stabilization backlog.
28
+
29
+ ---
30
+
31
+ ## 2. Current Architecture
32
+
33
+ Webspresso consists of 6 primary subsystems:
34
+
35
+ ```mermaid
36
+ graph TD
37
+ CLI[CLI Tooling / bin] --> AppInit[src/server.js: createApp]
38
+ AppInit --> Express[Express 5 Server]
39
+ AppInit --> PluginMgr[src/plugin-manager.js]
40
+ AppInit --> SvcRegistry[src/services: ServiceRegistry]
41
+ AppInit --> ShutdownMgr[core/shutdown: ShutdownManager]
42
+
43
+ Express --> FileRouter[src/file-router.js: mountPages]
44
+ FileRouter --> SSR[pages/**/*.njk + .js Loaders]
45
+ FileRouter --> API[pages/api/**/*.js Endpoints]
46
+
47
+ SSR --> SvcRegistry
48
+ API --> SvcRegistry
49
+
50
+ SvcRegistry --> ORM[core/orm: Repositories & Models]
51
+ ORM --> Knex[Knex DB Connection Pool]
52
+ ORM --> ORMCache[core/orm/cache: Query Cache]
53
+ ORM --> ModelEvents[core/orm/events: Django-style Signals]
54
+
55
+ PluginMgr --> AdminSPA[plugins/admin-panel: Mithril SPA]
56
+ PluginMgr --> ContentCMS[plugins/content: Headless CMS]
57
+ PluginMgr --> RealtimeLayer[core/realtime: WS/SSE/Socket.IO]
58
+ PluginMgr --> BackgroundQueue[core/queue: In-Memory/Knex/Redis]
59
+
60
+ subgraph "Parallel Mini-Kernel (Isolated Standalone Subsystem)"
61
+ Kernel[core/kernel] --> KernelEvents[core/kernel/events]
62
+ Kernel --> KernelFlows[core/kernel/flow]
63
+ Kernel --> KernelViews[core/kernel/view]
64
+ Kernel --> BaseRepo[core/kernel/base-repository]
65
+ end
66
+ ```
67
+
68
+ ### 2.1 Core SSR & File-Based Router (`src/server.js`, `src/file-router.js`)
69
+ - **Directory Scanning**: Scans `pages/`. Maps `.njk` templates to SSR routes and `pages/api/**/*.js` to REST API endpoints.
70
+ - **Parameter Resolution**: Converts `[param]` → `:param`, `[...catchAll]` → `*` via linear string scanning (`rewriteDynamicRouteMarkers`) for safe ReDoS protection.
71
+ - **Registration Ordering**: Strict 4-tier registration: Static literal paths → Deep dynamic paths → Shallow dynamic paths → Catch-all wildcards (`routeRegistrationMeta`).
72
+ - **Data Loading & Lifecycle**: Executes `_hooks.js` and route-specific `.js` companions (`load()`, `meta()`) upon matching.
73
+ - **Template Engine**: Safe Nunjucks engine with circular inheritance recursion protection (`configureSafeNunjucks` + `renderStackStorage` AsyncLocalStorage).
74
+ - **Chunked Transfer**: `res.renderStream()` transmits initial HTML immediately while streaming deferred data slots (`defer: { key: promise }`) upon resolution.
75
+
76
+ ### 2.2 Services Layer (`src/services/`)
77
+ - **Auto-Discovery**: Scans `services/` mapping files to dot-notated names (`user.create`) and camelCase aliases (`user.reset-password` → `user.resetPassword`).
78
+ - **Declarative Features**: Supports Zod `schema`, `auth` (boolean, role string/array, predicate), `timeout` (ms), `transaction: true` (automatic ACID transaction propagation), and `cache: { ttl, key }`.
79
+ - **Circular Call Detection**: Uses `Symbol.for('webspresso.service.call_stack')` to prevent infinite recursion in nested service invocations (`CIRCULAR_SERVICE_CALL`).
80
+ - **Sensitive Data Masking**: Automatically redacts sensitive keys (`password`, `token`, `secret`, `cvv`) from error logs and traces.
81
+
82
+ ### 2.3 ORM & Database Layer (`core/orm/`)
83
+ - **Model Definition**: `defineModel({ name, table, schema, relations, scopes, hidden, admin, cache })`.
84
+ - **Schema Types**: `zdb.string()`, `zdb.integer()`, `zdb.boolean()`, `zdb.json()`, `zdb.file()`, `zdb.nanoid()`.
85
+ - **Repository Pattern**: `db.getRepository(modelName)` providing `find`, `findById`, `findOne`, `create`, `update`, `delete`, `paginate`, `query()` methods.
86
+ - **Ambient Transactions**: `runWithAmbientTransaction(trx, callback)` uses `AsyncLocalStorage` to automatically bind queries and nested services to the active transaction without explicit `trx` arguments.
87
+ - **Query Caching**: `auto` (PK/find caching) and `smart` (tag-based invalidation) strategies.
88
+ - **Signals / Events**: `ModelEvents` class providing Django-style signals (`beforeCreate`, `afterSave`, `beforeDelete`).
89
+
90
+ ### 2.4 Mithril.js Admin Panel SPA (`plugins/admin-panel/`)
91
+ - Independent single-page application mounted at `/_admin`.
92
+ - Dynamic model CRUD forms, customizable widgets, custom pages (`componentFile` or `pagesDir`), single and bulk actions.
93
+ - Staff authentication session (`req.session.adminUser`) is strictly isolated from public site auth (`req.user`).
94
+
95
+ ### 2.5 Plugin Ecosystem (`plugins/`)
96
+ - Synchronous registration (`registerSync`), route readiness hook (`onRoutesReady`), CSP directive merging, and reverse-order `disposer` cleanup on shutdown.
97
+
98
+ ---
99
+
100
+ ## 3. HTTP Request Lifecycle
101
+
102
+ The diagram below illustrates the verified HTTP request lifecycle from `src/server.js` and `src/file-router.js`:
103
+
104
+ ```text
105
+ HTTP Request (Client)
106
+ ↓
107
+ Express 5.x App
108
+ ↓
109
+ Services Caller Injection Middleware (req.service = ...)
110
+ ↓
111
+ SSR Streaming Helper Injection Middleware (res.renderStream = ...)
112
+ ↓
113
+ Shutdown Draining Check (isShuttingDown ? Connection: close : next)
114
+ ↓
115
+ Security Headers (Helmet: CSP, HSTS, XSS, Referrer)
116
+ ↓
117
+ HTTP Response Compression (Streaming zlib Brotli/Gzip/Deflate)
118
+ ↓
119
+ Request Timeout Middleware (connect-timeout)
120
+ ↓
121
+ Body Parsers (express.json, express.urlencoded)
122
+ ↓
123
+ Halt on Timedout Guard
124
+ ↓
125
+ Auth Session & JWT Middlewares (req.user, req.auth)
126
+ ↓
127
+ Static Assets Handler (express.static if publicDir exists)
128
+ ↓
129
+ Client Runtime Assets (/__webspresso/client-runtime/* for Alpine/Swup)
130
+ ↓
131
+ File-Based Routing Matcher
132
+ ├── [API Route] pages/api/**/*.js
133
+ │ ↓
134
+ │ Route-level Middleware (preResolvedMw)
135
+ │ ↓
136
+ │ compileSchema & applySchema (Zod validation -> req.input)
137
+ │ ↓
138
+ │ Handler Function fn(req, res, next)
139
+ │ ↓
140
+ │ JSON Response res.json(...)
141
+ │
142
+ └── [SSR Route] pages/**/*.njk
143
+ ↓
144
+ Global & Route Hooks: onRequest → onRoute → beforeMiddleware
145
+ ↓
146
+ Route-level Middleware (preResolvedPageMw)
147
+ ↓
148
+ Global & Route Hooks: afterMiddleware → beforeLoad
149
+ ↓
150
+ Page Data Loader: load(req, ctx) → ctx.data
151
+ ↓
152
+ Global & Route Hooks: afterLoad
153
+ ↓
154
+ Page Meta Generator: meta(req, ctx) → ctx.meta
155
+ ↓
156
+ Global & Route Hooks: beforeRender
157
+ ↓
158
+ Nunjucks Template Render / Streaming (renderStream)
159
+ ↓
160
+ Content CMS Inline Edit Injection (if applicable)
161
+ ↓
162
+ Global & Route Hooks: afterRender
163
+ ↓
164
+ HTML Response (res.send / chunked stream)
165
+ ↓
166
+ [If Unmatched] -> 404 Handler (Custom function / 404.njk + 404.js load() / Default HTML/JSON)
167
+ ↓
168
+ [If Error Thrown] -> Central Error Boundary (normalizeError → app.setErrorHandler → 500.njk / Default HTML/JSON)
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 4. Service Execution Lifecycle
174
+
175
+ The verified service execution pipeline from `src/services/executor.js` and `src/services/registry.js`:
176
+
177
+ ```text
178
+ serviceRegistry.call(name, input, ctx, options) / req.service(name, input)
179
+ ↓
180
+ 1. Lookup: Name & CamelCase Alias Resolution (registry.get) -> If missing: NotFoundError ('SERVICE_NOT_FOUND')
181
+ ↓
182
+ 2. Authorization Guard (checkServiceAuth)
183
+ ├── Boolean true: Session check (ctx.user || req.user) -> If missing: UnauthorizedError (401)
184
+ ├── Role string / Role array: Role validation -> If unauthorized: ForbiddenError (403)
185
+ └── Predicate function (user, ctx) => boolean -> If rejected: ForbiddenError (403)
186
+ ↓
187
+ 3. Circular Call Guard: Symbol.for('webspresso.service.call_stack') check -> If cycle detected: WebspressoError ('CIRCULAR_SERVICE_CALL')
188
+ ↓
189
+ 4. Child Context Fork: Creates executionContext (new call stack, nested service caller, invalidate/clearCache methods)
190
+ ↓
191
+ 5. Schema Validation: validateServiceInput (Zod parse/safeParse, prototype pollution sanitization) -> If invalid: ValidationError (422)
192
+ ↓
193
+ 6. Ambient Transaction Propagation (options.transaction === true || serviceDef.transaction === true)
194
+ ├── Is transaction already active? (hasAmbientTransaction() || ctx.trx)
195
+ │ ├── YES: Reuse existing transaction within isolated child context.
196
+ │ └── NO: Start knex.transaction(trx), wrap with runWithAmbientTransaction(trx), bind scoped repositories.
197
+ ↓
198
+ 7. Cache / Memoization (if serviceDef.cache configured)
199
+ ├── Cache Hit: Return cached result (database and handler skipped).
200
+ └── Cache Miss: Execute handler, store result in cache.
201
+ ↓
202
+ 8. Timeout Race Boundary (serviceDef.timeout or options.timeout ms) -> If exceeded: WebspressoError ('SERVICE_TIMEOUT', 504)
203
+ ↓
204
+ 9. Handler Execution: handler(validatedInput, activeCtx)
205
+ ↓
206
+ 10. Return Result / Automatic Rollback & Sensitive Log Redaction on Failure
207
+ ```
208
+
209
+ ---
210
+
211
+ ## 5. Data, Transaction & Cache Lifecycle
212
+
213
+ ```text
214
+ Controller / Loader / Service
215
+ ↓
216
+ db.getRepository(modelName)
217
+ ↓
218
+ Repository Instance (core/orm/repository.js)
219
+ ↓
220
+ Resolve Active Knex:
221
+ ├── Is Ambient Transaction Storage active? (AsyncLocalStorage.getStore().trx)
222
+ │ ├── YES: Route query to trx connection (atomic execution).
223
+ │ └── NO: Use primary Database Connection Pool.
224
+ ↓
225
+ Apply Scopes (Soft delete: deleted_at IS NULL, Multi-tenant: tenant_id = ...)
226
+ ↓
227
+ Find / Query Operation:
228
+ ├── Is ORM Cache Layer active? (auto / smart)
229
+ │ ├── Cache Hit: Fingerprint match -> Return from Memory/Provider.
230
+ │ └── Cache Miss: Query DB -> ModelEvents ('beforeFind') -> Knex Query -> Deserialization (JSON fields) -> Eager Load Relations -> ModelEvents ('afterFind') -> Write to Cache.
231
+ │
232
+ Mutation Operation (create / update / delete):
233
+ ↓
234
+ ModelEvents ('beforeCreate' / 'beforeUpdate' / 'beforeDelete') -> Cancellable.
235
+ ↓
236
+ Schema Serializers (JSON fields, nanoid generation, timestamps)
237
+ ↓
238
+ Knex Query Execution (INSERT / UPDATE / DELETE)
239
+ ↓
240
+ ModelEvents ('afterCreate' / 'afterSave' / 'afterDelete')
241
+ ↓
242
+ ORM Cache Invalidation: Invalidate affected model tables and associated tags.
243
+ ```
244
+
245
+ ---
246
+
247
+ ## 6. Plugin Lifecycle
248
+
249
+ ```text
250
+ createApp({ plugins: [pluginA, pluginB, ...] })
251
+ ↓
252
+ 1. Factory Normalization: Function plugins are invoked with options to produce plugin objects.
253
+ ↓
254
+ 2. Dependency Resolution: Plugin dependencies (`dependencies: { auth: '^1.0.0' }`) validated via semver and sorted via Topological Sort.
255
+ ↓
256
+ 3. Registration Phase (pluginManager.registerSync):
257
+ - Invokes `register(ctx)` for each plugin.
258
+ - Named middlewares added to `ctx.middlewares`.
259
+ - Shutdown disposers registered via `ctx.shutdownManager.registerDisposer`.
260
+ - Plugin `plugin.csp` directives merged into Helmet CSP policy.
261
+ ↓
262
+ 4. Route Discovery & Setup:
263
+ - `mountPages` registers file-based routes.
264
+ - `pluginManager.setRoutes(routeMetadata)` exposes route metadata to plugins.
265
+ ↓
266
+ 5. onRoutesReady Hook Phase:
267
+ - Invokes `onRoutesReady(ctx)` for each plugin.
268
+ - Plugins attach custom routes and Nunjucks helpers via `ctx.addRoute()`, `ctx.addHelper()`, `ctx.addFilter()`.
269
+ ↓
270
+ 6. Runtime Operation:
271
+ - Routes and templates consume plugin APIs via `fsy.*`, `usePlugin(name)`, `req.service()`.
272
+ ↓
273
+ 7. Shutdown / Dispose Phase:
274
+ - Server shutdown triggered (`app.close()` or SIGTERM/SIGINT) via `ShutdownManager`.
275
+ - Registered `disposer` functions execute asynchronously in **reverse registration order** (LIFO).
276
+ ```
277
+
278
+ ---
279
+
280
+ ## 7. Public API Inventory
281
+
282
+ | API / Export | Location | Classification | Rationale & Notes |
283
+ | :--- | :--- | :--- | :--- |
284
+ | `createApp` (SSR) | `src/server.js`, `index.js` | **Stable candidate** | Main framework entry point. Core contract across 170+ tests. |
285
+ | `mountPages` / File Router | `src/file-router.js` | **Stable candidate** | File-based routing and server loader mechanism. |
286
+ | `defineModel` / `zdb` | `core/orm` | **Stable candidate** | Knex-based ORM and schema definition builder. |
287
+ | `createDatabase` | `core/orm` | **Stable candidate** | Knex + repository management. |
288
+ | `createServiceRegistry` / `defineService` | `src/services` | **Stable candidate** | Services layer API, Zod validation, and RBAC guards. |
289
+ | `errors.*` (WebspressoError, HttpError, etc.) | `core/errors` | **Stable candidate** | Central framework exception hierarchy. |
290
+ | `ShutdownManager` / `NodeHttpAdapter` | `core/shutdown` | **Stable candidate** | Graceful shutdown and socket draining manager. |
291
+ | `res.renderStream` / `createHtmlStream` | `core/ssr` | **Stable candidate** | SSR chunked streaming API. |
292
+ | `fsy.*` helpers (`asset`, `css`, `js`, `img`) | `src/helpers.js` | **Stable candidate** | Nunjucks template helper catalog. |
293
+ | `setAppContext` / `getDb` / `getAppContext` | `src/app-context.js` | **Needs cleanup** | Global singleton state. Retained for backward compatibility; replaced internally by `req.context`. |
294
+ | `compileSchema` / `applySchema` | `core/compileSchema.js` | **Stabilized** | Unified around `core/validation/index.js`. |
295
+ | `adminPanelPlugin` / `adminApi` | `plugins/admin-panel` | **Stable candidate** | Mithril.js admin panel module and widget registration API. |
296
+ | `realtimePlugin` / `createRealtime` | `plugins/realtime`, `core/realtime` | **Stable candidate** | WebSocket/SSE/Socket.IO adapter API. |
297
+ | `queuePlugin` / `createQueueManager` | `plugins/queue`, `core/queue` | **Stable candidate** | Memory/DB/Redis background queue API. |
298
+ | `basicAuthPlugin`, `corsPlugin`, `csrfPlugin` | `plugins/*` | **Stable candidate** | Zero-dependency security plugins. |
299
+ | `content` / `contentPlugin` | `core/content`, `plugins/content` | **Needs cleanup** | Headless CMS schema engine with slight overlap with ORM models. |
300
+ | `kernel` (`createApp`, `definePlugin`, `defineFlow`) | `core/kernel` | **Experimental / Standalone** | Isolated standalone mini-kernel. |
301
+ | `req.input` vs `validatedInput` | API / Services | **Stabilized** | API routes use `req.input`, services use validated handler argument via shared Zod core. |
302
+ | CLI commands (`webspresso *`) | `bin/commands/*` | **Stable candidate** | `dev`, `migrate`, `doctor`, `favicon:generate`, `seed` CLI contracts. |
303
+
304
+ ---
305
+
306
+ ## 8. Runtime Dependencies Analysis
307
+
308
+ ```text
309
+ ┌────────────────────────────────────────────────────────────────────────┐
310
+ │ WEBSPRESSO RUNTIME MATRIX │
311
+ ├──────────────────────────┬─────────────────────────────────────────────┤
312
+ │ Runtime-independent │ • core/errors (Error class hierarchy) │
313
+ │ (Pure JS Logic) │ • core/orm/types, model definitions │
314
+ │ │ • core/realtime/registry, reconnect-manager │
315
+ │ │ • core/content/schema, field-types │
316
+ │ │ • src/services/validator, memoize (core) │
317
+ │ │ • core/url-path-normalize.js │
318
+ ├──────────────────────────┼─────────────────────────────────────────────┤
319
+ │ Node-specific │ • core/shutdown (process.on, SIGTERM/SIGINT)│
320
+ │ (Node.js Built-in APIs) │ • core/orm/transaction (AsyncLocalStorage) │
321
+ │ │ • core/compression (native zlib streams) │
322
+ │ │ • src/server.js (renderStackStorage ALS) │
323
+ │ │ • core/auth/jwt, hash (crypto module) │
324
+ │ │ • src/file-router.js (fs, path scanning) │
325
+ │ │ • core/queue (EventEmitter, timers) │
326
+ ├──────────────────────────┼─────────────────────────────────────────────┤
327
+ │ Express-specific │ • src/server.js (express(), app.use, etc.) │
328
+ │ (Tight Express Coupling) │ • src/file-router.js (req, res, next chain) │
329
+ │ │ • plugins/* (Express route handlers) │
330
+ │ │ • core/auth/middleware.js (Express MWs) │
331
+ │ │ • core/ssr/stream.js (res.write, res.flush) │
332
+ ├──────────────────────────┼─────────────────────────────────────────────┤
333
+ │ Webspresso-specific │ • Nunjucks Safe Engine & Extensions │
334
+ │ (Framework Domain) │ • Model Repository & Query Builder │
335
+ │ │ • File Router Loader & Meta Conventions │
336
+ │ │ • Mithril Admin SPA Module Contract │
337
+ └──────────────────────────┴─────────────────────────────────────────────┘
338
+ ```
339
+
340
+ ---
341
+
342
+ ## 9. Architectural Conflict Resolutions
343
+
344
+ ### Conflict 1: `core/kernel` vs Main Framework (`src/server.js`, `src/services`, `core/orm`)
345
+ - **Resolution**: The main SSR framework (`src/server.js`, `src/plugin-manager.js`, `core/orm`) is the canonical framework architecture. `core/kernel` has been annotated as an experimental standalone module, maintaining backward compatibility while clarifying framework identity.
346
+
347
+ ### Conflict 2: API Validation (`compileSchema`) vs Service Validation (`services/validator`)
348
+ - **Resolution**: Extracted a unified validation utility (`core/validation/index.js`) providing extended Zod instances (`z.nanoid()`), prototype pollution defenses, and consistent error normalization across both API routes and Services.
349
+
350
+ ### Conflict 3: Three Distinct Event / Hook Mechanisms
351
+ - **Canonical Scopes**:
352
+ - `pages/_hooks.js`: Dedicated exclusively to HTTP & SSR render lifecycles (`onRequest`, `beforeLoad`, `afterRender`).
353
+ - `ModelEvents`: Dedicated exclusively to database / model mutations (`User.beforeCreate`, `User.afterSave`).
354
+ - `core/kernel/events.js`: Isolated alongside the standalone kernel.
355
+
356
+ ### Conflict 4: Implicit Global Context vs Instance Request Context
357
+ - **Resolution**: Formalized Express `req.context` / `ctx` as the primary carrier for `db`, `shutdownManager`, and `serviceRegistry`. `src/app-context.js` is preserved as a fallback for external caller compatibility.
358
+
359
+ ---
360
+
361
+ ## 10. Technical Debt & Stabilization Summary
362
+
363
+ | Priority | Area | Files | Status | Action Taken |
364
+ | :---: | :--- | :--- | :---: | :--- |
365
+ | **MEDIUM** | SQLite Default Value Warnings | `core/orm/index.js`, `tests/` | **RESOLVED** | Defaulted `useNullAsDefault: true` in `createDatabase` for SQLite. |
366
+ | **LOW** | Linear URL Path Trimming | `src/services/discovery.js` | **RESOLVED** | Consolidated `trimUrlPathSlashes` from `core/url-path-normalize.js`. |
367
+ | **HIGH** | TypeScript Definition Sync | `index.d.ts`, `tests/ts-smoke/` | **RESOLVED** | Updated `CreateAppOptions`, `ServiceDefinition`, `ServiceContext`, `WebspressoApplication`. |
368
+ | **MEDIUM** | Shared Zod Validation Core | `core/validation/index.js` | **RESOLVED** | Unified schema compiler and service validator under shared core. |
369
+ | **MEDIUM** | Standalone Kernel Isolation | `core/kernel/`, `index.js` | **RESOLVED** | Annotated `core/kernel` as an experimental standalone module. |
370
+ | **MEDIUM** | Formal Request Context | `src/server.js`, `src/file-router.js` | **RESOLVED** | Bound `req.context` container across all request flows. |
371
+
372
+ ---
373
+
374
+ ## 11. Test Coverage & Verification
375
+
376
+ ### Verified Test Metrics:
377
+ - **Test Files**: 176 test suites (including unit, integration, and security suites)
378
+ - **Total Tests**: 2,109 tests
379
+ - **Status**: 100% Passed (0 failed, 0 skipped)
380
+ - **Execution Time**: ~60–75 seconds
381
+
382
+ ---
383
+
384
+ ## 12. Risk Register
385
+
386
+ | Risk ID | Risk Description | Probability | Impact | Mitigation Strategy | Status |
387
+ | :---: | :--- | :---: | :---: | :--- | :---: |
388
+ | **R-01** | Global state collisions in multi-app tests | Low | High | Use `req.context` and pass database/service instances via container. | **MITIGATED** |
389
+ | **R-02** | Confusion between SSR and Kernel `createApp` | Low | Medium | Annotate `core/kernel` as standalone experimental module. | **MITIGATED** |
390
+ | **R-03** | Native binary version mismatch (`better-sqlite3`) | Low | High | Enforce Node.js 20 LTS target via `.nvmrc` and CI scripts. | **ACTIVE** |
391
+ | **R-04** | Zod validation divergence between API and Services | Low | Medium | Standardize on unified `core/validation/index.js`. | **MITIGATED** |
392
+
393
+ ---
394
+
395
+ ## 13. Stabilization Backlog
396
+
397
+ ```mermaid
398
+ graph TD
399
+ P0[Phase 0: Baseline & Test Verification] --> P1[Phase 1: Dead/Duplicate Cleanup]
400
+ P1 --> P2[Phase 2: Contract Stabilization]
401
+ P2 --> P3[Phase 3: Architecture Consolidation]
402
+ P3 --> P4[Phase 4: Runtime Boundaries]
403
+ P4 --> P5[Phase 5: Documentation Restructuring]
404
+ ```
405
+
406
+ ### Backlog Status:
407
+ - [x] **`P0-01`**: Verify baseline test suite and native binary compatibility (Node 20 LTS).
408
+ - [x] **`P1-01`**: Fix SQLite `useNullAsDefault` warnings in Knex configurations.
409
+ - [x] **`P1-02`**: Consolidate internal URL path trimming utilities.
410
+ - [x] **`P2-01`**: Synchronize `index.d.ts` with `createApp` and plugin options.
411
+ - [x] **`P3-01`**: Unify Zod validation extensions across API and Services (`core/validation`).
412
+ - [x] **`P3-02`**: Isolate `core/kernel` and annotate as experimental/standalone.
413
+ - [x] **`P4-01`**: Formalize Request Context container (`req.context`) to reduce global state reliance.
414
+ - [x] **`DOC-P1..P8`**: Complete documentation audit and restructuring (`docs/`, `llms.txt`, slimmed `README.md`).
415
+
416
+ ---
417
+
418
+ ## 14. "Do Not Touch" Core Invariants
419
+
420
+ The following components are highly stable, thoroughly tested, and performant in production. They must **not** be modified solely for aesthetic refactoring:
421
+
422
+ 1. **`src/file-router.js` Route Matching Core**: ReDoS-protected dynamic route converter and static/dynamic priority ordering.
423
+ 2. **`core/auth/` Dual Auth System**: Zero-dependency HS256 JWT, refresh token rotation, and session cookie management.
424
+ 3. **`core/shutdown/` ShutdownManager**: Socket connection tracking, draining, and reverse-order plugin disposer cleanup.
425
+ 4. **`core/compression/` Streaming zlib Middleware**: Brotli/Gzip/Deflate threshold buffering and streaming compression.
426
+ 5. **`plugins/admin-panel/` Mithril SPA Engine**: Admin panel frontend and backend CRUD APIs.
427
+ 6. **`core/orm/transaction.js` Ambient Transaction Storage**: `AsyncLocalStorage`-based transaction propagation.
428
+ 7. **Express 5 Framework Core**: Primary HTTP engine foundation.
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: webspresso-admin-and-plugins
3
+ description: >-
4
+ Extend the Mithril.js Admin Panel SPA and configure official plugins in Webspresso.
5
+ Use when creating custom admin pages (component.js, page.json), custom field renderers,
6
+ dashboard widgets, actions, or configuring plugins like fileManager, xlsx, csv, polar, realtime, csrf, cors, and basicAuth.
7
+ ---
8
+
9
+ # Webspresso Admin Panel & Plugins Skill
10
+
11
+ The Admin Panel is a modular Mithril.js SPA mounted at `/_admin` powered by `adminPanelPlugin({ db })`.
12
+
13
+ ---
14
+
15
+ ## 1. Custom Admin Pages (`pagesDir` or `registerPageDir`)
16
+
17
+ Folder structure for auto-discovered admin pages:
18
+ ```text
19
+ admin/pages/
20
+ └── system-stats/
21
+ ├── page.json
22
+ └── component.js
23
+ ```
24
+
25
+ ### `page.json`
26
+ ```json
27
+ {
28
+ "id": "system-stats",
29
+ "label": "System Statistics",
30
+ "icon": "activity",
31
+ "order": 10,
32
+ "layout": true,
33
+ "permission": "admin"
34
+ }
35
+ ```
36
+
37
+ ### `component.js` (Clean Mithril Component)
38
+ ```javascript
39
+ module.exports = {
40
+ oninit(vnode) {
41
+ vnode.state.stats = null;
42
+ vnode.state.loading = true;
43
+ m.request({ method: 'GET', url: '/_admin/api/custom/stats' }).then((res) => {
44
+ vnode.state.stats = res;
45
+ vnode.state.loading = false;
46
+ });
47
+ },
48
+ view(vnode) {
49
+ if (vnode.state.loading) return m('.p-6', 'Loading stats...');
50
+ return m('.space-y-4', [
51
+ m('h2.text-xl.font-bold', 'System Overview'),
52
+ m('.grid.grid-cols-3.gap-4', [
53
+ m('.card.p-4.border.rounded', [
54
+ m('.text-sm.text-gray-500', 'Total Users'),
55
+ m('.text-2xl.font-semibold', vnode.state.stats.usersCount),
56
+ ]),
57
+ ]),
58
+ ]);
59
+ },
60
+ };
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 2. Admin Panel Extension Points
66
+
67
+ ```javascript
68
+ // Register custom widget in dashboard
69
+ registry.registerWidget('recent-signups', {
70
+ label: 'Recent Signups',
71
+ component: require('./widgets/recent-signups'),
72
+ width: 'half', // 'full' | 'half' | 'third'
73
+ });
74
+
75
+ // Register single record action button
76
+ registry.registerAction('User', {
77
+ name: 'impersonate',
78
+ label: 'Impersonate',
79
+ icon: 'user-check',
80
+ handler: async (record) => { ... },
81
+ });
82
+
83
+ // Register custom field display/edit renderer
84
+ registry.registerFieldRenderer('color-picker', {
85
+ display: (val) => m('.w-6.h-6.rounded', { style: { backgroundColor: val } }),
86
+ edit: (val, onChange) => m('input[type=color]', { value: val, onchange: (e) => onChange(e.target.value) }),
87
+ });
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 3. Official Plugin Catalog & Usage
93
+
94
+ In `createApp({ plugins: [...] })`:
95
+
96
+ ```javascript
97
+ const {
98
+ adminPanelPlugin,
99
+ fileManagerPlugin,
100
+ xlsxPlugin,
101
+ csvPlugin,
102
+ basicAuthPlugin,
103
+ corsPlugin,
104
+ csrfPlugin,
105
+ realtimePlugin,
106
+ polarPlugin,
107
+ } = require('webspresso/plugins');
108
+
109
+ createApp({
110
+ plugins: [
111
+ adminPanelPlugin({ db }),
112
+ fileManagerPlugin({ baseDir: './public/uploads', publicBasePath: '/uploads' }),
113
+ xlsxPlugin(),
114
+ csvPlugin(),
115
+ basicAuthPlugin({ users: { admin: process.env.ADMIN_BASIC_AUTH_PASS }, routes: ['/metrics'] }),
116
+ corsPlugin({ origin: ['https://example.com'], credentials: true }),
117
+ csrfPlugin({ cookie: true }),
118
+ realtimePlugin({ adapter: 'websocket' }),
119
+ polarPlugin({ apiKey: process.env.POLAR_ACCESS_TOKEN }),
120
+ ],
121
+ });
122
+ ```
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: webspresso-framework
3
+ description: >-
4
+ Core workflow and guide for Webspresso, a lightweight, zero-dependency-sprawl full-stack
5
+ Node.js SSR and API framework. Use when scaffolding, architecting, building, or debugging
6
+ Webspresso applications, configuring plugins, dual auth, response compression, graceful shutdown,
7
+ and error boundaries.
8
+ ---
9
+
10
+ # Webspresso Framework Master Guide
11
+
12
+ Webspresso is a lightweight, zero-dependency-sprawl full-stack Node.js SSR & API framework featuring Next.js/Nuxt-style file-based routing, an intuitive Knex-based ORM, a modular plugin ecosystem, and a customizable Mithril.js SPA Admin Panel.
13
+
14
+ ## 🛡️ 4-Step Mandatory Agent Workflow Protocol
15
+
16
+ 1. **Discover & Triage**: Identify relevant topic guides (`.agents/`) and inspect existing files in `pages/api/`, `models/`, `services/`.
17
+ 2. **Contract Adherence**: Export `{ schema, middleware, handler }` for APIs, `defineModel` for ORM, `defineService` for services.
18
+ 3. **Zero External Dependencies**: Core functionality relies strictly on native Node.js modules (`crypto`, `path`, `fs`, `zlib`, `events`). NEVER install ad-hoc packages for JWT, passport, express-session, or custom routers.
19
+ 4. **Targeted Verification**: Run specific Vitest unit tests (`npx vitest run tests/...`) to ensure zero regressions.
20
+
21
+ ---
22
+
23
+ ## ⚖️ Golden Rules & Anti-Patterns
24
+
25
+ | Category | ❌ NEVER DO THIS (Anti-Pattern) | ✅ ALWAYS DO THIS (Webspresso Way) |
26
+ | :--- | :--- | :--- |
27
+ | **Routing** | `routes/index.js`, `express.Router()`, `app.get('/api/users')` | `pages/api/users.get.js` exporting `{ schema, handler }` |
28
+ | **Database** | `db('users').where({ id }).select()` (Raw Knex) | `db.getRepository('User').findById(id)` |
29
+ | **Business Logic** | `controllers/UserController.js` | `services/user/get.js` → `ctx.service('user.get', input)` |
30
+ | **Auth** | `npm i jsonwebtoken passport express-session` | Built-in `req.auth`, `core/auth`, `middleware: ['jwt']` |
31
+ | **SSR Rendering**| `res.render('profile.njk', data)` inside handlers | Companion loader `pages/profile.js` exporting `async function load()` |
32
+ | **Exceptions** | `res.status(404).json({ error: 'Not found' })` | `throw new NotFoundError('User not found')` |
33
+ | **Background** | `setTimeout(...)`, `npm i bullmq` | `jobs/user/welcome.js` → `req.queue.dispatch('user.welcome', data)` |
34
+
35
+ ---
36
+
37
+ ## 🚀 CLI Commands
38
+
39
+ ```bash
40
+ webspresso dev # Start dev server with hot reload
41
+ webspresso start # Start production server
42
+ webspresso doctor # Run system sanity checks
43
+ webspresso db:migrate # Run pending Knex migrations
44
+ webspresso db:seed # Run database seeders
45
+ webspresso agents:init # Scaffold AI Agent rules and skills
46
+ ```
47
+
48
+ ---
49
+
50
+ ## 🏗️ Core Architecture Overview
51
+
52
+ - **`pages/` & `pages/api/`**: File-based SSR templates (`.njk`), companion data loaders (`.js`), and method-suffixed API endpoints (`.get.js`, `.post.js`).
53
+ - **`services/`**: Auto-discovered domain services mapping to dot-separated names (`'user.create'`).
54
+ - **`models/`**: Schema-driven ORM models with `zdb` definitions, repositories, relations, scopes, and query cache.
55
+ - **`plugins/`**: Modular extension ecosystem (Admin Panel, Media Library, Polar Billing, CSV/XLSX, Realtime, CSRF, CORS, Basic Auth).
56
+ - **`views/`**: Nunjucks layouts, partials, and `fsy` template helpers.