outlet-orm 6.5.0 → 7.0.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.
@@ -0,0 +1,386 @@
1
+ # Outlet ORM - Security Best Practices
2
+
3
+ [← Back to Index](SKILL.md) | [Previous: API](API.md)
4
+
5
+ > 🔐 **Security**: This guide covers backend security practices when using Outlet ORM.
6
+
7
+ ---
8
+
9
+ ## Security Checklist
10
+
11
+ ### 🔴 Critical Priority
12
+
13
+ | Action | Description | Outlet ORM Feature |
14
+ |--------|-------------|-------------------|
15
+ |`.env`in`.gitignore`| Never commit secrets | Auto-connect from .env |
16
+ | Password hashing | Bcrypt with 10+ rounds | Use`utils/hash.js`|
17
+ | SQL Injection protection | Use ORM queries | ✅ Built-in protection |
18
+ | XSS protection | Sanitize inputs/outputs | Use middleware |
19
+ | Input validation | Validate ALL user data |`static rules`+ middleware |
20
+
21
+ ### 🟠 Important Priority
22
+
23
+ | Action | Description |
24
+ |--------|-------------|
25
+ | Secure JWT | Short expiration, refresh tokens |
26
+ | Rate limiting | Limit requests per IP |
27
+ | Security headers | Use Helmet.js |
28
+ | CSRF protection | Token for forms |
29
+ | CORS setup | Whitelist origins |
30
+
31
+ ---
32
+
33
+ ## Secure Project Structure (Layered Architecture)
34
+
35
+ ```
36
+ my-project/
37
+ ├── .env # ⚠️ NEVER commit
38
+ ├── .env.example # Template without secrets
39
+ ├── .gitignore
40
+ ├── src/
41
+ │ ├── controllers/ # 🎮 HTTP handling only
42
+ │ ├── services/ # ⚙️ Business logic
43
+ │ ├── repositories/ # 📦 Data access layer
44
+ │ ├── models/ # 📊 outlet-orm models
45
+ │ ├── middlewares/ # 🔒 CRITICAL for security
46
+ │ │ ├── auth.js # JWT authentication
47
+ │ │ ├── authorization.js # RBAC permissions
48
+ │ │ ├── rateLimiter.js # Anti-DDoS
49
+ │ │ ├── validator.js # Input validation
50
+ │ │ └── errorHandler.js # Error handling
51
+ │ ├── config/ # 🔒 Centralized config
52
+ │ │ └── security.js # Rate limit, helmet, CORS
53
+ │ ├── utils/ # 🔒 Security utilities
54
+ │ │ ├── hash.js # Bcrypt password hashing
55
+ │ │ └── token.js # JWT token generation
56
+ │ └── validators/ # 🔒 Validation schemas
57
+ ├── public/ # ✅ Only public folder
58
+ ├── logs/ # 📋 Not versioned
59
+ └── tests/
60
+ ```
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Outlet ORM Built-in Security
66
+
67
+ ### ✅ SQL Injection Protection
68
+
69
+ ```javascript
70
+ // ✅ SECURE - Parameters automatically escaped
71
+ const users = await User.where('email', userInput).get();
72
+
73
+ // ✅ SECURE - whereIn with array
74
+ const users = await User.whereIn('id', [1, 2, 3]).get();
75
+
76
+ // ⚠️ CAUTION with whereRaw - escape manually
77
+ const users = await User.whereRaw('email = ?', [userInput]).get();
78
+ ```
79
+
80
+ ### ✅ Mass Assignment Protection
81
+
82
+ ```javascript
83
+ class User extends Model {
84
+ // 🔒 Only these fields can be mass-assigned
85
+ static fillable = ['name', 'email'];
86
+
87
+ // 'role', 'is_admin' excluded = cannot be modified via create/fill
88
+ }
89
+
90
+ // ✅ SECURE - role is ignored even if in req.body
91
+ const user = await User.create(req.body);
92
+ ```
93
+
94
+ ### ✅ Hidden Attributes
95
+
96
+ ```javascript
97
+ class User extends Model {
98
+ // 🔒 Never exposed in JSON
99
+ static hidden = ['password', 'refresh_token', 'reset_token'];
100
+ }
101
+
102
+ const user = await User.find(1);
103
+ console.log(user.toJSON());
104
+ // { id: 1, name: "John", email: "..." }
105
+ // password is NOT included
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Secure Model Example
111
+
112
+ ```javascript
113
+ const { Model } = require('outlet-orm');
114
+ const { hashPassword, verifyPassword } = require('../utils/hash');
115
+
116
+ class User extends Model {
117
+ static table = 'users';
118
+
119
+ // 🔒 Mass assignment protection
120
+ static fillable = ['name', 'email', 'password'];
121
+
122
+ // 🔒 Never expose sensitive data
123
+ static hidden = ['password', 'refresh_token', 'reset_token'];
124
+
125
+ // Type casting
126
+ static casts = {
127
+ id: 'int',
128
+ email_verified: 'boolean',
129
+ created_at: 'date'
130
+ };
131
+
132
+ // 🔒 Validation rules
133
+ static rules = {
134
+ name: 'required|string|min:2|max:100',
135
+ email: 'required|email',
136
+ password: 'required|min:8'
137
+ };
138
+
139
+ // 🔒 Hash password before saving
140
+ static boot() {
141
+ this.creating(async (user) => {
142
+ const password = user.getAttribute('password');
143
+ if (password) {
144
+ user.setAttribute('password', await hashPassword(password));
145
+ }
146
+ });
147
+
148
+ this.updating(async (user) => {
149
+ const password = user.getAttribute('password');
150
+ // Only hash if password changed
151
+ if (password && !password.startsWith('$2b$')) {
152
+ user.setAttribute('password', await hashPassword(password));
153
+ }
154
+ });
155
+ }
156
+
157
+ // 🔒 Password verification method
158
+ async checkPassword(password) {
159
+ return verifyPassword(password, this.getAttribute('password'));
160
+ }
161
+ }
162
+
163
+ module.exports = User;
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Authentication Middleware
169
+
170
+ ```javascript
171
+ // middlewares/auth.js
172
+ const jwt = require('jsonwebtoken');
173
+ const { User } = require('../models');
174
+
175
+ const authenticate = async (req, res, next) => {
176
+ try {
177
+ const authHeader = req.headers.authorization;
178
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
179
+ return res.status(401).json({ error: 'Token missing' });
180
+ }
181
+
182
+ const token = authHeader.split(' ')[1];
183
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
184
+
185
+ const user = await User.find(decoded.userId);
186
+ if (!user) {
187
+ return res.status(401).json({ error: 'User not found' });
188
+ }
189
+
190
+ req.user = user;
191
+ next();
192
+ } catch (error) {
193
+ if (error.name === 'TokenExpiredError') {
194
+ return res.status(401).json({ error: 'Token expired' });
195
+ }
196
+ return res.status(401).json({ error: 'Invalid token' });
197
+ }
198
+ };
199
+
200
+ const authorize = (...roles) => {
201
+ return (req, res, next) => {
202
+ if (!req.user) {
203
+ return res.status(401).json({ error: 'Not authenticated' });
204
+ }
205
+
206
+ const userRole = req.user.getAttribute('role');
207
+ if (!roles.includes(userRole)) {
208
+ return res.status(403).json({ error: 'Access denied' });
209
+ }
210
+
211
+ next();
212
+ };
213
+ };
214
+
215
+ module.exports = { authenticate, authorize };
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Secure Route Example
221
+
222
+ ```javascript
223
+ const express = require('express');
224
+ const { body } = require('express-validator');
225
+ const { authenticate, authorize } = require('../middlewares/auth');
226
+ const { validate } = require('../middlewares/validator');
227
+ const UserController = require('../controllers/UserController');
228
+
229
+ const router = express.Router();
230
+
231
+ // 🔒 Public routes with strict rate limiting
232
+ router.post('/register',
233
+ validate([
234
+ body('name').trim().isLength({ min: 2, max: 100 }).escape(),
235
+ body('email').isEmail().normalizeEmail(),
236
+ body('password').isLength({ min: 8 }),
237
+ ]),
238
+ UserController.register
239
+ );
240
+
241
+ // 🔒 Protected routes
242
+ router.get('/profile',
243
+ authenticate,
244
+ UserController.getProfile
245
+ );
246
+
247
+ // 🔒 Admin only
248
+ router.delete('/users/:id',
249
+ authenticate,
250
+ authorize('admin'),
251
+ UserController.deleteUser
252
+ );
253
+
254
+ module.exports = router;
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Security Utilities
260
+
261
+ ### utils/hash.js
262
+
263
+ ```javascript
264
+ const bcrypt = require('bcrypt');
265
+
266
+ const SALT_ROUNDS = 12;
267
+
268
+ const hashPassword = async (password) => {
269
+ return bcrypt.hash(password, SALT_ROUNDS);
270
+ };
271
+
272
+ const verifyPassword = async (password, hash) => {
273
+ return bcrypt.compare(password, hash);
274
+ };
275
+
276
+ module.exports = { hashPassword, verifyPassword };
277
+ ```
278
+
279
+ ### utils/token.js
280
+
281
+ ```javascript
282
+ const jwt = require('jsonwebtoken');
283
+ const crypto = require('crypto');
284
+
285
+ const generateAccessToken = (userId) => {
286
+ return jwt.sign(
287
+ { userId },
288
+ process.env.JWT_SECRET,
289
+ { expiresIn: process.env.JWT_EXPIRES_IN || '15m' }
290
+ );
291
+ };
292
+
293
+ const generateRefreshToken = () => {
294
+ return crypto.randomBytes(64).toString('hex');
295
+ };
296
+
297
+ module.exports = { generateAccessToken, generateRefreshToken };
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Security Configuration
303
+
304
+ ### config/security.js
305
+
306
+ ```javascript
307
+ module.exports = {
308
+ // Rate limiting
309
+ rateLimit: {
310
+ windowMs: 15 * 60 * 1000, // 15 minutes
311
+ max: 100,
312
+ message: { error: 'Too many requests' }
313
+ },
314
+
315
+ // Strict rate limit for auth
316
+ authRateLimit: {
317
+ windowMs: 15 * 60 * 1000,
318
+ max: 5,
319
+ message: { error: 'Too many login attempts' }
320
+ },
321
+
322
+ // CORS
323
+ cors: {
324
+ origin: process.env.CORS_ORIGIN,
325
+ credentials: true,
326
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']
327
+ },
328
+
329
+ // JWT
330
+ jwt: {
331
+ secret: process.env.JWT_SECRET,
332
+ expiresIn: '15m'
333
+ }
334
+ };
335
+ ```
336
+
337
+ ---
338
+
339
+ ## Required Dependencies
340
+
341
+ ```bash
342
+ npm install helmet express-rate-limit xss-clean hpp bcrypt jsonwebtoken express-validator
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Common Security Mistakes
348
+
349
+ ### ❌ DON'T
350
+
351
+ ```javascript
352
+ // ❌ Never store passwords in plain text
353
+ user.setAttribute('password', req.body.password);
354
+
355
+ // ❌ Never expose sensitive data
356
+ static hidden = []; // Empty!
357
+
358
+ // ❌ Never use raw queries with user input
359
+ await db.execute(`SELECT * FROM users WHERE email = '${email}'`);
360
+
361
+ // ❌ Never commit .env
362
+ // .gitignore missing .env
363
+ ```
364
+
365
+ ### ✅ DO
366
+
367
+ ```javascript
368
+ // ✅ Hash passwords
369
+ user.setAttribute('password', await hashPassword(req.body.password));
370
+
371
+ // ✅ Hide sensitive fields
372
+ static hidden = ['password', 'refresh_token'];
373
+
374
+ // ✅ Use parameterised queries
375
+ await User.where('email', email).first();
376
+
377
+ // ✅ Use .env.example for templates
378
+ ```
379
+
380
+ ---
381
+
382
+ ## References
383
+
384
+ - [Full Security Guide](../../../docs/SECURITY.md)
385
+ - [Validation](ADVANCED.md#validation)
386
+ - [Events/Hooks](ADVANCED.md#events)
@@ -0,0 +1,98 @@
1
+ # Outlet ORM - Seeders
2
+
3
+ [← Back to Index](SKILL.md) | [Previous: Migrations](MIGRATIONS.md)
4
+
5
+ ## When to use seeders
6
+
7
+ Use seeders to:
8
+
9
+ - bootstrap reference data;
10
+ - prepare local development environments quickly;
11
+ - initializes integration test fixtures.
12
+
13
+ ## CLI commands
14
+
15
+ ```bash
16
+ # Create a seeder file
17
+ outlet-migrate make:seed UserSeeder
18
+
19
+ # Run all seeders (DatabaseSeeder is prioritised)
20
+ outlet-migrate seed
21
+
22
+ # Laravel-style alias
23
+ outlet-migrate db:seed
24
+
25
+ # Run one specific seeder
26
+ outlet-migrate seed --class UserSeeder
27
+ outlet-migrate seed -c UserSeeder
28
+ ```
29
+
30
+ ## Folder convention
31
+
32
+ ```text
33
+ database/
34
+ ├── migrations/
35
+ └── seeds/
36
+ ├── DatabaseSeeder.js
37
+ ├── RoleSeeder.js
38
+ └── UserSeeder.js
39
+ ```
40
+
41
+ ## Seeder API quick reference
42
+
43
+ -`this.insert(table, rowOrRows)`inserts one row or many rows;
44
+ -`this.call('OtherSeeder')`runs another seeder;
45
+ -`this.truncate(table)`clears a table before re-seeding.
46
+
47
+ ## Seeder example
48
+
49
+ ```javascript
50
+ const { Seeder } = require('outlet-orm');
51
+
52
+ class RoleSeeder extends Seeder {
53
+ async run() {
54
+ await this.insert('roles', [
55
+ { name: 'admin' },
56
+ { name: 'editor' }
57
+ ]);
58
+ }
59
+ }
60
+
61
+ module.exports = RoleSeeder;
62
+ ```
63
+
64
+ ## DatabaseSeeder orchestration
65
+
66
+ ```javascript
67
+ const { Seeder } = require('outlet-orm');
68
+
69
+ class DatabaseSeeder extends Seeder {
70
+ async run() {
71
+ await this.call('RoleSeeder');
72
+ await this.call('UserSeeder');
73
+ }
74
+ }
75
+
76
+ module.exports = DatabaseSeeder;
77
+ ```
78
+
79
+ ## Recommended flow
80
+
81
+ ```bash
82
+ outlet-migrate migrate
83
+ outlet-migrate seed
84
+ ```
85
+
86
+ For a clean local reset:
87
+
88
+ ```bash
89
+ outlet-migrate fresh --yes
90
+ outlet-migrate seed
91
+ ```
92
+
93
+ ## Best practice
94
+
95
+ - Keep seeders deterministic and idempotent.
96
+ - Control FK order explicitly in`DatabaseSeeder`.
97
+ - Keep heavy bulk data in dedicated import scripts.
98
+ - Prefer unique constraints to prevent duplicate seed data.
@@ -0,0 +1,205 @@
1
+ ---
2
+ name: outlet-orm-best-practices
3
+ description: Outlet ORM is a Laravel Eloquent-inspired ORM for Node.js with MySQL, PostgreSQL, and SQLite support. Use this skill when working with Outlet ORM models, queries, relationships, migrations, backup, and database operations. v6.0.0 adds a full Backup module (BackupManager, BackupScheduler, AES-256-GCM encryption, TCP daemon).
4
+ license: MIT
5
+ metadata:
6
+ author: omgbwa-yasse
7
+ version: "6.0.0"
8
+ source: https://github.com/omgbwa-yasse/outlet-orm
9
+ npm: https://www.npmjs.com/package/outlet-orm
10
+ ---
11
+
12
+ # Outlet ORM Best Practices
13
+
14
+ Comprehensive guide for using Outlet ORM - a Laravel Eloquent-inspired ORM for Node.js/TypeScript with support for MySQL, PostgreSQL, and SQLite.
15
+
16
+ > 🆕 **v7.0.0**: AI Integration — MCP Server (Model Context Protocol), AI Safety Guardrails, Prompt-based project initialization. See [AI.md](AI.md).
17
+ >
18
+ > 🔖 **v6.5.0**: Accessors & Mutators, firstOrCreate/firstOrNew/updateOrCreate, upsert, Observer pattern, cursor/stream.
19
+ >
20
+ > 🔖 **v6.0.0**: Full Backup module — `BackupManager`, `BackupScheduler`, AES-256-GCM `BackupEncryption`, `BackupSocketServer` TCP daemon, `BackupSocketClient` with remote restore. See [BACKUP.md](BACKUP.md).
21
+ >
22
+ > 🔖 **v5.0.0**: Full TypeScript support with Generic Model, typed Schema Builder, MigrationInterface and Copilot Skills integration.
23
+
24
+ ## Documentation Index
25
+
26
+ | Document | Description |
27
+ |----------|-------------|
28
+ | **[MODELS.md](MODELS.md)** | Model definition, CRUD, casts, timestamps, connections |
29
+ | **[QUERIES.md](QUERIES.md)** | Query Builder, WHERE clauses, joins, pagination |
30
+ | **[RELATIONS.md](RELATIONS.md)** | Relationships, Eager Loading, polymorphic, naming conventions |
31
+ | **[MIGRATIONS.md](MIGRATIONS.md)** | Schema Builder, CLI tools, column types, foreign keys |
32
+ | **[ADVANCED.md](ADVANCED.md)** | Transactions, Soft Deletes, Events, Validation, Best Practices |
33
+ | **[TYPESCRIPT.md](TYPESCRIPT.md)** | TypeScript types, generics, typed models, migrations |
34
+ | **[SECURITY.md](SECURITY.md)** | 🔐 Security best practices, authentication, authorisation |
35
+ | **[BACKUP.md](BACKUP.md)** | 🗄️ Backups, scheduling, AES-256-GCM encryption, TCP daemon, restore |
36
+ | **[AI.md](AI.md)** | 🤖 MCP Server, AI Safety Guardrails, Prompt-based Init |
37
+ | **[API.md](API.md)** | Complete API Reference |
38
+
39
+ ---
40
+
41
+ ## When to Apply
42
+
43
+ Reference these guidelines when:
44
+ - Defining models and table schemas [MODELS.md](MODELS.md)
45
+ - Building database queries [QUERIES.md](QUERIES.md)
46
+ - Implementing relationships [RELATIONS.md](RELATIONS.md)
47
+ - Using Eager Loading [RELATIONS.md](RELATIONS.md)
48
+ - Setting up migrations [MIGRATIONS.md](MIGRATIONS.md)
49
+ - Implementing transactions, soft deletes, events [ADVANCED.md](ADVANCED.md)
50
+ - Using TypeScript with typed models [TYPESCRIPT.md](TYPESCRIPT.md)
51
+ - Securing your backend application [SECURITY.md](SECURITY.md)
52
+ - Scheduling or encrypting database backups [BACKUP.md](BACKUP.md)
53
+ - Restoring a database from a backup file [BACKUP.md](BACKUP.md)
54
+ - Running a long-lived backup daemon over TCP [BACKUP.md](BACKUP.md)
55
+ - Exposing the ORM to AI agents via MCP [AI.md](AI.md)
56
+ - Generating projects from natural language prompts [AI.md](AI.md)
57
+ - Protecting against AI-initiated destructive operations [AI.md](AI.md)
58
+
59
+ ---
60
+
61
+ ## Prerequisites
62
+
63
+ - **Node.js**: >= 18 (required)
64
+ - **Database Drivers** (install only needed):
65
+ - MySQL/MariaDB:`npm install mysql2`
66
+ - PostgreSQL:`npm install pg`
67
+ - SQLite:`npm install sqlite3`
68
+
69
+ ```bash
70
+ npm install outlet-orm
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Recommended Project Structure (Layered Architecture)
76
+
77
+ When using Outlet ORM, organise your project following the **Layered Architecture** pattern:
78
+
79
+ > 🔐 **Security**: See the [Security Guide](../../../docs/SECURITY.md) for best practices.
80
+
81
+ ```
82
+ my-project/
83
+ ├── .env # ⚠️ NEVER commit (in .gitignore)
84
+ ├── .env.example # Template without secrets
85
+ ├── .gitignore
86
+ ├── package.json
87
+ ├── src/
88
+ │ ├── index.js # Entry point
89
+ │ ├── controllers/ # 🎮 Presentation Layer
90
+ │ │ └── UserController.js
91
+ │ ├── services/ # ⚙️ Business Logic Layer
92
+ │ │ └── UserService.js
93
+ │ ├── repositories/ # 📦 Data Access Layer
94
+ │ │ └── UserRepository.js
95
+ │ ├── models/ # 📊 Models Layer (outlet-orm)
96
+ │ │ └── User.js
97
+ │ ├── middlewares/ # 🔒 Auth, validation, rate limit
98
+ │ │ ├── auth.js
99
+ │ │ ├── validator.js
100
+ │ │ └── errorHandler.js
101
+ │ ├── routes/ # 🛤️ Route definitions
102
+ │ │ └── index.js
103
+ │ ├── config/ # 🔒 Configuration
104
+ │ │ ├── database.js
105
+ │ │ └── security.js
106
+ │ └── utils/ # 🔒 Hash, tokens, helpers
107
+ │ └── helpers.js
108
+ ├── database/
109
+ │ ├── config.js # Migration CLI config
110
+ │ ├── migrations/
111
+ │ ├── seeds/
112
+ │ └── backups/ # 🗄️ Backup files (full / partial / journal)
113
+ ├── public/ # ✅ Static files only
114
+ ├── logs/ # 📋 Not versioned
115
+ └── tests/
116
+ ├── unit/
117
+ └── integration/
118
+ ```
119
+
120
+ ### Architecture Flow
121
+
122
+ ```
123
+ ┌─────────────────────────────────────────────────────────────┐
124
+ │ HTTP REQUEST │
125
+ └─────────────────────────┬───────────────────────────────────┘
126
+
127
+ ┌─────────────────────────────────────────────────────────────┐
128
+ │ 🛤️ ROUTES Route to correct controller │
129
+ └─────────────────────────┬───────────────────────────────────┘
130
+
131
+ ┌─────────────────────────────────────────────────────────────┐
132
+ │ 🔒 MIDDLEWARES Validation, Auth, Rate Limiting │
133
+ └─────────────────────────┬───────────────────────────────────┘
134
+
135
+ ┌─────────────────────────────────────────────────────────────┐
136
+ │ 🎮 CONTROLLERS HTTP handling (req/res) only │
137
+ └─────────────────────────┬───────────────────────────────────┘
138
+
139
+ ┌─────────────────────────────────────────────────────────────┐
140
+ │ ⚙️ SERVICES Business logic, business rules │
141
+ └─────────────────────────┬───────────────────────────────────┘
142
+
143
+ ┌─────────────────────────────────────────────────────────────┐
144
+ │ 📦 REPOSITORIES Data access abstraction (CRUD) │
145
+ └─────────────────────────┬───────────────────────────────────┘
146
+
147
+ ┌─────────────────────────────────────────────────────────────┐
148
+ │ 📊 MODELS outlet-orm (User, Post, etc.) │
149
+ └─────────────────────────┬───────────────────────────────────┘
150
+
151
+ ┌─────────────────────────────────────────────────────────────┐
152
+ │ DATABASE │
153
+ └─────────────────────────────────────────────────────────────┘
154
+ ```
155
+
156
+ ### Layer Responsibilities
157
+
158
+ | Layer | Files | Responsibility | Security |
159
+ |-------|-------|----------------|----------|
160
+ | **Controllers** |`src/controllers/`| HTTP only (req/res) | Input validation |
161
+ | **Services** |`src/services/`| Business logic, rules | Authorisation |
162
+ | **Repositories** |`src/repositories/`| DB abstraction, queries | Sanitisation |
163
+ | **Models** |`src/models/`| Data structure, relationships | Fillable/Hidden |
164
+ | **Middlewares** |`src/middlewares/`| Auth, validation, errors | 🔒 **Critical** |
165
+ | **Config** |`src/config/`| Environment variables | 🔒 Reads .env |
166
+ | **Utils** |`src/utils/`| Hash, tokens, helpers | 🔒 Never expose |
167
+ | **Backups** |`database/backups/`| Backup files (.sql, .json, .enc) | 🗄️ Encrypted at rest |
168
+
169
+ ### Quick Setup Commands
170
+
171
+ ```bash
172
+ # Initialise project structure
173
+ outlet-init
174
+
175
+ # Create a migration
176
+ outlet-migrate make create_users_table
177
+
178
+ # Run migrations
179
+ outlet-migrate migrate
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Rule Categories by Priority
185
+
186
+ | Priority | Category | Impact | Document |
187
+ |----------|----------|--------|----------|
188
+ | 1 | Model Definition | CRITICAL | [MODELS.md](MODELS.md) |
189
+ | 2 | Query Building | CRITICAL | [QUERIES.md](QUERIES.md) |
190
+ | 3 | Relationships | HIGH | [RELATIONS.md](RELATIONS.md) |
191
+ | 4 | Eager Loading | HIGH | [RELATIONS.md](RELATIONS.md) |
192
+ | 5 | Transactions | MEDIUM-HIGH | [ADVANCED.md](ADVANCED.md) |
193
+ | 6 | Soft Deletes | MEDIUM | [ADVANCED.md](ADVANCED.md) |
194
+ | 7 | Validation & Events | MEDIUM | [ADVANCED.md](ADVANCED.md) |
195
+ | 8 | Migrations & CLI | LOW-MEDIUM | [MIGRATIONS.md](MIGRATIONS.md) |
196
+ | 9 | Backup & Restore | MEDIUM | [BACKUP.md](BACKUP.md) |
197
+ | 10 | AI / MCP Integration | MEDIUM | [AI.md](AI.md) |
198
+
199
+ ---
200
+
201
+ ## References
202
+
203
+ - <https://github.com/omgbwa-yasse/outlet-orm>
204
+ - <https://www.npmjs.com/package/outlet-orm>
205
+ - <https://github.com/omgbwa-yasse/outlet-orm/blob/main/docs/INDEX.md>