tlc-claude-code 0.6.4 → 0.7.1
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/CLAUDE.md +59 -0
- package/README.md +164 -121
- package/autofix.md +327 -0
- package/bin/install.js +23 -2
- package/bug.md +255 -0
- package/build.md +167 -21
- package/ci.md +414 -0
- package/claim.md +189 -0
- package/config.md +236 -0
- package/deploy.md +516 -0
- package/docs.md +494 -0
- package/edge-cases.md +340 -0
- package/export.md +456 -0
- package/help.md +84 -1
- package/init.md +56 -7
- package/issues.md +376 -0
- package/new-project.md +68 -4
- package/package.json +4 -2
- package/plan.md +15 -1
- package/progress.md +17 -0
- package/quality.md +273 -0
- package/release.md +135 -0
- package/server/dashboard/index.html +708 -0
- package/server/index.js +406 -0
- package/server/lib/plan-parser.js +146 -0
- package/server/lib/project-detector.js +301 -0
- package/server/package.json +19 -0
- package/server.md +742 -0
- package/who.md +151 -0
package/deploy.md
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# /tlc:deploy - VPS Deployment Server
|
|
2
|
+
|
|
3
|
+
Deploy your TLC project to a VPS for team collaboration.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/tlc:deploy [command]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
- `setup` - Configure deployment server
|
|
13
|
+
- `push` - Deploy current branch
|
|
14
|
+
- `status` - Check deployment status
|
|
15
|
+
- `logs` - View deployment logs
|
|
16
|
+
- `users` - Manage server users
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
22
|
+
│ VPS Server │
|
|
23
|
+
│ │
|
|
24
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
25
|
+
│ │ Branch │ │ Branch │ │ Branch │ │
|
|
26
|
+
│ │ main │ │ feat-auth │ │ fix-bug │ │
|
|
27
|
+
│ │ :3000 │ │ :3001 │ │ :3002 │ │
|
|
28
|
+
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
|
29
|
+
│ │ │ │ │
|
|
30
|
+
│ └────────────────┼────────────────┘ │
|
|
31
|
+
│ │ │
|
|
32
|
+
│ ┌───────────────────────┴───────────────────────┐ │
|
|
33
|
+
│ │ TLC Deploy Server │ │
|
|
34
|
+
│ │ :3147 │ │
|
|
35
|
+
│ │ - Dashboard (auth required) │ │
|
|
36
|
+
│ │ - API for deployments │ │
|
|
37
|
+
│ │ - Webhook receiver │ │
|
|
38
|
+
│ │ - Slack notifications │ │
|
|
39
|
+
│ └───────────────────────────────────────────────┘ │
|
|
40
|
+
│ │ │
|
|
41
|
+
│ ┌───────────────────────┴───────────────────────┐ │
|
|
42
|
+
│ │ Reverse Proxy (nginx) │ │
|
|
43
|
+
│ │ │ │
|
|
44
|
+
│ │ main.project.example.com → :3000 │ │
|
|
45
|
+
│ │ feat-auth.project.example.com → :3001 │ │
|
|
46
|
+
│ │ dashboard.project.example.com → :3147 │ │
|
|
47
|
+
│ └───────────────────────────────────────────────┘ │
|
|
48
|
+
└─────────────────────────────────────────────────────────────┘
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Setup
|
|
52
|
+
|
|
53
|
+
### 1. Server Requirements
|
|
54
|
+
|
|
55
|
+
- Ubuntu 22.04+ or similar
|
|
56
|
+
- Docker installed
|
|
57
|
+
- Node.js 20+
|
|
58
|
+
- nginx (reverse proxy)
|
|
59
|
+
- PostgreSQL (user database)
|
|
60
|
+
|
|
61
|
+
### 2. Configure Server
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
> /tlc:deploy setup
|
|
65
|
+
|
|
66
|
+
TLC Deployment Server Setup
|
|
67
|
+
|
|
68
|
+
VPS Configuration:
|
|
69
|
+
Host: deploy.example.com
|
|
70
|
+
SSH Key: ~/.ssh/id_rsa (detected)
|
|
71
|
+
|
|
72
|
+
Testing connection...
|
|
73
|
+
✓ Connected to deploy.example.com
|
|
74
|
+
|
|
75
|
+
Installing TLC Deploy Server...
|
|
76
|
+
✓ Dependencies installed
|
|
77
|
+
✓ Database created
|
|
78
|
+
✓ nginx configured
|
|
79
|
+
|
|
80
|
+
Domain Configuration:
|
|
81
|
+
Base domain: project.example.com
|
|
82
|
+
Branches will be: {branch}.project.example.com
|
|
83
|
+
|
|
84
|
+
Configure DNS:
|
|
85
|
+
*.project.example.com → VPS_IP
|
|
86
|
+
|
|
87
|
+
Admin User:
|
|
88
|
+
Email: admin@example.com
|
|
89
|
+
Password: (generated) K8x#mP2$nQ
|
|
90
|
+
|
|
91
|
+
Slack Integration (optional):
|
|
92
|
+
Webhook URL: https://hooks.slack.com/services/XXX
|
|
93
|
+
|
|
94
|
+
Configuration saved to .tlc.json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Local Configuration
|
|
98
|
+
|
|
99
|
+
In `.tlc.json`:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"deploy": {
|
|
104
|
+
"server": "deploy.example.com",
|
|
105
|
+
"domain": "project.example.com",
|
|
106
|
+
"sshKey": "~/.ssh/id_rsa",
|
|
107
|
+
"slack": {
|
|
108
|
+
"webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
|
|
109
|
+
"channel": "#deployments"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## User Management
|
|
116
|
+
|
|
117
|
+
### Authentication
|
|
118
|
+
|
|
119
|
+
Users table (PostgreSQL):
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
CREATE TABLE users (
|
|
123
|
+
id SERIAL PRIMARY KEY,
|
|
124
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
125
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
126
|
+
name VARCHAR(255),
|
|
127
|
+
role VARCHAR(50) DEFAULT 'engineer',
|
|
128
|
+
created_at TIMESTAMP DEFAULT NOW(),
|
|
129
|
+
last_login TIMESTAMP
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
-- Roles: admin, engineer, qa, po
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### User Commands
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
> /tlc:deploy users add
|
|
139
|
+
|
|
140
|
+
Email: bob@example.com
|
|
141
|
+
Name: Bob Smith
|
|
142
|
+
Role: engineer
|
|
143
|
+
Password: (generated) Qw3$rTy9
|
|
144
|
+
|
|
145
|
+
User created! They can login at:
|
|
146
|
+
https://dashboard.project.example.com
|
|
147
|
+
|
|
148
|
+
> /tlc:deploy users list
|
|
149
|
+
|
|
150
|
+
Users:
|
|
151
|
+
admin@example.com (admin) - Last login: today
|
|
152
|
+
alice@example.com (engineer) - Last login: 2h ago
|
|
153
|
+
bob@example.com (engineer) - Last login: never
|
|
154
|
+
qa@example.com (qa) - Last login: 1d ago
|
|
155
|
+
|
|
156
|
+
> /tlc:deploy users remove bob@example.com
|
|
157
|
+
|
|
158
|
+
User bob@example.com removed.
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### JWT Authentication
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// Server generates JWT on login
|
|
165
|
+
const token = jwt.sign(
|
|
166
|
+
{ userId: user.id, email: user.email, role: user.role },
|
|
167
|
+
process.env.JWT_SECRET,
|
|
168
|
+
{ expiresIn: '7d' }
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Protected routes check role
|
|
172
|
+
app.get('/api/admin/*', requireRole('admin'));
|
|
173
|
+
app.post('/api/deploy', requireRole(['admin', 'engineer']));
|
|
174
|
+
app.get('/api/status', requireRole(['admin', 'engineer', 'qa', 'po']));
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Deployment
|
|
178
|
+
|
|
179
|
+
### Push to Deploy
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
> /tlc:deploy push
|
|
183
|
+
|
|
184
|
+
Deploying branch: feat-auth
|
|
185
|
+
|
|
186
|
+
Pushing to VPS...
|
|
187
|
+
✓ Code uploaded
|
|
188
|
+
✓ Dependencies installed
|
|
189
|
+
✓ Tests passed (23/23)
|
|
190
|
+
✓ Container started
|
|
191
|
+
|
|
192
|
+
Deployment complete!
|
|
193
|
+
URL: https://feat-auth.project.example.com
|
|
194
|
+
|
|
195
|
+
Slack notification sent: #deployments
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Automatic Deployment
|
|
199
|
+
|
|
200
|
+
With webhook, pushing to GitHub triggers deployment:
|
|
201
|
+
|
|
202
|
+
```yaml
|
|
203
|
+
# GitHub Action
|
|
204
|
+
on:
|
|
205
|
+
push:
|
|
206
|
+
branches: ['**']
|
|
207
|
+
|
|
208
|
+
jobs:
|
|
209
|
+
deploy:
|
|
210
|
+
runs-on: ubuntu-latest
|
|
211
|
+
steps:
|
|
212
|
+
- name: Trigger deployment
|
|
213
|
+
run: |
|
|
214
|
+
curl -X POST https://dashboard.project.example.com/api/webhook/deploy \
|
|
215
|
+
-H "X-Webhook-Secret: ${{ secrets.DEPLOY_SECRET }}" \
|
|
216
|
+
-d '{"branch": "${{ github.ref_name }}", "sha": "${{ github.sha }}"}'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Deployment Status
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
> /tlc:deploy status
|
|
223
|
+
|
|
224
|
+
Active Deployments:
|
|
225
|
+
|
|
226
|
+
| Branch | URL | Status | Last Deploy |
|
|
227
|
+
|--------|-----|--------|-------------|
|
|
228
|
+
| main | main.project.example.com | ✓ Running | 2h ago |
|
|
229
|
+
| feat-auth | feat-auth.project.example.com | ✓ Running | 30m ago |
|
|
230
|
+
| fix-bug | fix-bug.project.example.com | ✗ Failed | 15m ago |
|
|
231
|
+
|
|
232
|
+
Total: 3 deployments (2 healthy, 1 failed)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### View Logs
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
> /tlc:deploy logs feat-auth
|
|
239
|
+
|
|
240
|
+
[2024-01-15 10:30:45] Container started
|
|
241
|
+
[2024-01-15 10:30:46] Listening on :3001
|
|
242
|
+
[2024-01-15 10:31:02] GET /api/users 200 12ms
|
|
243
|
+
[2024-01-15 10:31:15] POST /api/login 200 45ms
|
|
244
|
+
[2024-01-15 10:32:00] GET /api/users/123 404 8ms
|
|
245
|
+
|
|
246
|
+
[Press Ctrl+C to stop streaming]
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Slack Integration
|
|
250
|
+
|
|
251
|
+
### Notifications
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"deploy": {
|
|
256
|
+
"slack": {
|
|
257
|
+
"webhookUrl": "https://hooks.slack.com/...",
|
|
258
|
+
"channel": "#deployments",
|
|
259
|
+
"events": {
|
|
260
|
+
"deploy_start": true,
|
|
261
|
+
"deploy_success": true,
|
|
262
|
+
"deploy_fail": true,
|
|
263
|
+
"tests_fail": true,
|
|
264
|
+
"bug_created": true
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Message Examples
|
|
272
|
+
|
|
273
|
+
**Deploy Success:**
|
|
274
|
+
```
|
|
275
|
+
🚀 Deployment Successful
|
|
276
|
+
Branch: feat-auth
|
|
277
|
+
URL: https://feat-auth.project.example.com
|
|
278
|
+
Tests: 23/23 passing
|
|
279
|
+
Deployed by: Alice
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Deploy Failed:**
|
|
283
|
+
```
|
|
284
|
+
❌ Deployment Failed
|
|
285
|
+
Branch: fix-bug
|
|
286
|
+
Error: Tests failed (3 failing)
|
|
287
|
+
See logs: https://dashboard.project.example.com/logs/fix-bug
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Bug Created:**
|
|
291
|
+
```
|
|
292
|
+
🐛 New Bug Reported
|
|
293
|
+
BUG-015: Login button not responding
|
|
294
|
+
Severity: high
|
|
295
|
+
Reporter: QA Team
|
|
296
|
+
View: https://dashboard.project.example.com/bugs/15
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Custom Webhooks
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// In deploy server
|
|
303
|
+
async function notifySlack(event, data) {
|
|
304
|
+
const messages = {
|
|
305
|
+
deploy_start: `🔄 Deploying ${data.branch}...`,
|
|
306
|
+
deploy_success: `🚀 ${data.branch} deployed to ${data.url}`,
|
|
307
|
+
deploy_fail: `❌ ${data.branch} deployment failed: ${data.error}`,
|
|
308
|
+
tests_fail: `⚠️ Tests failing on ${data.branch}: ${data.failCount} failures`,
|
|
309
|
+
bug_created: `🐛 ${data.bugId}: ${data.title}`
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
await fetch(config.slack.webhookUrl, {
|
|
313
|
+
method: 'POST',
|
|
314
|
+
headers: { 'Content-Type': 'application/json' },
|
|
315
|
+
body: JSON.stringify({
|
|
316
|
+
channel: config.slack.channel,
|
|
317
|
+
text: messages[event],
|
|
318
|
+
attachments: buildAttachments(event, data)
|
|
319
|
+
})
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Dashboard Features
|
|
325
|
+
|
|
326
|
+
### For Engineers
|
|
327
|
+
|
|
328
|
+
- View all branch deployments
|
|
329
|
+
- Check logs and status
|
|
330
|
+
- Trigger manual deploys
|
|
331
|
+
- View test results
|
|
332
|
+
|
|
333
|
+
### For QA
|
|
334
|
+
|
|
335
|
+
- Access preview URLs
|
|
336
|
+
- Submit bugs with screenshots
|
|
337
|
+
- View task board
|
|
338
|
+
- Track bug status
|
|
339
|
+
|
|
340
|
+
### For PO
|
|
341
|
+
|
|
342
|
+
- View project progress
|
|
343
|
+
- Access previews
|
|
344
|
+
- Review completed features
|
|
345
|
+
- Track milestones
|
|
346
|
+
|
|
347
|
+
## Docker Configuration
|
|
348
|
+
|
|
349
|
+
Each branch runs in isolated container:
|
|
350
|
+
|
|
351
|
+
```dockerfile
|
|
352
|
+
# Generated per deployment
|
|
353
|
+
FROM node:20-alpine
|
|
354
|
+
|
|
355
|
+
WORKDIR /app
|
|
356
|
+
COPY package*.json ./
|
|
357
|
+
RUN npm ci --production
|
|
358
|
+
COPY . .
|
|
359
|
+
|
|
360
|
+
ENV PORT=3000
|
|
361
|
+
EXPOSE 3000
|
|
362
|
+
|
|
363
|
+
CMD ["npm", "start"]
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### docker-compose.yml (on VPS)
|
|
367
|
+
|
|
368
|
+
```yaml
|
|
369
|
+
version: '3.8'
|
|
370
|
+
|
|
371
|
+
services:
|
|
372
|
+
main:
|
|
373
|
+
build:
|
|
374
|
+
context: ./deployments/main
|
|
375
|
+
ports:
|
|
376
|
+
- "3000:3000"
|
|
377
|
+
restart: unless-stopped
|
|
378
|
+
|
|
379
|
+
feat-auth:
|
|
380
|
+
build:
|
|
381
|
+
context: ./deployments/feat-auth
|
|
382
|
+
ports:
|
|
383
|
+
- "3001:3000"
|
|
384
|
+
restart: unless-stopped
|
|
385
|
+
|
|
386
|
+
# Added dynamically per branch
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## nginx Configuration
|
|
390
|
+
|
|
391
|
+
```nginx
|
|
392
|
+
# /etc/nginx/sites-enabled/tlc-deploy
|
|
393
|
+
|
|
394
|
+
# Dashboard
|
|
395
|
+
server {
|
|
396
|
+
listen 443 ssl;
|
|
397
|
+
server_name dashboard.project.example.com;
|
|
398
|
+
|
|
399
|
+
ssl_certificate /etc/letsencrypt/live/project.example.com/fullchain.pem;
|
|
400
|
+
ssl_certificate_key /etc/letsencrypt/live/project.example.com/privkey.pem;
|
|
401
|
+
|
|
402
|
+
location / {
|
|
403
|
+
proxy_pass http://localhost:3147;
|
|
404
|
+
proxy_http_version 1.1;
|
|
405
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
406
|
+
proxy_set_header Connection "upgrade";
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
# Branch deployments (wildcard)
|
|
411
|
+
server {
|
|
412
|
+
listen 443 ssl;
|
|
413
|
+
server_name ~^(?<branch>.+)\.project\.example\.com$;
|
|
414
|
+
|
|
415
|
+
ssl_certificate /etc/letsencrypt/live/project.example.com/fullchain.pem;
|
|
416
|
+
ssl_certificate_key /etc/letsencrypt/live/project.example.com/privkey.pem;
|
|
417
|
+
|
|
418
|
+
location / {
|
|
419
|
+
# Port mapping from branch name
|
|
420
|
+
set $port 3000;
|
|
421
|
+
# Dynamic port resolution handled by deploy server
|
|
422
|
+
proxy_pass http://localhost:$port;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Security
|
|
428
|
+
|
|
429
|
+
### SSH Key Deployment
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
> /tlc:deploy setup --ssh
|
|
433
|
+
|
|
434
|
+
Generating deployment SSH key...
|
|
435
|
+
✓ Key generated: ~/.ssh/tlc_deploy
|
|
436
|
+
|
|
437
|
+
Add this to VPS authorized_keys:
|
|
438
|
+
ssh-rsa AAAA... tlc-deploy
|
|
439
|
+
|
|
440
|
+
Add to GitHub deploy keys (read-only):
|
|
441
|
+
https://github.com/org/repo/settings/keys
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Environment Variables
|
|
445
|
+
|
|
446
|
+
Secrets stored on VPS:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
# /opt/tlc-deploy/.env
|
|
450
|
+
JWT_SECRET=your-secret-here
|
|
451
|
+
DATABASE_URL=postgres://user:pass@localhost/tlc
|
|
452
|
+
GITHUB_WEBHOOK_SECRET=webhook-secret
|
|
453
|
+
SLACK_WEBHOOK_URL=https://hooks.slack.com/...
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Cleanup
|
|
457
|
+
|
|
458
|
+
### Remove old deployments
|
|
459
|
+
|
|
460
|
+
```
|
|
461
|
+
> /tlc:deploy cleanup
|
|
462
|
+
|
|
463
|
+
Stale deployments (no activity 7+ days):
|
|
464
|
+
- feat-old (14 days)
|
|
465
|
+
- test-branch (21 days)
|
|
466
|
+
|
|
467
|
+
Remove these? (Y/n) y
|
|
468
|
+
|
|
469
|
+
Removed 2 deployments.
|
|
470
|
+
Freed 1.2GB disk space.
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Example Workflow
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
# Engineer pushes code
|
|
477
|
+
git push origin feat-auth
|
|
478
|
+
|
|
479
|
+
# GitHub webhook triggers deploy
|
|
480
|
+
# Slack: "🔄 Deploying feat-auth..."
|
|
481
|
+
|
|
482
|
+
# Tests run, deployment starts
|
|
483
|
+
# Slack: "🚀 feat-auth deployed to https://feat-auth.project.example.com"
|
|
484
|
+
|
|
485
|
+
# QA tests the feature
|
|
486
|
+
# Opens dashboard, tests in preview
|
|
487
|
+
# Finds bug, submits via form
|
|
488
|
+
# Slack: "🐛 BUG-015: Login timeout on slow connection"
|
|
489
|
+
|
|
490
|
+
# Engineer sees notification, fixes
|
|
491
|
+
git commit -m "fix: increase login timeout"
|
|
492
|
+
git push
|
|
493
|
+
|
|
494
|
+
# New deployment triggers
|
|
495
|
+
# Slack: "🚀 feat-auth updated"
|
|
496
|
+
|
|
497
|
+
# QA re-tests, marks bug fixed
|
|
498
|
+
# PO reviews, approves feature
|
|
499
|
+
|
|
500
|
+
# Merge to main
|
|
501
|
+
git checkout main
|
|
502
|
+
git merge feat-auth
|
|
503
|
+
git push
|
|
504
|
+
|
|
505
|
+
# Main deployment updates
|
|
506
|
+
# Slack: "🚀 main deployed - includes feat-auth"
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Notes
|
|
510
|
+
|
|
511
|
+
- Each branch gets isolated container
|
|
512
|
+
- Automatic cleanup of merged branches
|
|
513
|
+
- SSL via Let's Encrypt (wildcard cert)
|
|
514
|
+
- All actions logged for audit
|
|
515
|
+
- Role-based access control
|
|
516
|
+
- Webhook secrets required
|