appydave-tools 0.21.2 → 0.22.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/bin/dam +137 -0
- data/docs/README.md +187 -90
- data/docs/architecture/dam/dam-cli-enhancements.md +642 -0
- data/docs/architecture/dam/dam-cli-implementation-guide.md +1041 -0
- data/docs/architecture/dam/dam-data-model.md +466 -0
- data/docs/architecture/dam/dam-visualization-requirements.md +641 -0
- data/docs/architecture/dam/implementation-roadmap.md +328 -0
- data/docs/architecture/dam/jan-collaboration-guide.md +309 -0
- data/lib/appydave/tools/dam/s3_operations.rb +57 -5
- data/lib/appydave/tools/dam/s3_scanner.rb +139 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +1 -0
- data/package.json +1 -1
- metadata +37 -32
- data/docs/development/CODEX-recommendations.md +0 -258
- data/docs/development/README.md +0 -100
- /data/docs/{development/pattern-comparison.md → architecture/cli/cli-pattern-comparison.md} +0 -0
- /data/docs/{development/cli-architecture-patterns.md → architecture/cli/cli-patterns.md} +0 -0
- /data/docs/{project-brand-systems-analysis.md → architecture/configuration/configuration-systems.md} +0 -0
- /data/docs/{dam → architecture/dam}/dam-vision.md +0 -0
- /data/docs/{dam/prd-client-sharing.md → architecture/dam/design-decisions/002-client-sharing.md} +0 -0
- /data/docs/{dam/prd-git-integration.md → architecture/dam/design-decisions/003-git-integration.md} +0 -0
- /data/docs/{prd-unified-brands-configuration.md → architecture/design-decisions/001-unified-brands-config.md} +0 -0
- /data/docs/{dam/session-summary-2025-11-09.md → architecture/design-decisions/session-2025-11-09.md} +0 -0
- /data/docs/{configuration/README.md → guides/configuration-setup.md} +0 -0
- /data/docs/{dam → guides/platforms}/windows/README.md +0 -0
- /data/docs/{dam → guides/platforms}/windows/dam-testing-plan-windows-powershell.md +0 -0
- /data/docs/{dam → guides/platforms}/windows/installation.md +0 -0
- /data/docs/{tools → guides/tools}/bank-reconciliation.md +0 -0
- /data/docs/{tools → guides/tools}/cli-actions.md +0 -0
- /data/docs/{tools → guides/tools}/configuration.md +0 -0
- /data/docs/{dam → guides/tools/dam}/dam-testing-plan.md +0 -0
- /data/docs/{dam/usage.md → guides/tools/dam/dam-usage.md} +0 -0
- /data/docs/{tools → guides/tools}/gpt-context.md +0 -0
- /data/docs/{tools → guides/tools}/index.md +0 -0
- /data/docs/{tools → guides/tools}/move-images.md +0 -0
- /data/docs/{tools → guides/tools}/name-manager.md +0 -0
- /data/docs/{tools → guides/tools}/prompt-tools.md +0 -0
- /data/docs/{tools → guides/tools}/subtitle-processor.md +0 -0
- /data/docs/{tools → guides/tools}/youtube-automation.md +0 -0
- /data/docs/{tools → guides/tools}/youtube-manager.md +0 -0
- /data/docs/{configuration → templates}/.env.example +0 -0
- /data/docs/{configuration → templates}/channels.example.json +0 -0
- /data/docs/{configuration → templates}/settings.example.json +0 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# DAM Data Model
|
|
2
|
+
|
|
3
|
+
**Digital Asset Management - Entity Schema and Data Sources**
|
|
4
|
+
|
|
5
|
+
This document defines the complete data model for the DAM (Digital Asset Management) system, including all entities, their relationships, data sources, and how state is inferred from the filesystem and configuration.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The DAM system manages video projects across multiple brands, team members, and storage locations. The data model is **inferred from filesystem structure and configuration** rather than stored in a database, making it git-friendly and deployment-agnostic.
|
|
12
|
+
|
|
13
|
+
**Key Principle:** All state is calculated at runtime from:
|
|
14
|
+
- Filesystem structure (project folders, file presence)
|
|
15
|
+
- Configuration files (`brands.json`, `settings.json`, `channels.json`)
|
|
16
|
+
- Generated manifests (`projects.json` per brand)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Entity Hierarchy
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
System (root)
|
|
24
|
+
├── Brands (6 brands: appydave, aitldr, voz, kiros, beauty-and-joy, supportsignal)
|
|
25
|
+
│ ├── Projects (varies by brand)
|
|
26
|
+
│ │ ├── Storage Locations (local, S3, SSD)
|
|
27
|
+
│ │ │ └── Files (recordings, assets, s3-staging, etc.)
|
|
28
|
+
│ │ └── Metadata (type, structure, disk usage)
|
|
29
|
+
│ └── Team Members (brand-specific access)
|
|
30
|
+
└── Users (cross-brand: david, jan, joy, vasilios, ronnie)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Core Entities
|
|
36
|
+
|
|
37
|
+
### 1. Brand
|
|
38
|
+
|
|
39
|
+
**Definition:** A content brand or client with its own video projects, team, and storage configuration.
|
|
40
|
+
|
|
41
|
+
**Data Source:** `~/.config/appydave/brands.json`
|
|
42
|
+
|
|
43
|
+
**Schema:**
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"name": "AppyDave",
|
|
47
|
+
"shortcut": "ad",
|
|
48
|
+
"type": "owned|client",
|
|
49
|
+
"youtube_channels": ["appydave"],
|
|
50
|
+
"team": ["david", "jan"],
|
|
51
|
+
"git_remote": "git@github.com:appydave-video-projects/v-appydave.git",
|
|
52
|
+
"locations": {
|
|
53
|
+
"video_projects": "/Users/davidcruwys/dev/video-projects/v-appydave",
|
|
54
|
+
"ssd_backup": "/Volumes/T7/youtube-PUBLISHED/appydave"
|
|
55
|
+
},
|
|
56
|
+
"aws": {
|
|
57
|
+
"profile": "david-appydave",
|
|
58
|
+
"region": "ap-southeast-1",
|
|
59
|
+
"s3_bucket": "appydave-video-projects",
|
|
60
|
+
"s3_prefix": "staging/v-appydave/"
|
|
61
|
+
},
|
|
62
|
+
"settings": {
|
|
63
|
+
"s3_cleanup_days": 90
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Properties:**
|
|
69
|
+
| Property | Type | Description | Example |
|
|
70
|
+
|----------|------|-------------|---------|
|
|
71
|
+
| `name` | string | Display name | `"AppyDave"` |
|
|
72
|
+
| `shortcut` | string | Short identifier | `"ad"` |
|
|
73
|
+
| `type` | enum | `"owned"` or `"client"` | `"owned"` |
|
|
74
|
+
| `youtube_channels` | array | YouTube channel codes | `["appydave"]` |
|
|
75
|
+
| `team` | array | User keys with access | `["david", "jan"]` |
|
|
76
|
+
| `git_remote` | string | Git repository URL | `"git@github.com:..."` |
|
|
77
|
+
| `locations.video_projects` | string | Local project root path | `"/Users/.../v-appydave"` |
|
|
78
|
+
| `locations.ssd_backup` | string | SSD backup base path | `"/Volumes/T7/..."` |
|
|
79
|
+
| `aws.profile` | string | AWS CLI profile name | `"david-appydave"` |
|
|
80
|
+
| `aws.s3_bucket` | string | S3 bucket name | `"appydave-video-projects"` |
|
|
81
|
+
| `aws.s3_prefix` | string | S3 key prefix | `"staging/v-appydave/"` |
|
|
82
|
+
| `settings.s3_cleanup_days` | number | S3 retention policy | `90` |
|
|
83
|
+
|
|
84
|
+
**Current Brands:**
|
|
85
|
+
- `appydave` (owned, David + Jan)
|
|
86
|
+
- `aitldr` (owned, David + Jan)
|
|
87
|
+
- `voz` (client, Vasilios)
|
|
88
|
+
- `beauty-and-joy` (owned, Joy + David)
|
|
89
|
+
- `kiros` (client, Ronnie)
|
|
90
|
+
- `supportsignal` (client, Ronnie)
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### 2. User
|
|
95
|
+
|
|
96
|
+
**Definition:** A person with access to one or more brands.
|
|
97
|
+
|
|
98
|
+
**Data Source:** `~/.config/appydave/brands.json` (users section)
|
|
99
|
+
|
|
100
|
+
**Schema:**
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"name": "David Cruwys",
|
|
104
|
+
"email": "david@appydave.com",
|
|
105
|
+
"role": "owner|team_member|client",
|
|
106
|
+
"default_aws_profile": "david-appydave"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Properties:**
|
|
111
|
+
| Property | Type | Description | Values |
|
|
112
|
+
|----------|------|-------------|--------|
|
|
113
|
+
| `name` | string | Full name | `"David Cruwys"` |
|
|
114
|
+
| `email` | string | Email address | `"david@appydave.com"` |
|
|
115
|
+
| `role` | enum | User type | `"owner"`, `"team_member"`, `"client"` |
|
|
116
|
+
| `default_aws_profile` | string | Default AWS profile | `"david-appydave"` |
|
|
117
|
+
|
|
118
|
+
**Current Users:**
|
|
119
|
+
- `david` - Owner (all brands)
|
|
120
|
+
- `jan` - Team member (appydave, aitldr)
|
|
121
|
+
- `joy` - Team member (beauty-and-joy)
|
|
122
|
+
- `vasilios` - Client (voz)
|
|
123
|
+
- `ronnie` - Client (kiros, supportsignal)
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### 3. Project
|
|
128
|
+
|
|
129
|
+
**Definition:** A video project belonging to a brand, with content spread across local, S3, and SSD storage.
|
|
130
|
+
|
|
131
|
+
**Data Source:**
|
|
132
|
+
- Primary: `{brand}/projects.json` (generated manifest)
|
|
133
|
+
- Filesystem: Project folders in `{brand}/`, `{brand}/archived/`, SSD ranges
|
|
134
|
+
|
|
135
|
+
**Schema:**
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"id": "b64-bmad-claude-sdk",
|
|
139
|
+
"type": "flivideo|storyline|general",
|
|
140
|
+
"storage": {
|
|
141
|
+
"local": {
|
|
142
|
+
"exists": true,
|
|
143
|
+
"structure": "flat|archived|null",
|
|
144
|
+
"has_heavy_files": false,
|
|
145
|
+
"has_light_files": true
|
|
146
|
+
},
|
|
147
|
+
"s3": {
|
|
148
|
+
"exists": true
|
|
149
|
+
},
|
|
150
|
+
"ssd": {
|
|
151
|
+
"exists": false,
|
|
152
|
+
"path": null
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Properties:**
|
|
159
|
+
| Property | Type | Description | Inferred From |
|
|
160
|
+
|----------|------|-------------|---------------|
|
|
161
|
+
| `id` | string | Project folder name | Filesystem |
|
|
162
|
+
| `type` | enum | Project workflow type | Folder structure + naming |
|
|
163
|
+
| `storage.local.exists` | boolean | Exists in local filesystem | `Dir.exist?` |
|
|
164
|
+
| `storage.local.structure` | enum | Storage structure type | Path location |
|
|
165
|
+
| `storage.local.has_heavy_files` | boolean | Contains video files | `*.{mp4,mov,avi,mkv,webm}` |
|
|
166
|
+
| `storage.local.has_light_files` | boolean | Contains text/assets | `*.{srt,jpg,png,md,json}` |
|
|
167
|
+
| `storage.s3.exists` | boolean | Has `s3-staging` folder | `Dir.exist?(s3-staging)` |
|
|
168
|
+
| `storage.ssd.exists` | boolean | Found on SSD | SSD filesystem scan |
|
|
169
|
+
| `storage.ssd.path` | string | SSD relative path | Project ID (or range path) |
|
|
170
|
+
|
|
171
|
+
**Project Types:**
|
|
172
|
+
| Type | Detection Logic | Example |
|
|
173
|
+
|------|-----------------|---------|
|
|
174
|
+
| `flivideo` | Pattern: `[a-z]\d{2}-name` | `b64-bmad-claude-sdk` |
|
|
175
|
+
| `storyline` | Has `data/storyline.json` | `boy-baker` |
|
|
176
|
+
| `general` | Everything else | `-01-25` |
|
|
177
|
+
|
|
178
|
+
**Local Structure Types:**
|
|
179
|
+
| Structure | Location | Purpose |
|
|
180
|
+
|-----------|----------|---------|
|
|
181
|
+
| `flat` | `{brand}/{project-id}/` | Active projects |
|
|
182
|
+
| `archived` | `{brand}/archived/{range}/{project-id}/` | Restored/archived projects |
|
|
183
|
+
| `null` | Not on local | SSD-only or missing |
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### 4. Storage Location
|
|
188
|
+
|
|
189
|
+
**Definition:** A physical or cloud location where project files reside.
|
|
190
|
+
|
|
191
|
+
**Three Storage Types:**
|
|
192
|
+
|
|
193
|
+
#### A. Local Storage
|
|
194
|
+
- **Path:** `{brand}/` or `{brand}/archived/{range}/`
|
|
195
|
+
- **Purpose:** Active development, recording, editing
|
|
196
|
+
- **Characteristics:**
|
|
197
|
+
- Git repository (light files only)
|
|
198
|
+
- Heavy files gitignored
|
|
199
|
+
- Structured folders (recordings/, assets/, s3-staging/, etc.)
|
|
200
|
+
|
|
201
|
+
#### B. S3 Staging Storage
|
|
202
|
+
- **Path (virtual):** `s3://{bucket}/{prefix}/{project-id}/`
|
|
203
|
+
- **Detection:** Presence of `{project-local}/s3-staging/` folder
|
|
204
|
+
- **Purpose:** Short-term collaboration (90 days)
|
|
205
|
+
- **Characteristics:**
|
|
206
|
+
- Transient (auto-cleanup after 90 days)
|
|
207
|
+
- Enables David ↔ Jan file exchange
|
|
208
|
+
- Shareable links for clients
|
|
209
|
+
|
|
210
|
+
#### C. SSD Backup Storage
|
|
211
|
+
- **Path:** `/Volumes/T7/{brand}/{range}/{project-id}/`
|
|
212
|
+
- **Purpose:** Long-term archive
|
|
213
|
+
- **Characteristics:**
|
|
214
|
+
- Cold storage (external drive)
|
|
215
|
+
- Organized in range folders (`b00-b49`, `b50-b99`)
|
|
216
|
+
- Not always mounted/available
|
|
217
|
+
|
|
218
|
+
**SSD Availability Detection:**
|
|
219
|
+
```ruby
|
|
220
|
+
ssd_available = Dir.exist?(brand_info.locations.ssd_backup)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### 5. File Categories
|
|
226
|
+
|
|
227
|
+
**Definition:** Files within a project, categorized by type and gitignore status.
|
|
228
|
+
|
|
229
|
+
**Heavy Files** (gitignored):
|
|
230
|
+
- `*.mp4`, `*.mov`, `*.avi`, `*.mkv`, `*.webm`
|
|
231
|
+
- Detection: `Dir.glob(File.join(dir, '*.{mp4,mov,...}'))`
|
|
232
|
+
|
|
233
|
+
**Light Files** (git-tracked):
|
|
234
|
+
- `*.srt`, `*.vtt` (subtitles)
|
|
235
|
+
- `*.jpg`, `*.png` (thumbnails, assets)
|
|
236
|
+
- `*.md`, `*.txt` (documentation)
|
|
237
|
+
- `*.json`, `*.yml` (metadata)
|
|
238
|
+
- Detection: `Dir.glob(File.join(dir, '**/*.{srt,vtt,...}'))`
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Data Sources Hierarchy
|
|
243
|
+
|
|
244
|
+
### Configuration Files (Read Once, Cached)
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
~/.config/appydave/
|
|
248
|
+
├── brands.json # Brand definitions, team, AWS config
|
|
249
|
+
├── settings.json # Global paths (video-projects-root, etc.)
|
|
250
|
+
├── channels.json # YouTube channel metadata (optional)
|
|
251
|
+
└── youtube-automation.json # Automation workflows (out of scope)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Generated Manifests (Regenerated on Demand)
|
|
255
|
+
|
|
256
|
+
#### Brand-Level Manifests
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
{video-projects-root}/
|
|
260
|
+
├── v-appydave/
|
|
261
|
+
│ └── projects.json # Brand manifest (auto-generated)
|
|
262
|
+
├── v-aitldr/
|
|
263
|
+
│ └── projects.json
|
|
264
|
+
└── v-voz/
|
|
265
|
+
└── projects.json
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Command:** `dam manifest <brand>` or `dam manifest all`
|
|
269
|
+
|
|
270
|
+
**What It Contains:**
|
|
271
|
+
- All projects for the brand
|
|
272
|
+
- Storage locations (local/S3/SSD)
|
|
273
|
+
- Disk usage totals
|
|
274
|
+
- Project types
|
|
275
|
+
|
|
276
|
+
**Regeneration Triggers:**
|
|
277
|
+
- Explicit: `dam manifest <brand>` command
|
|
278
|
+
- Explicit: `dam refresh <brand>` (manifest + S3 scan)
|
|
279
|
+
- Implicit: None (must be manually triggered)
|
|
280
|
+
|
|
281
|
+
#### Project-Level Manifests (Optional/Transient)
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
{video-projects-root}/v-appydave/
|
|
285
|
+
├── b64-bmad-claude-sdk/
|
|
286
|
+
│ ├── .project-manifest.json # Project manifest (optional, transient)
|
|
287
|
+
│ ├── recordings/
|
|
288
|
+
│ ├── assets/
|
|
289
|
+
│ └── s3-staging/
|
|
290
|
+
├── b65-guy-monroe-marketing-plan/
|
|
291
|
+
│ ├── .project-manifest.json # Project manifest (optional, transient)
|
|
292
|
+
│ └── ...
|
|
293
|
+
└── b70-ito.ai-doubled-productivity/
|
|
294
|
+
├── .project-manifest.json # Project manifest (optional, transient)
|
|
295
|
+
└── ...
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**Command:** `dam project-manifest <brand> <project>`
|
|
299
|
+
|
|
300
|
+
**What It Contains:**
|
|
301
|
+
- Detailed file tree (directory structure)
|
|
302
|
+
- File counts per directory
|
|
303
|
+
- Subdirectory breakdown (e.g., `recordings/recordings-bmad-v6/`)
|
|
304
|
+
- Heavy/light file summaries
|
|
305
|
+
|
|
306
|
+
**Characteristics:**
|
|
307
|
+
- **Transient** - Not required, regenerate on demand
|
|
308
|
+
- **Git-ignored** - Too volatile to commit (add to `.gitignore`)
|
|
309
|
+
- **Optional** - Dashboard works without it (falls back to brand manifest booleans)
|
|
310
|
+
- **On-demand** - Only generate when needed for detailed project view
|
|
311
|
+
|
|
312
|
+
**Regeneration Triggers:**
|
|
313
|
+
- Explicit: `dam project-manifest <brand> <project>` command
|
|
314
|
+
- Explicit: Dashboard button (future - local dev only)
|
|
315
|
+
- Implicit: None
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## State Inference Rules
|
|
320
|
+
|
|
321
|
+
### Project Existence
|
|
322
|
+
|
|
323
|
+
| Condition | Result |
|
|
324
|
+
|-----------|--------|
|
|
325
|
+
| `Dir.exist?("{brand}/{id}")` | `storage.local.exists = true, structure = "flat"` |
|
|
326
|
+
| `Dir.exist?("{brand}/archived/{range}/{id}")` | `storage.local.exists = true, structure = "archived"` |
|
|
327
|
+
| Neither exists | `storage.local.exists = false, structure = null` |
|
|
328
|
+
|
|
329
|
+
### S3 Staging Status
|
|
330
|
+
|
|
331
|
+
| Condition | Result |
|
|
332
|
+
|-----------|--------|
|
|
333
|
+
| `Dir.exist?("{project}/s3-staging")` | `storage.s3.exists = true` |
|
|
334
|
+
| Otherwise | `storage.s3.exists = false` |
|
|
335
|
+
|
|
336
|
+
**Note:** This detects the **local marker folder**, not actual S3 contents. The `s3-staging/` folder is used to stage files before S3 upload.
|
|
337
|
+
|
|
338
|
+
### SSD Backup Status
|
|
339
|
+
|
|
340
|
+
**Search Order:**
|
|
341
|
+
1. Flat: `{ssd_base}/{project-id}/`
|
|
342
|
+
2. Calculated range: `{ssd_base}/{range}/{project-id}/`
|
|
343
|
+
3. Exhaustive search: All range folders in `{ssd_base}/*/`
|
|
344
|
+
|
|
345
|
+
**Result:** `storage.ssd.exists = true` if found anywhere
|
|
346
|
+
|
|
347
|
+
### Sync State (Inferred)
|
|
348
|
+
|
|
349
|
+
| Local | S3 | SSD | Interpretation |
|
|
350
|
+
|-------|----|----|----------------|
|
|
351
|
+
| ✅ | ✅ | ❌ | **Active collaboration** - David & Jan working |
|
|
352
|
+
| ✅ | ❌ | ❌ | **Local only** - Not shared yet |
|
|
353
|
+
| ❌ | ✅ | ❌ | **Remote only** - Need to download |
|
|
354
|
+
| ✅ | ❌ | ✅ | **Archived** - Published, local for reference |
|
|
355
|
+
| ❌ | ❌ | ✅ | **Cold storage** - Historical archive |
|
|
356
|
+
| ✅ | ✅ | ✅ | **Fully backed up** - All locations |
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Disk Usage Calculation
|
|
361
|
+
|
|
362
|
+
**Calculated Fields in Manifest:**
|
|
363
|
+
```json
|
|
364
|
+
{
|
|
365
|
+
"disk_usage": {
|
|
366
|
+
"local": {
|
|
367
|
+
"total_bytes": 12399975489,
|
|
368
|
+
"total_mb": 11825.54,
|
|
369
|
+
"total_gb": 11.55
|
|
370
|
+
},
|
|
371
|
+
"ssd": {
|
|
372
|
+
"total_bytes": 429749225514,
|
|
373
|
+
"total_mb": 409840.8,
|
|
374
|
+
"total_gb": 400.24
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Calculation Method:**
|
|
381
|
+
- Walk entire directory tree
|
|
382
|
+
- Sum `File.size(file)` for all files
|
|
383
|
+
- Convert bytes → MB, GB
|
|
384
|
+
- Performed at manifest generation time (not real-time)
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Relationships
|
|
389
|
+
|
|
390
|
+
### Brand → Projects (1:N)
|
|
391
|
+
- One brand has many projects
|
|
392
|
+
- Projects identified by folder name
|
|
393
|
+
- Manifest lists all projects for brand
|
|
394
|
+
|
|
395
|
+
### Brand → Users (M:N)
|
|
396
|
+
- Brands have `team` array
|
|
397
|
+
- Users can belong to multiple brands
|
|
398
|
+
- Example: David is on all brands, Jan is on appydave + aitldr
|
|
399
|
+
|
|
400
|
+
### Project → Storage Locations (1:3)
|
|
401
|
+
- Each project can exist in:
|
|
402
|
+
- Local (0 or 1)
|
|
403
|
+
- S3 (0 or 1)
|
|
404
|
+
- SSD (0 or 1)
|
|
405
|
+
- Valid combinations: Any subset of {local, s3, ssd}
|
|
406
|
+
|
|
407
|
+
### User → AWS Profile (N:1)
|
|
408
|
+
- Each user has `default_aws_profile`
|
|
409
|
+
- Multiple users can share same AWS profile (e.g., Jan uses david-appydave)
|
|
410
|
+
- AWS profiles defined in `~/.aws/credentials` (outside DAM scope)
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Data Flow
|
|
415
|
+
|
|
416
|
+
### Manifest Generation
|
|
417
|
+
```
|
|
418
|
+
1. Load brands.json (configuration)
|
|
419
|
+
2. Scan local filesystem ({brand}/, {brand}/archived/*/)
|
|
420
|
+
3. Scan SSD filesystem (if available)
|
|
421
|
+
4. Detect S3 staging (local folder presence)
|
|
422
|
+
5. Calculate disk usage (recursive file size sum)
|
|
423
|
+
6. Generate projects.json (per brand)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### S3 Sync Detection
|
|
427
|
+
```
|
|
428
|
+
1. Check for local s3-staging folder
|
|
429
|
+
2. List S3 bucket contents (AWS API call)
|
|
430
|
+
3. Compare MD5 hashes or timestamps
|
|
431
|
+
4. Determine sync status (in-sync, needs-upload, needs-download)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Note:** MD5 comparison is used by S3 sync tools but not currently exposed in the manifest.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Missing / Out of Scope
|
|
439
|
+
|
|
440
|
+
**What's NOT in the current data model:**
|
|
441
|
+
|
|
442
|
+
1. **S3 actual contents** - Manifest only tracks local `s3-staging/` folder existence
|
|
443
|
+
2. **File-level metadata** - No per-file tracking (size, MD5, timestamps)
|
|
444
|
+
3. **FliVideo chapter structure** - Not exposed at manifest level
|
|
445
|
+
4. **Storyline scripts** - Not parsed into manifest
|
|
446
|
+
5. **Transcripts** - Not indexed (though important for workflows)
|
|
447
|
+
6. **YouTube publish status** - No link between project and published video
|
|
448
|
+
7. **Project state machine** - No "recording", "editing", "published" status
|
|
449
|
+
8. **Team permissions** - No granular access control (inferred from brand team list)
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Future Enhancements
|
|
454
|
+
|
|
455
|
+
**Potential additions to data model:**
|
|
456
|
+
|
|
457
|
+
1. **S3 actual sync status** - Query AWS API for real S3 contents, not just local folder
|
|
458
|
+
2. **File manifest** - Per-project file listing with sizes, MD5s, timestamps
|
|
459
|
+
3. **Transcript index** - Parse and index all `.srt` files
|
|
460
|
+
4. **Chapter structure** - FliVideo recording organization
|
|
461
|
+
5. **Project metadata** - Title, description, recording date
|
|
462
|
+
6. **State tracking** - Workflow status (planned → recording → editing → published)
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
**Last updated**: 2025-11-18
|