miolo 3.0.0-beta.152 → 3.0.0-beta.154

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.
@@ -153,8 +153,8 @@ export function copyTemplate(sourcePath, destPath, appName, options = {}) {
153
153
  fs.copyFileSync(srcPath, destItemPath)
154
154
  }
155
155
  } else if (stat.isDirectory()) {
156
- // Only copy src/, db/ and docker/ directories
157
- if (item === 'src' || item === 'docker'|| item === 'db') {
156
+ // Copy src/, db/, docker/, and .agent/ directories
157
+ if (item === 'src' || item === 'docker' || item === 'db' || item === '.agent') {
158
158
  copyDirectory(srcPath, destItemPath, appName, options)
159
159
  }
160
160
  }
@@ -74,6 +74,17 @@ for (const dir of dirsToCopy) {
74
74
  }
75
75
  }
76
76
 
77
+ // Copy skills from workspace root
78
+ const skillsSrc = path.resolve(__dirname, '../../../../skills')
79
+ const skillsDest = path.join(templatePath, '.agent', 'skills')
80
+ if (fs.existsSync(skillsSrc)) {
81
+ fs.mkdirSync(path.join(templatePath, '.agent'), { recursive: true })
82
+ copyDirRecursive(skillsSrc, skillsDest)
83
+ console.log('[prepare-template] ✓ Copied skills/')
84
+ } else {
85
+ console.warn('[prepare-template] ⚠ Skills directory not found at', skillsSrc)
86
+ }
87
+
77
88
  // Step 4: Update package.json versions
78
89
  console.log('[prepare-template] Updating package.json versions...')
79
90
  const templatePackageJsonPath = path.join(templatePath, 'package.json')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo",
3
- "version": "3.0.0-beta.152",
3
+ "version": "3.0.0-beta.154",
4
4
  "description": "all-in-one koa-based server",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -30,7 +30,8 @@
30
30
  "template",
31
31
  "template/.env",
32
32
  "template/.env.production",
33
- "template/.editorconfig"
33
+ "template/.editorconfig",
34
+ "template/.agent"
34
35
  ],
35
36
  "scripts": {
36
37
  "lint": "npx xeira lint ./src",
@@ -0,0 +1,251 @@
1
+ ---
2
+ name: miolo-app-arch
3
+ description: Standard architecture patterns for miolo applications. Use when creating, modifying, or reviewing miolo applications to ensure proper project structure, directory organization, and file placement following miolo conventions established in miolo-sample.
4
+ ---
5
+
6
+ # Miolo Application Architecture
7
+
8
+ This skill defines the standard architecture for miolo applications based on miolo-sample, the reference implementation for miolo apps.
9
+
10
+ ## Project Structure Overview
11
+
12
+ ```
13
+ miolo-app/
14
+ ├── package.json # npm scripts and dependencies
15
+ ├── .env # Development environment variables
16
+ ├── .env.production # Production environment variables
17
+ ├── .editorconfig # Editor configuration
18
+ ├── .gitignore # Git ignore rules
19
+ ├── components.json # shadcn/ui configuration
20
+ ├── jsconfig.json # JavaScript/Import path configuration
21
+ ├── eslint.config.js # ESLint configuration
22
+ ├── postcss.config.js # PostCSS/Tailwind configuration
23
+ ├── docker/ # Docker deployment configuration
24
+ ├── db/ # Database initialization (optional)
25
+ ├── build/ # Production build output
26
+ ├── src/ # Source code
27
+ │ ├── cli/ # Client-side React application
28
+ │ ├── ns/ # Shared code (namespace)
29
+ │ ├── server/ # Backend server code
30
+ │ └── static/ # Static assets
31
+ ```
32
+
33
+ ## Root Files
34
+
35
+ ### package.json Scripts
36
+
37
+ Standard npm scripts for miolo development and deployment:
38
+
39
+ ```json
40
+ {
41
+ "scripts": {
42
+ "reset": "rm -fr node_modules package-lock.json && npm i",
43
+ "lint": "npx xeira lint src",
44
+ "dev": "npx miolo dev",
45
+ "deb": "npx miolo deb",
46
+ "create-bin": "npx miolo create-bin",
47
+ "build-client": "npx miolo build-client",
48
+ "build-server": "npx miolo build-server",
49
+ "build": "npm run build-client && npm run build-server && npm run create-bin",
50
+ "start": "node ./build/server/run.mjs start",
51
+ "stop": "node ./build/server/run.mjs stop",
52
+ "restart": "node ./build/server/run.mjs restart"
53
+ }
54
+ }
55
+ ```
56
+
57
+ **Key scripts:**
58
+ - `dev` - Development mode with hot reload
59
+ - `deb` - Development mode with hot reload and debugging
60
+ - `build` - Complete production build
61
+ - `start/stop/restart` - Production server management
62
+
63
+ ### Import Aliases
64
+
65
+ Configure path aliases in `package.json`:
66
+
67
+ ```json
68
+ {
69
+ "imports": {
70
+ "#cli/*": "./src/cli/*",
71
+ "#ns/*": "./src/ns/*",
72
+ "#server/*": "./src/server/*",
73
+ "#static/*": "./src/static/*"
74
+ }
75
+ }
76
+ ```
77
+
78
+ Use these aliases consistently in imports: `import Thing from '#server/routes/thing.mjs'`
79
+
80
+ ### Environment Files
81
+
82
+ - `.env` - Development configuration (database, ports, session salt, etc.)
83
+ - `.env.production` - Production overrides
84
+
85
+ ## Directory Structure
86
+
87
+ ### docker/
88
+
89
+ Docker deployment configuration:
90
+ - `docker-compose.yaml` - Service orchestration
91
+ - `Dockerfile` - Container build instructions
92
+
93
+ ### db/ (optional)
94
+
95
+ Database initialization scripts:
96
+ - `init.sh` - Database creation and setup script
97
+ - `sql/` - SQL migration files (executed in alphabetical order)
98
+
99
+ Not required for all apps, but recommended for PostgreSQL-based applications.
100
+
101
+ ### build/
102
+
103
+ Production build output (generated, not versioned):
104
+ - `cli/` - Built client application
105
+ - `server/` - Built server application
106
+
107
+ Created by `npm run build`, used in production deployment.
108
+
109
+ ### src/cli/
110
+
111
+ Client-side React application code. **Fixed subdirectory structure**:
112
+
113
+ ```
114
+ src/cli/
115
+ ├── App.jsx # Root application component
116
+ ├── entry-cli.jsx # Client entry point
117
+ ├── index.html # HTML template
118
+ ├── components/ # React components (shadcn/ui, custom)
119
+ │ ├── ui/ # shadcn/ui components
120
+ │ └── ... # Custom components
121
+ ├── config/ # Client configuration
122
+ ├── context/ # React contexts (data, session, theme, ui)
123
+ │ ├── data/
124
+ │ ├── session/
125
+ │ ├── theme/
126
+ │ └── ui/
127
+ ├── hooks/ # Custom React hooks
128
+ ├── layout/ # Layout components (sidebar, nav, etc.)
129
+ ├── lib/ # Client utilities
130
+ └── pages/ # Page components
131
+ ├── dash/ # Dashboard pages
132
+ ├── offline/ # Unauthenticated pages (login, etc.)
133
+ └── ... # Feature-specific page directories
134
+ ```
135
+
136
+ **Rules:**
137
+ - Respect the subdirectory structure
138
+ - Place new components in appropriate subdirectories
139
+ - Pages go in `pages/`, grouped by feature
140
+ - Reusable UI components in `components/`
141
+ - Contexts follow the established pattern (Context.jsx, Provider.jsx, useContext.mjs)
142
+
143
+ ### src/ns/
144
+
145
+ Shared code accessible from both client and server:
146
+
147
+ ```
148
+ src/ns/
149
+ └── models/ # Data models
150
+ ├── base/ # Base classes (BaseModel, BaseArray, etc.)
151
+ └── ... # Application-specific models
152
+ ```
153
+
154
+ Use for code that needs to run in both environments.
155
+
156
+ ### src/server/
157
+
158
+ Backend server code. **Semi-fixed subdirectory structure**:
159
+
160
+ ```
161
+ src/server/
162
+ ├── server.mjs # Server entry point
163
+ ├── cache/ # Cache implementations
164
+ ├── db/ # Database layer
165
+ │ ├── io/ # Database I/O operations (queries)
166
+ │ │ ├── users/ # User-related queries
167
+ │ │ ├── todos/ # Example: todo queries
168
+ │ │ └── ... # Feature-specific query directories
169
+ │ └── triggers/ # Database triggers
170
+ ├── lib/ # Server libraries
171
+ ├── miolo/ # Miolo server configuration
172
+ │ ├── auth/ # Authentication strategies
173
+ │ ├── cache.mjs # Cache configuration
174
+ │ ├── cron/ # Cron jobs
175
+ │ ├── db.mjs # Database configuration
176
+ │ ├── http.mjs # HTTP configuration
177
+ │ ├── index.mjs # Main miolo config
178
+ │ ├── routes/ # Base route configuration
179
+ │ └── ssr/ # Server-side rendering
180
+ ├── routes/ # API endpoints (developers add here)
181
+ │ ├── index.mjs # Route registration
182
+ │ ├── users/ # User endpoints
183
+ │ └── ... # Feature-specific route directories
184
+ └── utils/ # Server utilities
185
+ ```
186
+
187
+ **Rules:**
188
+ - `cache/`, `lib/`, `utils/`, `miolo/` are relatively fixed
189
+ - **Developers add new API endpoints in `routes/`**
190
+ - **Database queries go in `db/io/`**, organized by domain
191
+ - Each route directory contains endpoint handlers
192
+ - Register new routes in `routes/index.mjs`
193
+
194
+ **Key pattern:** When adding a new feature:
195
+ 1. Create queries in `db/io/feature-name/`
196
+ 2. Create route handlers in `routes/feature-name/`
197
+ 3. Register routes in `routes/index.mjs`
198
+
199
+ ### src/static/
200
+
201
+ Static assets:
202
+
203
+ ```
204
+ src/static/
205
+ ├── fonts/ # Custom fonts
206
+ ├── img/ # Images
207
+ │ ├── default/ # Default images (avatars, etc.)
208
+ │ └── ...
209
+ ├── public/ # Public root files (favicon, robots.txt)
210
+ └── style/ # Global CSS
211
+ ```
212
+
213
+ ## Development Workflow
214
+
215
+ 1. **Create app**: `npx miolo create <app-name>`
216
+ 2. **Develop**: `npm run dev` (hot reload on port from .env)
217
+ 3. **Build**: `npm run build` (creates production build/)
218
+ 4. **Deploy**: Use docker/ configuration or build/server/run.mjs
219
+
220
+ ## Best Practices
221
+
222
+ 1. **Respect directory structure** - Don't create new top-level directories without reason
223
+ 2. **Use import aliases** - Always use `#cli/`, `#server/`, etc. for imports
224
+ 3. **Follow naming conventions** - Use lowercase with hyphens for directories, camelCase for files
225
+ 4. **Organize by feature** - In routes/ and db/io/, group by domain/feature
226
+ 5. **Keep server config in miolo/** - Don't modify unless necessary
227
+ 6. **Use contexts for state** - Follow established context patterns in cli/context/
228
+
229
+ ## Common Patterns
230
+
231
+ **Adding a new feature:**
232
+ ```
233
+ 1. Add database queries: src/server/db/io/myfeature/*.mjs
234
+ 2. Add API routes: src/server/routes/myfeature/*.mjs
235
+ 3. Register routes: src/server/routes/index.mjs
236
+ 4. Add client pages: src/cli/pages/myfeature/*.jsx
237
+ 5. Add components if needed: src/cli/components/myfeature/*.jsx
238
+ ```
239
+
240
+ **Adding authentication:**
241
+ - Strategies in `src/server/miolo/auth/`
242
+ - Configure in `src/server/miolo/index.mjs`
243
+
244
+ **Adding static assets:**
245
+ - Images: `src/static/img/`
246
+ - Fonts: `src/static/fonts/`
247
+ - Root files: `src/static/public/`
248
+
249
+ ## Architecture created by `npx miolo create`
250
+
251
+ The `miolo create` command generates this structure automatically. Maintain it throughout development to ensure consistency with miolo conventions and compatibility with miolo tooling.
@@ -0,0 +1,295 @@
1
+ ---
2
+ name: miolo-auth
3
+ description: Authentication configuration and strategies for miolo applications. Use when implementing, modifying, or troubleshooting authentication, configuring auth strategies (credentials, basic, guest), or setting up user sessions.
4
+ ---
5
+
6
+ # Miolo Authentication
7
+
8
+ Authentication configuration and strategies for miolo applications.
9
+
10
+ ## Authentication Strategies
11
+
12
+ Miolo supports multiple built-in authentication strategies in `src/server/miolo/auth/`:
13
+
14
+ ```
15
+ src/server/miolo/auth/
16
+ ├── credentials.mjs # Username/password authentication
17
+ ├── basic.mjs # HTTP Basic authentication
18
+ ├── guest.mjs # Guest/anonymous access
19
+ └── custom.mjs # Custom authentication logic
20
+ ```
21
+
22
+ ## Configuring Authentication
23
+
24
+ Authentication is configured in `src/server/miolo/index.mjs`:
25
+
26
+ ```javascript
27
+ import auth from './auth/credentials.mjs'
28
+ // or: import auth from './auth/basic.mjs'
29
+ // or: import auth from './auth/guest.mjs'
30
+
31
+ export default {
32
+ auth,
33
+ // ... other config
34
+ }
35
+ ```
36
+
37
+ ## Credentials Strategy (Default)
38
+
39
+ Username/password authentication with database-backed users.
40
+
41
+ **File:** `src/server/miolo/auth/credentials.mjs`
42
+
43
+ ```javascript
44
+ import { db_user_auth } from '#server/db/io/users/auth.mjs'
45
+
46
+ export default {
47
+ urls: {
48
+ login: '/page/login',
49
+ logout: '/page/logout',
50
+ home: '/'
51
+ },
52
+
53
+ async login(ctx, credentials) {
54
+ const { username, password } = credentials
55
+
56
+ const user = await db_user_auth(ctx, { username, password })
57
+
58
+ if (!user) {
59
+ return { ok: false, error: 'Invalid credentials' }
60
+ }
61
+
62
+ return { ok: true, user }
63
+ },
64
+
65
+ async logout(ctx) {
66
+ // Cleanup if needed
67
+ return { ok: true }
68
+ }
69
+ }
70
+ ```
71
+
72
+ **Key elements:**
73
+ - `urls` - Define login, logout, home page paths
74
+ - `login(ctx, credentials)` - Validates credentials, returns user or error
75
+ - `logout(ctx)` - Optional cleanup on logout
76
+ - Uses database function from `db/io/users/auth.mjs`
77
+
78
+ ## Basic Authentication
79
+
80
+ HTTP Basic Auth for simple API access.
81
+
82
+ **File:** `src/server/miolo/auth/basic.mjs`
83
+
84
+ ```javascript
85
+ export default {
86
+ async login(ctx, credentials) {
87
+ const { username, password } = credentials
88
+
89
+ // Validate against environment or database
90
+ if (username === process.env.API_USER &&
91
+ password === process.env.API_PASSWORD) {
92
+ return {
93
+ ok: true,
94
+ user: { id: 1, username, role: 'api' }
95
+ }
96
+ }
97
+
98
+ return { ok: false, error: 'Invalid credentials' }
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## Guest/Anonymous Access
104
+
105
+ Allow unauthenticated access (useful for read-only apps).
106
+
107
+ **File:** `src/server/miolo/auth/guest.mjs`
108
+
109
+ ```javascript
110
+ export default {
111
+ async login(ctx) {
112
+ return {
113
+ ok: true,
114
+ user: { id: 0, username: 'guest', role: 'guest' }
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ ## User Session
121
+
122
+ After successful login, user is available in routes:
123
+
124
+ ```javascript
125
+ export async function r_protected_route(ctx, params) {
126
+ const user = ctx.state.user
127
+
128
+ // User object contains:
129
+ // - id
130
+ // - username
131
+ // - email
132
+ // - any other fields returned from login
133
+
134
+ ctx.miolo.logger.info(`User ${user.id} accessing route`)
135
+
136
+ return { ok: true, data: { userId: user.id } }
137
+ }
138
+ ```
139
+
140
+ ## Protecting Routes
141
+
142
+ Routes are protected by adding `auth` configuration:
143
+
144
+ ```javascript
145
+ const auth = {
146
+ require: true,
147
+ action: 'redirect',
148
+ redirect_url: '/page/login'
149
+ }
150
+
151
+ export default [{
152
+ prefix: 'api',
153
+ routes: [
154
+ // Public route
155
+ { method: 'GET', url: '/public/data', callback: r_public },
156
+
157
+ // Protected route
158
+ { method: 'GET', url: '/user/profile', auth, callback: r_profile },
159
+ ]
160
+ }]
161
+ ```
162
+
163
+ ## Database User Authentication
164
+
165
+ User authentication typically queries the database:
166
+
167
+ **File:** `src/server/db/io/users/auth.mjs`
168
+
169
+ ```javascript
170
+ import { sha512 } from '#server/utils/crypt.mjs'
171
+
172
+ export async function db_user_auth(ctx, params) {
173
+ const { username, password } = params
174
+
175
+ const salt = process.env.MIOLO_SESSION_SALT
176
+ const hashedPassword = sha512(password, salt)
177
+
178
+ const user = await ctx.miolo.db.query(`
179
+ SELECT id, username, email, name
180
+ FROM u_user
181
+ WHERE username = $1 AND password = $2
182
+ `, [username, hashedPassword])
183
+
184
+ return user.rows[0] || null
185
+ }
186
+ ```
187
+
188
+ **Key elements:**
189
+ - Hash password with session salt
190
+ - Query user by username and hashed password
191
+ - Return user object or null
192
+ - Don't return password in user object
193
+
194
+ ## Password Hashing
195
+
196
+ Use the provided crypto utilities:
197
+
198
+ ```javascript
199
+ import { sha512 } from '#server/utils/crypt.mjs'
200
+
201
+ const salt = process.env.MIOLO_SESSION_SALT
202
+ const hashedPassword = sha512(plainPassword, salt)
203
+ ```
204
+
205
+ **Session salt** is configured in `.env`:
206
+ ```
207
+ MIOLO_SESSION_SALT=your-random-salt-here
208
+ ```
209
+
210
+ ## Changing Password
211
+
212
+ Pattern for password change:
213
+
214
+ **File:** `src/server/db/io/users/pwd.mjs`
215
+
216
+ ```javascript
217
+ import { sha512 } from '#server/utils/crypt.mjs'
218
+
219
+ export async function db_user_change_password(ctx, params) {
220
+ const { user_id, old_password, new_password } = params
221
+
222
+ const salt = process.env.MIOLO_SESSION_SALT
223
+
224
+ // Verify old password
225
+ const user = await ctx.miolo.db.query(`
226
+ SELECT id FROM u_user
227
+ WHERE id = $1 AND password = $2
228
+ `, [user_id, sha512(old_password, salt)])
229
+
230
+ if (user.rows.length === 0) {
231
+ throw new Error('Invalid current password')
232
+ }
233
+
234
+ // Update to new password
235
+ const newHash = sha512(new_password, salt)
236
+ await ctx.miolo.db.query(`
237
+ UPDATE u_user
238
+ SET password = $1
239
+ WHERE id = $2
240
+ `, [newHash, user_id])
241
+
242
+ return { changed: true }
243
+ }
244
+ ```
245
+
246
+ ## Custom Authentication
247
+
248
+ For complex scenarios, implement custom logic:
249
+
250
+ **File:** `src/server/miolo/auth/custom.mjs`
251
+
252
+ ```javascript
253
+ export default {
254
+ urls: {
255
+ login: '/auth/custom',
256
+ logout: '/auth/logout',
257
+ home: '/'
258
+ },
259
+
260
+ async login(ctx, credentials) {
261
+ // Custom logic: OAuth, LDAP, etc.
262
+ const user = await yourCustomAuthLogic(credentials)
263
+
264
+ if (!user) {
265
+ return { ok: false, error: 'Authentication failed' }
266
+ }
267
+
268
+ return { ok: true, user }
269
+ },
270
+
271
+ async logout(ctx) {
272
+ // Custom cleanup
273
+ await yourCustomLogoutLogic(ctx)
274
+ return { ok: true }
275
+ }
276
+ }
277
+ ```
278
+
279
+ ## Best Practices
280
+
281
+ 1. **Never store plain passwords** - Always hash with salt
282
+ 2. **Use strong session salt** - Set `MIOLO_SESSION_SALT` in `.env`
283
+ 3. **Don't return passwords** - User object should never include password
284
+ 4. **Validate on server** - Never trust client-side authentication
285
+ 5. **Use HTTPS in production** - Protect credentials in transit
286
+ 6. **Rate limit login attempts** - Prevent brute force attacks
287
+ 7. **Log authentication events** - Track successful and failed logins
288
+
289
+ ## Examples from miolo-sample
290
+
291
+ See actual implementations:
292
+ - `src/server/miolo/auth/credentials.mjs` - Default auth strategy
293
+ - `src/server/db/io/users/auth.mjs` - User authentication query
294
+ - `src/server/db/io/users/pwd.mjs` - Password change logic
295
+ - `src/server/utils/crypt.mjs` - Hashing utilities