create-daloy 0.1.21 → 0.1.23

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
@@ -18,6 +18,7 @@ The CLI is interactive when arguments are missing. It will ask you for:
18
18
  `deno-basic` runtime template
19
19
  - Whether to install dependencies
20
20
  - Whether to initialize a git repository
21
+ - Whether to add hardened GitHub Actions and security/governance files
21
22
 
22
23
  Interactive runs use a polished terminal UI with a DaloyJS welcome banner,
23
24
  arrow-key template and package-manager pickers, progress indicators, and a
@@ -30,6 +31,8 @@ script-friendly transcript with the same decisions and next steps.
30
31
  pnpm create daloy@latest my-api \
31
32
  --template node-basic \
32
33
  --package-manager pnpm \
34
+ --with-ci \
35
+ --code-owner @acme/security \
33
36
  --install \
34
37
  --git
35
38
  ```
@@ -44,6 +47,8 @@ pnpm create daloy@latest my-api \
44
47
  | `--install` / `--no-install` | Install dependencies after scaffolding. Defaults to interactive. |
45
48
  | `--git` / `--no-git` | Initialize a git repository. Defaults to interactive. |
46
49
  | `--minimal` | Strip the bookstore demo route and the built-in `/docs` + `/openapi.json` routes so only the framework bootstrap and `/healthz` ship. |
50
+ | `--with-ci` / `--no-ci` | Add the hardened GitHub Actions, Dependabot, CODEOWNERS, SECURITY.md, and lockfile-source verification bundle. |
51
+ | `--code-owner <owner>` | Replace the CODEOWNERS placeholder when `--with-ci` is used, for example `@acme/security`. |
47
52
  | `--force` | Overwrite an existing non-empty directory. |
48
53
  | `--yes` | Accept all defaults; never prompt. |
49
54
  | `--help` | Print usage and exit. |
@@ -118,14 +123,50 @@ Sentinel comments (`// daloy-minimal:strip-start <tag>` /
118
123
  `// daloy-minimal:strip-end <tag>`) survive a default scaffold so you can
119
124
  re-run with `--minimal`, or delete the marked blocks by hand later.
120
125
 
126
+ ## Hardened GitHub security bundle
127
+
128
+ Pass `--with-ci` when you want the generated project to start with the same
129
+ security posture as a serious company repo:
130
+
131
+ ```bash
132
+ pnpm create daloy@latest my-api \
133
+ --template node-basic \
134
+ --package-manager pnpm \
135
+ --with-ci \
136
+ --code-owner @acme/security
137
+ ```
138
+
139
+ For Node-style templates, the bundle adds:
140
+
141
+ - `.github/workflows/ci.yml` with top-level `permissions: {}`, pinned actions,
142
+ `harden-runner`, `persist-credentials: false`, no package-manager cache, and
143
+ install scripts disabled.
144
+ - `.github/workflows/release.yml` as a disabled-by-default npm trusted publishing
145
+ skeleton. It only publishes when `NPM_PUBLISH_ENABLED=true`, the package is no
146
+ longer private, and the protected `npm-publish` environment is configured.
147
+ - CodeQL, OpenSSF Scorecard, zizmor, Dependabot, CODEOWNERS, and `SECURITY.md`.
148
+ - `scripts/verify-lockfile-sources.mjs` plus a `verify:lockfile` package script
149
+ that rejects git dependencies and non-registry tarball URLs in text lockfiles.
150
+
151
+ For `deno-basic`, `--with-ci` generates a Deno-native CI workflow plus CodeQL,
152
+ Scorecard, zizmor, Dependabot for GitHub Actions, CODEOWNERS, and `SECURITY.md`.
153
+ It does not generate an npm release workflow because the Deno template has no
154
+ `package.json`.
155
+
156
+ If you omit `--code-owner`, the generated CODEOWNERS file uses
157
+ `@your-org/security-team` as a placeholder. Replace it before relying on branch
158
+ protection. You should also enable GitHub secret scanning, push protection, and
159
+ required status checks in the repository settings.
160
+
121
161
  ## What the CLI guarantees
122
162
 
123
163
  - Zero runtime dependencies (uses only Node built-ins) for a clean supply-chain footprint.
124
164
  - A modern terminal experience with Unicode/color capability detection and ASCII fallbacks.
125
165
  - Templates are copied verbatim from this package's `templates/` directory.
126
- - Files and folders prefixed with `_` are renamed on copy (`_gitignore` → `.gitignore`, `_npmrc` → `.npmrc`, `_agents/` → `.agents/`) to survive npm packing.
166
+ - Files and folders prefixed with `_` are renamed on copy (`_gitignore` → `.gitignore`, `_npmrc` → `.npmrc`, `_github/` → `.github`, `_agents/` → `.agents/`) to survive npm packing.
127
167
  - pnpm-specific `.npmrc` hardening is kept only when you choose `pnpm`; other package managers get a clean project without unsupported config warnings.
128
168
  - pnpm projects ship with `ignore-scripts=true`, `minimum-release-age=1440`, `verify-store-integrity=true`, `prefer-frozen-lockfile=true`, and `strict-peer-dependencies=true` by default.
169
+ - `--with-ci` projects ship with pinned GitHub Actions workflows, CODEOWNERS, Dependabot, SECURITY.md, and lockfile-source verification.
129
170
  - The CLI never executes template scripts and never makes network calls beyond the package manager you select.
130
171
 
131
172
  ## AI agent helper files
@@ -13,6 +13,7 @@ import { fileURLToPath } from "node:url";
13
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
14
  const PKG_ROOT = path.resolve(__dirname, "..");
15
15
  const TEMPLATES_DIR = path.join(PKG_ROOT, "templates");
16
+ const CI_TEMPLATES_DIR = path.join(TEMPLATES_DIR, "_ci");
16
17
 
17
18
  const TEMPLATE_OPTIONS = [
18
19
  {
@@ -43,10 +44,10 @@ const TEMPLATE_OPTIONS = [
43
44
  ];
44
45
 
45
46
  const PACKAGE_MANAGER_OPTIONS = [
46
- { value: "pnpm", title: "pnpm", description: "Recommended for DaloyJS projects" },
47
- { value: "npm", title: "npm", description: "Use the npm client you already have" },
48
- { value: "yarn", title: "Yarn", description: "Classic create workflow" },
49
- { value: "bun", title: "Bun", description: "Fast install and runtime tooling" },
47
+ { value: "pnpm", title: "pnpm", description: "Recommended default with the hardened pnpm workspace settings" },
48
+ { value: "npm", title: "npm", description: "Use the stock npm CLI with rewritten scripts and docs" },
49
+ { value: "yarn", title: "Yarn", description: "Yarn workflow with rewritten scripts and lockfile-friendly installs" },
50
+ { value: "bun", title: "Bun", description: "Bun package manager for fast installs; runtime templates stay Bun-native" },
50
51
  ];
51
52
 
52
53
  const TEMPLATES = TEMPLATE_OPTIONS.map((option) => option.value);
@@ -56,6 +57,7 @@ const RENAME_ON_COPY = new Map([
56
57
  ["_gitignore", ".gitignore"],
57
58
  ["_npmrc", ".npmrc"],
58
59
  ["_env.example", ".env.example"],
60
+ ["_github", ".github"],
59
61
  // Directory: holds skill files for AI coding agents under
60
62
  // `.agents/skills/<skill-name>/SKILL.md`. Templates author this as
61
63
  // `_agents/` so npm pack does not drop the dotfolder during publish.
@@ -72,6 +74,8 @@ const NO_PACKAGE_JSON_TEMPLATES = new Set(["deno-basic"]);
72
74
  // `daloy-minimal:strip-start <tag>` / `daloy-minimal:strip-end <tag>`
73
75
  // sentinels.
74
76
  const MINIMAL_STRIP_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".mjs", ".cjs", ".md"]);
77
+ const CI_PLACEHOLDER_EXTENSIONS = new Set([".json", ".md", ".mjs", ".yaml", ".yml"]);
78
+ const CI_PLACEHOLDER_FILES = new Set(["CODEOWNERS"]);
75
79
 
76
80
  // ----------------------------------------------------------------------------
77
81
  // Terminal capability detection + style primitives.
@@ -308,6 +312,8 @@ ${heading("Options")}
308
312
  ${color(COLORS.green, "--install / --no-install")} Install dependencies after scaffolding.
309
313
  ${color(COLORS.green, "--git / --no-git")} Initialize a git repository.
310
314
  ${color(COLORS.green, "--minimal")} Strip the bookstore + Swagger/OpenAPI demo routes.
315
+ ${color(COLORS.green, "--with-ci / --no-ci")} Add hardened GitHub Actions + governance files.
316
+ ${color(COLORS.green, "--code-owner <owner>")} CODEOWNERS owner for --with-ci, e.g. @acme/security.
311
317
  ${color(COLORS.green, "--force")} Overwrite an existing non-empty directory.
312
318
  ${color(COLORS.green, "--yes, -y")} Accept all defaults; never prompt.
313
319
  ${color(COLORS.green, "--help, -h")} Print this help.
@@ -353,6 +359,8 @@ function parseArgs(argv) {
353
359
  version: false,
354
360
  listTemplates: false,
355
361
  minimal: false,
362
+ ci: undefined,
363
+ codeOwner: undefined,
356
364
  };
357
365
  const args = [...argv];
358
366
  while (args.length) {
@@ -363,6 +371,10 @@ function parseArgs(argv) {
363
371
  else if (a === "--yes" || a === "-y") out.yes = true;
364
372
  else if (a === "--force") out.force = true;
365
373
  else if (a === "--minimal") out.minimal = true;
374
+ else if (a === "--with-ci") out.ci = true;
375
+ else if (a === "--no-ci") out.ci = false;
376
+ else if (a === "--code-owner") out.codeOwner = args.shift();
377
+ else if (a?.startsWith("--code-owner=")) out.codeOwner = a.slice("--code-owner=".length);
366
378
  else if (a === "--install") out.install = true;
367
379
  else if (a === "--no-install") out.install = false;
368
380
  else if (a === "--git") out.git = true;
@@ -391,6 +403,11 @@ function detectPackageManager() {
391
403
  }
392
404
 
393
405
  const VALID_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
406
+ // Match the GitHub CODEOWNERS owner grammar: a personal handle (@user), an
407
+ // organization team (@org/team), or an email address. Anything else is
408
+ // rejected so the scaffolded CODEOWNERS stays meaningful for branch protection.
409
+ const VALID_CODE_OWNER =
410
+ /^(?:@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,38})(?:\/[a-zA-Z0-9][a-zA-Z0-9._-]*)?|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})$/;
394
411
 
395
412
  function validateProjectName(name) {
396
413
  if (!name || !name.trim()) return "Project name cannot be empty.";
@@ -532,6 +549,167 @@ async function normalizePackageManagerFiles(dir, packageManager) {
532
549
  }
533
550
  }
534
551
 
552
+ function hasPackageScript(packageJson, scriptName) {
553
+ return typeof packageJson?.scripts?.[scriptName] === "string";
554
+ }
555
+
556
+ function runScriptCommand(packageManager, scriptName) {
557
+ if (packageManager === "pnpm") return `pnpm ${scriptName}`;
558
+ if (packageManager === "npm") return scriptName === "test" ? "npm test" : `npm run ${scriptName}`;
559
+ if (packageManager === "yarn") return scriptName === "test" ? "yarn test" : `yarn run ${scriptName}`;
560
+ if (packageManager === "bun") return scriptName === "test" ? "bun test" : `bun run ${scriptName}`;
561
+ return `${packageManager} run ${scriptName}`;
562
+ }
563
+
564
+ function installCommand(packageManager) {
565
+ if (packageManager === "pnpm") return "pnpm install --frozen-lockfile --ignore-scripts";
566
+ if (packageManager === "npm") return "npm ci --ignore-scripts";
567
+ if (packageManager === "yarn") return "yarn install --frozen-lockfile --ignore-scripts";
568
+ if (packageManager === "bun") return "bun install --frozen-lockfile --ignore-scripts";
569
+ return `${packageManager} install`;
570
+ }
571
+
572
+ function auditCommand(packageManager) {
573
+ if (packageManager === "pnpm") return "pnpm audit --prod";
574
+ if (packageManager === "npm") return "npm audit --omit=dev";
575
+ if (packageManager === "yarn") return "yarn audit --groups dependencies";
576
+ if (packageManager === "bun") return "bun audit";
577
+ return "";
578
+ }
579
+
580
+ function setupPackageManagerStep(packageManager) {
581
+ if (packageManager === "pnpm") {
582
+ return ` - name: Set up pnpm
583
+ uses: pnpm/action-setup@ac6db6d3c1f721f886538a378a2d73e85697340a # v6
584
+ with:
585
+ version: 11.1.2
586
+ run_install: false`;
587
+ }
588
+ if (packageManager === "yarn") {
589
+ return ` - name: Enable Corepack
590
+ run: corepack enable`;
591
+ }
592
+ if (packageManager === "bun") return setupBunStep();
593
+ return "";
594
+ }
595
+
596
+ function setupBunStep() {
597
+ return ` - name: Set up Bun
598
+ uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
599
+ with:
600
+ bun-version: latest`;
601
+ }
602
+
603
+ function workflowStep(name, command) {
604
+ return ` - name: ${name}
605
+ run: ${command}`;
606
+ }
607
+
608
+ function multilineWorkflowStep(name, command) {
609
+ return ` - name: ${name}
610
+ run: |
611
+ ${command
612
+ .split("\n")
613
+ .map((line) => ` ${line}`)
614
+ .join("\n")}`;
615
+ }
616
+
617
+ async function readPackageJsonIfPresent(dir) {
618
+ const file = path.join(dir, "package.json");
619
+ if (!existsSync(file)) return null;
620
+ return JSON.parse(await readFile(file, "utf8"));
621
+ }
622
+
623
+ async function writePackageJson(dir, packageJson) {
624
+ await writeFile(path.join(dir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n", "utf8");
625
+ }
626
+
627
+ async function addLockfileVerifyScript(dir) {
628
+ const packageJson = await readPackageJsonIfPresent(dir);
629
+ if (!packageJson) return;
630
+ packageJson.scripts ??= {};
631
+ packageJson.scripts["verify:lockfile"] = "node scripts/verify-lockfile-sources.mjs";
632
+ await writePackageJson(dir, packageJson);
633
+ }
634
+
635
+ function renderCiReplacements({ packageManager, template, packageJson, codeOwner }) {
636
+ const setupPm = setupPackageManagerStep(packageManager);
637
+ const needsBunRuntime = template === "bun-basic" && packageManager !== "bun";
638
+ const audit = auditCommand(packageManager);
639
+ const buildStep = hasPackageScript(packageJson, "build") ? workflowStep("Build", runScriptCommand(packageManager, "build")) : "";
640
+ const auditStep = audit ? workflowStep("Audit production dependencies", audit) : "";
641
+ const tagVersionCheck = `set -eu
642
+ tag_version="\${GITHUB_REF_NAME#v}"
643
+ pkg_version="$(node -p "require('./package.json').version")"
644
+ if [ "$tag_version" != "$pkg_version" ]; then
645
+ echo "::error::Tag $GITHUB_REF_NAME does not match package.json version $pkg_version"
646
+ exit 1
647
+ fi`;
648
+
649
+ return new Map([
650
+ ["__CODE_OWNER__", codeOwner],
651
+ ["__SETUP_PACKAGE_MANAGER_STEP__", setupPm],
652
+ ["__SETUP_BUN_RUNTIME_STEP__", needsBunRuntime ? setupBunStep() : ""],
653
+ ["__INSTALL_COMMAND__", installCommand(packageManager)],
654
+ ["__VERIFY_LOCKFILE_COMMAND__", runScriptCommand(packageManager, "verify:lockfile")],
655
+ ["__TYPECHECK_COMMAND__", runScriptCommand(packageManager, "typecheck")],
656
+ ["__TEST_COMMAND__", runScriptCommand(packageManager, "test")],
657
+ ["__BUILD_STEP__", buildStep],
658
+ ["__AUDIT_STEP__", auditStep],
659
+ ["__TAG_VERSION_CHECK_STEP__", multilineWorkflowStep("Verify tag matches package.json version", tagVersionCheck)],
660
+ ]);
661
+ }
662
+
663
+ async function replacePlaceholdersInTree(dir, replacements) {
664
+ const entries = await readdir(dir, { withFileTypes: true });
665
+ for (const entry of entries) {
666
+ const full = path.join(dir, entry.name);
667
+ if (entry.isDirectory()) {
668
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
669
+ await replacePlaceholdersInTree(full, replacements);
670
+ continue;
671
+ }
672
+ if (!entry.isFile()) continue;
673
+ if (!CI_PLACEHOLDER_EXTENSIONS.has(path.extname(entry.name)) && !CI_PLACEHOLDER_FILES.has(entry.name)) {
674
+ continue;
675
+ }
676
+ const raw = await readFile(full, "utf8");
677
+ let next = raw;
678
+ for (const [placeholder, value] of replacements) {
679
+ next = next.replaceAll(placeholder, value);
680
+ }
681
+ if (next !== raw) await writeFile(full, next, "utf8");
682
+ }
683
+ }
684
+
685
+ async function copyCiBundle(targetDir, template, packageManager, skipPackageManager, codeOwner) {
686
+ const flavor = skipPackageManager ? "deno" : "node";
687
+ const sourceDir = path.join(CI_TEMPLATES_DIR, flavor);
688
+ if (!existsSync(sourceDir)) {
689
+ throw new Error(`CI template bundle "${flavor}" is missing from this CLI build.`);
690
+ }
691
+ await copyTemplate(sourceDir, targetDir);
692
+
693
+ const candidate = codeOwner?.trim() ?? "";
694
+ if (candidate && !VALID_CODE_OWNER.test(candidate)) {
695
+ throw new Error(
696
+ `Invalid --code-owner "${candidate}". Use a GitHub handle (@user), a team (@org/team), or an email address.`,
697
+ );
698
+ }
699
+ const owner = candidate || "@your-org/security-team";
700
+ if (skipPackageManager) {
701
+ await replacePlaceholdersInTree(targetDir, new Map([["__CODE_OWNER__", owner]]));
702
+ return;
703
+ }
704
+
705
+ await addLockfileVerifyScript(targetDir);
706
+ const packageJson = await readPackageJsonIfPresent(targetDir);
707
+ await replacePlaceholdersInTree(
708
+ targetDir,
709
+ renderCiReplacements({ packageManager, template, packageJson, codeOwner: owner }),
710
+ );
711
+ }
712
+
535
713
  /**
536
714
  * `--minimal` post-processor.
537
715
  *
@@ -864,7 +1042,7 @@ function createSpinner(initialMessage) {
864
1042
  };
865
1043
  }
866
1044
 
867
- function printSummary({ projectName, template, packageManager, installDeps, skipPackageManager }) {
1045
+ function printSummary({ projectName, template, packageManager, installDeps, skipPackageManager, withCi }) {
868
1046
  const templateMeta = TEMPLATE_OPTIONS.find((option) => option.value === template);
869
1047
  const templateLabel = templateMeta ? `${templateMeta.title} ${color(COLORS.dim, `(${template})`)}` : template;
870
1048
  const summaryLines = [
@@ -878,6 +1056,9 @@ function printSummary({ projectName, template, packageManager, installDeps, skip
878
1056
  } else {
879
1057
  summaryLines.push(`${color(COLORS.gray, "Manager ")} ${color(COLORS.cyan, packageManager)}`);
880
1058
  }
1059
+ if (withCi) {
1060
+ summaryLines.push(`${color(COLORS.gray, "Security ")} ${color(COLORS.cyan, "GitHub CI bundle")}`);
1061
+ }
881
1062
  console.log("");
882
1063
  console.log(renderBox(summaryLines, { accent: COLORS.green }));
883
1064
  console.log("");
@@ -1016,6 +1197,11 @@ async function main() {
1016
1197
  initGit = rl ? await askYesNo(rl, "Initialize a git repository?", true) : false;
1017
1198
  }
1018
1199
 
1200
+ let withCi = opts.ci;
1201
+ if (withCi === undefined) {
1202
+ withCi = rl ? await askYesNo(rl, "Add hardened GitHub Actions and security files?", false) : false;
1203
+ }
1204
+
1019
1205
  rl?.close();
1020
1206
 
1021
1207
  if (interactive) {
@@ -1042,6 +1228,11 @@ async function main() {
1042
1228
  }
1043
1229
  }
1044
1230
 
1231
+ if (withCi) {
1232
+ await copyCiBundle(targetDir, template, packageManager, skipPackageManager, opts.codeOwner);
1233
+ logStep("GitHub security bundle added", skipPackageManager ? "deno" : packageManager);
1234
+ }
1235
+
1045
1236
  if (initGit) {
1046
1237
  const code = await run("git", ["init", "--quiet"], targetDir);
1047
1238
  if (code === 0) {
@@ -1068,7 +1259,7 @@ async function main() {
1068
1259
  }
1069
1260
  }
1070
1261
 
1071
- printSummary({ projectName, template, packageManager, installDeps, skipPackageManager });
1262
+ printSummary({ projectName, template, packageManager, installDeps, skipPackageManager, withCi });
1072
1263
  } catch (err) {
1073
1264
  rl?.close();
1074
1265
  if (err && err.message === "Cancelled") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-daloy",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Scaffold a new DaloyJS project. Run with `pnpm create daloy`, `npm create daloy@latest`, `yarn create daloy`, or `bun create daloy`.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,32 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ This project is generated by `create-daloy`. Apply security fixes to the
6
+ currently deployed branch and keep dependencies current through review.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Do not open a public issue for suspected vulnerabilities. Use your company's
11
+ private intake process, GitHub private vulnerability reporting, or the security
12
+ contact for this repository.
13
+
14
+ ## Generated controls
15
+
16
+ The `--with-ci` bundle adds these defaults:
17
+
18
+ - GitHub Actions workflows use top-level `permissions: {}` and job-scoped permissions.
19
+ - Fork pull requests use `pull_request`, not `pull_request_target`.
20
+ - Third-party actions are pinned to commit SHAs.
21
+ - `actions/checkout` uses `persist-credentials: false`.
22
+ - Deno CI runs `deno task typecheck` and `deno task test` with the template's narrow permission flags.
23
+ - CodeQL, OpenSSF Scorecard, zizmor, Dependabot for GitHub Actions, and CODEOWNERS are generated.
24
+
25
+ ## Required repository settings
26
+
27
+ Before relying on these files for a company project:
28
+
29
+ 1. Replace `@your-org/security-team` in `.github/CODEOWNERS` or pass `--code-owner` when scaffolding.
30
+ 2. Protect the `main` branch and require the CI, CodeQL, Scorecard, and zizmor checks.
31
+ 3. Enable GitHub secret scanning and push protection.
32
+ 4. Keep Deno permissions narrow; do not switch tasks to `--allow-all`.
@@ -0,0 +1,17 @@
1
+ # Replace the placeholder owner with the GitHub user or team that must review
2
+ # privileged files before relying on CODEOWNERS protection.
3
+
4
+ * __CODE_OWNER__
5
+
6
+ # Workflow / CI / CD.
7
+ /.github/ __CODE_OWNER__
8
+ /.github/workflows/ __CODE_OWNER__
9
+ /.github/dependabot.yml __CODE_OWNER__
10
+ /.github/CODEOWNERS __CODE_OWNER__
11
+
12
+ # Files that affect dependency resolution or runtime permissions.
13
+ /deno.json __CODE_OWNER__
14
+ /deno.lock __CODE_OWNER__
15
+
16
+ # Vulnerability handling.
17
+ /SECURITY.md __CODE_OWNER__
@@ -0,0 +1,15 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: github-actions
5
+ directory: "/"
6
+ schedule:
7
+ interval: weekly
8
+ day: monday
9
+ open-pull-requests-limit: 10
10
+ groups:
11
+ actions:
12
+ patterns:
13
+ - "*"
14
+ commit-message:
15
+ prefix: "chore(actions)"
@@ -0,0 +1,47 @@
1
+ # Hardened Deno CI generated by create-daloy --with-ci.
2
+ name: CI
3
+
4
+ on:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ permissions: {}
11
+
12
+ concurrency:
13
+ group: ci-${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ verify:
18
+ name: Verify
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 20
21
+ permissions:
22
+ contents: read
23
+
24
+ steps:
25
+ - name: Harden runner
26
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
27
+ with:
28
+ egress-policy: audit
29
+ disable-sudo: true
30
+ disable-file-monitoring: false
31
+
32
+ - name: Checkout
33
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
34
+ with:
35
+ persist-credentials: false
36
+ show-progress: false
37
+
38
+ - name: Set up Deno
39
+ uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4
40
+ with:
41
+ deno-version: v2.x
42
+
43
+ - name: Typecheck
44
+ run: deno task typecheck
45
+
46
+ - name: Test
47
+ run: deno task test
@@ -0,0 +1,56 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "37 4 * * 1"
10
+
11
+ permissions: {}
12
+
13
+ jobs:
14
+ analyze:
15
+ name: Analyze (${{ matrix.language }})
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 30
18
+ permissions:
19
+ security-events: write
20
+ packages: read
21
+ actions: read
22
+ contents: read
23
+
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ include:
28
+ - language: javascript-typescript
29
+ build-mode: none
30
+ - language: actions
31
+ build-mode: none
32
+
33
+ steps:
34
+ - name: Harden runner
35
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
36
+ with:
37
+ egress-policy: audit
38
+ disable-sudo: true
39
+
40
+ - name: Checkout
41
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
42
+ with:
43
+ persist-credentials: false
44
+ show-progress: false
45
+
46
+ - name: Initialize CodeQL
47
+ uses: github/codeql-action/init@52485aec7be33610227643b0fe83936b8b5f061a # v3
48
+ with:
49
+ languages: ${{ matrix.language }}
50
+ build-mode: ${{ matrix.build-mode }}
51
+ queries: security-extended,security-and-quality
52
+
53
+ - name: Perform CodeQL Analysis
54
+ uses: github/codeql-action/analyze@52485aec7be33610227643b0fe83936b8b5f061a # v3
55
+ with:
56
+ category: "/language:${{ matrix.language }}"
@@ -0,0 +1,46 @@
1
+ name: Scorecard
2
+
3
+ on:
4
+ branch_protection_rule:
5
+ schedule:
6
+ - cron: "23 5 * * 2"
7
+ push:
8
+ branches: [main]
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ analysis:
14
+ name: Scorecard analysis
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 15
17
+ permissions:
18
+ security-events: write
19
+ id-token: write
20
+ contents: read
21
+ actions: read
22
+
23
+ steps:
24
+ - name: Harden runner
25
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
26
+ with:
27
+ egress-policy: audit
28
+ disable-sudo: true
29
+
30
+ - name: Checkout
31
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
32
+ with:
33
+ persist-credentials: false
34
+ show-progress: false
35
+
36
+ - name: Run analysis
37
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
38
+ with:
39
+ results_file: results.sarif
40
+ results_format: sarif
41
+ publish_results: true
42
+
43
+ - name: Upload to code-scanning
44
+ uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
45
+ with:
46
+ sarif_file: results.sarif
@@ -0,0 +1,38 @@
1
+ name: Zizmor
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ schedule:
8
+ - cron: "0 7 * * *"
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ zizmor:
14
+ name: Lint workflows
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 10
17
+ permissions:
18
+ security-events: write
19
+ contents: read
20
+ actions: read
21
+
22
+ steps:
23
+ - name: Harden runner
24
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
25
+ with:
26
+ egress-policy: audit
27
+ disable-sudo: true
28
+
29
+ - name: Checkout
30
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
31
+ with:
32
+ persist-credentials: false
33
+ show-progress: false
34
+
35
+ - name: Run zizmor
36
+ uses: zizmorcore/zizmor-action@b572f7b1a1c2d41efaab43d504f68d215c3cd727 # v0.5.4
37
+ with:
38
+ version: v1.25.0
@@ -0,0 +1,36 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ This project is generated by `create-daloy`. Apply security fixes to the
6
+ currently deployed branch and keep dependencies current through Dependabot.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Do not open a public issue for suspected vulnerabilities. Use your company's
11
+ private intake process, GitHub private vulnerability reporting, or the security
12
+ contact for this repository.
13
+
14
+ ## Generated controls
15
+
16
+ The `--with-ci` bundle adds these defaults:
17
+
18
+ - GitHub Actions workflows use top-level `permissions: {}` and job-scoped permissions.
19
+ - Fork pull requests use `pull_request`, not `pull_request_target`.
20
+ - Third-party actions are pinned to commit SHAs.
21
+ - `actions/checkout` uses `persist-credentials: false`.
22
+ - Dependency installs run with lifecycle scripts disabled.
23
+ - Package-manager caches are disabled in CI to avoid cache-poisoning bridges.
24
+ - Lockfile source verification rejects git dependencies and non-registry tarball URLs.
25
+ - CodeQL, OpenSSF Scorecard, zizmor, Dependabot, and CODEOWNERS are generated.
26
+ - npm publishing is disabled until `NPM_PUBLISH_ENABLED=true` is set and npm trusted publishing is configured.
27
+
28
+ ## Required repository settings
29
+
30
+ Before relying on these files for a company project:
31
+
32
+ 1. Replace `@your-org/security-team` in `.github/CODEOWNERS` or pass `--code-owner` when scaffolding.
33
+ 2. Protect the `main` branch and require the CI, CodeQL, Scorecard, and zizmor checks.
34
+ 3. Enable GitHub secret scanning and push protection.
35
+ 4. Configure a protected `npm-publish` Environment before enabling npm publish.
36
+ 5. Keep `ignore-scripts=true` and the `pnpm-workspace.yaml` supply-chain settings on when using pnpm.
@@ -0,0 +1,25 @@
1
+ # Replace the placeholder owner with the GitHub user or team that must review
2
+ # privileged files before relying on CODEOWNERS protection.
3
+
4
+ * __CODE_OWNER__
5
+
6
+ # Workflow / CI / CD.
7
+ /.github/ __CODE_OWNER__
8
+ /.github/workflows/ __CODE_OWNER__
9
+ /.github/workflows/release.yml __CODE_OWNER__
10
+ /.github/dependabot.yml __CODE_OWNER__
11
+ /.github/CODEOWNERS __CODE_OWNER__
12
+
13
+ # Files that affect dependency resolution, install scripts, or publishing.
14
+ /package.json __CODE_OWNER__
15
+ /package-lock.json __CODE_OWNER__
16
+ /npm-shrinkwrap.json __CODE_OWNER__
17
+ /pnpm-lock.yaml __CODE_OWNER__
18
+ /pnpm-workspace.yaml __CODE_OWNER__
19
+ /yarn.lock __CODE_OWNER__
20
+ /bun.lock __CODE_OWNER__
21
+ /.npmrc __CODE_OWNER__
22
+ /scripts/verify-lockfile-sources.mjs __CODE_OWNER__
23
+
24
+ # Vulnerability handling.
25
+ /SECURITY.md __CODE_OWNER__
@@ -0,0 +1,28 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: github-actions
5
+ directory: "/"
6
+ schedule:
7
+ interval: weekly
8
+ day: monday
9
+ open-pull-requests-limit: 10
10
+ groups:
11
+ actions:
12
+ patterns:
13
+ - "*"
14
+ commit-message:
15
+ prefix: "chore(actions)"
16
+
17
+ - package-ecosystem: npm
18
+ directory: "/"
19
+ schedule:
20
+ interval: weekly
21
+ day: monday
22
+ open-pull-requests-limit: 10
23
+ versioning-strategy: increase-if-necessary
24
+ groups:
25
+ dev-dependencies:
26
+ dependency-type: development
27
+ commit-message:
28
+ prefix: "chore(deps)"
@@ -0,0 +1,65 @@
1
+ # Hardened CI generated by create-daloy --with-ci.
2
+ name: CI
3
+
4
+ on:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ permissions: {}
11
+
12
+ concurrency:
13
+ group: ci-${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ verify:
18
+ name: Verify
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 20
21
+ permissions:
22
+ contents: read
23
+
24
+ steps:
25
+ - name: Harden runner
26
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
27
+ with:
28
+ egress-policy: audit
29
+ disable-sudo: true
30
+ disable-file-monitoring: false
31
+
32
+ - name: Checkout
33
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
34
+ with:
35
+ persist-credentials: false
36
+ show-progress: false
37
+
38
+ __SETUP_PACKAGE_MANAGER_STEP__
39
+
40
+ - name: Set up Node.js
41
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
42
+ with:
43
+ node-version: 24
44
+ # Package-manager caching is intentionally disabled. Shared caches
45
+ # can bridge fork PRs into trusted branches when mis-keyed.
46
+
47
+ __SETUP_BUN_RUNTIME_STEP__
48
+
49
+ - name: Install dependencies
50
+ run: __INSTALL_COMMAND__
51
+ env:
52
+ npm_config_ignore_scripts: "true"
53
+
54
+ - name: Verify lockfile sources
55
+ run: __VERIFY_LOCKFILE_COMMAND__
56
+
57
+ - name: Typecheck
58
+ run: __TYPECHECK_COMMAND__
59
+
60
+ - name: Test
61
+ run: __TEST_COMMAND__
62
+
63
+ __BUILD_STEP__
64
+
65
+ __AUDIT_STEP__
@@ -0,0 +1,56 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "37 4 * * 1"
10
+
11
+ permissions: {}
12
+
13
+ jobs:
14
+ analyze:
15
+ name: Analyze (${{ matrix.language }})
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 30
18
+ permissions:
19
+ security-events: write
20
+ packages: read
21
+ actions: read
22
+ contents: read
23
+
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ include:
28
+ - language: javascript-typescript
29
+ build-mode: none
30
+ - language: actions
31
+ build-mode: none
32
+
33
+ steps:
34
+ - name: Harden runner
35
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
36
+ with:
37
+ egress-policy: audit
38
+ disable-sudo: true
39
+
40
+ - name: Checkout
41
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
42
+ with:
43
+ persist-credentials: false
44
+ show-progress: false
45
+
46
+ - name: Initialize CodeQL
47
+ uses: github/codeql-action/init@52485aec7be33610227643b0fe83936b8b5f061a # v3
48
+ with:
49
+ languages: ${{ matrix.language }}
50
+ build-mode: ${{ matrix.build-mode }}
51
+ queries: security-extended,security-and-quality
52
+
53
+ - name: Perform CodeQL Analysis
54
+ uses: github/codeql-action/analyze@52485aec7be33610227643b0fe83936b8b5f061a # v3
55
+ with:
56
+ category: "/language:${{ matrix.language }}"
@@ -0,0 +1,125 @@
1
+ # Hardened npm publish skeleton generated by create-daloy --with-ci.
2
+ #
3
+ # Publishing is disabled until you set the repository variable
4
+ # NPM_PUBLISH_ENABLED=true, remove "private": true from package.json, and
5
+ # configure npm trusted publishing for this repository/environment.
6
+ name: Publish
7
+
8
+ on:
9
+ push:
10
+ tags:
11
+ - "v*"
12
+ workflow_dispatch:
13
+
14
+ permissions: {}
15
+
16
+ concurrency:
17
+ group: publish-${{ github.ref }}
18
+ cancel-in-progress: false
19
+
20
+ jobs:
21
+ verify:
22
+ name: Verify before publish
23
+ runs-on: ubuntu-latest
24
+ timeout-minutes: 20
25
+ permissions:
26
+ contents: read
27
+ steps:
28
+ - name: Harden runner
29
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
30
+ with:
31
+ egress-policy: audit
32
+ disable-sudo: true
33
+
34
+ - name: Checkout
35
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
36
+ with:
37
+ persist-credentials: false
38
+ show-progress: false
39
+
40
+ __SETUP_PACKAGE_MANAGER_STEP__
41
+
42
+ - name: Set up Node.js
43
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
44
+ with:
45
+ node-version: 24
46
+
47
+ __SETUP_BUN_RUNTIME_STEP__
48
+
49
+ - name: Install dependencies
50
+ run: __INSTALL_COMMAND__
51
+ env:
52
+ npm_config_ignore_scripts: "true"
53
+
54
+ - name: Verify lockfile sources
55
+ run: __VERIFY_LOCKFILE_COMMAND__
56
+
57
+ - name: Typecheck
58
+ run: __TYPECHECK_COMMAND__
59
+
60
+ - name: Test
61
+ run: __TEST_COMMAND__
62
+
63
+ __BUILD_STEP__
64
+
65
+ publish-npm:
66
+ name: Publish npm package
67
+ needs: verify
68
+ if: vars.NPM_PUBLISH_ENABLED == 'true'
69
+ runs-on: ubuntu-latest
70
+ timeout-minutes: 15
71
+ environment:
72
+ name: ${{ vars.NPM_PUBLISH_ENVIRONMENT || 'npm-publish' }}
73
+ url: https://www.npmjs.com/package/${{ github.event.repository.name }}
74
+ permissions:
75
+ contents: read
76
+ id-token: write
77
+
78
+ steps:
79
+ - name: Harden runner
80
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
81
+ with:
82
+ egress-policy: block
83
+ allowed-endpoints: >
84
+ api.github.com:443
85
+ github.com:443
86
+ objects.githubusercontent.com:443
87
+ registry.npmjs.org:443
88
+ fulcio.sigstore.dev:443
89
+ rekor.sigstore.dev:443
90
+ tuf-repo-cdn.sigstore.dev:443
91
+ disable-sudo: true
92
+
93
+ - name: Checkout
94
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
95
+ with:
96
+ persist-credentials: false
97
+ show-progress: false
98
+
99
+ __SETUP_PACKAGE_MANAGER_STEP__
100
+
101
+ - name: Set up Node.js
102
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
103
+ with:
104
+ node-version: 24
105
+ registry-url: "https://registry.npmjs.org"
106
+
107
+ __SETUP_BUN_RUNTIME_STEP__
108
+
109
+ - name: Install dependencies
110
+ run: __INSTALL_COMMAND__
111
+ env:
112
+ npm_config_ignore_scripts: "true"
113
+
114
+ - name: Refuse private package publish
115
+ run: |
116
+ node -e "const pkg = require('./package.json'); if (pkg.private) { console.error('package.json is private; remove private:true before enabling npm publish'); process.exit(1); }"
117
+
118
+ __TAG_VERSION_CHECK_STEP__
119
+
120
+ __BUILD_STEP__
121
+
122
+ - name: Publish to npm with provenance
123
+ run: npm publish --access public --provenance
124
+ env:
125
+ NPM_CONFIG_PROVENANCE: "true"
@@ -0,0 +1,46 @@
1
+ name: Scorecard
2
+
3
+ on:
4
+ branch_protection_rule:
5
+ schedule:
6
+ - cron: "23 5 * * 2"
7
+ push:
8
+ branches: [main]
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ analysis:
14
+ name: Scorecard analysis
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 15
17
+ permissions:
18
+ security-events: write
19
+ id-token: write
20
+ contents: read
21
+ actions: read
22
+
23
+ steps:
24
+ - name: Harden runner
25
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
26
+ with:
27
+ egress-policy: audit
28
+ disable-sudo: true
29
+
30
+ - name: Checkout
31
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
32
+ with:
33
+ persist-credentials: false
34
+ show-progress: false
35
+
36
+ - name: Run analysis
37
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
38
+ with:
39
+ results_file: results.sarif
40
+ results_format: sarif
41
+ publish_results: true
42
+
43
+ - name: Upload to code-scanning
44
+ uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
45
+ with:
46
+ sarif_file: results.sarif
@@ -0,0 +1,38 @@
1
+ name: Zizmor
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ schedule:
8
+ - cron: "0 7 * * *"
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ zizmor:
14
+ name: Lint workflows
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 10
17
+ permissions:
18
+ security-events: write
19
+ contents: read
20
+ actions: read
21
+
22
+ steps:
23
+ - name: Harden runner
24
+ uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
25
+ with:
26
+ egress-policy: audit
27
+ disable-sudo: true
28
+
29
+ - name: Checkout
30
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
31
+ with:
32
+ persist-credentials: false
33
+ show-progress: false
34
+
35
+ - name: Run zizmor
36
+ uses: zizmorcore/zizmor-action@b572f7b1a1c2d41efaab43d504f68d215c3cd727 # v0.5.4
37
+ with:
38
+ version: v1.25.0
@@ -0,0 +1,61 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+
3
+ const TEXT_LOCKFILES = ["pnpm-lock.yaml", "package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "bun.lock"];
4
+ const BINARY_LOCKFILES = ["bun.lockb"];
5
+ const GIT_SOURCE_PATTERN = /(?:specifier:\s*)?(?:github:|git\+|git:\/\/|ssh:\/\/git@|git@github\.com:)/i;
6
+ const URL_PATTERN = /(?:tarball|resolved)["':\s]+(?<url>https?:\/\/[^"'\s},]+)/i;
7
+ const ALLOWED_TARBALL_PREFIXES = ["https://registry.npmjs.org/", "https://registry.yarnpkg.com/"];
8
+
9
+ async function exists(file) {
10
+ try {
11
+ await access(file);
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ function findForbiddenSources(lockfile) {
19
+ const findings = [];
20
+ const lines = lockfile.split(/\r?\n/);
21
+ for (const [index, rawLine] of lines.entries()) {
22
+ const text = rawLine.trim();
23
+ if (GIT_SOURCE_PATTERN.test(text)) {
24
+ findings.push({ line: index + 1, reason: "git dependency source", text });
25
+ continue;
26
+ }
27
+
28
+ const url = URL_PATTERN.exec(text)?.groups?.url;
29
+ if (url && !ALLOWED_TARBALL_PREFIXES.some((prefix) => url.startsWith(prefix))) {
30
+ findings.push({ line: index + 1, reason: "non-registry tarball source", text });
31
+ }
32
+ }
33
+ return findings;
34
+ }
35
+
36
+ let checked = false;
37
+ let failed = false;
38
+
39
+ for (const file of TEXT_LOCKFILES) {
40
+ if (!(await exists(file))) continue;
41
+ checked = true;
42
+ const findings = findForbiddenSources(await readFile(file, "utf8"));
43
+ for (const finding of findings) {
44
+ failed = true;
45
+ console.error(`${file}: ${finding.reason} on line ${finding.line}: ${finding.text}`);
46
+ }
47
+ }
48
+
49
+ for (const file of BINARY_LOCKFILES) {
50
+ if (await exists(file)) {
51
+ failed = true;
52
+ console.error(`${file}: binary lockfiles cannot be source-verified; use a text lockfile in CI.`);
53
+ }
54
+ }
55
+
56
+ if (!checked) {
57
+ failed = true;
58
+ console.error("No text lockfile found. Commit a lockfile before relying on CI.");
59
+ }
60
+
61
+ if (failed) process.exitCode = 1;
@@ -16,7 +16,7 @@
16
16
  "gen": "pnpm gen:openapi && pnpm gen:client"
17
17
  },
18
18
  "dependencies": {
19
- "@daloyjs/core": "^0.5.0",
19
+ "@daloyjs/core": "^0.7.5",
20
20
  "zod": "^4.4.3"
21
21
  },
22
22
  "devDependencies": {
@@ -10,7 +10,7 @@
10
10
  "test": "node --import tsx/esm --test tests/**/*.test.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@daloyjs/core": "^0.5.0",
13
+ "@daloyjs/core": "^0.7.5",
14
14
  "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {
@@ -8,8 +8,8 @@
8
8
  "gen:openapi": "deno run --allow-net --allow-env --allow-read --allow-write scripts/dump-openapi.ts"
9
9
  },
10
10
  "imports": {
11
- "@daloyjs/core": "npm:@daloyjs/core@^0.5.0",
12
- "@daloyjs/core/": "npm:@daloyjs/core@^0.5.0/",
11
+ "@daloyjs/core": "npm:@daloyjs/core@^0.7.5",
12
+ "@daloyjs/core/": "npm:@daloyjs/core@^0.7.5/",
13
13
  "zod": "npm:zod@^4.4.3"
14
14
  },
15
15
  "compilerOptions": {
@@ -18,7 +18,7 @@
18
18
  "audit": "pnpm audit --prod"
19
19
  },
20
20
  "dependencies": {
21
- "@daloyjs/core": "^0.5.0",
21
+ "@daloyjs/core": "^0.7.5",
22
22
  "zod": "^4.4.3"
23
23
  },
24
24
  "devDependencies": {
@@ -10,7 +10,7 @@
10
10
  "test": "node --import tsx/esm --test tests/**/*.test.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@daloyjs/core": "^0.5.0",
13
+ "@daloyjs/core": "^0.7.5",
14
14
  "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {