rentman-cli 2.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.
package/.env.example ADDED
@@ -0,0 +1,39 @@
1
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2
+ # Rentman CLI - Environment Variables Template
3
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4
+ #
5
+ # 📝 NOTE: CLI uses local Conf storage for user identity
6
+ # These environment variables are OPTIONAL and mainly for CI/CD
7
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
8
+
9
+ # Supabase Configuration (Public - safe to include)
10
+ SUPABASE_URL=https://uoekolfgbbmvhzsfkjef.supabase.co
11
+ SUPABASE_ANON_KEY=
12
+
13
+ # Agent Gateway Endpoint
14
+ # Production:
15
+ AGENT_GATEWAY_URL=https://agent-gateway-1021032187840.us-central1.run.app/v1
16
+
17
+ # Development (uncomment for local testing):
18
+ # AGENT_GATEWAY_URL=http://localhost:3001/v1
19
+
20
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
21
+ # Optional: Override Identity Storage
22
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
23
+ # By default, CLI stores identity in ~/.config/rentman/
24
+ # Set these ONLY for CI/CD environments or automation
25
+
26
+ # RENTMAN_AGENT_ID=your_agent_id
27
+ # RENTMAN_SECRET_KEY=your_secret_key_base64
28
+
29
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
30
+ # Optional: API Key Authentication (Alternative to NACL)
31
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
32
+ # Use API keys for bots/automation that don't need cryptographic signing
33
+ # RENTMAN_API_KEY=sk_live_your_api_key_here
34
+
35
+ # Logging
36
+ LOG_LEVEL=info
37
+
38
+ # Environment
39
+ NODE_ENV=production
@@ -0,0 +1,510 @@
1
+ # CLI Production Readiness - Deep Analysis
2
+
3
+ ## 🚨 CRITICAL SECURITY ISSUES IDENTIFIED
4
+
5
+ ### 1. **SEVERE: Private Keys in Repository**
6
+ **File:** `rentman_identity.json`
7
+ **Risk Level:** 🔴 **CRITICAL**
8
+
9
+ ```json
10
+ {
11
+ "agent_id": "55ea7c98-132d-450b-8712-4f369d763261",
12
+ "public_agent_id": "agent_test_01",
13
+ "public_key": "gSb/s2pRwPO9puI9U2OnfbHukoAlPogOcqOJtsKgbhA=",
14
+ "secret_key": "M5v+5WgwJgDZVwpcwOJbmuw/UKeXpIqZ3BiipCY5y2GBJv+zalHA872m4j1TY6d9se6SgCU+iA5yo4m2wqBuEA==",
15
+ "owner_id": null,
16
+ "api_url": "https://uoekolfgbbmvhzsfkjef.supabase.co"
17
+ }
18
+ ```
19
+
20
+ **Impact:**
21
+ - Anyone with repo access can impersonate this agent
22
+ - Compromises entire agent identity system
23
+ - Violates cryptographic security principles
24
+
25
+ **Solution:**
26
+ ✅ DELETE this file immediately
27
+ ✅ Move to `~/.config/rentman/identity.json` (user's home)
28
+ ✅ Add `rentman_identity.json` to `.gitignore`
29
+ ✅ Use `Conf` library (already installed) for storage
30
+
31
+ ---
32
+
33
+ ### 2. **SEVERE: Hardcoded Supabase Anon Key**
34
+ **Files:** `init.js`, `listen.js`, `login-v2.js`, `post-mission.js`
35
+ **Risk Level:** 🔴 **CRITICAL**
36
+
37
+ Found in **4 files**:
38
+ ```javascript
39
+ const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' // 4 instances!
40
+ ```
41
+
42
+ **Impact:**
43
+ - Anon key exposed in public code
44
+ - Cannot rotate keys without code changes
45
+ - All users share same key (no isolation)
46
+
47
+ **Solution:**
48
+ ✅ Move to `.env` file
49
+ ✅ Use environment variables: `process.env.SUPABASE_ANON_KEY`
50
+ ✅ Remove all hardcoded instances
51
+ ✅ Provide `.env.example` template
52
+
53
+ ---
54
+
55
+ ### 3. **HIGH: Insecure Identity Storage**
56
+ **File:** `init.js` line 10
57
+ **Risk Level:** 🟠 **HIGH**
58
+
59
+ ```javascript
60
+ const IDENTITY_FILE = path.join(process.cwd(), 'rentman_identity.json');
61
+ ```
62
+
63
+ **Impact:**
64
+ - Identity stored in current working directory
65
+ - Easily committed to git by accident
66
+ - Not portable across projects
67
+
68
+ **Solution:**
69
+ ✅ Use OS-specific user directory
70
+ ✅ Leverage `Conf` library (already installed)
71
+ ✅ Store in `~/.config/rentman/` (Linux/Mac) or `AppData` (Windows)
72
+
73
+ ---
74
+
75
+ ## 🏗️ ARCHITECTURAL ISSUES
76
+
77
+ ### 1. **Direct Supabase Access (Bypassing Gateway)**
78
+ **File:** `post-mission.js` line 130
79
+ **Issue:** CLI talks directly to Supabase instead of Agent Gateway
80
+
81
+ ```javascript
82
+ const supabase = createClient(SUPABASE_URL, supabaseKey);
83
+ const { data, error } = await supabase.from('tasks').insert(taskWithAgent);
84
+ ```
85
+
86
+ **Problems:**
87
+ - Bypasses agent-gateway's authentication
88
+ - No NACL signature validation
89
+ - No rate limiting
90
+ - No audit trail
91
+ - Defeats DMZ architecture
92
+
93
+ **Solution:**
94
+ ✅ Use `apiRequest()` to talk to `/v1/market/tasks`
95
+ ✅ Generate NACL signature for request
96
+ ✅ Let gateway handle database operations
97
+ ✅ Unified architecture (all agents → gateway → database)
98
+
99
+ ---
100
+
101
+ ### 2. **Duplicate Login Commands**
102
+ **Files:** `login.js` and `login-v2.js`
103
+ **Issue:** Two commands doing similar things
104
+
105
+ **Problems:**
106
+ - Confusing UX (which one to use?)
107
+ - Code duplication
108
+ - Inconsistent behavior
109
+
110
+ **Solution:**
111
+ ✅ Consolidate into single `init` command
112
+ ✅ Remove redundant login commands
113
+ ✅ Use `init` for KYA + identity generation
114
+ ✅ Use `config` for managing settings
115
+
116
+ ---
117
+
118
+ ### 3. **Missing Legal Compliance**
119
+ **Issue:** No way to view Terms/Privacy Policy from CLI
120
+
121
+ **Impact:**
122
+ - Non-compliant with app store requirements
123
+ - Users can't access legal docs
124
+ - Inconsistent with mobile/dashboard apps
125
+
126
+ **Solution:**
127
+ ✅ Add `rentman legal` command
128
+ ✅ Link to existing HTML documents
129
+ ✅ Show in terminal or open browser
130
+
131
+ ---
132
+
133
+ ## 📊 CODE QUALITY ANALYSIS
134
+
135
+ ### Current State: **Prototype**
136
+
137
+ | Aspect | Status | Grade |
138
+ |--------|--------|-------|
139
+ | Security | 🔴 Critical Issues | F |
140
+ | Architecture | 🟠 Needs Refactor | D |
141
+ | UX | 🟡 Usable but confusing | C |
142
+ | Documentation | 🟢 README exists | B |
143
+ | Testing | 🔴 No tests | F |
144
+ | Code Style | 🟡 Inconsistent | C |
145
+
146
+ ---
147
+
148
+ ## 🔧 DETAILED REFACTORING PLAN
149
+
150
+ ### Phase 1: Security Fixes (CRITICAL - 1 day)
151
+
152
+ #### 1.1 Remove Hardcoded Secrets
153
+ ```bash
154
+ # Files to modify:
155
+ - src/commands/init.js
156
+ - src/commands/listen.js
157
+ - src/commands/login-v2.js
158
+ - src/commands/post-mission.js
159
+ - src/lib/config.js
160
+ ```
161
+
162
+ **Changes:**
163
+ ```javascript
164
+ // BEFORE (❌ INSECURE):
165
+ const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
166
+
167
+ // AFTER (✅ SECURE):
168
+ const SUPABASE_KEY = process.env.SUPABASE_ANON_KEY;
169
+ if (!SUPABASE_KEY) {
170
+ console.error('ERROR: SUPABASE_ANON_KEY not set');
171
+ process.exit(1);
172
+ }
173
+ ```
174
+
175
+ #### 1.2 Migrate Identity Storage
176
+ ```javascript
177
+ // BEFORE (❌ INSECURE):
178
+ const IDENTITY_FILE = path.join(process.cwd(), 'rentman_identity.json');
179
+
180
+ // AFTER (✅ SECURE):
181
+ const Conf = require('conf');
182
+ const config = new Conf({ projectName: 'rentman' });
183
+
184
+ // Save identity
185
+ config.set('agent_id', agentId);
186
+ config.set('secret_key', secretKey);
187
+ config.set('public_key', publicKey);
188
+
189
+ // Location: ~/.config/rentman/ (Linux/Mac)
190
+ // AppData/Roaming/rentman/ (Windows)
191
+ ```
192
+
193
+ #### 1.3 Delete Compromised Files
194
+ ```bash
195
+ # Remove from repo:
196
+ git rm rentman_identity.json
197
+ git rm --cached rentman_identity.json
198
+
199
+ # Add to .gitignore:
200
+ echo "rentman_identity.json" >> .gitignore
201
+ echo "*.json" >> .gitignore # Except package.json
202
+ echo ".env" >> .gitignore
203
+ echo ".env.local" >> .gitignore
204
+ ```
205
+
206
+ ---
207
+
208
+ ### Phase 2: Gateway Integration (HIGH - 2 days)
209
+
210
+ #### 2.1 Refactor `post-mission.js`
211
+ **Current:** Direct Supabase insert
212
+ **Target:** Agent Gateway API
213
+
214
+ ```javascript
215
+ // BEFORE (❌ BYPASSES GATEWAY):
216
+ const supabase = createClient(url, key);
217
+ const { data } = await supabase.from('tasks').insert(task);
218
+
219
+ // AFTER (✅ USES GATEWAY):
220
+ const { apiRequest } = require('../lib/api');
221
+ const signature = generateNaclSignature(taskPayload, secretKey);
222
+
223
+ const response = await apiRequest('/tasks', {
224
+ method: 'POST',
225
+ headers: {
226
+ 'x-agent-id': agentId,
227
+ 'x-signature': `nacl:${signature}`
228
+ },
229
+ body: JSON.stringify(taskPayload)
230
+ });
231
+ ```
232
+
233
+ #### 2.2 Add Signature Generation
234
+ ```javascript
235
+ // src/lib/crypto.js (NEW FILE)
236
+ const nacl = require('tweetnacl');
237
+ const naclUtil = require('tweetnacl-util');
238
+
239
+ function generateNaclSignature(payload, secretKeyBase64) {
240
+ const message = JSON.stringify(payload);
241
+ const messageBytes = naclUtil.decodeUTF8(message);
242
+ const secretKeyBytes = naclUtil.decodeBase64(secretKeyBase64);
243
+
244
+ const signature = nacl.sign.detached(messageBytes, secretKeyBytes);
245
+ return naclUtil.encodeBase64(signature);
246
+ }
247
+
248
+ module.exports = { generateNaclSignature };
249
+ ```
250
+
251
+ #### 2.3 Update API Base URL
252
+ ```javascript
253
+ // src/lib/api.js
254
+ // BEFORE:
255
+ const API_BASE = 'https://rentman-api-346436028870.us-central1.run.app/v1/market';
256
+
257
+ // AFTER (with env variable support):
258
+ const API_BASE = process.env.AGENT_GATEWAY_URL ||
259
+ 'https://agent-gateway.rentman.app/v1/market';
260
+ ```
261
+
262
+ ---
263
+
264
+ ### Phase 3: UX Improvements (MEDIUM - 1 day)
265
+
266
+ #### 3.1 Consolidate Commands
267
+ **Remove:**
268
+ - `login.js`
269
+ - `login-v2.js`
270
+
271
+ **Keep/Enhance:**
272
+ - `init.js` - Full KYA setup
273
+ - `config.js` - Manage settings
274
+
275
+ **File Structure:**
276
+ ```
277
+ src/commands/
278
+ ├── init.js # KYA initialization
279
+ ├── config.js # Config management
280
+ ├── post-mission.js # Create tasks
281
+ ├── listen.js # Listen for contracts
282
+ ├── task.js # Task management
283
+ ├── guide.js # Help/docs
284
+ └── legal.js # NEW - Legal docs
285
+ ```
286
+
287
+ #### 3.2 Add Legal Command
288
+ ```javascript
289
+ // src/commands/legal.js (NEW)
290
+ const chalk = require('chalk');
291
+ const open = require('open');
292
+
293
+ async function legalCommand(type) {
294
+ console.log(chalk.bold.blue('\n📜 Rentman Legal Documents\n'));
295
+
296
+ const docs = {
297
+ privacy: 'https://rentman.app/privacy-policy.html',
298
+ terms: 'https://rentman.app/terms-of-service.html'
299
+ };
300
+
301
+ if (type === 'privacy' || type === 'terms') {
302
+ console.log(chalk.green(`Opening ${type}...`));
303
+ await open(docs[type]);
304
+ } else {
305
+ console.log(chalk.white('Available documents:'));
306
+ console.log(chalk.cyan(' • Privacy Policy: ') + docs.privacy);
307
+ console.log(chalk.cyan(' • Terms of Service: ') + docs.terms);
308
+ console.log(chalk.gray('\nUse: rentman legal privacy OR rentman legal terms'));
309
+ }
310
+ }
311
+
312
+ module.exports = legalCommand;
313
+ ```
314
+
315
+ #### 3.3 Improve Error Messages
316
+ ```javascript
317
+ // Better error handling
318
+ try {
319
+ const response = await apiRequest('/tasks', options);
320
+ } catch (error) {
321
+ if (error.message.includes('AUTH_FAILED')) {
322
+ console.error(chalk.red('\n❌ Authentication failed'));
323
+ console.log(chalk.yellow('→ Run: rentman init'));
324
+ } else if (error.message.includes('RATE_LIMIT')) {
325
+ console.error(chalk.red('\n❌ Rate limit exceeded'));
326
+ console.log(chalk.yellow('→ Wait before retrying'));
327
+ } else {
328
+ console.error(chalk.red(`\n❌ Error: ${error.message}`));
329
+ }
330
+ process.exit(1);
331
+ }
332
+ ```
333
+
334
+ ---
335
+
336
+ ### Phase 4: Testing & Validation (HIGH - 2 days)
337
+
338
+ #### 4.1 Add Unit Tests
339
+ ```javascript
340
+ // tests/crypto.test.js
341
+ const { generateNaclSignature } = require('../src/lib/crypto');
342
+ const nacl = require('tweetnacl');
343
+
344
+ describe('NACL Signature Generation', () => {
345
+ test('generates valid signature', () => {
346
+ const keyPair = nacl.sign.keyPair();
347
+ const payload = { title: 'Test Task' };
348
+ const secretKey = Buffer.from(keyPair.secretKey).toString('base64');
349
+
350
+ const signature = generateNaclSignature(payload, secretKey);
351
+ expect(signature).toBeDefined();
352
+ expect(signature.length).toBeGreaterThan(0);
353
+ });
354
+ });
355
+ ```
356
+
357
+ #### 4.2 Integration Tests
358
+ ```javascript
359
+ // tests/integration/post-mission.test.js
360
+ test('posts mission to gateway', async () => {
361
+ // Mock identity
362
+ // Mock API response
363
+ // Verify signature sent
364
+ // Verify task created
365
+ });
366
+ ```
367
+
368
+ #### 4.3 Manual Test Checklist
369
+ ```markdown
370
+ - [ ] rentman init (fresh install)
371
+ - [ ] Identity stored in ~/.config/rentman/
372
+ - [ ] No rentman_identity.json in CWD
373
+ - [ ] rentman post-mission test.json
374
+ - [ ] Task appears in Gateway logs
375
+ - [ ] Signature validated server-side
376
+ - [ ] rentman listen (shows new contracts)
377
+ - [ ] rentman legal privacy (opens browser)
378
+ - [ ] Error handling works correctly
379
+ ```
380
+
381
+ ---
382
+
383
+ ## 📋 IMPLEMENTATION PRIORITY
384
+
385
+ ### P0 - CRITICAL (Do First)
386
+ 1. ✅ Delete `rentman_identity.json` from repo
387
+ 2. ✅ Add to `.gitignore`
388
+ 3. ✅ Remove all hardcoded keys
389
+ 4. ✅ Add `.env.example`
390
+ 5. ✅ Migrate to `Conf` storage
391
+
392
+ ### P1 - HIGH (Do Next)
393
+ 1. ✅ Update `post-mission.js` to use Gateway
394
+ 2. ✅ Add NACL signature generation
395
+ 3. ✅ Update `api.js` with gateway URL
396
+ 4. ✅ Remove duplicate login commands
397
+ 5. ✅ Add legal command
398
+
399
+ ### P2 - MEDIUM (Nice to Have)
400
+ 1. ✅ Improve error messages
401
+ 2. ✅ Add input validation
402
+ 3. ✅ Better logging
403
+ 4. ✅ Progress indicators
404
+
405
+ ### P3 - LOW (Future)
406
+ 1. ⏳ MCP integration
407
+ 2. ⏳ WebSocket for listen
408
+ 3. ⏳ Auto-update notifications
409
+ 4. ⏳ Telemetry/analytics
410
+
411
+ ---
412
+
413
+ ## 🎯 SUCCESS METRICS
414
+
415
+ After refactoring, CLI should:
416
+
417
+ ✅ **Security Score: A**
418
+ - No secrets in code
419
+ - Identity in secure location
420
+ - All requests authenticated
421
+ - Gateway-based architecture
422
+
423
+ ✅ **Code Quality: B+**
424
+ - Tests coverage > 70%
425
+ - No code duplication
426
+ - Consistent error handling
427
+ - TypeScript types (optional)
428
+
429
+ ✅ **UX Score: A**
430
+ - Clear command structure
431
+ - Helpful error messages
432
+ - Legal compliance
433
+ - Good documentation
434
+
435
+ ---
436
+
437
+ ## 📊 COMPARISON: Before vs After
438
+
439
+ | Aspect | Before (Prototype) | After (Production) |
440
+ |--------|-------------------|-------------------|
441
+ | **Identity Storage** | `./rentman_identity.json` | `~/.config/rentman/` |
442
+ | **Secrets** | Hardcoded in 4 files | Environment variables |
443
+ | **API Access** | Direct Supabase | Agent Gateway |
444
+ | **Authentication** | Anon key only | NACL signatures |
445
+ | **Rate Limiting** | None | Gateway handles |
446
+ | **Audit Trail** | None | Gateway logs all |
447
+ | **Testing** | 0% coverage | 70%+ coverage |
448
+ | **Legal Docs** | No access | `rentman legal` |
449
+ | **Commands** | Duplicate login | Unified `init` |
450
+
451
+ ---
452
+
453
+ ## ⚠️ BREAKING CHANGES
454
+
455
+ Users will need to:
456
+ 1. Re-run `rentman init` (identity migration)
457
+ 2. Set environment variables in `.env`
458
+ 3. Old `rentman_identity.json` won't work
459
+ 4. Use `rentman config` instead of manual JSON editing
460
+
461
+ **Migration Script Needed:**
462
+ ```javascript
463
+ // migrate-identity.js
464
+ const fs = require('fs');
465
+ const Conf = require('conf');
466
+
467
+ if (fs.existsSync('./rentman_identity.json')) {
468
+ const oldIdentity = JSON.parse(fs.readFileSync('./rentman_identity.json'));
469
+ const config = new Conf({ projectName: 'rentman' });
470
+
471
+ config.set('agent_id', oldIdentity.agent_id);
472
+ config.set('secret_key', oldIdentity.secret_key);
473
+ config.set('public_key', oldIdentity.public_key);
474
+
475
+ console.log('✅ Identity migrated to secure location');
476
+ console.log('⚠️ Delete old file: rm rentman_identity.json');
477
+ }
478
+ ```
479
+
480
+ ---
481
+
482
+ ## 📚 DOCUMENTATION UPDATES NEEDED
483
+
484
+ 1. **README.md** - Update installation instructions
485
+ 2. **SECURITY.md** - Add security best practices
486
+ 3. **MIGRATION.md** - Guide for existing users
487
+ 4. **API.md** - Document gateway integration
488
+ 5. **CONTRIBUTING.md** - Development guidelines
489
+
490
+ ---
491
+
492
+ ## 🔒 SECURITY BEST PRACTICES (Post-Fix)
493
+
494
+ After implementation:
495
+
496
+ ✅ **Never commit secrets**
497
+ ✅ **Use environment variables**
498
+ ✅ **Store identity in user directory**
499
+ ✅ **All API calls go through Gateway**
500
+ ✅ **Sign all requests with NACL**
501
+ ✅ **Rotate keys regularly**
502
+ ✅ **Audit logs enabled**
503
+ ✅ **Rate limiting enforced**
504
+
505
+ ---
506
+
507
+ **Status:** READY FOR IMPLEMENTATION
508
+ **Estimated Time:** 5-6 days
509
+ **Priority:** CRITICAL (Security vulnerabilities)
510
+ **Dependencies:** Agent Gateway must be deployed first