zyket 1.2.18 → 1.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/AGENTS.md +407 -0
- package/README.md +175 -279
- package/SECURITY.md +40 -0
- package/bin/cli.js +310 -202
- package/index.js +4 -3
- package/package.json +7 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/skills/build/SKILL.md +88 -0
- package/src/extensions/bullboard/index.js +14 -3
- package/src/extensions/interactive-storage/index.js +25 -9
- package/src/extensions/interactive-storage/routes/delete-folder.js +13 -1
- package/src/extensions/interactive-storage/routes/delete.js +14 -3
- package/src/extensions/interactive-storage/routes/download.js +22 -3
- package/src/extensions/interactive-storage/routes/info.js +13 -0
- package/src/services/auth/index.js +46 -28
- package/src/services/express/Express.js +32 -15
- package/src/services/express/RequireAdminMiddleware.js +14 -0
- package/src/services/express/RequireAuthMiddleware.js +46 -0
- package/src/services/express/index.js +7 -5
- package/src/services/socketio/AuthGuard.js +33 -0
- package/src/services/socketio/SocketIO.js +3 -1
- package/src/services/socketio/index.js +2 -1
- package/src/services/template-manager/index.js +1 -0
- package/src/templates/api-rest/.env.example +24 -0
- package/src/templates/api-rest/README.md +50 -0
- package/src/templates/api-rest/index.js +18 -0
- package/src/templates/api-rest/src/models/Task.js +18 -0
- package/src/templates/api-rest/src/routes/tasks/[id].js +42 -0
- package/src/templates/api-rest/src/routes/tasks/index.js +26 -0
- package/src/templates/api-rest/src/services/auth/auth.js +9 -0
- package/src/templates/api-rest/src/services/auth/index.js +23 -0
- package/src/templates/realtime-chat/.env.example +26 -0
- package/src/templates/realtime-chat/README.md +38 -0
- package/src/templates/realtime-chat/frontend/.env.example +3 -0
- package/src/templates/realtime-chat/frontend/index.html +12 -0
- package/src/templates/realtime-chat/frontend/main.jsx +18 -0
- package/src/templates/realtime-chat/frontend/src/hooks/useAuth.jsx +27 -0
- package/src/templates/realtime-chat/frontend/src/hooks/useChatSocket.jsx +29 -0
- package/src/templates/realtime-chat/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
- package/src/templates/realtime-chat/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
- package/src/templates/realtime-chat/frontend/src/store/storeAuth.jsx +11 -0
- package/src/templates/realtime-chat/frontend/src/views/AuthView.jsx +70 -0
- package/src/templates/realtime-chat/frontend/src/views/ChatView.jsx +69 -0
- package/src/templates/realtime-chat/frontend/styles.css +1 -0
- package/src/templates/realtime-chat/frontend/vite.config.js +7 -0
- package/src/templates/realtime-chat/index.js +14 -0
- package/src/templates/realtime-chat/src/guards/auth.js +3 -0
- package/src/templates/realtime-chat/src/handlers/connection.js +23 -0
- package/src/templates/realtime-chat/src/handlers/message.js +29 -0
- package/src/templates/realtime-chat/src/services/auth/auth.js +8 -0
- package/src/templates/realtime-chat/src/services/auth/index.js +19 -0
- package/src/templates/saas-multitenant/.env.example +22 -0
- package/src/templates/saas-multitenant/README.md +71 -0
- package/src/templates/saas-multitenant/frontend/.env.example +3 -0
- package/src/templates/saas-multitenant/frontend/index.html +12 -0
- package/src/templates/saas-multitenant/frontend/main.jsx +18 -0
- package/src/templates/saas-multitenant/frontend/src/hooks/useAuth.jsx +27 -0
- package/src/templates/saas-multitenant/frontend/src/hooks/useProjects.jsx +41 -0
- package/src/templates/saas-multitenant/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
- package/src/templates/saas-multitenant/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
- package/src/templates/saas-multitenant/frontend/src/store/storeAuth.jsx +13 -0
- package/src/templates/saas-multitenant/frontend/src/views/AuthView.jsx +70 -0
- package/src/templates/saas-multitenant/frontend/src/views/DashboardView.jsx +131 -0
- package/src/templates/saas-multitenant/frontend/styles.css +1 -0
- package/src/templates/saas-multitenant/frontend/vite.config.js +7 -0
- package/src/templates/saas-multitenant/index.js +14 -0
- package/src/templates/saas-multitenant/src/middlewares/RequireOrganization.js +22 -0
- package/src/templates/saas-multitenant/src/models/Project.js +17 -0
- package/src/templates/saas-multitenant/src/routes/admin/stats.js +15 -0
- package/src/templates/saas-multitenant/src/routes/projects/index.js +34 -0
- package/src/templates/saas-multitenant/src/services/auth/auth.js +8 -0
- package/src/templates/saas-multitenant/src/services/auth/index.js +43 -0
- package/src/utils/EnvManager.js +23 -0
package/README.md
CHANGED
|
@@ -1,279 +1,175 @@
|
|
|
1
|
-
# Zyket
|
|
2
|
-
|
|
3
|
-
Zyket is a Node.js framework
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Getting
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
npx
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
// src/
|
|
98
|
-
const {
|
|
99
|
-
|
|
100
|
-
module.exports = class
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
console.log("MyCustomService has been booted!");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
doSomething() {
|
|
180
|
-
return "Something was done.";
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Register the service in your main `index.js` file:
|
|
186
|
-
|
|
187
|
-
```javascript
|
|
188
|
-
// index.js
|
|
189
|
-
const { Kernel } = require("zyket");
|
|
190
|
-
const MyCustomService = require("./src/services/MyCustomService");
|
|
191
|
-
|
|
192
|
-
const kernel = new Kernel({
|
|
193
|
-
services: [
|
|
194
|
-
// [name, class, [constructor_args]]
|
|
195
|
-
["my-service", MyCustomService, []]
|
|
196
|
-
]
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
kernel.boot();
|
|
200
|
-
```
|
|
201
|
-
Services are reusable components specified in the kernel configuration. Each service must include a boot() function that is executed when the kernel starts.
|
|
202
|
-
|
|
203
|
-
```javascript
|
|
204
|
-
module.exports = class LoggerService {
|
|
205
|
-
this.#container;
|
|
206
|
-
|
|
207
|
-
boot(container, enableLogging = true) {
|
|
208
|
-
this.#container = container;
|
|
209
|
-
console.log("LoggerService Booted");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
info(message) {
|
|
213
|
-
if(!enableLogging) return;
|
|
214
|
-
console.log(`[INFO]: ${message}`);
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Then, when booting the kernel, specify the service:
|
|
220
|
-
|
|
221
|
-
```javascript
|
|
222
|
-
const { Kernel } = require("zyket");
|
|
223
|
-
const LoggerService = require("./LoggerService");
|
|
224
|
-
|
|
225
|
-
const kernel = new Kernel({
|
|
226
|
-
services: [["logger", LoggerService, ['@service_container', true]],
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
kernel.boot().then(() => console.log(`Kernel Booted`));
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
## Default Services
|
|
233
|
-
Zyket includes some default services that provide essential functionality. These services can be overridden or extended if needed.
|
|
234
|
-
|
|
235
|
-
#### Cache Services
|
|
236
|
-
- **Name** `cache`
|
|
237
|
-
- **Description** Provides caching functionality using a Redis adapter.
|
|
238
|
-
- **Configuration** Add `CACHE_URL` in your `.env` file to activate caching.
|
|
239
|
-
|
|
240
|
-
#### Database Service
|
|
241
|
-
- **Name** `database`
|
|
242
|
-
- **Description** Manages database connections using a MariaDB/Sequelize adapter.
|
|
243
|
-
- **Configuration** Add `DATABASE_URL` in your `.env` file to enable the database connection.
|
|
244
|
-
|
|
245
|
-
#### S3 Service
|
|
246
|
-
- **Name** `s3`
|
|
247
|
-
- **Description** Provides S3-compatible object storage using MinIO.
|
|
248
|
-
- **Configuration** Add the following variables in your `.env` file to enable the service
|
|
249
|
-
- `S3_ENDPOINT`
|
|
250
|
-
- `S3_PORT`
|
|
251
|
-
- `S3_USE_SSL`
|
|
252
|
-
- `S3_ACCESS_KEY`
|
|
253
|
-
- `S3_SECRET_KEY`
|
|
254
|
-
|
|
255
|
-
#### Logger Service
|
|
256
|
-
- **Name** `logger`
|
|
257
|
-
- **Description** Handles logging for the application.
|
|
258
|
-
- **Configuration**
|
|
259
|
-
- Change `LOG_DIRECTORY` in `.env` file to set a custom log directory.
|
|
260
|
-
- Set `DEBUG` in `.env` file to enable or disable debug logging.
|
|
261
|
-
|
|
262
|
-
#### Socket.io Service
|
|
263
|
-
- **Name** `socketio`
|
|
264
|
-
- **Description** Manages the WebSocket server.
|
|
265
|
-
- **Configuration** Add `PORT` in your `.env` file to define the listening port for Socket.io.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
## Contributing
|
|
269
|
-
|
|
270
|
-
We welcome contributions from the community! If you'd like to improve Zyket, feel free to:
|
|
271
|
-
|
|
272
|
-
- Report issues and suggest features on GitHub Issues
|
|
273
|
-
|
|
274
|
-
- Submit pull requests with bug fixes or enhancements
|
|
275
|
-
|
|
276
|
-
- Improve the documentation
|
|
277
|
-
|
|
278
|
-
Let's build a better framework together! 🚀
|
|
279
|
-
|
|
1
|
+
# Zyket
|
|
2
|
+
|
|
3
|
+
Zyket is a service-oriented Node.js framework for building real-time and REST applications with **Express 5**, **Socket.IO**, **better-auth**, and **Sequelize/BullMQ/MinIO**. Inspired by Symfony, it pairs a dependency-injection container with filesystem-based auto-discovery: drop a file in the right folder and the framework wires it up.
|
|
4
|
+
|
|
5
|
+
> **Building with an AI agent?** See **[AGENTS.md](AGENTS.md)** for a complete, machine-readable reference, and **[SECURITY.md](SECURITY.md)** for hardening guidance.
|
|
6
|
+
|
|
7
|
+
## Getting started
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mkdir my-app && cd my-app
|
|
11
|
+
npm install zyket
|
|
12
|
+
|
|
13
|
+
# Initialize from a template (interactive picker)
|
|
14
|
+
npx zyket init
|
|
15
|
+
# …or pick one directly:
|
|
16
|
+
npx zyket init api-rest # default | api-rest | saas-multitenant | realtime-chat
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`init` scaffolds the template, generates a `.env`, writes `package.json` with the right dependencies, and installs them. Templates that ship authentication need their tables created once:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @better-auth/cli migrate
|
|
23
|
+
node index.js
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Templates
|
|
27
|
+
|
|
28
|
+
| Template | What you get |
|
|
29
|
+
|----------|--------------|
|
|
30
|
+
| `default` | General starter (backend + optional React frontend) |
|
|
31
|
+
| `api-rest` | Backend-only REST API with auth and a protected CRUD resource |
|
|
32
|
+
| `saas-multitenant` | Multi-tenant SaaS (organizations, roles) + React dashboard |
|
|
33
|
+
| `realtime-chat` | Authenticated real-time chat (Socket.IO) + React UI |
|
|
34
|
+
|
|
35
|
+
### Manual boot
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
// index.js
|
|
39
|
+
const { Kernel } = require("zyket");
|
|
40
|
+
|
|
41
|
+
const kernel = new Kernel({
|
|
42
|
+
services: [
|
|
43
|
+
["auth", require("./src/services/auth"), ["@service_container"]],
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
kernel.boot().then(() => console.log("Kernel booted!"));
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
On first run Zyket creates a `.env` and a `src/` directory with boilerplate.
|
|
51
|
+
|
|
52
|
+
## Core concepts
|
|
53
|
+
|
|
54
|
+
- **Routes & Middlewares** — REST endpoints via Express, auto-discovered from `src/routes`.
|
|
55
|
+
- **Handlers & Guards** — Socket.IO events and their authorization, from `src/handlers` / `src/guards`.
|
|
56
|
+
- **Services** — reusable units managed by a DI container (`logger`, `database`, `cache`, `s3`, `events`, `scheduler`, `bullmq`, `socketio`, `express`, `auth`).
|
|
57
|
+
- **Extensions** — post-boot plugins (e.g. BullBoard, interactive storage).
|
|
58
|
+
- **Templates & CLI** — scaffold whole projects or individual components.
|
|
59
|
+
|
|
60
|
+
### Routes
|
|
61
|
+
|
|
62
|
+
File path maps to the URL: `src/routes/index.js` → `/`, `src/routes/users/[id].js` → `/users/:id`. Methods: `get`, `post`, `put`, `delete`.
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
const { Route, RequireAuthMiddleware } = require("zyket");
|
|
66
|
+
|
|
67
|
+
module.exports = class extends Route {
|
|
68
|
+
middlewares = { post: [new RequireAuthMiddleware()] };
|
|
69
|
+
|
|
70
|
+
async get({ container, request }) {
|
|
71
|
+
return { items: [] }; // → { success: true, items: [] }
|
|
72
|
+
}
|
|
73
|
+
async post({ container, request }) {
|
|
74
|
+
if (!request.body.name) return { success: false, message: "name required", status: 400 };
|
|
75
|
+
return { created: true, status: 201 };
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Return an object (wrapped as `{ success: true, ... }`), set `status` to change the HTTP code, return a `Buffer` for a download, or `new RedirectResponse(url)` to redirect.
|
|
81
|
+
|
|
82
|
+
### Middlewares
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const { Middleware } = require("zyket");
|
|
86
|
+
|
|
87
|
+
module.exports = class extends Middleware {
|
|
88
|
+
async handle({ container, request, response, next }) {
|
|
89
|
+
next(); // respond to block, or next() to continue
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Socket.IO handlers & guards
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
// src/handlers/message.js → "message" event
|
|
98
|
+
const { Handler } = require("zyket");
|
|
99
|
+
|
|
100
|
+
module.exports = class extends Handler {
|
|
101
|
+
guards = ["auth"];
|
|
102
|
+
async handle({ container, socket, data, io }) {
|
|
103
|
+
io.emit("message", data);
|
|
104
|
+
return { ok: true };
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
// src/guards/auth.js — reuse the built-in session guard
|
|
111
|
+
module.exports = require("zyket").AuthGuard;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Authentication
|
|
115
|
+
|
|
116
|
+
Zyket ships first-class auth via [better-auth](https://better-auth.com) mounted at `/api/auth/*`, with the admin, bearer, and (optional) organization plugins. Customize by subclassing `AuthService`; protect routes/sockets with `RequireAuthMiddleware`, `RequireAdminMiddleware`, and `AuthGuard`.
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
const { Route, RequireAdminMiddleware } = require("zyket");
|
|
120
|
+
|
|
121
|
+
module.exports = class extends Route {
|
|
122
|
+
middlewares = { get: [new RequireAdminMiddleware()] };
|
|
123
|
+
async get() { return { secret: "admins only" }; }
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Cookies are environment-aware: `sameSite=lax` in local dev (works over `http://localhost`), and `sameSite=none; secure` when `AUTH_CROSS_DOMAIN=true` for cross-domain HTTPS deployments. See [AGENTS.md §6](AGENTS.md#6-authentication-better-auth).
|
|
128
|
+
|
|
129
|
+
## Services
|
|
130
|
+
|
|
131
|
+
Default services activate from environment variables (see [AGENTS.md §3–4](AGENTS.md#3-environment-variables)). Register your own in the Kernel:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
const { Service } = require("zyket");
|
|
135
|
+
|
|
136
|
+
module.exports = class MyService extends Service {
|
|
137
|
+
#container;
|
|
138
|
+
constructor(container) { super("my-service"); this.#container = container; }
|
|
139
|
+
async boot() { /* init */ }
|
|
140
|
+
doThing() { return "done"; }
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
const kernel = new Kernel({
|
|
146
|
+
services: [["my-service", MyService, ["@service_container"]]],
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Default services and their activation:
|
|
151
|
+
|
|
152
|
+
| Service | Env to enable |
|
|
153
|
+
|---------|---------------|
|
|
154
|
+
| `database` | `DATABASE_URL` (+ `DATABASE_DIALECT`, default `sqlite`) |
|
|
155
|
+
| `cache` | always (`CACHE_URL=redis://…` for Redis, else in-memory) |
|
|
156
|
+
| `s3` | `S3_ENDPOINT` + `S3_ACCESS_KEY` + `S3_SECRET_KEY` (MinIO) |
|
|
157
|
+
| `socketio` | `DISABLE_SOCKET=false` |
|
|
158
|
+
| `bullmq` | `DISABLE_BULLMQ=false` + `QUEUES=...` |
|
|
159
|
+
| `scheduler` | `DISABLE_SCHEDULER=false` |
|
|
160
|
+
| `events` | `DISABLE_EVENTS=false` |
|
|
161
|
+
| `vite` | `VITE_ROOT` + `DISABLE_VITE=false` |
|
|
162
|
+
| `auth` | manual registration (requires `sqlite`/`postgresql`) |
|
|
163
|
+
|
|
164
|
+
## Security
|
|
165
|
+
|
|
166
|
+
Zyket bakes in several defaults (random per-project `AUTH_SECRET`, fail-closed BullBoard, configurable payload limits, path-traversal guards on storage). Review **[SECURITY.md](SECURITY.md)** before going to production — notably rate limiting and `helmet` are not bundled.
|
|
167
|
+
|
|
168
|
+
## Tooling for AI agents
|
|
169
|
+
|
|
170
|
+
- **[AGENTS.md](AGENTS.md)** — full framework reference.
|
|
171
|
+
- **Claude Code plugin** (`plugin/`) — skills to scaffold and use Zyket (`generate`, `build`).
|
|
172
|
+
|
|
173
|
+
## Contributing
|
|
174
|
+
|
|
175
|
+
Issues and pull requests are welcome — bug fixes, features, and documentation improvements. Let's build a better framework together. 🚀
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Seguridad — Zyket
|
|
2
|
+
|
|
3
|
+
Auditoría de seguridad del framework y estado de las correcciones.
|
|
4
|
+
Leyenda: `[x]` hecho · `[ ]` pendiente · 🔴 crítico · 🟠 alto · 🟡 medio · 🔵 bajo
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ✅ Resuelto
|
|
9
|
+
|
|
10
|
+
- [x] 🔴 **`.env` ignorado en git.** Añadido `.env` / `*.sqlite` al `.gitignore` para evitar fuga de `AUTH_SECRET`, claves S3 y credenciales de BD.
|
|
11
|
+
- [x] 🔴 **`AUTH_SECRET` aleatorio + fail-closed.** `#addAuthEnvVariables` genera ahora un secreto con `crypto.randomBytes(32)` por proyecto y lo inyecta en `process.env` para el primer arranque. `#requireAuthSecret()` aborta el boot si el secreto falta o es uno de los valores estáticos conocidos. → [src/services/auth/index.js](src/services/auth/index.js)
|
|
12
|
+
- [x] 🔴 **Autenticación en Storage realmente aplicada.** Antes los `middlewares` del constructor se guardaban pero no se usaban; ahora se aplican a todas las rutas y métodos (auth antes de multer en `upload`). La autenticación se inyecta vía `new InteractiveStorageExtension({ middlewares: [authMiddleware] })`. → [src/extensions/interactive-storage/index.js](src/extensions/interactive-storage/index.js)
|
|
13
|
+
- [x] 🔴 **BullBoard fail-closed.** Si no hay `BULLBOARD_ADMIN_PASSWORD` ni `middlewares`, el panel **no se monta** (antes quedaba público). Soporta `middlewares` por constructor. → [src/extensions/bullboard/index.js](src/extensions/bullboard/index.js)
|
|
14
|
+
- [x] 🟠 **Inyección de cabecera en descarga.** `Content-Disposition` ahora sanea el nombre (basename + ASCII filtrado + `filename*=UTF-8''`) evitando breakout de comillas/CRLF. → [src/extensions/interactive-storage/routes/download.js](src/extensions/interactive-storage/routes/download.js)
|
|
15
|
+
- [x] 🟠 **Path traversal en `normalizePath`.** Se eliminan segmentos `..` / `.` además de normalizar slashes. → [src/extensions/interactive-storage/index.js](src/extensions/interactive-storage/index.js#L150)
|
|
16
|
+
- [x] 🟡 **Límite en borrado masivo.** `delete` ahora rechaza lotes mayores a `maxDeleteBatch` (por defecto 100, configurable en el constructor de la extensión) → evita borrado masivo / agotamiento de recursos en una sola petición. → [src/extensions/interactive-storage/routes/delete.js](src/extensions/interactive-storage/routes/delete.js)
|
|
17
|
+
- [x] 🟡 **`requireEmailVerification` personalizable.** Nuevo getter `requireEmailVerification` (por defecto `false`, manteniendo el comportamiento previo) sobreescribible al extender `AuthService`. → [src/services/auth/index.js](src/services/auth/index.js#L71)
|
|
18
|
+
- [x] 🟡 **Límite en borrado de carpeta.** `delete-folder` rechaza prefijos con más de `maxDeleteBatch` archivos (mismo tope configurable que `delete`). → [src/extensions/interactive-storage/routes/delete-folder.js](src/extensions/interactive-storage/routes/delete-folder.js)
|
|
19
|
+
- [x] 🟠 **Validación de `fileName` en `download`/`info`.** Se rechazan (`400`) claves con segmentos `..`/`.`, backslashes o que empiecen por `/` antes de llegar al cliente S3. → [download.js](src/extensions/interactive-storage/routes/download.js), [info.js](src/extensions/interactive-storage/routes/info.js)
|
|
20
|
+
- [x] 🟡 **Límites de payload configurables (default 10 MB).** Body JSON vía `HTTP_JSON_LIMIT` y socket vía `SOCKET_MAX_HTTP_BUFFER_SIZE` (ambos por defecto 10 MB, incluidos en el `.env` generado). → [Express.js](src/services/express/Express.js#L32), [SocketIO.js](src/services/socketio/SocketIO.js#L32), [EnvManager.js](src/utils/EnvManager.js)
|
|
21
|
+
- [x] 🟡 **Swagger protegible opcionalmente.** `SWAGGER_PASSWORD` activa HTTP Basic auth (usuario configurable con `SWAGGER_USER`, default `admin`); `DISABLE_SWAGGER=true` lo desactiva por completo. Si queda abierto se emite un warning. → [src/services/express/Express.js](src/services/express/Express.js#L44)
|
|
22
|
+
- [x] 🟡 **No se filtra `error.message` al cliente.** Las 4 respuestas `500` (rutas y middlewares, en `boot` y `registerRoutes`) devuelven ahora un genérico `Internal Server Error`; el detalle (incluido el stack) queda solo en los logs del servidor. → [src/services/express/Express.js](src/services/express/Express.js)
|
|
23
|
+
- [x] 🟠 **Cookies dependientes del entorno.** Ya no se fuerza `sameSite:"none"` + `secure` + cross-subdomain siempre. Por defecto `sameSite:"lax"` y `secure` solo en producción (login funciona en `http://localhost`); `AUTH_CROSS_DOMAIN=true` activa `none`+`secure`+cross-subdomain para front/back en dominios distintos (HTTPS). → [src/services/auth/index.js](src/services/auth/index.js#L126-L165)
|
|
24
|
+
- [x] 🟢 **Helpers de autorización en el framework.** Nuevos `RequireAuthMiddleware`, `RequireAdminMiddleware` (rutas) y `AuthGuard` (sockets), exportados desde `zyket`, para proteger rutas/eventos con la sesión de better-auth. → [src/services/express/RequireAuthMiddleware.js](src/services/express/RequireAuthMiddleware.js), [src/services/socketio/AuthGuard.js](src/services/socketio/AuthGuard.js)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⏳ Pendiente
|
|
29
|
+
|
|
30
|
+
### 🟠 Alto
|
|
31
|
+
- [ ] **CSRF de OAuth / account linking.** `account.skipStateCookieCheck: true` junto a `accountLinking.enabled: true` desactiva la verificación de `state` → riesgo de account takeover. Quitar `skipStateCookieCheck`. → [src/services/auth/index.js](src/services/auth/index.js#L189-L191)
|
|
32
|
+
- [ ] **Socket.IO CORS `origin:"*"` + guard por defecto que no bloquea.** Restringir origins (reutilizar `TRUSTED_ORIGINS`) y que el guard por defecto deniegue sin sesión válida. → [src/services/socketio/SocketIO.js](src/services/socketio/SocketIO.js#L32), [src/templates/default/src/guards/default.js](src/templates/default/src/guards/default.js)
|
|
33
|
+
|
|
34
|
+
### 🟡 Medio
|
|
35
|
+
- [ ] **Rate limiting** (login, reset password, upload) con `express-rate-limit`. → [src/services/express/Express.js](src/services/express/Express.js)
|
|
36
|
+
- [ ] **Cabeceras de seguridad** con `helmet`. → [src/services/express/Express.js](src/services/express/Express.js)
|
|
37
|
+
|
|
38
|
+
### 🔵 Bajo / Higiene
|
|
39
|
+
- [ ] **Reducir superficie de drivers de BD** (`sqlite3` + `better-sqlite3` + `pg` + `mariadb`).
|
|
40
|
+
- [ ] **Documentar guía de despliegue seguro** (variables obligatorias en producción, HTTPS, secretos).
|