@haus-tech/haus-workflow 0.27.0 → 0.28.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.7.2",
2
+ "version": "2.7.3",
3
3
  "items": [
4
4
  {
5
5
  "id": "haus.nextjs-patterns",
@@ -1374,6 +1374,7 @@
1374
1374
  "whenNotToUse": "Repos that already run a secret-scanning pre-commit hook, or that cannot install gitleaks.",
1375
1375
  "tags": ["security", "workflow"],
1376
1376
  "repoRoles": [],
1377
+ "ecosystem": "security",
1377
1378
  "installMode": "copy-selected",
1378
1379
  "tokenEstimate": 220,
1379
1380
  "tokenBudget": 320,
@@ -15,8 +15,25 @@ Before any setup work, probe **everything** the workspace will need and surface
15
15
  - **PHP environment** — `valet`, `herd`, `ddev`, or `php` on PATH, if any repo is a PHP/WordPress site.
16
16
  - **WP-CLI** — `wp --version`, if any repo's `seed:` pulls a WordPress DB.
17
17
  - **Node versions** — the versions named in each repo's `.nvmrc` / `engines.node` are installable via `nvm`.
18
+ - **Data-access preflight** — for every data load the workspace will run (each repo's `seed` **and** the workspace `seeds`), check up front that the user can actually reach the source, so nobody ends up with a half-set-up environment that only fails at the seed step. See below.
18
19
 
19
- Then list the repos and what each will run (node, deps, localdev steps), **report every gap at once**, and get a single go-ahead. For **reused** local clones, ask whether to re-run setup. For each gap, name what it blocks; the user decides whether to fix it now (**ask before any global/system install**) or proceed and skip the affected steps. Don't begin per-repo work until this gate is acknowledged.
20
+ ### Data-access preflight
21
+
22
+ The single most common way cloneAndSetup leaves a **half-completed environment** is discovering at the `seed:` step — after cloning, installing, and bringing up services — that the user lacks the AWS/SSH/etc. access to pull the data. Catch it **here**, before any heavy work, and make the data outcome a deliberate choice.
23
+
24
+ 1. **Collect every seed:** each repo's `seed` plus the workspace `seeds`. For each, determine its required access:
25
+ - If `seed` is an **object with `access`**, run each entry's `check` (a read-only probe; exit 0 = reachable).
26
+ - If `seed` is a **bare string**, infer the channel and probe generically: `aws …`/SSM → `aws sts get-caller-identity`; `dep db:pull …` / `ssh`/`scp`/`rsync <user@host>` → `ssh -o BatchMode=yes -o ConnectTimeout=5 <host> true`; `northflank …` → `northflank whoami`. A purely local seed (no remote) needs nothing.
27
+ 2. **Report one table** alongside the rest of the gate — per data source: its `label`, the access it needs, and ✓ reachable / ✗ + the `login` remedy (verbatim).
28
+ 3. **Resolve every ✗ with one consolidated choice**, then remember it for the run:
29
+ - **Set up access now** → print the `login` text, let the user do it, **re-check**, then seed normally.
30
+ - **Create that DB EMPTY for now** (only when `empty-ok` is true — the default) → the datastore comes up empty (schema via migrations/`needs:`), the app still boots, and the user can run that one seed later. Name the exact command to fill it.
31
+ - **Abort.**
32
+ 4. **Only a gap on a seed with `empty-ok: false` is a HARD STOP** (the repo is genuinely broken without data — log in or abort). Every other gap offers the empty path; one source's missing access never blocks another's.
33
+
34
+ This is the one prompt the "no half-completed environment" goal justifies. The two valid end-states are **seeded** or **deliberately empty** — never a third "did the expensive work then died at seed."
35
+
36
+ Then list the repos and what each will run (node, deps, localdev steps, **data sources + the chosen seed/empty plan**), **report every gap at once**, and get a single go-ahead. For **reused** local clones, ask whether to re-run setup. For each gap, name what it blocks; the user decides whether to fix it now (**ask before any global/system install**) or proceed and skip the affected steps. Don't begin per-repo work until this gate is acknowledged.
20
37
 
21
38
  ## Step 3 — Per-repo dependency pass
22
39
 
@@ -50,6 +67,16 @@ needs: [mysql] # services this repo requires; provisioned in Docker, env wired t
50
67
  needsEnv: [WP_HOME, DB_NAME] # env keys that must be present to run/serve
51
68
  build: 'yarn build' # optional: the build command (run after deps)
52
69
  seed: 'dep db:pull staging-oderland' # optional: how to load data; remote/destructive → confirm first
70
+ # `seed` may also be an OBJECT when the load needs external access (AWS, SSH, …) so the
71
+ # Step-2 data-access preflight can check it up front and offer an empty-DB fallback:
72
+ seed:
73
+ run: './scripts/pull-aws-db.sh --yes' # the seed command
74
+ empty-ok: true # default true: skipping yields a coherent EMPTY DB (schema via migrations).
75
+ # # false = the repo is broken without data → a missing-access gap HARD-STOPS.
76
+ access: # what the user must have to run `run`; each entry probed in the Step-2 preflight
77
+ - label: 'AWS CLI credentials — eu-north-1 / 842675986884'
78
+ check: 'aws sts get-caller-identity --region eu-north-1' # read-only probe; exit 0 = OK
79
+ login: 'Set up the AWS CLI (brew install awscli; aws configure …) — or pick empty DB.'
53
80
  serve: # optional: how it runs (printed as a next-step, never auto-started)
54
81
  via: herd # herd | valet | docker | command — for PHP envs, bring-your-own (don't install)
55
82
  url: 'https://example.test'
@@ -77,6 +104,16 @@ env:
77
104
  # source: { repo: <repo>, provides: '<value>' } # … a value produced by another repo
78
105
  sinks:
79
106
  - { repo: <repo>, key: DB_NAME } # written under `key` into each sink's .env
107
+ seeds: # optional: data sources NOT owned by a manifest repo (e.g. a shared WordPress host
108
+ # pulled by a workspace script). Same shape as a per-repo `seed` object; included in
109
+ # the Step-2 data-access preflight.
110
+ - label: 'WordPress host (example.se)'
111
+ run: './scripts/pull-wp-example.sh'
112
+ empty-ok: true
113
+ access:
114
+ - label: 'SSH user@host'
115
+ check: 'ssh -o BatchMode=yes -o ConnectTimeout=5 user@host true'
116
+ login: 'Add your SSH key to the host (ssh-add …) / request access — or skip the pull.'
80
117
  ```
81
118
 
82
119
  ### Run order
@@ -87,7 +124,7 @@ env:
87
124
  - **`needs`** → add the service to the **workspace compose project** and `docker compose up -d` if not already running (namespaced by `COMPOSE_PROJECT_NAME`, free host ports per instance; not the repo's own bind-mounting compose). Comes up **empty**; record host ports in the workspace `localdev.yml` `env` map — data lands in `seed:`.
88
125
  - **`build`** → run it (honor any node version the repo's docs note).
89
126
  - **`serve`** → for `via: herd` / PHP envs, install nothing — verify the dev's environment serves `web/`, and report the URL.
90
- - **`seed`** → populate the empty datastore. **Always a distinct, confirm-gated step, separate from `needs:` bring-up** (don't conflate "DB up" with "DB has data"). Before running, **check its prerequisites and report any gap instead of running blind** — e.g. WP-CLI present (for `wp` / `db:pull` seeds), the target repo's **`.env` written** (the seed reads connection values from it — done in the Env step above), the **SSH alias resolves** (for remote pulls like `dep db:pull staging-oderland`). **Confirm first** for every remote (SSH) or destructive (overwrites data) seed — every run, even on re-run. Missing prerequisite → skip with a clear message, don't guess.
127
+ - **`seed`** → populate the empty datastore (`seed.run`, or the bare-string form). **Always a distinct, confirm-gated step, separate from `needs:` bring-up** (don't conflate "DB up" with "DB has data"). **Honor the data plan chosen in the Step-2 data-access preflight** — don't re-discover access here: if the user chose _empty_ for this source, skip it (the DB stays empty, schema via migrations) and print the command to fill it later; if they chose _seed_, run it. Still verify the run-time prerequisites the preflight couldn't (the target repo's **`.env` written** — done in the Env step above; WP-CLI present for `wp`/`db:pull` seeds) and **confirm first** for every remote (SSH/AWS) or destructive (overwrites data) seed — every run, even on re-run. Missing prerequisite → skip with a clear message, don't guess.
91
128
  - **`steps`** (escape hatch) → run in order, selecting `node:` per step, `optional:` failures continue, **confirming before any `remote:`/`destructive:` step** — every run, even on re-run.
92
129
  4. **Links** (workspace-owned, performed generically — do NOT call a repo's own `setup-dev-mode.sh`, which is deprecated):
93
130
  - `symlink` → `ln -s <from> <to>`; replace an existing symlink, but never clobber a real directory without confirmation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haus-tech/haus-workflow",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Haus AI workflow CLI for Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "CHANGELOG.md"
21
21
  ],
22
22
  "scripts": {
23
- "build": "tsup src/cli.ts --format esm --dts --clean --out-dir dist --external @inquirer/checkbox",
23
+ "build": "rm -rf dist && esbuild src/cli.ts --bundle --packages=external --platform=node --format=esm --outdir=dist --external:@inquirer/checkbox",
24
24
  "dev": "tsx src/cli.ts",
25
25
  "test": "node scripts/run-tests.mjs tests/**/*.test.js",
26
26
  "test:fast": "node scripts/test-fast.mjs",
@@ -47,7 +47,6 @@
47
47
  "execa": "9.6.1",
48
48
  "fast-glob": "3.3.3",
49
49
  "fs-extra": "11.3.5",
50
- "ignore": "6.0.2",
51
50
  "semver": "7.8.0",
52
51
  "yaml": "2.8.4"
53
52
  },
@@ -59,13 +58,13 @@
59
58
  "@typescript-eslint/eslint-plugin": "8.59.3",
60
59
  "@typescript-eslint/parser": "8.59.3",
61
60
  "c8": "11.0.0",
61
+ "esbuild": "0.28.1",
62
62
  "eslint": "9.39.4",
63
63
  "eslint-plugin-import": "2.32.0",
64
64
  "lefthook": "1.13.6",
65
65
  "prettier": "3.8.3",
66
66
  "release-it": "20.0.1",
67
- "tsup": "8.5.1",
68
- "tsx": "4.21.0",
67
+ "tsx": "4.22.4",
69
68
  "typescript": "5.9.3"
70
69
  },
71
70
  "engines": {
package/dist/cli.d.ts DELETED
@@ -1 +0,0 @@
1
- #!/usr/bin/env node