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 +39 -0
- package/CLI_PRODUCTION_ANALYSIS.md +510 -0
- package/IMPLEMENTATION_REPORT.md +245 -0
- package/README.md +72 -0
- package/SECURITY_FIXES_README.md +336 -0
- package/_DELETED_rentman_identity.json.bak +8 -0
- package/_backup_old_cli_20260208_130317/src/commands/init.js +118 -0
- package/_backup_old_cli_20260208_130317/src/commands/login-v2.js +62 -0
- package/_backup_old_cli_20260208_130317/src/commands/login.js +40 -0
- package/_backup_old_cli_20260208_130317/src/commands/post-mission.js +179 -0
- package/_backup_old_cli_20260208_130317/src/index.js +135 -0
- package/bin/rentman.js +7 -0
- package/gen_identity.js +23 -0
- package/migrate-identity.js +75 -0
- package/mission.json +21 -0
- package/package.json +37 -0
- package/src/commands/config.js +44 -0
- package/src/commands/guide.js +26 -0
- package/src/commands/init.js +147 -0
- package/src/commands/legal.js +78 -0
- package/src/commands/listen.js +88 -0
- package/src/commands/post-mission.js +202 -0
- package/src/commands/task.js +126 -0
- package/src/index.js +247 -0
- package/src/lib/api.js +120 -0
- package/src/lib/config.js +34 -0
- package/src/lib/crypto.js +80 -0
- package/src/lib/secure-config.js +118 -0
- package/test-integration.js +135 -0
- package/test_mission_v6.json +11 -0
- package/test_mission_v7.json +11 -0
- package/test_task.json +11 -0
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
|