gufi-cli 0.1.50 → 0.1.52

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 (37) hide show
  1. package/dist/commands/docs.js +1 -5
  2. package/dist/index.js +1 -0
  3. package/dist/lib/docs-resolver.d.ts +8 -0
  4. package/dist/lib/docs-resolver.js +27 -0
  5. package/dist/mcp.d.ts +3 -1
  6. package/dist/mcp.js +232 -34
  7. package/docs/dev-guide/1-01-architecture.md +358 -0
  8. package/docs/dev-guide/1-02-multi-tenant.md +415 -0
  9. package/docs/dev-guide/1-03-column-types.md +594 -0
  10. package/docs/dev-guide/1-04-json-config.md +442 -0
  11. package/docs/dev-guide/1-05-authentication.md +427 -0
  12. package/docs/dev-guide/2-01-api-reference.md +564 -0
  13. package/docs/dev-guide/2-02-automations.md +508 -0
  14. package/docs/dev-guide/2-03-gufi-cli.md +568 -0
  15. package/docs/dev-guide/2-04-realtime.md +401 -0
  16. package/docs/dev-guide/2-05-permissions.md +497 -0
  17. package/docs/dev-guide/2-06-integrations-overview.md +104 -0
  18. package/docs/dev-guide/2-07-stripe.md +173 -0
  19. package/docs/dev-guide/2-08-nayax.md +297 -0
  20. package/docs/dev-guide/2-09-ourvend.md +226 -0
  21. package/docs/dev-guide/2-10-tns.md +177 -0
  22. package/docs/dev-guide/2-11-custom-http.md +268 -0
  23. package/docs/dev-guide/3-01-custom-views.md +555 -0
  24. package/docs/dev-guide/3-02-webhooks-api.md +446 -0
  25. package/docs/mcp/00-overview.md +329 -0
  26. package/docs/mcp/01-architecture.md +220 -0
  27. package/docs/mcp/02-modules.md +285 -0
  28. package/docs/mcp/03-fields.md +357 -0
  29. package/docs/mcp/04-views.md +613 -0
  30. package/docs/mcp/05-automations.md +461 -0
  31. package/docs/mcp/06-api.md +480 -0
  32. package/docs/mcp/07-packages.md +246 -0
  33. package/docs/mcp/08-common-errors.md +284 -0
  34. package/docs/mcp/09-examples.md +453 -0
  35. package/docs/mcp/README.md +71 -0
  36. package/docs/mcp/tool-descriptions.json +49 -0
  37. package/package.json +3 -2
@@ -0,0 +1,427 @@
1
+ ---
2
+ id: authentication
3
+ title: "Authentication & Security"
4
+ description: "JWT tokens, sessions, and security best practices"
5
+ icon: Key
6
+ category: dev
7
+ part: 1
8
+ ---
9
+
10
+ # Authentication & Security
11
+
12
+ JWT tokens, sessions, and security best practices
13
+
14
+ ## Authentication Flow
15
+
16
+ Gufi uses a dual-layer JWT authentication system for security and seamless user experience.
17
+
18
+ ### Overview
19
+
20
+ ```
21
+ ┌─────────────────────────────────────────────────────────────┐
22
+ │ Authentication Flow │
23
+ ├─────────────────────────────────────────────────────────────┤
24
+ │ │
25
+ │ Login Request │
26
+ │ │ │
27
+ │ ▼ │
28
+ │ ┌─────────────┐ │
29
+ │ │ Backend │──────┐ │
30
+ │ │ Validates │ │ │
31
+ │ └─────────────┘ │ │
32
+ │ │ │ │
33
+ │ ▼ ▼ │
34
+ │ ┌─────────────┐ ┌─────────────┐ │
35
+ │ │ Access │ │ Refresh │ │
36
+ │ │ Token │ │ Cookie │ │
37
+ │ │ (15 min) │ │ (7 days) │ │
38
+ │ └─────────────┘ └─────────────┘ │
39
+ │ │ │ │
40
+ │ ▼ │ │
41
+ │ API Requests ◄───────────┘ (auto-refresh) │
42
+ │ │
43
+ └─────────────────────────────────────────────────────────────┘
44
+ ```
45
+
46
+ ## Login Process
47
+
48
+ ### Step 1: User Credentials
49
+
50
+ ```http
51
+ POST /api/auth/login
52
+ Content-Type: application/json
53
+
54
+ {
55
+ "email": "user@company.com",
56
+ "password": "securePassword123"
57
+ }
58
+ ```
59
+
60
+ ### Step 2: Server Validates
61
+
62
+ 1. Find user by email
63
+ 2. Verify password hash (bcrypt)
64
+ 3. Check account status
65
+ 4. Load company memberships
66
+
67
+ ### Step 3: Token Generation
68
+
69
+ **Access Token (JWT)**
70
+ - Short-lived: 15 minutes
71
+ - Contains: user ID, company ID, roles
72
+ - Sent in response body
73
+
74
+ **Refresh Token (HttpOnly Cookie)**
75
+ - Long-lived: 7 days
76
+ - Contains: user ID, token family ID
77
+ - Set as HttpOnly, Secure, SameSite cookie
78
+
79
+ ### Response
80
+
81
+ ```json
82
+ {
83
+ "token": "eyJhbGciOiJIUzI1NiIs...",
84
+ "user": {
85
+ "id": 123,
86
+ "email": "user@company.com",
87
+ "name": "John Doe",
88
+ "companies": [
89
+ { "id": 146, "name": "Acme Corp", "roles": ["Admin"] }
90
+ ]
91
+ }
92
+ }
93
+ ```
94
+
95
+ Plus Set-Cookie header for refresh token.
96
+
97
+ ## Token Structure
98
+
99
+ ### Access Token Payload
100
+
101
+ ```json
102
+ {
103
+ "sub": "123",
104
+ "email": "user@company.com",
105
+ "company_id": 146,
106
+ "roles": ["Admin"],
107
+ "platform_role": "client",
108
+ "iat": 1699999000,
109
+ "exp": 1699999900
110
+ }
111
+ ```
112
+
113
+ ### Key Claims
114
+
115
+ | Claim | Description |
116
+ |---|---|
117
+ | sub | User ID |
118
+ | company_id | Active company |
119
+ | roles | Company-specific roles |
120
+ | platform_role | Platform-wide role (admin/consultant/client) |
121
+ | exp | Expiration timestamp |
122
+
123
+ ## Token Refresh
124
+
125
+ ### Automatic Refresh
126
+
127
+ Frontend proactively refreshes 30 seconds before expiry:
128
+
129
+ ```typescript
130
+ // Frontend checks every minute
131
+ const checkTokenExpiry = () => {
132
+ const payload = decodeJwt(token);
133
+ const expiresIn = payload.exp * 1000 - Date.now();
134
+
135
+ if (expiresIn < 30000) {
136
+ refreshToken();
137
+ }
138
+ };
139
+ ```
140
+
141
+ ### Refresh Endpoint
142
+
143
+ ```http
144
+ POST /api/auth/refresh
145
+ Cookie: refresh_token=...
146
+ ```
147
+
148
+ Response:
149
+ ```json
150
+ {
151
+ "token": "eyJhbGciOiJIUzI1NiIs..."
152
+ }
153
+ ```
154
+
155
+ New refresh cookie also set.
156
+
157
+ ### Token Rotation
158
+
159
+ Each refresh generates a new refresh token, invalidating the old one. This prevents token theft attacks.
160
+
161
+ ## Using Tokens
162
+
163
+ ### API Requests
164
+
165
+ ```http
166
+ GET /api/tables/products
167
+ Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
168
+ X-Company-ID: 146
169
+ ```
170
+
171
+ ### Backend Validation
172
+
173
+ ```javascript
174
+ // middleware/auth.js
175
+ const authenticateUserToken = async (req, res, next) => {
176
+ const token = req.headers.authorization?.replace('Bearer ', '');
177
+
178
+ if (!token) {
179
+ return res.status(401).json({ error: 'No token provided' });
180
+ }
181
+
182
+ try {
183
+ const payload = jwt.verify(token, process.env.JWT_SECRET);
184
+ req.user = payload;
185
+
186
+ // Validate company access
187
+ const companyId = req.headers['x-company-id'];
188
+ if (companyId && companyId !== String(payload.company_id)) {
189
+ // Verify user has access to requested company
190
+ const hasAccess = await checkCompanyAccess(payload.sub, companyId);
191
+ if (!hasAccess) {
192
+ return res.status(403).json({ error: 'Access denied' });
193
+ }
194
+ }
195
+
196
+ next();
197
+ } catch (error) {
198
+ return res.status(401).json({ error: 'Invalid token' });
199
+ }
200
+ };
201
+ ```
202
+
203
+ ## Platform Roles
204
+
205
+ ### Role Hierarchy
206
+
207
+ | Role | Description | Access |
208
+ |---|---|---|
209
+ | admin | Platform administrator | Everything |
210
+ | consultant | Developer/consultant | Developer tools, Marketplace, no company management |
211
+ | client | Regular user | Basic access, own companies only |
212
+
213
+ ### Checking Platform Role
214
+
215
+ **Frontend:**
216
+ ```typescript
217
+ import { usePlatformRole } from '@/hooks/usePlatformRole';
218
+
219
+ const { isAdmin, isConsultant, canAccessDeveloperCenter } = usePlatformRole();
220
+ ```
221
+
222
+ **Backend:**
223
+ ```javascript
224
+ const platformRole = req.user?.platform_role || 'client';
225
+
226
+ if (platformRole !== 'admin') {
227
+ return res.status(403).json({ error: 'Admin only' });
228
+ }
229
+ ```
230
+
231
+ ## Company Roles
232
+
233
+ ### Per-Company Permissions
234
+
235
+ Users can have different roles in different companies:
236
+
237
+ ```
238
+ User 123
239
+ ├── Company A: Admin
240
+ ├── Company B: Manager
241
+ └── Company C: Viewer
242
+ ```
243
+
244
+ ### Role-Based Access
245
+
246
+ ```javascript
247
+ // Check company-specific role
248
+ const companyMembership = await getCompanyMembership(userId, companyId);
249
+ const roles = companyMembership.roles; // ['Admin', 'Sales']
250
+
251
+ if (!roles.includes('Admin')) {
252
+ // Limited access
253
+ }
254
+ ```
255
+
256
+ ## Security Features
257
+
258
+ ### Password Requirements
259
+
260
+ - Minimum 8 characters
261
+ - At least one number
262
+ - bcrypt hashing with salt rounds: 12
263
+
264
+ ### Rate Limiting
265
+
266
+ | Endpoint | Limit |
267
+ |---|---|
268
+ | /auth/login | 5 attempts per minute |
269
+ | /auth/refresh | 10 per minute |
270
+ | /auth/reset-password | 3 per hour |
271
+
272
+ ### Account Lockout
273
+
274
+ After 5 failed login attempts:
275
+
276
+ 1. Account locked for 15 minutes
277
+ 2. Email notification sent
278
+ 3. Admin can unlock manually
279
+
280
+ ### Two-Factor Authentication
281
+
282
+ Optional 2FA using TOTP:
283
+
284
+ ```http
285
+ POST /api/auth/login
286
+ {
287
+ "email": "user@company.com",
288
+ "password": "password",
289
+ "totp_code": "123456"
290
+ }
291
+ ```
292
+
293
+ ## Session Management
294
+
295
+ ### Active Sessions
296
+
297
+ Users can view active sessions:
298
+
299
+ ```http
300
+ GET /api/auth/sessions
301
+ ```
302
+
303
+ Returns:
304
+ ```json
305
+ {
306
+ "sessions": [
307
+ {
308
+ "id": "sess_123",
309
+ "device": "Chrome on Windows",
310
+ "ip": "192.168.1.1",
311
+ "lastActive": "2024-01-15T10:30:00Z",
312
+ "current": true
313
+ }
314
+ ]
315
+ }
316
+ ```
317
+
318
+ ### Revoking Sessions
319
+
320
+ ```http
321
+ DELETE /api/auth/sessions/sess_123
322
+ ```
323
+
324
+ Or revoke all:
325
+ ```http
326
+ DELETE /api/auth/sessions
327
+ ```
328
+
329
+ ## API Keys
330
+
331
+ ### For Integrations
332
+
333
+ API keys provide machine-to-machine authentication:
334
+
335
+ ```http
336
+ GET /api/tables/products
337
+ Authorization: Bearer api_key_xxxxx
338
+ X-Company-ID: 146
339
+ ```
340
+
341
+ ### Key Properties
342
+
343
+ | Property | Description |
344
+ |---|---|
345
+ | name | Descriptive name |
346
+ | permissions | read, write, delete |
347
+ | company_id | Bound to company |
348
+ | last_used | Last usage timestamp |
349
+
350
+ ### Creating Keys
351
+
352
+ ```http
353
+ POST /api/keys
354
+ {
355
+ "name": "My Integration",
356
+ "company_id": 146,
357
+ "permissions": ["read", "write"]
358
+ }
359
+ ```
360
+
361
+ ## Logout
362
+
363
+ ### Endpoint
364
+
365
+ ```http
366
+ POST /api/auth/logout
367
+ ```
368
+
369
+ Actions:
370
+ 1. Invalidate refresh token
371
+ 2. Clear refresh cookie
372
+ 3. Optionally invalidate all sessions
373
+
374
+ ### Frontend
375
+
376
+ ```typescript
377
+ const logout = async () => {
378
+ await fetch('/api/auth/logout', { method: 'POST' });
379
+ clearLocalStorage();
380
+ redirectToLogin();
381
+ };
382
+ ```
383
+
384
+ ## Security Best Practices
385
+
386
+ ### Token Storage
387
+
388
+ ```typescript
389
+ // Good: Store access token in memory only
390
+ let accessToken = null;
391
+
392
+ // Bad: Store in localStorage (XSS vulnerable)
393
+ localStorage.setItem('token', token);
394
+ ```
395
+
396
+ ### HTTPS Only
397
+
398
+ All production endpoints require HTTPS. HTTP requests are rejected.
399
+
400
+ ### CORS Configuration
401
+
402
+ ```javascript
403
+ const corsOptions = {
404
+ origin: ['https://app.gogufi.com'],
405
+ credentials: true, // For cookies
406
+ methods: ['GET', 'POST', 'PUT', 'DELETE']
407
+ };
408
+ ```
409
+
410
+ ### Security Headers
411
+
412
+ ```
413
+ Strict-Transport-Security: max-age=31536000; includeSubDomains
414
+ X-Content-Type-Options: nosniff
415
+ X-Frame-Options: DENY
416
+ X-XSS-Protection: 1; mode=block
417
+ Content-Security-Policy: default-src 'self'
418
+ ```
419
+
420
+ ## Error Codes
421
+
422
+ | Code | Meaning | Action |
423
+ |---|---|---|
424
+ | 401 | Token invalid/expired | Refresh or re-login |
425
+ | 403 | Access denied | Check permissions |
426
+ | 423 | Account locked | Wait or contact admin |
427
+ | 429 | Too many requests | Wait and retry |