appydave-tools 0.16.0 → 0.17.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/AGENTS.md +22 -0
  4. data/CHANGELOG.md +12 -0
  5. data/CLAUDE.md +206 -51
  6. data/README.md +144 -11
  7. data/bin/archive_project.rb +249 -0
  8. data/bin/configuration.rb +21 -1
  9. data/bin/generate_manifest.rb +357 -0
  10. data/bin/sync_from_ssd.rb +236 -0
  11. data/bin/vat +623 -0
  12. data/docs/README.md +169 -0
  13. data/docs/configuration/.env.example +19 -0
  14. data/docs/configuration/README.md +394 -0
  15. data/docs/configuration/channels.example.json +26 -0
  16. data/docs/configuration/settings.example.json +6 -0
  17. data/docs/development/CODEX-recommendations.md +123 -0
  18. data/docs/development/README.md +100 -0
  19. data/docs/development/cli-architecture-patterns.md +1604 -0
  20. data/docs/development/pattern-comparison.md +284 -0
  21. data/docs/prd-unified-brands-configuration.md +792 -0
  22. data/docs/project-brand-systems-analysis.md +934 -0
  23. data/docs/vat/dam-vision.md +123 -0
  24. data/docs/vat/session-summary-2025-11-09.md +297 -0
  25. data/docs/vat/usage.md +508 -0
  26. data/docs/vat/vat-testing-plan.md +801 -0
  27. data/lib/appydave/tools/configuration/models/brands_config.rb +238 -0
  28. data/lib/appydave/tools/configuration/models/config_base.rb +7 -0
  29. data/lib/appydave/tools/configuration/models/settings_config.rb +4 -0
  30. data/lib/appydave/tools/vat/config.rb +153 -0
  31. data/lib/appydave/tools/vat/config_loader.rb +91 -0
  32. data/lib/appydave/tools/vat/manifest_generator.rb +239 -0
  33. data/lib/appydave/tools/vat/project_listing.rb +198 -0
  34. data/lib/appydave/tools/vat/project_resolver.rb +132 -0
  35. data/lib/appydave/tools/vat/s3_operations.rb +560 -0
  36. data/lib/appydave/tools/version.rb +1 -1
  37. data/lib/appydave/tools.rb +9 -1
  38. data/package.json +1 -1
  39. metadata +57 -3
  40. data/docs/dam/overview.md +0 -28
@@ -0,0 +1,792 @@
1
+ # PRD: Unified Brands Configuration System
2
+
3
+ **Status**: Draft for Review
4
+ **Author**: Claude (with David Cruwys)
5
+ **Date**: 2025-11-09
6
+ **Version**: 1.0
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ Create a unified `brands.json` configuration system that consolidates video project brand management, integrating with existing `channels.json` (YouTube) and `settings.json` (global) configs. This eliminates the fragmented `.video-tools.env` files and provides a centralized, team-friendly configuration approach for multi-brand video project collaboration.
13
+
14
+ ---
15
+
16
+ ## Problem Statement
17
+
18
+ ### Current Issues
19
+
20
+ 1. **Fragmented Configuration**: Three disconnected systems
21
+ - `settings.json` (global paths)
22
+ - `channels.json` (YouTube metadata) - only 2/7 brands configured
23
+ - `.video-tools.env` (per-brand secrets) - only 1/7 brands has this file
24
+
25
+ 2. **Missing Multi-User Support**:
26
+ - Only David's credentials configured
27
+ - No structure for Jan, Vasilios, Ronnie to use their own AWS credentials
28
+ - No clear team access model
29
+
30
+ 3. **Code Bugs**:
31
+ - `ConfigLoader.load()` doesn't exist (should be `load_from_repo()`)
32
+ - AWS CLI dependency instead of AWS SDK gem
33
+ - Hardcoded brand shortcuts in `Config.expand_brand()`
34
+
35
+ 4. **Incomplete Coverage**:
36
+ - 7 brand directories exist
37
+ - 2 configured in `channels.json`
38
+ - 1 has `.video-tools.env`
39
+ - Brands: appydave, voz, aitldr, kiros, beauty-and-joy, supportsignal
40
+
41
+ 5. **Relationship Ambiguity**:
42
+ - Brands vs. YouTube channels not clearly defined
43
+ - Some brands are owned (appydave, aitldr, beauty-and-joy)
44
+ - Some brands are client work (voz, kiros, supportsignal)
45
+ - Not all brands publish to YouTube
46
+
47
+ ---
48
+
49
+ ## Goals
50
+
51
+ ### Primary Goals
52
+
53
+ 1. **Unified Configuration**: Single source of truth for brand metadata via `brands.json`
54
+ 2. **Multi-User Support**: Enable David, Jan, Vasilios, Ronnie to use their own AWS credentials
55
+ 3. **Security**: Separate secrets (AWS credentials) from metadata (brand config)
56
+ 4. **Consistency**: All 7 brands properly configured and accessible
57
+ 5. **Tool Integration**: `ad_config` (alias to `bin/configuration.rb`) manages all configs
58
+
59
+ ### Secondary Goals
60
+
61
+ 1. Migrate from AWS CLI shell commands to AWS SDK gem
62
+ 2. Fix `ConfigLoader` bugs
63
+ 3. Remove `.video-tools.env` dependency
64
+ 4. Link brands ↔ YouTube channels where applicable
65
+
66
+ ### Non-Goals
67
+
68
+ 1. **No business logic on brand types**: `owned` vs `client` is metadata only
69
+ 2. **No client isolation**: Single S3 bucket with prefixes (current architecture)
70
+ 3. **No required YouTube channels**: Brands can exist without YouTube channels
71
+ 4. **No complex permissions**: Use AWS IAM for access control
72
+
73
+ ---
74
+
75
+ ## User Stories
76
+
77
+ ### As David (Owner)
78
+ - I want to configure all 7 brands in one place
79
+ - I want to use my AWS credentials for brands I manage (appydave, aitldr, joy)
80
+ - I want team members to use their own credentials for brands they manage
81
+ - I want `ad_config` to show me all brands and their configuration status
82
+
83
+ ### As Jan (Team Member)
84
+ - I want to access most brands (except maybe appydave core) with my AWS credentials
85
+ - I want to see which brands I have access to
86
+ - I want VAT commands to automatically use my AWS profile
87
+
88
+ ### As Vasilios (Client - VOZ)
89
+ - I want to access only v-voz brand with my AWS credentials
90
+ - I want VAT to work for my brand without seeing other brands
91
+
92
+ ### As Ronnie (Client - Kiros/SupportSignal)
93
+ - I want to access v-kiros and v-supportsignal with my AWS credentials
94
+ - I want isolated access to only my client brands
95
+
96
+ ### As Developer (Using VAT)
97
+ - I want `vat list` to show all brands I have access to
98
+ - I want `vat s3-up appydave b65` to use the correct AWS profile automatically
99
+ - I want clear error messages if my AWS credentials are missing/invalid
100
+
101
+ ---
102
+
103
+ ## Architecture
104
+
105
+ ### Configuration File Structure
106
+
107
+ ```
108
+ ~/.config/appydave/
109
+ ├── settings.json # Global tool settings
110
+ ├── channels.json # YouTube channel configs (existing)
111
+ ├── brands.json # NEW: Video project brands
112
+ └── youtube_automation.json
113
+
114
+ ~/.aws/
115
+ └── credentials # AWS profiles (standard AWS CLI format)
116
+ ```
117
+
118
+ ### brands.json Schema
119
+
120
+ ```json
121
+ {
122
+ "brands": {
123
+ "appydave": {
124
+ "name": "AppyDave",
125
+ "shortcut": "ad",
126
+ "type": "owned",
127
+ "youtube_channels": ["appydave"],
128
+ "team": ["david", "jan"],
129
+ "locations": {
130
+ "video_projects": "/Users/davidcruwys/dev/video-projects/v-appydave",
131
+ "ssd_backup": "/Volumes/T7/youtube-PUBLISHED/appydave"
132
+ },
133
+ "aws": {
134
+ "profile": "david-appydave",
135
+ "region": "ap-southeast-1",
136
+ "s3_bucket": "appydave-video-projects",
137
+ "s3_prefix": "staging/v-appydave/"
138
+ },
139
+ "settings": {
140
+ "s3_cleanup_days": 90
141
+ }
142
+ },
143
+ "voz": {
144
+ "name": "VOZ Creative",
145
+ "shortcut": "voz",
146
+ "type": "client",
147
+ "youtube_channels": [],
148
+ "team": ["vasilios"],
149
+ "locations": {
150
+ "video_projects": "/Users/davidcruwys/dev/video-projects/v-voz",
151
+ "ssd_backup": "/Volumes/T7/voz"
152
+ },
153
+ "aws": {
154
+ "profile": "vasilios-voz",
155
+ "region": "ap-southeast-1",
156
+ "s3_bucket": "appydave-video-projects",
157
+ "s3_prefix": "staging/v-voz/"
158
+ }
159
+ },
160
+ "aitldr": {
161
+ "name": "AITLDR",
162
+ "shortcut": "ai",
163
+ "type": "owned",
164
+ "youtube_channels": ["aitldr"],
165
+ "team": ["david", "jan"],
166
+ "aws": {
167
+ "profile": "david-appydave",
168
+ "region": "ap-southeast-1",
169
+ "s3_bucket": "appydave-video-projects",
170
+ "s3_prefix": "staging/v-aitldr/"
171
+ }
172
+ },
173
+ "beauty-and-joy": {
174
+ "name": "Beauty & Joy",
175
+ "shortcut": "joy",
176
+ "type": "owned",
177
+ "youtube_channels": [],
178
+ "team": ["joy", "david"],
179
+ "aws": {
180
+ "profile": "david-appydave",
181
+ "region": "ap-southeast-1",
182
+ "s3_bucket": "appydave-video-projects",
183
+ "s3_prefix": "staging/v-beauty-and-joy/"
184
+ }
185
+ },
186
+ "kiros": {
187
+ "name": "Kiros",
188
+ "shortcut": "kiros",
189
+ "type": "client",
190
+ "youtube_channels": [],
191
+ "team": ["ronnie"],
192
+ "aws": {
193
+ "profile": "ronnie-kiros",
194
+ "region": "ap-southeast-1",
195
+ "s3_bucket": "appydave-video-projects",
196
+ "s3_prefix": "staging/v-kiros/"
197
+ }
198
+ },
199
+ "supportsignal": {
200
+ "name": "SupportSignal",
201
+ "shortcut": "ss",
202
+ "type": "client",
203
+ "youtube_channels": [],
204
+ "team": ["ronnie"],
205
+ "aws": {
206
+ "profile": "ronnie-kiros",
207
+ "region": "ap-southeast-1",
208
+ "s3_bucket": "appydave-video-projects",
209
+ "s3_prefix": "staging/v-supportsignal/"
210
+ }
211
+ }
212
+ },
213
+ "users": {
214
+ "david": {
215
+ "name": "David Cruwys",
216
+ "email": "david@appydave.com",
217
+ "role": "owner",
218
+ "default_aws_profile": "david-appydave"
219
+ },
220
+ "jan": {
221
+ "name": "Jan",
222
+ "role": "team_member",
223
+ "default_aws_profile": "jan-appydave"
224
+ },
225
+ "vasilios": {
226
+ "name": "Vasilios Kapenekas",
227
+ "role": "client",
228
+ "default_aws_profile": "vasilios-voz"
229
+ },
230
+ "ronnie": {
231
+ "name": "Ronnie",
232
+ "role": "client",
233
+ "default_aws_profile": "ronnie-kiros"
234
+ },
235
+ "joy": {
236
+ "name": "Joy",
237
+ "role": "owner",
238
+ "default_aws_profile": "joy-beauty"
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### AWS Credentials (separate file)
245
+
246
+ **Location**: `~/.aws/credentials` (standard AWS CLI format)
247
+
248
+ ```ini
249
+ [david-appydave]
250
+ aws_access_key_id = YOUR_ACCESS_KEY_HERE
251
+ aws_secret_access_key = YOUR_SECRET_KEY_HERE
252
+
253
+ [jan-appydave]
254
+ aws_access_key_id = YOUR_ACCESS_KEY_HERE
255
+ aws_secret_access_key = YOUR_SECRET_KEY_HERE
256
+
257
+ [vasilios-voz]
258
+ aws_access_key_id = YOUR_ACCESS_KEY_HERE
259
+ aws_secret_access_key = YOUR_SECRET_KEY_HERE
260
+
261
+ [ronnie-kiros]
262
+ aws_access_key_id = YOUR_ACCESS_KEY_HERE
263
+ aws_secret_access_key = YOUR_SECRET_KEY_HERE
264
+
265
+ [joy-beauty]
266
+ aws_access_key_id = YOUR_ACCESS_KEY_HERE
267
+ aws_secret_access_key = YOUR_SECRET_KEY_HERE
268
+ ```
269
+
270
+ **Security Benefits**:
271
+ - ✅ Never in git (standard AWS practice)
272
+ - ✅ Standard AWS tooling (`aws configure --profile`)
273
+ - ✅ Per-user credentials
274
+ - ✅ Separate from metadata
275
+
276
+ ---
277
+
278
+ ## Data Model
279
+
280
+ ### BrandInfo Class
281
+
282
+ ```ruby
283
+ class BrandInfo
284
+ attr_accessor :key, :name, :shortcut, :type, :youtube_channels,
285
+ :team, :locations, :aws, :settings
286
+
287
+ def initialize(key, data)
288
+ @key = key
289
+ @name = data['name']
290
+ @shortcut = data['shortcut']
291
+ @type = data['type'] # 'owned' or 'client' (metadata only)
292
+ @youtube_channels = data['youtube_channels'] || []
293
+ @team = data['team'] || []
294
+ @locations = BrandLocation.new(data['locations'] || {})
295
+ @aws = BrandAws.new(data['aws'] || {})
296
+ @settings = BrandSettings.new(data['settings'] || {})
297
+ end
298
+ end
299
+
300
+ class BrandLocation
301
+ attr_accessor :video_projects, :ssd_backup
302
+ end
303
+
304
+ class BrandAws
305
+ attr_accessor :profile, :region, :s3_bucket, :s3_prefix
306
+ end
307
+
308
+ class BrandSettings
309
+ attr_accessor :s3_cleanup_days
310
+ end
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Features & Requirements
316
+
317
+ ### Feature 1: BrandsConfig Model
318
+
319
+ **Description**: New configuration model parallel to `ChannelsConfig`
320
+
321
+ **Requirements**:
322
+ - [ ] Create `lib/appydave/tools/configuration/models/brands_config.rb`
323
+ - [ ] Implement `BrandsConfig < ConfigBase`
324
+ - [ ] Methods:
325
+ - `get_brand(brand_key)` → returns `BrandInfo`
326
+ - `set_brand(brand_key, brand_info)` → saves brand
327
+ - `brands()` → returns array of all `BrandInfo`
328
+ - `get_brands_for_user(user_key)` → filters by team membership
329
+ - `key?(key)` → check if brand exists
330
+ - `print()` → tabular display of all brands
331
+ - [ ] Type-safe classes: `BrandInfo`, `BrandLocation`, `BrandAws`, `BrandSettings`
332
+ - [ ] Default data structure
333
+ - [ ] Config file: `~/.config/appydave/brands.json`
334
+
335
+ **Acceptance Criteria**:
336
+ - BrandsConfig loads/saves brands.json correctly
337
+ - All 7 brands can be configured
338
+ - Validation ensures required fields present
339
+ - Print displays tabular brand information
340
+
341
+ ---
342
+
343
+ ### Feature 2: Integration with Configuration::Config
344
+
345
+ **Description**: Register brands configuration in central config system
346
+
347
+ **Requirements**:
348
+ - [ ] Update `lib/appydave/tools/configuration/config.rb`
349
+ - [ ] Add `register_config(:brands, Models::BrandsConfig)`
350
+ - [ ] Method: `Config.brands` returns `BrandsConfig` instance
351
+ - [ ] Method: `Config.configure` includes brands setup
352
+
353
+ **Acceptance Criteria**:
354
+ - `ad_config -p brands` prints brands configuration
355
+ - `ad_config -c` creates default brands.json if missing
356
+ - `ad_config -e` opens brands.json in editor
357
+
358
+ ---
359
+
360
+ ### Feature 3: Migrate VAT to Use brands.json
361
+
362
+ **Description**: Remove dependency on `.video-tools.env`, use `brands.json` instead
363
+
364
+ **Requirements**:
365
+
366
+ **3a. Update Vat::Config**:
367
+ - [ ] Remove hardcoded brand shortcuts (joy, ss)
368
+ - [ ] Read brand shortcuts from `brands.json`
369
+ - [ ] `brand_path()` reads from `brands.json` locations
370
+ - [ ] `expand_brand()` reads from `brands.json` shortcuts
371
+ - [ ] `available_brands()` reads from `brands.json`
372
+ - [ ] Remove `valid_brand?()` check for `.video-tools.env`
373
+
374
+ **3b. Update Vat::ConfigLoader**:
375
+ - [ ] Deprecate `ConfigLoader` entirely (no longer needed)
376
+ - [ ] OR: Refactor to load from `brands.json` instead of `.video-tools.env`
377
+ - [ ] Method: `ConfigLoader.load_brand(brand_key)` → loads from `brands.json`
378
+ - [ ] Fix bug: `ConfigLoader.load()` doesn't exist (called by S3Operations:19)
379
+
380
+ **3c. Update S3Operations**:
381
+ - [ ] Initialize with `brand_key` instead of `brand_path`
382
+ - [ ] Load config from `brands.json`: `config = Config.brands.get_brand(brand_key)`
383
+ - [ ] Get AWS profile: `config.aws.profile`
384
+ - [ ] Get S3 bucket: `config.aws.s3_bucket`
385
+ - [ ] Get S3 prefix: `config.aws.s3_prefix`
386
+
387
+ **Acceptance Criteria**:
388
+ - VAT commands work with brands.json
389
+ - No dependency on `.video-tools.env`
390
+ - All 7 brands accessible
391
+ - `vat list` shows all configured brands
392
+
393
+ ---
394
+
395
+ ### Feature 4: AWS SDK Integration
396
+
397
+ **Description**: Replace AWS CLI shell commands with AWS SDK gem
398
+
399
+ **Requirements**:
400
+ - [ ] Add gem dependency: `spec.add_dependency 'aws-sdk-s3', '~> 1.0'`
401
+ - [ ] Update `S3Operations` to use AWS SDK
402
+ - [ ] Initialize S3 client with profile from `brands.json`:
403
+ ```ruby
404
+ Aws::S3::Client.new(
405
+ profile: config.aws.profile,
406
+ region: config.aws.region
407
+ )
408
+ ```
409
+ - [ ] Replace 5 AWS CLI operations:
410
+ 1. `aws s3api head-object` → `s3_client.head_object()`
411
+ 2. `aws s3 cp` (upload) → `s3_client.put_object()`
412
+ 3. `aws s3 cp` (download) → `s3_client.get_object()`
413
+ 4. `aws s3 rm` → `s3_client.delete_object()`
414
+ 5. `aws s3api list-objects-v2` → `s3_client.list_objects_v2()`
415
+
416
+ **Acceptance Criteria**:
417
+ - No AWS CLI dependency
418
+ - S3 operations use SDK gem
419
+ - AWS credentials from `~/.aws/credentials` profiles
420
+ - Error handling for missing/invalid credentials
421
+ - All existing VAT S3 commands work (s3-up, s3-down, s3-status, s3-cleanup)
422
+
423
+ ---
424
+
425
+ ### Feature 5: Update bin/vat Command
426
+
427
+ **Description**: Ensure VAT CLI works with new brands.json system
428
+
429
+ **Requirements**:
430
+ - [ ] Update `parse_s3_args()` to use brands config
431
+ - [ ] Remove `ENV['BRAND_PATH']` workaround (line 203)
432
+ - [ ] Update help text to reference brands.json
433
+ - [ ] Update `vat help config` to show brands.json setup
434
+
435
+ **Acceptance Criteria**:
436
+ - `vat list` shows all brands from brands.json
437
+ - `vat s3-*` commands use AWS SDK with correct profiles
438
+ - Help text accurate
439
+
440
+ ---
441
+
442
+ ### Feature 6: Migration Tool
443
+
444
+ **Description**: Migrate existing `.video-tools.env` → `brands.json` + `~/.aws/credentials`
445
+
446
+ **Requirements**:
447
+ - [ ] Create `bin/migrate_brands_config.rb`
448
+ - [ ] Read existing `.video-tools.env` files
449
+ - [ ] Generate `brands.json` structure
450
+ - [ ] Generate `~/.aws/credentials` profiles
451
+ - [ ] Show migration summary
452
+ - [ ] Backup original files
453
+
454
+ **Acceptance Criteria**:
455
+ - Migration tool converts v-appydave/.video-tools.env successfully
456
+ - Generates complete brands.json with all 7 brands
457
+ - AWS credentials extracted to ~/.aws/credentials
458
+ - User can review before committing changes
459
+
460
+ ---
461
+
462
+ ### Feature 7: Documentation
463
+
464
+ **Requirements**:
465
+ - [ ] Update `docs/vat/vat-testing-plan.md`
466
+ - Remove references to `.video-tools.env`
467
+ - Add references to `brands.json`
468
+ - Update setup instructions
469
+ - [ ] Create `docs/brands-configuration.md`
470
+ - Explain brands.json structure
471
+ - Setup guide for new team members
472
+ - AWS profile setup instructions
473
+ - [ ] Update `CLAUDE.md`
474
+ - Document brands configuration system
475
+ - Update VAT configuration section
476
+
477
+ ---
478
+
479
+ ## Technical Specifications
480
+
481
+ ### Code Structure
482
+
483
+ ```
484
+ lib/appydave/tools/
485
+ ├── configuration/
486
+ │ ├── config.rb # Update: register brands
487
+ │ └── models/
488
+ │ ├── brands_config.rb # NEW
489
+ │ ├── channels_config.rb # Existing
490
+ │ └── settings_config.rb # Existing
491
+
492
+ └── vat/
493
+ ├── config.rb # Update: use brands.json
494
+ ├── config_loader.rb # Deprecate or refactor
495
+ ├── s3_operations.rb # Update: AWS SDK + brands.json
496
+ ├── project_listing.rb # Update: use brands.json
497
+ └── project_resolver.rb # Update: use brands.json
498
+
499
+ bin/
500
+ ├── configuration.rb # Update: support brands
501
+ ├── vat # Update: use brands.json
502
+ └── migrate_brands_config.rb # NEW
503
+
504
+ docs/
505
+ ├── prd-unified-brands-configuration.md # This file
506
+ ├── brands-configuration.md # NEW: User guide
507
+ └── vat/
508
+ └── vat-testing-plan.md # Update references
509
+ ```
510
+
511
+ ---
512
+
513
+ ## Testing Strategy
514
+
515
+ ### Unit Tests
516
+
517
+ - [ ] `spec/appydave/tools/configuration/models/brands_config_spec.rb`
518
+ - Test load/save brands.json
519
+ - Test get_brand(), brands(), get_brands_for_user()
520
+ - Test validation
521
+ - Test print()
522
+
523
+ - [ ] Update `spec/appydave/tools/vat/config_spec.rb`
524
+ - Test brand_path() reads from brands.json
525
+ - Test expand_brand() uses brands.json shortcuts
526
+ - Test available_brands() from brands.json
527
+
528
+ - [ ] Update `spec/appydave/tools/vat/s3_operations_spec.rb`
529
+ - Mock AWS SDK client
530
+ - Test all 5 S3 operations with SDK
531
+ - Test AWS profile loading
532
+
533
+ ### Integration Tests
534
+
535
+ - [ ] Test `ad_config -p brands` prints all brands
536
+ - [ ] Test `ad_config -c` creates brands.json
537
+ - [ ] Test `vat list` with brands.json
538
+ - [ ] Test `vat s3-up` with AWS SDK and profiles
539
+ - [ ] Test migration tool with sample .video-tools.env
540
+
541
+ ### Manual Testing
542
+
543
+ - [ ] Setup brands.json on David's machine
544
+ - [ ] Setup AWS profiles for David
545
+ - [ ] Test all VAT commands
546
+ - [ ] Verify other team members can set up their profiles
547
+
548
+ ---
549
+
550
+ ## Migration Plan
551
+
552
+ ### Phase 1: Foundation (Week 1) ✅ COMPLETED
553
+
554
+ **Goal**: Create brands.json infrastructure
555
+
556
+ 1. ✅ Create `BrandsConfig` model
557
+ 2. ✅ Register with `Configuration::Config`
558
+ 3. ✅ Write unit tests
559
+ 4. ✅ Test `ad_config` commands
560
+ 5. ✅ Populate all 6 brands (appydave, voz, aitldr, kiros, joy, ss)
561
+
562
+ **Deliverable**: Working brands.json system
563
+
564
+ **Status**: Complete (2025-11-09)
565
+
566
+ ---
567
+
568
+ ### Phase 2: VAT Integration (Week 2) ✅ COMPLETED
569
+
570
+ **Goal**: VAT uses brands.json
571
+
572
+ 1. ✅ Update `Vat::Config` to read brands.json
573
+ 2. ✅ Refactor/deprecate `ConfigLoader`
574
+ 3. ✅ Update VAT commands
575
+ 4. ✅ Update unit tests
576
+
577
+ **Deliverable**: VAT works with brands.json (still using AWS CLI)
578
+
579
+ **Status**: Complete (2025-11-09)
580
+
581
+ ---
582
+
583
+ ### Phase 3: AWS SDK (Week 2-3) ✅ COMPLETED
584
+
585
+ **Goal**: Replace AWS CLI with SDK
586
+
587
+ 1. ✅ Add aws-sdk-s3 gem
588
+ 2. ✅ Refactor `S3Operations` to use SDK
589
+ 3. ✅ Test with AWS profiles
590
+ 4. ✅ Update integration tests
591
+ 5. ✅ Implement dependency injection pattern
592
+ 6. ✅ Add S3 cleanup local command
593
+ 7. ✅ Fix S3 status to show local-only files
594
+ 8. ✅ Rename cleanup commands (s3-cleanup-remote, s3-cleanup-local)
595
+
596
+ **Deliverable**: VAT uses AWS SDK with profiles from brands.json
597
+
598
+ **Status**: Complete (2025-11-09)
599
+ - 289 tests passing
600
+ - 90.59% code coverage
601
+ - RuboCop clean
602
+ - Manually tested by David
603
+
604
+ ---
605
+
606
+ ### Phase 4: Migration & Cleanup (Week 3)
607
+
608
+ **Goal**: Complete migration, remove old system
609
+
610
+ 1. Create migration tool
611
+ 2. Migrate David's setup
612
+ 3. Test all VAT workflows
613
+ 4. Update documentation
614
+ 5. Remove `.video-tools.env` dependency
615
+ 6. Update testing plan
616
+
617
+ **Deliverable**: Production-ready unified configuration system
618
+
619
+ ---
620
+
621
+ ### Phase 5: Team Onboarding (Week 4)
622
+
623
+ **Goal**: Enable team members to configure their access
624
+
625
+ 1. Document setup process
626
+ 2. Create AWS IAM users (if needed)
627
+ 3. Help Jan/Vasilios/Ronnie configure profiles
628
+ 4. Test multi-user access
629
+
630
+ **Deliverable**: All team members using VAT with their own credentials
631
+
632
+ ---
633
+
634
+ ## Success Criteria
635
+
636
+ ### Must Have (MVP)
637
+
638
+ - [ ] All 7 brands configured in brands.json
639
+ - [ ] AWS credentials in ~/.aws/credentials profiles
640
+ - [ ] VAT commands work with brands.json
641
+ - [ ] S3 operations use AWS SDK gem
642
+ - [ ] No dependency on .video-tools.env
643
+ - [ ] All existing tests pass
644
+ - [ ] Migration tool works
645
+ - [ ] Documentation complete
646
+
647
+ ### Should Have
648
+
649
+ - [ ] Team members can configure their own profiles
650
+ - [ ] Multi-user access tested
651
+ - [ ] Error messages helpful for missing credentials
652
+ - [ ] `ad_config` prints brand summary
653
+
654
+ ### Nice to Have
655
+
656
+ - [ ] Brand-channel linking visible in `ad_config`
657
+ - [ ] Validate AWS profiles are configured
658
+ - [ ] Auto-detect current user
659
+ - [ ] Brand access enforcement (by team membership)
660
+
661
+ ---
662
+
663
+ ## Risks & Mitigations
664
+
665
+ | Risk | Impact | Mitigation |
666
+ |------|--------|------------|
667
+ | Breaking existing VAT workflows | High | Thorough testing, migration tool, rollback plan |
668
+ | AWS SDK complexity | Medium | Start with simple operations, test extensively |
669
+ | Team member setup friction | Medium | Clear documentation, setup scripts |
670
+ | ConfigLoader refactoring breaks things | High | Incremental changes, test coverage |
671
+ | .video-tools.env still needed for legacy scripts | Low | Audit all usages first |
672
+
673
+ ---
674
+
675
+ ## Open Questions
676
+
677
+ 1. **User detection**: How should VAT detect current user (david, jan, etc.)?
678
+ - Option A: `whoami` system user
679
+ - Option B: Config setting `~/.config/appydave/settings.json` → `current_user`
680
+ - Option C: Environment variable `APPYDAVE_USER`
681
+
682
+ 2. **AWS profile fallback**: What if profile doesn't exist?
683
+ - Try user's default profile?
684
+ - Error with setup instructions?
685
+
686
+ 3. **Brand access enforcement**: Should VAT check team membership?
687
+ - Or rely on AWS IAM to deny access?
688
+
689
+ 4. **SSD backup**: Should all brands share same SSD path structure?
690
+ - Current: `/Volumes/T7/youtube-PUBLISHED/{brand}/`
691
+ - Or allow custom per-brand paths?
692
+
693
+ 5. **Legacy bin/ scripts**: What about `archive_project.rb`, `sync_from_ssd.rb`, `generate_manifest.rb`?
694
+ - Migrate to brands.json?
695
+ - Integrate into `vat` command?
696
+ - Leave as-is?
697
+
698
+ ---
699
+
700
+ ## Appendix A: Current vs. Proposed
701
+
702
+ ### Current System
703
+
704
+ ```
705
+ Configuration Sources:
706
+ 1. settings.json → video-projects-root only
707
+ 2. channels.json → 2/7 brands, YouTube metadata
708
+ 3. .video-tools.env → 1/7 brands, AWS credentials
709
+
710
+ AWS Access:
711
+ - Hardcoded in .video-tools.env
712
+ - Only David's credentials
713
+ - AWS CLI shell commands
714
+
715
+ Brand Discovery:
716
+ - Hardcoded shortcuts (joy, ss)
717
+ - Scans filesystem for v-* directories
718
+ - No central registration
719
+ ```
720
+
721
+ ### Proposed System
722
+
723
+ ```
724
+ Configuration Sources:
725
+ 1. settings.json → global paths (unchanged)
726
+ 2. channels.json → YouTube metadata (unchanged)
727
+ 3. brands.json → ALL brand metadata (NEW)
728
+ 4. ~/.aws/credentials → AWS profiles (standard)
729
+
730
+ AWS Access:
731
+ - Per-user profiles in ~/.aws/credentials
732
+ - AWS SDK gem (no CLI dependency)
733
+ - Profile name from brands.json
734
+
735
+ Brand Discovery:
736
+ - Registered in brands.json
737
+ - Shortcuts defined in brands.json
738
+ - Team membership tracked
739
+ ```
740
+
741
+ ---
742
+
743
+ ## Appendix B: Example Workflows
744
+
745
+ ### Setup New Brand (VOZ)
746
+
747
+ ```bash
748
+ # 1. Add brand to brands.json
749
+ ad_config -e
750
+ # Add voz brand config with Vasilios's AWS profile
751
+
752
+ # 2. Vasilios configures his AWS credentials
753
+ aws configure --profile vasilios-voz
754
+ # Enters his AWS_ACCESS_KEY_ID and SECRET
755
+
756
+ # 3. Test access
757
+ vat list voz
758
+ vat s3-status voz boy-baker
759
+ ```
760
+
761
+ ### Developer Using VAT
762
+
763
+ ```bash
764
+ # List all brands I have access to
765
+ vat list
766
+
767
+ # Work with specific brand (auto-detects profile)
768
+ cd ~/dev/video-projects/v-appydave/b65-*
769
+ vat s3-up --dry-run
770
+
771
+ # Explicit brand
772
+ vat s3-up appydave b65
773
+ # Uses aws.profile from brands.json → david-appydave
774
+ ```
775
+
776
+ ---
777
+
778
+ ## Sign-Off
779
+
780
+ **Product Owner**: David Cruwys
781
+ **Developer**: Claude
782
+ **Reviewer**: ___________
783
+
784
+ **Approval Date**: ___________
785
+
786
+ ---
787
+
788
+ **Next Steps After Approval**:
789
+ 1. Review and approve PRD
790
+ 2. Create implementation plan with tasks
791
+ 3. Begin Phase 1: BrandsConfig model
792
+ 4. Weekly progress reviews