@dboio/cli 0.19.7 → 0.20.3

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/README.md CHANGED
@@ -140,7 +140,6 @@ my-project/
140
140
  │ │ └── app/ # Default application bin
141
141
  │ ├── automation/ # Automation entity records
142
142
  │ ├── app_version/ # App version entity records
143
- │ ├── entity/ # Entity definitions
144
143
  │ ├── entity_column/ # Column definitions
145
144
  │ ├── entity_column_value/ # Column value definitions
146
145
  │ ├── extension/ # Extension entity records (organized by descriptor type)
@@ -149,7 +148,7 @@ my-project/
149
148
  │ ├── integration/ # Integration entity records
150
149
  │ ├── security/ # Security policy records
151
150
  │ ├── security_column/ # Column-level security records
152
- │ ├── data_source/ # (created when data sources exist)
151
+ │ ├── data_source/ # Data source configs + entity (table) definitions
153
152
  │ ├── group/ # (created when groups exist)
154
153
  │ ├── site/ # (created when sites exist)
155
154
  │ └── redirect/ # (created when redirects exist)
@@ -203,7 +202,9 @@ Per-user settings (plugin scopes, completed migrations) are stored globally in `
203
202
 
204
203
  > **Upgrading to 0.16.0+**: `metadata_templates.json` is renamed to `metadata_schema.json`. The `_contentColumns` field in metadata files is renamed to `_companionReferenceColumns`. Extension companion file prompts during `dbo clone` are replaced by automatic derivation from `descriptor_definition` `form-control-code` data. Migration 011 runs automatically on first use.
205
204
 
206
- > **Upgrading to 0.14.0+**: Metadata files now use `name.metadata~uid.json` instead of `name~uid.metadata.json`. Migration 008 automatically renames all metadata files.
205
+ > **Upgrading to 0.19.0+**: Metadata filenames no longer include `~UID` (e.g. `colors.metadata.json` instead of `colors.metadata~uid.json`). The UID is stored inside the JSON. Migration 013 automatically renames all metadata files.
206
+
207
+ > **Upgrading to 0.14.0+**: Metadata files previously used `name.metadata~uid.json` instead of `name~uid.metadata.json`. Migration 008 handles this rename automatically.
207
208
 
208
209
  > **Upgrading to 0.13.3+**: Entity and extension companion files no longer include `~UID` in the filename. Migration 007 automatically renames legacy files.
209
210
 
@@ -298,8 +299,11 @@ Certain files live at the **project root** (not inside `lib/`) but are still tra
298
299
  | `manifest.json` | content | Yes | [PWA web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) |
299
300
  | `CLAUDE.md` | content | No | Claude Code project instructions |
300
301
  | `README.md` | content | Yes | Project readme |
302
+ | `package.json` | content | No | Node.js package metadata and scripts |
303
+ | `.dboignore` | content | No | DBO CLI ignore patterns |
304
+ | `.gitignore` | content | No | Git ignore patterns |
301
305
 
302
- **`dbo clone`** writes all three to the project root. If the server has no record for a file, a stub is generated automatically (`manifest.json` from app metadata, `CLAUDE.md` and `README.md` from app name/description).
306
+ **`dbo clone`** writes all six to the project root. If the server has no record for a file, a stub is generated automatically (`manifest.json` from app metadata, `CLAUDE.md` and `README.md` from app name/description, `package.json` as a minimal stub). Matching works regardless of the server record's `BinID`: records are matched by name, `@`-reference, or `Path`, then relocated to the root — whether they live in `lib/bins/app/`, another bin, or have `BinID=null`. Records with `BinID=null` that aren't in the configured list are also promoted to the project root automatically.
303
307
 
304
308
  **`dbo push`** auto-creates the companion metadata in `lib/bins/app/` for any listed root file that exists locally but has no tracked metadata yet — no manual `dbo adopt` needed before the first push.
305
309
 
@@ -322,11 +326,11 @@ The list of root content files is stored in `.app/config.json` under `rootConten
322
326
 
323
327
  ```json
324
328
  {
325
- "rootContentFiles": ["CLAUDE.md", "README.md", "manifest.json"]
329
+ "rootContentFiles": ["CLAUDE.md", "README.md", "manifest.json", "package.json", ".dboignore", ".gitignore"]
326
330
  }
327
331
  ```
328
332
 
329
- - **Absent**: defaults are written on the first `dbo push` — `["CLAUDE.md", "README.md", "manifest.json"]`
333
+ - **Absent**: defaults are written on the first `dbo push` — `["CLAUDE.md", "README.md", "manifest.json", "package.json", ".dboignore", ".gitignore"]`
330
334
  - **`[]`, `false`, or `null`**: feature disabled — no root content files are auto-managed
331
335
  - **Custom list**: any filename can be added; metadata is derived from the file extension
332
336
 
@@ -424,7 +428,7 @@ dbo init --scaffold --yes # scaffold dirs non-intera
424
428
  | `--clone` | Clone the app after initialization |
425
429
  | `-g, --global` | Install Claude commands globally (`~/.claude/commands/`) |
426
430
  | `--local` | Install Claude commands to project (`.claude/commands/`) |
427
- | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`) |
431
+ | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`). Note: `data_source/` is always scaffolded and also holds `entity` (table definition) records |
428
432
  | `--dboignore` | Create `.dboignore` with default patterns (use with `--force` to overwrite existing) |
429
433
  | `-y, --yes` | Skip all interactive prompts (legacy migration, Claude Code setup) |
430
434
  | `--non-interactive` | Alias for `--yes` |
@@ -490,7 +494,7 @@ The project's reference domain is stored in `.app/<shortName>.metadata.json._dom
490
494
  7. **Saves `.app/directories.json`** — maps BinIDs to directory paths for file placement
491
495
  8. **Writes content files** — decodes base64 content, creates `*.metadata.json` + content files in the correct bin directory. Filename columns and companion file extraction preferences are auto-applied with sensible defaults on first clone (use `--configure` to re-prompt)
492
496
  9. **Downloads media files** — classifies records into three scopes before downloading: `app` (`/media/<app>/app/...` or no FullPath — always downloaded), `user` (`/media/<app>/user/...` — opt-in, preference saved as `UserMedia` in `config.json`), and `foreign` (`/media/<other_app>/...` — silently skipped with stale metadata written). Fetches using a fallback chain: `FullPath` directly (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`. 404 errors create stale metadata to prevent re-prompting. Errors are logged to `.app/errors.log`
493
- 10. **Processes entity-dir records** — entities matching project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are saved as `.metadata.json` files in their corresponding directory (e.g., `extension/`, `data_source/`)
497
+ 10. **Processes entity-dir records** — entities matching project directories (`extension`, `app_version`, `data_source`, `entity`, `site`, `group`, `integration`, `automation`) are saved as `.metadata.json` files in their corresponding directory. Note: `entity` (table definitions) shares `lib/data_source/` with `data_source` records rather than using a separate directory
494
498
  11. **Processes other entities** — remaining entities with a `BinID` are placed in the corresponding bin directory
495
499
  12. **Saves `.app/<shortName>.metadata.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
496
500
  13. **Orphan cleanup** — any local `.metadata.json` files whose UID is absent from the server response are automatically moved to `trash/` along with their companion content and media files. This prevents stale records (deleted server-side) from causing false positives in `dbo push`. Skipped during `--entity-filter` clones
@@ -584,13 +588,14 @@ Where do you want me to place filename.ext?
584
588
 
585
589
  #### Entity directory processing
586
590
 
587
- Entity types that correspond to project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are processed into their named directories without requiring a `BinID`:
591
+ Entity types that correspond to project directories (`extension`, `app_version`, `data_source`, `entity`, `site`, `group`, `integration`, `automation`) are processed into their named directories without requiring a `BinID`:
588
592
 
589
593
  | Entity Key | Directory |
590
594
  |------------|-----------|
591
595
  | `extension` | `extension/<Descriptor>/` (see below) |
592
596
  | `app_version` | `app_version/` |
593
597
  | `data_source` | `data_source/` |
598
+ | `entity` | `data_source/` (co-located with data source records) |
594
599
  | `site` | `site/` |
595
600
  | `group` | `group/` |
596
601
  | `integration` | `integration/` |
@@ -600,7 +605,7 @@ For each entity type, the CLI prompts to choose which column becomes the filenam
600
605
 
601
606
  If any columns contain base64-encoded content, the CLI prompts to extract them as companion files. Extracted columns produce files named `<name>.<Column>.<ext>` alongside the metadata, with `@reference` entries in the metadata and a `_companionReferenceColumns` array (legacy name: `_contentColumns`, supported for backward compatibility).
602
607
 
603
- **Companion file naming convention:** Only `.metadata.json` files carry the `~UID` suffix (e.g. `Add-Asst-Execute-Security.metadata~wxl6ivcwfkix3zgantszjg.json`). Companion content files use the natural base name without `~UID` (e.g. `Add-Asst-Execute-Security.String5.html`). When a `{title}` is defined in the `@reference` expression (see [Metadata Schema](#metadata-schema)), the title replaces the column name in the filename (e.g. `Add-Asst-Execute-Security.Add-Form-Parameters.js` instead of `Add-Asst-Execute-Security.String5.js`). If two records share the same name within a directory, the second gets a `-1` suffix. Migration 007 automatically renames legacy `~UID` companion files to the natural convention.
608
+ **Companion file naming convention:** Metadata files use `name.metadata.json` (e.g. `Add-Asst-Execute-Security.metadata.json`). The UID is stored inside the JSON, not in the filename. Companion content files use the natural base name (e.g. `Add-Asst-Execute-Security.String5.html`). When a `{title}` is defined in the `@reference` expression (see [Metadata Schema](#metadata-schema)), the title replaces the column name in the filename (e.g. `Add-Asst-Execute-Security.Add-Form-Parameters.js` instead of `Add-Asst-Execute-Security.String5.js`). If two records share the same name within a directory, the second gets a `-1` suffix (e.g. `Add-Asst-Execute-Security-1.metadata.json`); content records have priority over output records for the unsuffixed slot.
604
609
 
605
610
  Use `-y` to skip prompts (uses `Name` column, no content extraction).
606
611
 
@@ -644,7 +649,7 @@ dbo clone -e extension --descriptor-types false # Flat layout (no descript
644
649
 
645
650
  #### Entity children embedding
646
651
 
647
- When a server entity record contains nested child records (e.g., `entity_column` records nested under `entity` parents), `dbo clone` embeds them inline in the parent's `.metadata~uid.json` file under a `children` key:
652
+ When a server entity record contains nested child records (e.g., `entity_column` records nested under `entity` parents), `dbo clone` embeds them inline in the parent's `.metadata.json` file under a `children` key:
648
653
 
649
654
  ```json
650
655
  {
@@ -693,7 +698,8 @@ project/
693
698
  docs/ # ← root-placed documentation MD files (optional)
694
699
  MyDoc.md
695
700
  data_source/
696
- MySQL-Primary.metadata.json
701
+ MySQL-Primary.metadata.json # _entity: "data_source"
702
+ Users.metadata.json # _entity: "entity" (table defs co-locate here)
697
703
  site/
698
704
  MainSite.metadata.json
699
705
  # Media files placed by BinID into bins/ (alongside content)
package/bin/dbo.js CHANGED
@@ -101,4 +101,9 @@ program.addCommand(tagCommand);
101
101
  // Show welcome message on first run
102
102
  checkFirstRun();
103
103
 
104
+ // Show help (exit 0) when invoked with no arguments
105
+ if (process.argv.length <= 2) {
106
+ program.help();
107
+ }
108
+
104
109
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dboio/cli",
3
- "version": "0.19.7",
3
+ "version": "0.20.3",
4
4
  "description": "CLI for the DBO.io framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbo",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "DBO.io CLI integration for Claude Code",
5
5
  "author": {
6
6
  "name": "DBO.io"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: dbo
3
- description: Run DBO.io CLI commands for local file sync, project management, and deployment (push/pull/clone/add/rm/diff/build/deploy). NOT for direct API operations — for data reads/writes and runtime queries, use the REST API via curl with .app/cookies.txt instead.
4
- allowed-tools: Read, Write, Glob, Bash(git status:*), Bash(git branch:*), Bash(git diff:*), Bash(ls:*), Bash(dbo init:*), Bash(dbo login:*), Bash(dbo status:*), Bash(dbo deploy:*), Bash(dbo add:*), Bash(dbo clone:*), Bash(dbo push:*), Bash(dbo pull:*), Bash(dbo diff:*), Bash(dbo rm:*), Bash(dbo mv:*), Bash(dbo run:*), Bash(dbo install:*), Bash(dbo build:*), Bash(git stash:*), Bash(grep:*), Bash(which dbo:*)
3
+ description: Run DBO.io CLI commands for local file sync, project management, and deployment (push/pull/clone/adopt/rm/diff/build/deploy). NOT for direct API operations — for data reads/writes and runtime queries, use the REST API via curl with .app/cookies.txt instead.
4
+ allowed-tools: Read, Write, Glob, Bash(git status:*), Bash(git branch:*), Bash(git diff:*), Bash(ls:*), Bash(dbo init:*), Bash(dbo login:*), Bash(dbo status:*), Bash(dbo deploy:*), Bash(dbo adopt:*), Bash(dbo clone:*), Bash(dbo push:*), Bash(dbo pull:*), Bash(dbo diff:*), Bash(dbo rm:*), Bash(dbo mv:*), Bash(dbo run:*), Bash(dbo install:*), Bash(dbo build:*), Bash(git stash:*), Bash(grep:*), Bash(which dbo:*)
5
5
  user-invokable: true
6
6
  ---
7
7
 
@@ -12,7 +12,7 @@ Run `dbo` CLI commands for local file operations, project management, and deploy
12
12
  ## CLI vs REST API — When to use what
13
13
 
14
14
  **Use this CLI skill for file operations:**
15
- - `pull`, `push`, `add`, `clone`, `rm`, `diff` — sync files between local project and server
15
+ - `pull`, `push`, `adopt`, `clone`, `rm`, `diff` — sync files between local project and server
16
16
  - `deploy` — push a file to DBO by UID or named shorthand (shorthands defined in `.app/deploy_config.json`)
17
17
  - `build`, `run` — compile source and run lifecycle scripts (configured in `.app/scripts.json`)
18
18
  - `init`, `login`, `status` — project setup and auth
@@ -43,10 +43,10 @@ dbo $ARGUMENTS
43
43
  | `init` | Initialize `.app/` configuration |
44
44
  | `login` / `logout` | Authenticate / clear session |
45
45
  | `status` | Show config, domain, session info |
46
- | `clone` | Clone an app to local project structure (media filtered by scope: app/user/foreign) |
47
- | `pull` | Pull records to local files |
46
+ | `clone` | Full project setup: config, bin dirs, dependencies, schema, then all records. Also used to refresh deps/schema without a full re-clone (see below). |
47
+ | `pull` | Content-only update — re-downloads changed records into existing local files. No dependency sync, no config changes, no scaffolding. Use this for routine day-to-day syncing. |
48
48
  | `push` | Push local changes to server |
49
- | `add` | Add a new file to DBO.io |
49
+ | `adopt` | Create metadata companion for a local file (required before `push` for new files). Always pass `-e <entity>` — auto-inference is unreliable for content files. |
50
50
  | `diff` | Compare local files vs server versions |
51
51
  | `rm` | Remove file and stage server deletion |
52
52
  | `deploy` | Push a file to DBO by UID or named shorthand |
@@ -54,6 +54,19 @@ dbo $ARGUMENTS
54
54
  | `run` | Run a named script from `.app/scripts.json` |
55
55
  | `install` | Install/upgrade CLI, plugins (alias: `i`) |
56
56
 
57
+ ## clone vs pull — when to use each
58
+
59
+ | Situation | Command |
60
+ |-----------|---------|
61
+ | First-time project setup | `dbo clone` |
62
+ | Get latest file changes from server (routine) | `dbo pull` |
63
+ | Refresh a dependency app (`app_dependencies/`) | `dbo clone --dependencies <name> -y` |
64
+ | Refresh schema.json from server | `dbo clone --schema -y` (also re-clones records) |
65
+ | Add a new dependency app to the project | `dbo clone --dependencies <name> -y` |
66
+ | Re-clone without touching deps | `dbo clone --no-deps` |
67
+
68
+ `dbo pull` is a subset of `dbo clone`. It calls the same underlying logic but skips config setup, dependency sync, directory scaffolding, and collision detection. Use `pull` whenever you just need updated file content.
69
+
57
70
  ## Common workflows
58
71
 
59
72
  ```bash
@@ -61,6 +74,12 @@ dbo $ARGUMENTS
61
74
  dbo init --domain my-domain.com --app myapp --clone
62
75
  dbo login
63
76
 
77
+ # Routine content sync (day-to-day)
78
+ dbo pull # re-download changed records
79
+ dbo pull -y # auto-accept all incoming changes
80
+ dbo pull -e content # only content records
81
+ dbo pull --dry-run # preview what would change
82
+
64
83
  # Edit and push
65
84
  dbo push # push all changes in current dir
66
85
  dbo push lib/bins/app/assets/ # push specific directory
@@ -76,14 +95,22 @@ dbo push --no-scripts # push without any hooks
76
95
  dbo deploy css:colors # deploy using deploy_config.json shorthand
77
96
  dbo deploy albain3dwkofbhnd1qtd1q # deploy by UID directly
78
97
 
79
- # Pull
80
- dbo pull -e content --filter 'AppID=10100'
81
-
82
- # Add new files
83
- dbo add assets/css/newstyle.css
84
- dbo add . # scan for un-added files
98
+ # Add a new file (adopt → push — both steps required for new assets)
99
+ # Always pass -e <entity>. Auto-inference is unreliable; omitting -e causes failure.
100
+ dbo adopt -e content lib/bins/app/assets/css/newstyle.css # HTML/CSS/JS → content
101
+ dbo push lib/bins/app/assets/css/newstyle.css
102
+ dbo adopt -e media lib/bins/app/assets/img/logo.png # images/binaries → media
103
+ dbo push lib/bins/app/assets/img/logo.png
85
104
 
86
105
  # Compare and merge
87
106
  dbo diff # compare all local vs server
88
107
  dbo diff -y # auto-accept all server changes
108
+
109
+ # Refresh dependencies and/or schema
110
+ # clone is the dependency/schema refresh mechanism — not intuitive from the name.
111
+ # --dependencies adds the app to config.json deps (union) then syncs only those apps (force).
112
+ dbo clone --dependencies operator -y # re-fetch one dependency
113
+ dbo clone --dependencies _system,operator -y # multiple deps (comma-separated)
114
+ dbo clone --schema -y # refresh schema.json (also re-clones records)
115
+ dbo clone --dependencies operator --schema -y # dep + schema in one pass
89
116
  ```
@@ -140,7 +140,6 @@ my-project/
140
140
  │ │ └── app/ # Default application bin
141
141
  │ ├── automation/ # Automation entity records
142
142
  │ ├── app_version/ # App version entity records
143
- │ ├── entity/ # Entity definitions
144
143
  │ ├── entity_column/ # Column definitions
145
144
  │ ├── entity_column_value/ # Column value definitions
146
145
  │ ├── extension/ # Extension entity records (organized by descriptor type)
@@ -149,7 +148,7 @@ my-project/
149
148
  │ ├── integration/ # Integration entity records
150
149
  │ ├── security/ # Security policy records
151
150
  │ ├── security_column/ # Column-level security records
152
- │ ├── data_source/ # (created when data sources exist)
151
+ │ ├── data_source/ # Data source configs + entity (table) definitions
153
152
  │ ├── group/ # (created when groups exist)
154
153
  │ ├── site/ # (created when sites exist)
155
154
  │ └── redirect/ # (created when redirects exist)
@@ -203,7 +202,9 @@ Per-user settings (plugin scopes, completed migrations) are stored globally in `
203
202
 
204
203
  > **Upgrading to 0.16.0+**: `metadata_templates.json` is renamed to `metadata_schema.json`. The `_contentColumns` field in metadata files is renamed to `_companionReferenceColumns`. Extension companion file prompts during `dbo clone` are replaced by automatic derivation from `descriptor_definition` `form-control-code` data. Migration 011 runs automatically on first use.
205
204
 
206
- > **Upgrading to 0.14.0+**: Metadata files now use `name.metadata~uid.json` instead of `name~uid.metadata.json`. Migration 008 automatically renames all metadata files.
205
+ > **Upgrading to 0.19.0+**: Metadata filenames no longer include `~UID` (e.g. `colors.metadata.json` instead of `colors.metadata~uid.json`). The UID is stored inside the JSON. Migration 013 automatically renames all metadata files.
206
+
207
+ > **Upgrading to 0.14.0+**: Metadata files previously used `name.metadata~uid.json` instead of `name~uid.metadata.json`. Migration 008 handles this rename automatically.
207
208
 
208
209
  > **Upgrading to 0.13.3+**: Entity and extension companion files no longer include `~UID` in the filename. Migration 007 automatically renames legacy files.
209
210
 
@@ -298,8 +299,11 @@ Certain files live at the **project root** (not inside `lib/`) but are still tra
298
299
  | `manifest.json` | content | Yes | [PWA web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) |
299
300
  | `CLAUDE.md` | content | No | Claude Code project instructions |
300
301
  | `README.md` | content | Yes | Project readme |
302
+ | `package.json` | content | No | Node.js package metadata and scripts |
303
+ | `.dboignore` | content | No | DBO CLI ignore patterns |
304
+ | `.gitignore` | content | No | Git ignore patterns |
301
305
 
302
- **`dbo clone`** writes all three to the project root. If the server has no record for a file, a stub is generated automatically (`manifest.json` from app metadata, `CLAUDE.md` and `README.md` from app name/description).
306
+ **`dbo clone`** writes all six to the project root. If the server has no record for a file, a stub is generated automatically (`manifest.json` from app metadata, `CLAUDE.md` and `README.md` from app name/description, `package.json` as a minimal stub). Matching works regardless of the server record's `BinID`: records are matched by name, `@`-reference, or `Path`, then relocated to the root — whether they live in `lib/bins/app/`, another bin, or have `BinID=null`. Records with `BinID=null` that aren't in the configured list are also promoted to the project root automatically.
303
307
 
304
308
  **`dbo push`** auto-creates the companion metadata in `lib/bins/app/` for any listed root file that exists locally but has no tracked metadata yet — no manual `dbo adopt` needed before the first push.
305
309
 
@@ -322,11 +326,11 @@ The list of root content files is stored in `.app/config.json` under `rootConten
322
326
 
323
327
  ```json
324
328
  {
325
- "rootContentFiles": ["CLAUDE.md", "README.md", "manifest.json"]
329
+ "rootContentFiles": ["CLAUDE.md", "README.md", "manifest.json", "package.json", ".dboignore", ".gitignore"]
326
330
  }
327
331
  ```
328
332
 
329
- - **Absent**: defaults are written on the first `dbo push` — `["CLAUDE.md", "README.md", "manifest.json"]`
333
+ - **Absent**: defaults are written on the first `dbo push` — `["CLAUDE.md", "README.md", "manifest.json", "package.json", ".dboignore", ".gitignore"]`
330
334
  - **`[]`, `false`, or `null`**: feature disabled — no root content files are auto-managed
331
335
  - **Custom list**: any filename can be added; metadata is derived from the file extension
332
336
 
@@ -424,7 +428,7 @@ dbo init --scaffold --yes # scaffold dirs non-intera
424
428
  | `--clone` | Clone the app after initialization |
425
429
  | `-g, --global` | Install Claude commands globally (`~/.claude/commands/`) |
426
430
  | `--local` | Install Claude commands to project (`.claude/commands/`) |
427
- | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`) |
431
+ | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`). Note: `data_source/` is always scaffolded and also holds `entity` (table definition) records |
428
432
  | `--dboignore` | Create `.dboignore` with default patterns (use with `--force` to overwrite existing) |
429
433
  | `-y, --yes` | Skip all interactive prompts (legacy migration, Claude Code setup) |
430
434
  | `--non-interactive` | Alias for `--yes` |
@@ -490,7 +494,7 @@ The project's reference domain is stored in `.app/<shortName>.metadata.json._dom
490
494
  7. **Saves `.app/directories.json`** — maps BinIDs to directory paths for file placement
491
495
  8. **Writes content files** — decodes base64 content, creates `*.metadata.json` + content files in the correct bin directory. Filename columns and companion file extraction preferences are auto-applied with sensible defaults on first clone (use `--configure` to re-prompt)
492
496
  9. **Downloads media files** — classifies records into three scopes before downloading: `app` (`/media/<app>/app/...` or no FullPath — always downloaded), `user` (`/media/<app>/user/...` — opt-in, preference saved as `UserMedia` in `config.json`), and `foreign` (`/media/<other_app>/...` — silently skipped with stale metadata written). Fetches using a fallback chain: `FullPath` directly (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`. 404 errors create stale metadata to prevent re-prompting. Errors are logged to `.app/errors.log`
493
- 10. **Processes entity-dir records** — entities matching project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are saved as `.metadata.json` files in their corresponding directory (e.g., `extension/`, `data_source/`)
497
+ 10. **Processes entity-dir records** — entities matching project directories (`extension`, `app_version`, `data_source`, `entity`, `site`, `group`, `integration`, `automation`) are saved as `.metadata.json` files in their corresponding directory. Note: `entity` (table definitions) shares `lib/data_source/` with `data_source` records rather than using a separate directory
494
498
  11. **Processes other entities** — remaining entities with a `BinID` are placed in the corresponding bin directory
495
499
  12. **Saves `.app/<shortName>.metadata.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
496
500
  13. **Orphan cleanup** — any local `.metadata.json` files whose UID is absent from the server response are automatically moved to `trash/` along with their companion content and media files. This prevents stale records (deleted server-side) from causing false positives in `dbo push`. Skipped during `--entity-filter` clones
@@ -584,13 +588,14 @@ Where do you want me to place filename.ext?
584
588
 
585
589
  #### Entity directory processing
586
590
 
587
- Entity types that correspond to project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are processed into their named directories without requiring a `BinID`:
591
+ Entity types that correspond to project directories (`extension`, `app_version`, `data_source`, `entity`, `site`, `group`, `integration`, `automation`) are processed into their named directories without requiring a `BinID`:
588
592
 
589
593
  | Entity Key | Directory |
590
594
  |------------|-----------|
591
595
  | `extension` | `extension/<Descriptor>/` (see below) |
592
596
  | `app_version` | `app_version/` |
593
597
  | `data_source` | `data_source/` |
598
+ | `entity` | `data_source/` (co-located with data source records) |
594
599
  | `site` | `site/` |
595
600
  | `group` | `group/` |
596
601
  | `integration` | `integration/` |
@@ -600,7 +605,7 @@ For each entity type, the CLI prompts to choose which column becomes the filenam
600
605
 
601
606
  If any columns contain base64-encoded content, the CLI prompts to extract them as companion files. Extracted columns produce files named `<name>.<Column>.<ext>` alongside the metadata, with `@reference` entries in the metadata and a `_companionReferenceColumns` array (legacy name: `_contentColumns`, supported for backward compatibility).
602
607
 
603
- **Companion file naming convention:** Only `.metadata.json` files carry the `~UID` suffix (e.g. `Add-Asst-Execute-Security.metadata~wxl6ivcwfkix3zgantszjg.json`). Companion content files use the natural base name without `~UID` (e.g. `Add-Asst-Execute-Security.String5.html`). When a `{title}` is defined in the `@reference` expression (see [Metadata Schema](#metadata-schema)), the title replaces the column name in the filename (e.g. `Add-Asst-Execute-Security.Add-Form-Parameters.js` instead of `Add-Asst-Execute-Security.String5.js`). If two records share the same name within a directory, the second gets a `-1` suffix. Migration 007 automatically renames legacy `~UID` companion files to the natural convention.
608
+ **Companion file naming convention:** Metadata files use `name.metadata.json` (e.g. `Add-Asst-Execute-Security.metadata.json`). The UID is stored inside the JSON, not in the filename. Companion content files use the natural base name (e.g. `Add-Asst-Execute-Security.String5.html`). When a `{title}` is defined in the `@reference` expression (see [Metadata Schema](#metadata-schema)), the title replaces the column name in the filename (e.g. `Add-Asst-Execute-Security.Add-Form-Parameters.js` instead of `Add-Asst-Execute-Security.String5.js`). If two records share the same name within a directory, the second gets a `-1` suffix (e.g. `Add-Asst-Execute-Security-1.metadata.json`); content records have priority over output records for the unsuffixed slot.
604
609
 
605
610
  Use `-y` to skip prompts (uses `Name` column, no content extraction).
606
611
 
@@ -644,7 +649,7 @@ dbo clone -e extension --descriptor-types false # Flat layout (no descript
644
649
 
645
650
  #### Entity children embedding
646
651
 
647
- When a server entity record contains nested child records (e.g., `entity_column` records nested under `entity` parents), `dbo clone` embeds them inline in the parent's `.metadata~uid.json` file under a `children` key:
652
+ When a server entity record contains nested child records (e.g., `entity_column` records nested under `entity` parents), `dbo clone` embeds them inline in the parent's `.metadata.json` file under a `children` key:
648
653
 
649
654
  ```json
650
655
  {
@@ -693,7 +698,8 @@ project/
693
698
  docs/ # ← root-placed documentation MD files (optional)
694
699
  MyDoc.md
695
700
  data_source/
696
- MySQL-Primary.metadata.json
701
+ MySQL-Primary.metadata.json # _entity: "data_source"
702
+ Users.metadata.json # _entity: "entity" (table defs co-locate here)
697
703
  site/
698
704
  MainSite.metadata.json
699
705
  # Media files placed by BinID into bins/ (alongside content)
@@ -0,0 +1,135 @@
1
+ # Dual-Platform Maintenance Strategy
2
+
3
+ ## Overview
4
+
5
+ The dbo.io API runs on two parallel codebases during the .NET Core migration period:
6
+
7
+ - **`src/webapp-framework/`** — ASP.NET 4.7.2 (Windows), the current production platform
8
+ - **`src/webapp-core/`** — .NET Core 8 (Linux), functionally tested, being prepared for production
9
+
10
+ Both share identical `App_Code/` directories containing all business logic (~249 .cs files). Going forward, new feature work must be applied to both codebases until webapp-framework is retired.
11
+
12
+ ## File Structure
13
+
14
+ ### Shared Code (`App_Code/dboio/`)
15
+
16
+ These directories exist in both `webapp-framework` and `webapp-core` and must stay in sync for feature changes:
17
+
18
+ - `Data/` — entities, data sources, API add-ons, app operations, output/query system
19
+ - `Data/App/` — AppManager, application-level operations
20
+ - `Data/DataSource/` — MySQL, SQL Server, ODBC data source implementations
21
+ - `Data/Output/` — output rendering, query building
22
+ - `Web/Controllers/` — all MVC/API controllers
23
+ - `Web/Security/` — authentication, authorization, SAML
24
+ - `Web/` — caching (ICacheProvider, Redis, HttpRuntime), session, delivery pipeline
25
+ - `Util/` — encryption, email, file/zip utilities
26
+
27
+ ### webapp-framework Only (Windows)
28
+
29
+ - `App_Start/` — legacy ASP.NET startup
30
+ - `Web.config` + `web.*.config` — IIS configuration files
31
+ - `Global.asax` / `Global.asax.cs` — application lifecycle
32
+ - `Account/` — legacy account pages
33
+
34
+ ### webapp-core Only (Linux)
35
+
36
+ - `Program.cs` — .NET Core entry point and middleware pipeline
37
+ - `Middleware/` — 9 middleware classes (ported from HttpModules)
38
+ - `Shims/` — compatibility shims (HttpContext, Cache, ConfigurationManager, CaseInsensitiveFileProvider)
39
+ - `appsettings.json` / `appsettings.*.json` — .NET Core configuration
40
+ - `log4net.config` — Core-specific logging configuration
41
+
42
+ ## Change Categories
43
+
44
+ ### Category 1: Core-Only Infrastructure
45
+
46
+ Changes that only apply to `webapp-core`. No transfer to `webapp-framework` needed.
47
+
48
+ Examples:
49
+ - Middleware files (`Middleware/*.cs`)
50
+ - Shim files (`Shims/*.cs`)
51
+ - `Program.cs`
52
+ - `appsettings*.json`, `log4net.config`
53
+ - `App_Code/Properties/AssemblyInfo.cs` (platform-diverged)
54
+ - `App_Code/Global.asax.cs` (platform-diverged)
55
+ - Build/deploy scripts (`build/deploy-core.sh`, `build/boot-deploy.sh`)
56
+ - AWS infrastructure (EFS, CloudWatch, Launch Templates)
57
+
58
+ When a transfer review issue is created for Category 1 files, close it as "not planned."
59
+
60
+ ### Category 2: Shared Business Logic
61
+
62
+ Changes to business logic in `App_Code/dboio/` that affect both platforms.
63
+
64
+ Examples:
65
+ - Entity classes, data access (`Data/`, `Data/App/`, `Data/DataSource/`)
66
+ - Controllers (`Web/Controllers/`)
67
+ - Security (`Web/Security/`)
68
+ - Cache logic (`Web/` cache providers)
69
+ - Utility classes (`Util/`)
70
+ - Any bug fix or feature in shared code
71
+
72
+ When a transfer review issue is created for Category 2 files, apply the equivalent change to `src/webapp-framework/App_Code/`, then close the issue.
73
+
74
+ ## Automated Transfer Review Workflow
75
+
76
+ A GitHub Action (`.github/workflows/transfer-review.yml`) monitors pushes to all branches.
77
+
78
+ ### How it works
79
+
80
+ 1. Triggers on any push that modifies files under `src/webapp-core/App_Code/`
81
+ 2. Filters out excluded subdirectories (configurable in the workflow YAML)
82
+ 3. Creates a GitHub issue labeled `netcore-aspnet-transfer`
83
+ 4. Lists all changed App_Code files, the commit hash, branch, and author
84
+
85
+ ### Reviewing transfer issues
86
+
87
+ 1. Open the issue and review the changed files
88
+ 2. If all changes are Category 1 (Core-only): close as "not planned"
89
+ 3. If any changes are Category 2 (shared): apply to `webapp-framework`, then close with a reference to the transfer commit
90
+
91
+ ### Exclusion list
92
+
93
+ The workflow YAML contains an `EXCLUDE_PATTERNS` array. Add subdirectory names to suppress issues for known Core-only paths within `App_Code/`:
94
+
95
+ ```bash
96
+ EXCLUDE_PATTERNS=(
97
+ # "Properties"
98
+ # Add more as patterns emerge
99
+ )
100
+ ```
101
+
102
+ ## Commit Message Conventions
103
+
104
+ No strict format required, but these prefixes help identify change scope:
105
+
106
+ - **`webapp-core:`** — Core-only changes (Category 1, no transfer needed)
107
+ - **`webapp-framework:`** — Framework-only changes
108
+ - **No prefix** — changes that apply to both platforms, or general feature work
109
+
110
+ Examples:
111
+ - `webapp-core: fix middleware ordering for auth` (Category 1)
112
+ - `Task XXXX | entity: add new validation rule #NNN` (Category 2, needs transfer)
113
+
114
+ ## Development Flow
115
+
116
+ 1. New business logic typically starts in `webapp-framework` (production platform)
117
+ 2. After committing, manually apply the same change to `webapp-core`
118
+ 3. Core-only infrastructure work happens only in `webapp-core`
119
+ 4. The transfer review workflow catches the reverse case (Core-first changes that may need Framework transfer)
120
+
121
+ ## Retirement Criteria for webapp-framework
122
+
123
+ `webapp-framework` can be retired when ALL of the following are met:
124
+
125
+ 1. **Functional parity** — webapp-core handles all production traffic without regressions
126
+ 2. **Production cutover** — load balancer routes 100% of traffic to Core servers
127
+ 3. **Stability period** — at least 30 days of production traffic on Core with no regressions
128
+ 4. **Client sign-off** — explicit approval to decommission Windows servers
129
+ 5. **Rollback plan verified** — confirmed ability to revert to webapp-framework if needed
130
+
131
+ After retirement:
132
+ - Archive `src/webapp-framework/` (do not delete immediately)
133
+ - Remove the transfer review workflow
134
+ - Remove the `netcore-aspnet-transfer` label
135
+ - Update this document
@@ -6,7 +6,7 @@ description: >-
6
6
  or when the white-paper provides architecture context but you need behavioral
7
7
  rules. Covers file operations, build recipes, metadata handling, and common
8
8
  gotchas.
9
- user-invokable: true
9
+ user-invocable: true
10
10
  ---
11
11
 
12
12
  # DBO Project Cookbook
@@ -20,12 +20,13 @@ For architecture context, load the **white-paper** skill. For CLI command refere
20
20
  ## DOs
21
21
 
22
22
  - **DO use UIDs, not numeric IDs, in templates.** Numeric IDs change across environments (dev → staging → prod). UIDs are stable and portable.
23
- - **DO run `dbo adopt` before pushing new files.** Every file in `lib/` needs a metadata companion. `dbo adopt path/to/file -e {entity}` creates one. Without it, `dbo push` won't know what server record to target.
23
+ - **DO always pass `-e <entity>` when running `dbo adopt`.** Every file in `lib/` needs a metadata companion. `dbo adopt path/to/file -e {entity}` creates one. Without it, `dbo push` won't know what server record to target. **Never omit `-e`** — auto-inference fails for most `lib/bins/` files because the directory maps to multiple entity types. Use `-e content` for HTML/CSS/JS/SQL, `-e media` for images and binaries.
24
24
  - **DO build from `src/` before pushing compiled assets.** Check `.app/scripts.json` for the build command. Run `npm run build` or the specific build script, then push the compiled output from `lib/`.
25
25
  - **DO check `.app/scripts.json` for build/postpush chains before manual deploys.** A file may have postpush hooks that auto-deploy dependent assets. Pushing manually with `dbo deploy` bypasses these chains.
26
- - **DO read the metadata file before modifying a server-tracked file.** The `.metadata~{uid}.json` companion tells you what entity, column, and record the file maps to. This context prevents wrong-target pushes.
26
+ - **DO read the metadata file before modifying a server-tracked file.** The `.metadata.json` companion tells you what entity, column, and record the file maps to (check the `UID` field inside the JSON). This context prevents wrong-target pushes.
27
27
  - **DO use `dbo diff` to verify local vs server state before bulk pushes.** Catches unexpected server-side changes that would be overwritten.
28
28
  - **DO check `app_dependencies/` for parent app patterns when building extensions.** Descriptor definitions, CSS design tokens, and JS APIs from the parent app define what's available.
29
+ - **DO know that `dbo clone` skips dependencies that are already up to date.** Before re-cloning a dependency, the CLI hits `/api/app/object/<name>?UpdatedAfter=<stored-date>` and compares `_LastUpdated`. If the server hasn't changed, the dep is skipped silently. Use `--force` or `--schema` to bypass this check and force a re-clone.
29
30
  - **DO use the REST API with `.app/cookies.txt` for data operations, CLI for file operations.** The CLI handles metadata sync; the API handles data reads/writes. Don't cross these boundaries.
30
31
  - **DO check `.app/deploy_config.json` for existing shorthands before creating deploy commands.** Shorthands are auto-generated by `dbo clone` and `dbo adopt`.
31
32
  - **DO use `dbo push --confirm false` to validate before committing a push.** Dry-run catches issues without touching the server.
@@ -135,6 +136,15 @@ Look at `targets.{file}.build` for compile commands and `targets.{file}.postpush
135
136
  **Cause:** You pushed only the content record but not the media companion (or vice versa).
136
137
  **Fix:** Push both — check `deploy_config.json` for paired `{name}` and `{name}_media` entries.
137
138
 
139
+ ### `dbo adopt` fails — entity cannot be inferred
140
+ **Symptom:** `dbo adopt path/to/file` errors with "entity cannot be inferred" or similar.
141
+ **Cause:** `-e <entity>` was omitted. Auto-inference only works for exact directive template matches. Files in `lib/bins/` (HTML, CSS, JS, SQL) almost never infer correctly because `lib/bins/` maps to multiple entity types.
142
+ **Fix:** Always pass `-e content` for text/code files, `-e media` for images and binaries:
143
+ ```bash
144
+ dbo adopt lib/bins/app/user_first_names.html -e content
145
+ dbo adopt lib/bins/app/assets/img/logo.png -e media
146
+ ```
147
+
138
148
  ### Wrong entity type on adopt
139
149
  **Symptom:** Pushed file lands in unexpected server location.
140
150
  **Cause:** Used wrong `-e` flag on `dbo adopt` (e.g., `-e media` for a text file).