@emdash-cms/plugin-forms@0.2.5
25 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
31827e97a6 |
chore(deps-dev): bump the dev-dependencies group across 1 directory with 10 updates (#2142)
Bumps the dev-dependencies group with 10 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@changesets/cli](https://github.com/changesets/changesets) | `2.31.0` | `2.31.1` | | [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) | `0.58.0` | `0.59.0` | | [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) | `1.73.0` | `1.74.0` | | [oxlint-tsgolint](https://github.com/oxc-project/tsgolint) | `0.24.0` | `0.25.0` | | [pkg-pr-new](https://github.com/stackblitz-labs/pkg.pr.new/tree/HEAD/packages/cli) | `0.0.75` | `0.0.78` | | [prettier](https://github.com/prettier/prettier) | `3.9.1` | `3.9.5` | | [@tailwindcss/cli](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-cli) | `4.3.1` | `4.3.3` | | [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright) | `4.1.9` | `4.1.10` | | [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.9` | `4.1.10` | | [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.1` | `4.3.3` | Updates `@changesets/cli` from 2.31.0 to 2.31.1 - [Release notes](https://github.com/changesets/changesets/releases) - [Commits](https://github.com/changesets/changesets/compare/@changesets/cli@2.31.0...@changesets/cli@2.31.1) Updates `oxfmt` from 0.58.0 to 0.59.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxfmt/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxfmt_v0.59.0/npm/oxfmt) Updates `oxlint` from 1.73.0 to 1.74.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.74.0/npm/oxlint) Updates `oxlint-tsgolint` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/oxc-project/tsgolint/releases) - [Commits](https://github.com/oxc-project/tsgolint/compare/v0.24.0...v0.25.0) Updates `pkg-pr-new` from 0.0.75 to 0.0.78 - [Commits](https://github.com/stackblitz-labs/pkg.pr.new/commits/v0.0.78/packages/cli) Updates `prettier` from 3.9.1 to 3.9.5 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.9.1...3.9.5) Updates `@tailwindcss/cli` from 4.3.1 to 4.3.3 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/@tailwindcss-cli) Updates `@vitest/browser-playwright` from 4.1.9 to 4.1.10 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/browser-playwright) Updates `@vitest/ui` from 4.1.9 to 4.1.10 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/ui) Updates `@tailwindcss/vite` from 4.3.1 to 4.3.3 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/@tailwindcss-vite) --- updated-dependencies: - dependency-name: "@changesets/cli" dependency-version: 2.31.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: oxfmt dependency-version: 0.59.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxlint dependency-version: 1.74.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxlint-tsgolint dependency-version: 0.25.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: pkg-pr-new dependency-version: 0.0.78 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: prettier dependency-version: 3.9.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/cli" dependency-version: 4.3.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@vitest/browser-playwright" dependency-version: 4.1.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@vitest/ui" dependency-version: 4.1.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/vite" dependency-version: 4.3.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
b530d4f1ea |
chore(deps): update oxlint 1.73 and oxlint-tsgolint 0.24 (#1919)
Bumps oxlint 1.71.0 to 1.73.0 and oxlint-tsgolint 0.23.0 to 0.24.0. The stricter no-unnecessary-type-assertion rule flagged 82 redundant assertions. Removed them via autofix, dropped the now-dangling no-unsafe-type-assertion disable comments, removed the type-only imports left unused, and added justified no-base-to-string suppressions at the few sites where a removed assertion had been narrowing an unknown scalar for String(). Compile-time only; emitted output is unchanged. |
||
|
|
138bb2faa2 |
chore: bump oxfmt to 0.58.0 and pin CI npx version (#1869)
Runs the format pass with the updated formatter and pins oxfmt in the auto-format and format-command workflows so npx doesn't silently fetch a newer version than what's used locally. |
||
|
|
bb84dda914 |
chore(deps-dev): bump the dev-dependencies group with 8 updates (#1699)
Bumps the dev-dependencies group with 8 updates: | Package | From | To | | --- | --- | --- | | [@axe-core/playwright](https://github.com/dequelabs/axe-core-npm) | `4.11.3` | `4.12.1` | | [@playwright/test](https://github.com/microsoft/playwright) | `1.60.0` | `1.61.1` | | [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) | `0.54.0` | `0.56.0` | | [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) | `1.69.0` | `1.71.0` | | [prettier](https://github.com/prettier/prettier) | `3.8.4` | `3.9.1` | | [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright) | `4.1.8` | `4.1.9` | | [playwright](https://github.com/microsoft/playwright) | `1.60.0` | `1.61.1` | | [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.8` | `4.1.9` | Updates `@axe-core/playwright` from 4.11.3 to 4.12.1 - [Release notes](https://github.com/dequelabs/axe-core-npm/releases) - [Changelog](https://github.com/dequelabs/axe-core-npm/blob/develop/CHANGELOG.md) - [Commits](https://github.com/dequelabs/axe-core-npm/commits) Updates `@playwright/test` from 1.60.0 to 1.61.1 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.60.0...v1.61.1) Updates `oxfmt` from 0.54.0 to 0.56.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxfmt/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxfmt_v0.56.0/npm/oxfmt) Updates `oxlint` from 1.69.0 to 1.71.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.71.0/npm/oxlint) Updates `prettier` from 3.8.4 to 3.9.1 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.8.4...3.9.1) Updates `@vitest/browser-playwright` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/browser-playwright) Updates `playwright` from 1.60.0 to 1.61.1 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.60.0...v1.61.1) Updates `@vitest/ui` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/ui) --- updated-dependencies: - dependency-name: "@axe-core/playwright" dependency-version: 4.12.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@playwright/test" dependency-version: 1.61.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxfmt dependency-version: 0.56.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxlint dependency-version: 1.71.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: prettier dependency-version: 3.9.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitest/browser-playwright" dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: playwright dependency-version: 1.61.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitest/ui" dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
5b6c542c78 | Upgrade pnpm | ||
|
|
82c7352a5b |
chore(deps-dev): bump the dev-dependencies group with 4 updates (#1529)
Bumps the dev-dependencies group with 4 updates: [@e18e/eslint-plugin](https://github.com/e18e/eslint-plugin), [prettier](https://github.com/prettier/prettier), [@tailwindcss/cli](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-cli) and [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite). Updates `@e18e/eslint-plugin` from 0.5.0 to 0.5.1 - [Release notes](https://github.com/e18e/eslint-plugin/releases) - [Commits](https://github.com/e18e/eslint-plugin/compare/0.5.0...0.5.1) Updates `prettier` from 3.8.3 to 3.8.4 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.8.3...3.8.4) Updates `@tailwindcss/cli` from 4.3.0 to 4.3.1 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/@tailwindcss-cli) Updates `@tailwindcss/vite` from 4.3.0 to 4.3.1 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/@tailwindcss-vite) --- updated-dependencies: - dependency-name: "@e18e/eslint-plugin" dependency-version: 0.5.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: prettier dependency-version: 3.8.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/cli" dependency-version: 4.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/vite" dependency-version: 4.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
74bc6ee5d8 |
chore(deps-dev): bump the dev-dependencies group across 1 directory with 6 updates (#1412)
Bumps the dev-dependencies group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) | `0.52.0` | `0.54.0` | | [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) | `1.67.0` | `1.69.0` | | [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography) | `0.5.19` | `0.5.20` | | [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright) | `4.1.7` | `4.1.8` | | [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.7` | `4.1.8` | | [@flue/cli](https://github.com/withastro/flue/tree/HEAD/packages/cli) | `0.8.1` | `0.10.0` | Updates `oxfmt` from 0.52.0 to 0.54.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxfmt/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxfmt_v0.54.0/npm/oxfmt) Updates `oxlint` from 1.67.0 to 1.69.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.69.0/npm/oxlint) Updates `@tailwindcss/typography` from 0.5.19 to 0.5.20 - [Release notes](https://github.com/tailwindlabs/tailwindcss-typography/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss-typography/compare/v0.5.19...v0.5.20) Updates `@vitest/browser-playwright` from 4.1.7 to 4.1.8 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/browser-playwright) Updates `@vitest/ui` from 4.1.7 to 4.1.8 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/ui) Updates `@flue/cli` from 0.8.1 to 0.10.0 - [Changelog](https://github.com/withastro/flue/blob/main/CHANGELOG.md) - [Commits](https://github.com/withastro/flue/commits/v0.10.0/packages/cli) --- updated-dependencies: - dependency-name: oxfmt dependency-version: 0.54.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxlint dependency-version: 1.69.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@tailwindcss/typography" dependency-version: 0.5.20 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@vitest/browser-playwright" dependency-version: 4.1.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@vitest/ui" dependency-version: 4.1.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@flue/cli" dependency-version: 0.10.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
7a66d39631 |
chore(deps-dev): bump the dev-dependencies group across 1 directory with 15 updates (#1265)
Bumps the dev-dependencies group with 15 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@axe-core/playwright](https://github.com/dequelabs/axe-core-npm) | `4.11.1` | `4.11.3` | | [@changesets/changelog-github](https://github.com/changesets/changesets) | `0.5.2` | `0.7.0` | | [@changesets/cli](https://github.com/changesets/changesets) | `2.29.8` | `2.31.0` | | [@e18e/eslint-plugin](https://github.com/e18e/eslint-plugin) | `0.2.0` | `0.5.0` | | [@playwright/test](https://github.com/microsoft/playwright) | `1.58.0` | `1.60.0` | | [oxfmt](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt) | `0.34.0` | `0.52.0` | | [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) | `1.66.0` | `1.67.0` | | [prettier](https://github.com/prettier/prettier) | `3.8.1` | `3.8.3` | | [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.29.0` | `7.29.7` | | [@tailwindcss/cli](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-cli) | `4.1.18` | `4.3.0` | | [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright) | `4.1.5` | `4.1.7` | | [playwright](https://github.com/microsoft/playwright) | `1.58.2` | `1.60.0` | | [vitest-browser-react](https://github.com/vitest-community/vitest-browser-react) | `2.0.5` | `2.2.0` | | [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.5` | `4.1.7` | | [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.2.1` | `4.3.0` | Updates `@axe-core/playwright` from 4.11.1 to 4.11.3 - [Release notes](https://github.com/dequelabs/axe-core-npm/releases) - [Changelog](https://github.com/dequelabs/axe-core-npm/blob/develop/CHANGELOG.md) - [Commits](https://github.com/dequelabs/axe-core-npm/compare/v4.11.1...v4.11.3) Updates `@changesets/changelog-github` from 0.5.2 to 0.7.0 - [Release notes](https://github.com/changesets/changesets/releases) - [Commits](https://github.com/changesets/changesets/compare/@changesets/read@0.5.2...@changesets/changelog-github@0.7.0) Updates `@changesets/cli` from 2.29.8 to 2.31.0 - [Release notes](https://github.com/changesets/changesets/releases) - [Commits](https://github.com/changesets/changesets/commits/@changesets/cli@2.31.0) Updates `@e18e/eslint-plugin` from 0.2.0 to 0.5.0 - [Release notes](https://github.com/e18e/eslint-plugin/releases) - [Commits](https://github.com/e18e/eslint-plugin/compare/0.2.0...0.5.0) Updates `@playwright/test` from 1.58.0 to 1.60.0 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.58.0...v1.60.0) Updates `oxfmt` from 0.34.0 to 0.52.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxfmt/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxfmt_v0.52.0/npm/oxfmt) Updates `oxlint` from 1.66.0 to 1.67.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.67.0/npm/oxlint) Updates `prettier` from 3.8.1 to 3.8.3 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.8.1...3.8.3) Updates `@babel/core` from 7.29.0 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-core) Updates `@tailwindcss/cli` from 4.1.18 to 4.3.0 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.0/packages/@tailwindcss-cli) Updates `@vitest/browser-playwright` from 4.1.5 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/browser-playwright) Updates `playwright` from 1.58.2 to 1.60.0 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.58.2...v1.60.0) Updates `vitest-browser-react` from 2.0.5 to 2.2.0 - [Release notes](https://github.com/vitest-community/vitest-browser-react/releases) - [Commits](https://github.com/vitest-community/vitest-browser-react/compare/v2.0.5...v2.2.0) Updates `@vitest/ui` from 4.1.5 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/ui) Updates `@tailwindcss/vite` from 4.2.1 to 4.3.0 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.0/packages/@tailwindcss-vite) --- updated-dependencies: - dependency-name: "@axe-core/playwright" dependency-version: 4.11.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@changesets/changelog-github" dependency-version: 0.7.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@changesets/cli" dependency-version: 2.31.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@e18e/eslint-plugin" dependency-version: 0.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@playwright/test" dependency-version: 1.60.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxfmt dependency-version: 0.52.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: oxlint dependency-version: 1.67.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: prettier dependency-version: 3.8.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@babel/core" dependency-version: 7.29.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/cli" dependency-version: 4.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitest/browser-playwright" dependency-version: 4.1.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: playwright dependency-version: 1.60.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: vitest-browser-react dependency-version: 2.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitest/ui" dependency-version: 4.1.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@tailwindcss/vite" dependency-version: 4.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
d4e306c69a |
Investigate-bot fix gate, preview self-consistency, and bot identity fixes (#1259)
* ci: publish all public packages as previews and pin pkg-pr-new Derive the pkg.pr.new publish set from globs (./packages/*, ./packages/plugins/*) instead of a hardcoded list. pkg.pr.new skips private packages, so the test fixtures are excluded automatically while every public package, including the previously missing registry-client, plugin-types and auth-atproto, now gets a preview. This keeps preview installs self-consistent: emdash's preview references sibling packages via workspace:*, and pkg.pr.new can only rewrite those to matching preview URLs when the siblings are published in the same run. Omitting one made the dep fall back to npm's released version, which broke when source had drifted (e.g. registry-client's ./env export added without a release). Also pin pkg-pr-new as a root devDependency and run it via pnpm exec rather than pnpm dlx, per the tool's CI guidance. * fix(ci): correct investigate-bot identity and split triage labels Two orchestrator-workflow fixes: - Commit identity was emdash-bot[bot] / bot@emdashcms.com, but the GitHub App slug is emdashbot. Use emdashbot[bot] and the users.noreply.github.com attribution email, matching every other workflow. This also makes the github.actor guards in auto-format and auto-extract match the bot's own commits. - intended-behavior outcomes now get a new triage/by-design label instead of sharing triage/reproduced with confirmed bugs. The two need opposite follow-up (likely close vs. needs a fix), so they should not share a label. * feat(flue): broaden investigate-bot fix gate, run fix on a cheaper model The fix stage only ran at verify=bug AND diagnose.confidence=high, where high meant 'mechanical, one-line, no ambiguity'. That conflated two independent questions: is the root cause certain, and is the fix obvious? Real, fixable bugs (e.g. #1178, #1199) were parked at triage/reproduced because one clearly-correct fix existed among several shapes, which forced a medium rating. Decouple the axes: - confidence now rates root-cause certainty only. - a new fixApproach (mechanical | clear-best-option | needs-design-decision) rates fix clarity. - the gate becomes verdict=bug AND confidence!=low AND fixApproach!=needs-design-decision. Diagnose also now emits a concrete proposedFix (always), which feeds the fix stage as its spec and doubles as the maintainer's starting point when the fix is deferred. The fix stage runs on a separate, cheaper agent (kimi-k2.6) in its own session: the reasoning is already done, so it is guided implementation. It shares the on-disk checkout, so staged edits still reach the orchestrator. Configurable via FLUE_FIX_MODEL. Reframe the skill cost model: the output is a reporter-verified candidate branch a maintainer reviews, not a merge, so a clear, test-backed fix is worth attempting even when it is more than a one-liner. Update diagnose/verify/fix skills, _INVESTIGATE.md and README; delete the stale PLAN.md. * fix(ci): wire triage/by-design into label cleanup and project sync Addresses review on #1259. The new triage/by-design label was missing from two places: - investigate.yml's reproducing-transition cleanup loop, so a re-triggered by-design issue could carry triage/by-design alongside triage/reproducing. - triage-project-sync.yml's STATE_BY_LABEL/PRECEDENCE, so by-design issues resolved to no state and stopped syncing to the board. Maps triage/by-design -> 'By design' board option (terminal verdict, ranked just below reproduced in precedence). The 'By design' single- select option must be added to Project #3's 'Triage State' field; until then the sync warns-and-skips rather than failing. |
||
|
|
20c87fe924 |
chore: gate lint warnings in CI, clear the existing pile (#1147)
* fix(workerd): clear all lint warnings and tsgo errors - Replace untyped `as T` casts in bridge dispatch with predicate-backed `require*`/`optional*` helpers - Introduce `asContentDb()` for dynamic ec_* tables (single justified narrowing) - Drop unnecessary `as keyof Database` casts for tables already in the static schema - Validate marshaled RequestInit at the http/fetch boundary - Typed HttpError class in backing-service for status-bearing errors - getPluginStorageConfig now returns the real PluginStorageConfig shape - WorkerdSandboxedPlugin implements SandboxedPluginInstance (the previous SandboxedPlugin symbol did not exist) - Add typecheck script so the package participates in pnpm typecheck No runtime behaviour changes. * chore: bump oxlint and update disable-comment format Upgrade oxlint (1.49 -> 1.66) and oxlint-tsgolint (0.15 -> 0.23). The newer oxlint renamed the unused unicorn/prevent-abbreviations rule and switched the canonical typescript-eslint plugin name to typescript, which changes how inline disable comments are written. Mechanical rename: `typescript-eslint(rule-name)` -> `typescript/rule-name` in all eslint-disable comments. Without this, ~120 disable comments stopped suppressing the rules they were meant to. Also drops unicorn/prevent-abbreviations from .oxlintrc.json (no longer a valid rule). * ci: gate lint warnings so they cannot regress `pnpm lint` now passes `--deny-warnings` to oxlint, so any warning is a non-zero exit. CI inherits this through the existing lint job. The blocker was the existing pile of warnings, so this commit also clears them: - `packages/core/src/astro/middleware.ts`: collapse duplicated `virtualSandboxRunnerModule as Record<...>` casts behind one local binding inside a block-form disable, and convert the remaining parenthesis-form disables that newer oxlint stopped recognising. - `packages/core/src/astro/middleware/auth.ts` and 14 API route files: drop unnecessary `emdash!` non-null assertions; the preceding `requireDb(emdash?.db)` guard already narrows. - `packages/core/src/emdash-runtime.ts`: drop unnecessary `as ResolvedPlugin[]` and `emdash!` casts; annotate the two remaining trusted dynamic-import sites with a single disable line. - `packages/plugin-cli/src/build/pipeline.ts`: replace the chain of `as Record<string, unknown>` casts with `isRecord` / `isStringArray` predicate narrowing. - `packages/cloudflare/src/sandbox/bridge.ts`: drop the `this.env.DB as D1Database` cast (already that type). - `packages/core/src/client/index.ts`, `packages/core/src/astro/integration/index.ts`, `packages/registry-client/src/credentials/index.ts`: remove three unused imports. Newer oxlint flagged config-level issues too: - `packages/workerd/tsconfig.json`: add explicit `rootDir`. - `packages/contentful-to-portable-text/tsconfig.json`: drop the `rootDir` that excluded `test/**/*` from `include`. - `packages/core/src/page/absolute-url.ts`: fix the disable comment rule name so `no-control-regex` is suppressed (the regex intentionally matches control chars). - `lunaria.config.ts`: convert block-form disable to next-line form with the new rule path. Finally, four newer rules are disabled at the repo level: `no-underscore-dangle` (Portable Text uses `_type`/`_key` by spec), `typescript/consistent-return`, `typescript/no-unnecessary-type-conversion`, `typescript/no-unnecessary-type-parameters`, and `typescript/no-useless-default-assignment` (the rule errors out under `strict: false`, which the test plugins use deliberately). These can be re-enabled in follow-up PRs once their hits are triaged. |
||
|
|
792f73c12c |
chore: bump pnpm to 11.1.3 and pin scaffolded sites to a recent pnpm (#1115)
- Bump root packageManager via `corepack use pnpm@latest`. - Sync script bakes the root's packageManager into each template's package.json, so scaffolded sites auto-track the monorepo pin. - create-emdash strips packageManager when the user picks npm/yarn/bun so corepack doesn't force pnpm on a non-pnpm user. - Drop dead `pnpm.onlyBuiltDependencies` from demo/fixture/template package.json files; pnpm 11 ignores `package.json#pnpm` and the root `allowBuilds` already covers these binaries. - AGENTS.md / auto-implementer.md: drop `--silent` from lint commands; pnpm 11 prints the `$ command` line to stderr, so JSON pipes cleanly without it. |
||
|
|
74a9078b00 |
ci(release): reconcile lockfile before gated changeset commands (#1104)
* ci(release): reconcile lockfile before gated changeset commands verifyDepsBeforeRun: error gates pnpm run/exec. The frozen install in the release job does not refresh the lockfile's overrides hash, so a lockfile whose overrides drifted from pnpm-workspace.yaml passes the frozen install but trips the gate on `pnpm run changeset:version` / `pnpm changeset publish`, killing every release before it versions or publishes. A non-frozen install is not gated and reconciles the hash; changesets/action commits the result, self-healing the repo. * ci(release): reconcile lockfile inside the changeset command, not as a prior step changesets/action does git checkout changeset-release/main + git reset --hard right before running the version/publish command, so any reconcile placed in an earlier workflow step is discarded by that reset and the gated 'pnpm changeset' call still trips verifyDepsBeforeRun. Move the non-frozen install into a single non-gated node entrypoint the action invokes, so it runs after the action's git work and immediately before the gated pnpm call. Drop the now-unreferenced changeset:version script. * style: format * ci(release): use --prefer-frozen-lockfile for the reconcile changeset publish rebuilds packages via prepublishOnly at pack time. A non-frozen reconcile could re-resolve in-range transitive deps so shipped bits diverge from tested bits. prefer-frozen reconciles the deps state to satisfy verifyDepsBeforeRun without re-resolving when the lockfile is satisfiable, and falls back to a full install (e.g. after changeset version bumps workspace versions) when it isn't. * ci(release): revert reconcile to --no-frozen-lockfile The PR's purpose is to reliably clear ERR_PNPM_VERIFY_DEPS_BEFORE_RUN. --no-frozen-lockfile is pnpm's documented remediation and unconditionally refreshes the deps-state hash. --prefer-frozen-lockfile's fast path is gated by a satisfiability check that may not include the settings hash, so it could skip the rewrite in exactly the stale-metadata case this fixes. The shipped-vs-tested concern that motivated prefer-frozen is low-probability, pre-existing, and negligible when the lockfile is satisfiable (no re-resolution occurs). --------- Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com> |
||
|
|
c0ce915c55 |
feat(plugin-cli): sandboxed plugin authoring CLI (#1057)
* feat(registry-cli): extend manifest schema with identity + trust contract
First phase of the sandboxed plugin redesign (#1028b). Adds the
manifest fields that make `src/index.ts` and the in-code descriptor
factory redundant. The trust contract is now hand-authored in the
manifest, where a security reviewer can find it without grep.
New required fields:
- `slug`: ASCII letter then letters/digits/hyphens/underscores, max 64
chars. Matches the registry lexicon's rkey grammar via the shared
PLUGIN_SLUG_RE in @emdash-cms/plugin-types.
- `version`: semver 2.0 subset, no build-metadata (atproto rkeys can't
contain `+`). Validated via PLUGIN_VERSION_RE.
- `publisher`: now required (was optional in #1028a). The runtime
cannot compute the plugin's AT URI without it; making it optional
meant the plugin couldn't load locally before first publish.
New optional fields with sensible defaults:
- `capabilities`: array of capability strings. Defaults to []. Each
entry validated against the current vocabulary; deprecated names are
hard-rejected with a hint at the replacement (no deprecation window
for new authoring).
- `allowedHosts`: array of host patterns. Defaults to []. Required
non-empty when `network:request` is declared without
`:unrestricted`. Forbidden when `:unrestricted` is declared.
- `storage`: map of collection name -> { indexes, uniqueIndexes? }.
Defaults to {}.
The cross-field rule for network:request / allowedHosts mirrors the
release-extension lexicon's networkRequestConstraints behaviour, so
authors hit the schema error here rather than a PDS validation error
at publish time.
Schema regenerated. 33 new tests; 204 total passing.
Part of #1028b. The bundle rewrite, init command, plugin migrations,
and `localPlugin` dev helper land in subsequent commits.
* feat(registry-cli): bundle reads identity + trust contract from manifest
Second phase of the sandboxed plugin redesign (#1028b). Bundle no longer
imports src/index.ts for a descriptor factory; the manifest is the
source of truth for identity (slug, version) and the trust contract
(capabilities, allowedHosts, storage). Bundle still probes the runtime
code for the hook/route surface — that's a syntactic property that
needs the code to exist.
Changes to bundle:
- Drop the main-entry build and descriptor extraction. No more
src/index.ts probing, no more `createPlugin` / default-factory /
default-object format detection.
- Replace `resolveEntries`: just locates emdash-plugin.jsonc (loaded
through the same loader the CLI's validate uses) and confirms
src/plugin.ts exists. No more package.json `exports` parsing.
- Replace `extractResolvedPlugin` with `assembleResolvedPlugin`: builds
the ResolvedPlugin shape from the manifest, then probes
src/plugin.ts for hook/route names.
- Probe (renamed from `augmentWithSandboxProbe` to `probePluginSurface`)
now reads src/plugin.ts. Hard-fails if the default export isn't a
definePlugin result.
- New error codes: MISSING_MANIFEST, MISSING_PLUGIN_ENTRY,
MANIFEST_INVALID. Old MISSING_PACKAGE_JSON / MISSING_ENTRYPOINT /
MAIN_BUILD_FAILED gone.
- Admin entry handling (admin.js, adminPages, adminWidgets) deferred
to a follow-up issue. The redesign hasn't touched admin yet; that
surface stays as-is and is gated on the descriptor's `admin` field
which no longer exists. When admin lands again it'll be a manifest
field with its own probe.
Changes to translate.ts:
- `NormalisedManifest` gains slug, version, publisher (required),
capabilities, allowedHosts, storage. Publisher is no longer
Optional — the schema enforces it.
Fixtures:
- `minimal-plugin/`: src/index.ts gone, sandbox-entry.ts renamed to
plugin.ts, new emdash-plugin.jsonc with identity + trust contract.
- `bad-plugin/`: stripped to manifest-only (no src/), exercises
MISSING_PLUGIN_ENTRY. Old "declares hooks but no sandbox entry"
case isn't possible anymore — there's no descriptor declaring
anything.
Net diff: -228 lines.
* feat(registry-cli): init command scaffolds a sandboxed plugin
Third phase of the redesign (#1028b). Adds `emdash-registry init [name]`
which produces the three-file plugin layout introduced by the previous
commits: emdash-plugin.jsonc, src/plugin.ts, package.json, plus a
tsconfig, README, .gitignore, and a passing test.
Modes:
- Interactive (default on a TTY): clack prompts for each unset field
with sensible defaults. ESC / Ctrl+C cancels cleanly.
- `--yes` / `-y` (non-interactive): no prompts; unset fields become
TODO placeholders in the manifest. The author fixes them before
first use.
- Non-TTY (CI, pipes): same as `--yes`; prompting into a non-
interactive stdin would hang.
Pre-fills:
- Publisher: the active session's handle from FileCredentialStore.
Resolved through @atcute/identity-resolver to a DID before write
so the runtime never sees a mutable handle. The handle is emitted
as a `// <handle>` line comment next to the pinned DID for `git
diff` readability — same convention as the post-publish write-back.
- Author name / email: `git config user.name` / `user.email`.
- Repo: `git remote get-url origin`, normalised from SSH to https
(`git@github.com:foo/bar.git` → `https://github.com/foo/bar`).
Falls back to `package.json#repository.url` if no git remote.
- License, description: `package.json` in the target dir if one
exists (for the "scaffold into existing repo skeleton" case).
Slug defaults to the positional `name`, `basename(--dir)`, or
basename(cwd) in that order. Every flag is optional in every mode.
Exported `resolveHandleToDid` from manifest/publisher.ts so init
can use the same resolver the post-publish write-back does.
Tests: 44 new (template renderers, scaffold filesystem behaviour,
environment probe). 249 total in the package.
* feat(plugins): migrate in-tree sandboxed plugins to the new layout
Fourth phase of the redesign (#1028b). Moves the 5 in-tree sandboxed
plugins to the manifest + src/plugin.ts shape so they become the
canonical references a plugin author looks at.
Each plugin's layout changes from:
src/index.ts (descriptor factory, ~50 lines)
src/sandbox-entry.ts (runtime code via definePlugin)
package.json (main / exports / files / build scripts)
to:
emdash-plugin.jsonc (identity + trust contract + admin surface)
src/plugin.ts (runtime code, unchanged)
package.json (private, typecheck script only)
Plugins migrated:
- atproto
- audit-log
- marketplace-test
- sandboxed-test
- webhook-notifier
Schema gains `admin` (pages + widgets) since four of the five plugins
declare admin surface. Mirrors PluginAdminPage / PluginDashboardWidget
in core. Atproto's plugin.test.ts rewritten to assert against the
manifest instead of the deleted descriptor factory.
KNOWN BREAKAGE: demos that import the old factories
(`auditLogPlugin()`, `webhookNotifierPlugin()`) from
astro.config.mjs are broken until the next commit ships
`@emdash-cms/registry-cli/dev`'s `localPlugin(dir)` helper and
updates the demos.
All published plugins still work — the bundled manifest.json shape
is unchanged. Only authoring changed.
* feat(registry-cli): add localPlugin(dir) dev helper + wire demos
Final piece of the sandboxed-plugin redesign (#1028b). Closes the gap
the plugin migrations opened — demos that previously imported
`auditLogPlugin()` / `webhookNotifierPlugin()` factories now consume
the plugins through their source directories.
New subpath `@emdash-cms/registry-cli/dev` exports `localPlugin(dir)`,
which:
- Reads `<dir>/emdash-plugin.jsonc` via the same loader the CLI uses.
- Confirms `<dir>/src/plugin.ts` exists.
- Resolves the manifest's publisher (handle → DID) so the descriptor
is in canonical form.
- Returns a PluginDescriptor-shaped object with `entrypoint` set to
the absolute `file://` URL of `src/plugin.ts`. Vite resolves the
URL through its standard fs path resolver — no build step needed.
The descriptor carries id, version, capabilities, allowedHosts,
storage, and (when declared) adminPages + adminWidgets from the
manifest. Plugins that don't expose admin surface pass through
without the optional fields, keeping the descriptor tidy.
Demos updated:
- demos/simple: auditLogPlugin() → localPlugin("../../packages/plugins/audit-log")
- demos/plugins-demo: auditLog + webhookNotifier the same way
- demos/cloudflare: webhookNotifier via localPlugin
- infra/cache-demo, infra/blog-demo: same
Trusted plugins (formsPlugin, embedsPlugin, apiTestPlugin) keep their
factory-based imports — they're not on the new shape and aren't part
of this redesign's scope.
Errors surface as a structured LocalPluginError with codes:
- MANIFEST_INVALID
- PLUGIN_ENTRY_MISSING
- PUBLISHER_UNRESOLVED
Tests: 10 new (descriptor shape, error paths, admin pass-through).
259 total in the package.
* feat(plugin-cli): rework sandboxed plugin authoring, build, and CLI
Renames @emdash-cms/registry-cli to @emdash-cms/plugin-cli and the
binary emdash-registry to emdash-plugin. Adds build + dev commands,
consolidates the build pipeline so bundle is a thin packaging step on
top of build. Introduces a strict author-facing SandboxedPlugin type
via the new emdash/plugin type-only subpath; sandboxed plugins now
default-export a bare { hooks?, routes? } object with satisfies
SandboxedPlugin and have no runtime emdash import. Drops definePlugin
and the build shim for sandboxed plugins (definePlugin is native-only
now). Migrates the five in-tree sandboxed plugins to the new shape.
Manifest version is optional and reconciled with package.json#version.
* fix(plugin-cli): adversarial review fixes
- init scaffold emits the new `satisfies SandboxedPlugin` shape and
npm-shape package.json (build/dev scripts, ./sandbox export, plugin-cli
devDep) instead of the broken `definePlugin` template
- publish reads package.json#version and reconciles via normaliseManifest
so the new "version in package.json only" pattern actually publishes;
malformed package.json surfaces a CliError, not a misleading
VERSION_MISSING further down
- dev watcher serialises rebuilds (queue collapsed to one follow-up),
closes the watcher before draining pending on Ctrl-C, short-circuits
scheduleRebuild during shutdown, handles Windows path separators in
the outDir ignore glob, clears pending+queuedTrigger in finally so an
IIFE rejection can't deadlock the session, and removes SIGINT handlers
on shutdown
- adapter normalises ctx.request to SandboxedRequest shape in-process
so handlers see the same { url, method, headers: Record } promised by
the strict type; null/array/non-object default exports rejected with
a plugin-id-bearing message
- build's readPackageMeta rejects empty/non-string version with the
same strictness as publish, killing the build-pass/publish-fail
asymmetry
- pipeline probe rejects invalid hook config (errorPolicy, priority,
timeout) so untyped JS authors get a build error rather than a
silently-wrong runtime contract
- versionless minimal-plugin fixture so bundle/publish/build integration
tests exercise the package.json-as-source-of-truth path
- definePlugin error wording softened for native-plugin authors whose
id field has a typo
- pipeline error messages and stale comments updated for the no-shim,
no-definePlugin authoring shape
- removed dead EMDASH_SHIM from the Cloudflare sandbox runner
- changesets retargeted to @emdash-cms/plugin-cli; scaffold/atproto/core
comments scrubbed for stale registry-cli references
* style: format
* docs(changesets): switch plugin migration examples to diff fences
* style: format
* Fix changeset ordering
* fix(ci): plugin build uses node-direct path; sweep stale registry-cli refs
In-workspace plugins use `node node_modules/@emdash-cms/plugin-cli/dist/index.mjs build`
because pnpm doesn't create the bin shim for a workspace package whose
bin target doesn't exist at install time. Plugin authors outside the
workspace get a published bin with a real dist, so `emdash-plugin build`
works for them via the natural scaffold.
Also fixes stale registry-cli references the rename pass missed:
- .oxfmtrc.json: schema ignore path
- .oxlintrc.json: 7 type-aware-cost allowlist entries
- .github/workflows/ci.yml: build filter includes plugin-cli for test:unit
- package.json: test:unit script
- packages/plugin-types/package.json: description
The schema file is regenerated to match what gen-schema produces. The
previously committed version had been hand-reformatted post-regen and
disagreed with the generator's output.
* fix(ci): remove legacy marketplace bundle path; address review findings
- Delete `packages/marketplace/tests/publish-e2e.test.ts` — invoked the
legacy `emdash plugin bundle` from core CLI against the new
manifest-driven plugin layout, which it doesn't understand.
- Remove the validate-plugins CI job — it used the same legacy CLI
command. Plugin validation is now covered by `pnpm build`, which
runs the new `emdash-plugin build` probe + manifest checks against
every in-tree sandboxed plugin.
- Fix `no-base-to-string` lint errors in audit-log/plugin.ts. The
canonical ContentHookEvent types `event.content.id` as unknown;
`String(unknown)` lands on '[object Object]' for record IDs. Added
a small `stringifyId` helper that returns '' for non-string/number
inputs so the caller's existence check skips bad rows.
- pipeline.ts now hard-errors when the probed module has no `default`
export, instead of silently falling through to an empty plugin
(build had been writing dist/ artifacts with empty hooks/routes for
any source that used `export const plugin = ...`).
- Scaffold README camelCases hyphenated slugs for the import binding.
Slugs like `my-plugin` were producing `import my-plugin from ...`
which is a syntax error. Test added with a hyphenated fixture.
Both bot review comments addressed.
* style: format
* fix(plugin-cli): bump test timeout to 30s for bundle tests on slow CI
bundle.test.ts > 'produces a tarball + manifest for a minimal valid
plugin' timed out at the 5s default on the GitHub-hosted runner.
The test runs the full build pipeline (tsdown probe + transpile +
tarball pack), which is fast locally (<2s) but cold-starts at 5-8s
on CI. Bump to 30s globally for the plugin-cli vitest config.
* chore: update lockfile
---------
Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ascorbic <213306+ascorbic@users.noreply.github.com>
Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
|
||
|
|
5051274bf0 |
chore: harden pnpm supply-chain config (#1068)
* chore: harden pnpm supply-chain config Pin pnpm (packageManager: pnpm@11.1.2) so the build-script/trust schema is deterministic, and add supply-chain hardening to pnpm-workspace.yaml: - minimumReleaseAge 1440 (24h publish cooldown); @rolldown/* and @emnapi/* excluded (vite8/rolldown-rc exact-pins these per-arch binaries; their release cadence structurally conflicts with the cooldown and they are not an attack surface worth the friction) - strictDepBuilds + explicit allowBuilds: build scripts run only for @parcel/watcher, sharp, better-sqlite3, esbuild, workerd; core-js-pure denied (donation postinstall, not needed) - dangerouslyAllowAllBuilds false - blockExoticSubdeps true, with an @astrojs/telemetry -> 3.3.0 override (infra/cache-demo's pkg.pr.new Astro cache-support preview pulls telemetry via URL; the override keeps the guard on) - trustPolicy no-downgrade with a reviewed, version-pinned trustPolicyExclude (vite@6.4.1, chokidar@4.0.3, semver@6.3.1, @portabletext/toolkit@3.0.3, reselect@5.1.1 -- all benign publish-method changes / old pre-provenance pins, not takeovers) - verifyStoreIntegrity, strictStorePkgContentCheck, verifyDepsBeforeRun error Move enable-pre-post-scripts from .npmrc to pnpm-workspace.yaml (enablePrePostScripts: true; canonical location, also silences the npm "unknown config" warning). Remove .npmrc entirely -- provenance is implied by OIDC trusted publishing. Lockfile regenerated under the hardened config with pnpm 11.1.2. * chore: address Copilot review on supply-chain hardening - Remove stale root pnpm.onlyBuiltDependencies (dead under pinned pnpm 11; allowBuilds in pnpm-workspace.yaml is the single source) - Narrow cooldown excludes: @rolldown/* -> @rolldown/binding-*, and @emnapi/* -> @emnapi/core/@emnapi/runtime, so the cooldown stays active for JS like @rolldown/pluginutils / @emnapi/wasi-threads - Drop the dangling CONTRIBUTING.md pointer (no such policy doc) - Override @ungap/structured-clone to ^1.3.1 (1.3.0 deprecated, CWE-502) - Regenerate the lockfile from a clean store so the astro pkg.pr.new tarball regains its SRI integrity (the earlier warm-store regen dropped it; @astrojs/cloudflare and @lunariajs/core never had SRI, pre-PR included -- pnpm doesn't record it for those URLs) Re-resolved clean under pnpm 11.1.2 with the narrowed excludes. * fix: resolve #1053 type errors for strict consumers (#1076) * fix: resolve #1053 type errors for strict consumers Closes #1053. Two parts: 1. wordpress-plugin.ts: the analyze-endpoint error body from response.json() is unknown under @cloudflare/workers-types; narrow it before reading .message (was the reported TS18046). The other reported error (byline.ts kysely Transaction variance) was TS5.x behaviour, resolved by the TS6 upgrade in #1074. 2. Stop shipping raw .ts for the source-exported subpaths (emdash/routes/*, emdash/api/route-utils, emdash/api/schemas, emdash/auth/providers/*). They are compiled to dist (.mjs + .d.mts), so a strict consumer's tsc only ever sees declarations (skipLibCheck covers them), eliminating the dual-package Database identity wall that is #1053's root cause. ./ui and .astro stay source (the consumer's Astro build must process them). - tsdown: route entrypoints fed via inputOptions.input (literal object, not entry globs -- [param] dirs are glob char-classes). entryFileNames + resolveRoute share one routeArtifactName() so rolldown's reserved [name]/[hash] placeholders cannot mangle dynamic-route artifacts. - A fast static guard (scripts/typecheck-public-source.mjs, wired into CI) fails if any subpath export ships raw .ts/.tsx again. Verified: pnpm build, pnpm typecheck, demos+templates typecheck, demo build (route injection e2e), lint baseline unchanged. * style: format * fix(build): externalize self/optional deps so route entries don't bundle them Compiling the route/admin entries made tsdown try to bundle deps it could not resolve at build time -- 'emdash' (the package importing itself) and '@cloudflare/kumo' (admin-only, not an emdash dep). CI escalates tsdown's bundling advisory to a fatal error. - Externalize 'emdash' (self): compiled routes import it; resolved at the consumer's runtime where the package is installed. - Externalize @aws-sdk/* (optional S3 deps, runtime-only). - Keep the *-admin.tsx providers as source (bridge the admin React + @cloudflare/kumo runtime, like .astro/./ui); revert their exports. - inlineOnly: false -- nothing is unintentionally bundled (all deps external, only our own src is); silences the CI-escalated advisory. Guard's allowlist generalized to RUNTIME_COUPLED (Astro + admin React). * test: route-injection entrypoint now resolves to compiled artifact resolveRoute resolves emdash/routes/* to the compiled dist artifact with routeArtifactName applied ([ ] -> _), so the media catch-all route's entrypoint is api/media/file/_...key_ not [...key].ts. The catch-all pattern assertion (the actual guarantee) is unchanged. --------- Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com> --------- Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com> |
||
|
|
ed917d9d53 |
chore: upgrade to TypeScript 6, pin tsgo beta, fix dual-load config (#1074)
- catalog typescript ^5.9.3 -> ^6.0.3 (current stable) - pin @typescript/native-preview to 7.0.0-dev.20260421.2 (beta) to stop silent compiler drift from the floating ^7.0.0-dev range - runtime.ts: key stored config on a Symbol.for registry entry instead of a typed globalThis var, removing the TS2403 dual-load (dist+src) error and matching the existing isolate-singleton pattern - auth/create-emdash: add explicit types:[node]; the catalog bump's lockfile re-resolution stopped implicit @types/node auto-inclusion |
||
|
|
06d5f3f016 | fix(forms): unwrap public definition responses (#983) | ||
|
|
943df46d62 |
feat: plugin registry packages (lexicons, client, CLI) (#923)
* feat(registry-lexicons): scaffold @emdash-cms/registry-lexicons package
Adds a new package that generates TypeScript types and runtime validation
schemas from the EmDash plugin registry lexicons under
com.emdashcms.experimental.*. First package on the implementation path for
RFC 0001 (Decentralized Plugin Registry).
The lexicons themselves still live on the wip/plugin-rfc branch; they are
copied into the package at build time so the published artifact ships them.
Codegen via @atcute/lex-cli (matches the rest of the codebase, which uses
@atcute/* rather than @atproto/*). The single external lexicon ref to
com.atproto.label.defs#label resolves through @atcute/atproto.
Generated output is checked into src/generated/ so consumers do not need
the codegen toolchain. The public API exposes namespace re-exports
(PackageProfile, PackageRelease, AggregatorSearchPackages, ...), an NSID
constant map, and module augmentation of @atcute/lexicons/ambient so
@atcute/client callers get strong typing on these records and XRPC methods
automatically.
Tests build representative records, validate them via the generated runtime
schemas, and assert NSID-map completeness, catching codegen drift,
schema/type drift, and NSID typos.
oxlint: ignores **/src/generated/** (codegen output uses side-effect imports
for module augmentation that the linter flags).
EXPERIMENTAL: NSIDs and shapes will change while RFC 0001 is in flight.
* feat(registry-client): scaffold @emdash-cms/registry-client package
Atproto-aware client for the EmDash plugin registry, structured as three
independent layers so consumers pull in only what they need:
- **credentials**: persists publisher sessions between CLI invocations.
Three implementations: FileCredentialStore (~/.emdash/credentials.json
with mode 0600 and atomic temp-file rename), EnvCredentialStore
(read-only, reads EMDASH_PUBLISHER_* env vars for CI), and
MemoryCredentialStore (tests). defaultCredentialStore() picks env vs
file based on which env vars are set.
- **publishing**: thin wrapper over @atcute/client for repo operations
against the publisher's PDS — putRecord, uploadBlob, getRecord,
listRecords. Built around a pre-authenticated atproto fetch handler;
the interactive OAuth flow lives in the CLI (separate PR), not here,
so this layer stays unit-testable without a real PDS.
- **discovery**: read-only XRPC client over an aggregator. No
authentication. Threads atproto-accept-labelers through every request
so callers can configure which labellers' hard-takedown labels the
aggregator applies.
The two publisher-side and consumer-side surfaces are deliberately split —
the admin UI's install flow only needs discovery and shouldn't have to
pull in OAuth deps.
Reuses atcute primitives throughout rather than rolling our own:
- Did, Handle, Nsid, Blob, ResourceUri from @atcute/lexicons
- isDid, isHandle from @atcute/lexicons/syntax for env-var validation
- ClientResponseError from @atcute/client (re-exported as the canonical
error type for consumers; replaces hand-rolled DiscoveryError /
PublishingError)
- ok() helper from @atcute/client to throw on non-2xx, keeping the call
sites linear
Ambient module augmentation for com.atproto.repo.* XRPC methods is pulled
in via type-only side-effect import of @atcute/atproto, so we get strongly
typed putRecord/getRecord/etc. calls without dragging the runtime
validation schemas into the publishing client.
Adds @atcute/atproto, @atcute/client, @atcute/lex-cli, @atcute/lexicons,
and @atcute/oauth-node-client to the workspace catalog so future packages
share one source of truth for atcute pinning. The new
@emdash-cms/registry-lexicons and @emdash-cms/registry-client packages
both consume catalog refs.
31 tests cover credential store semantics (in-memory, filesystem
atomicity, env-var validation, read-only error paths), discovery client
behaviour (XRPC paths, accept-labelers header threading, error mapping),
and publishing client behaviour (putRecord body shape, validate flag,
error mapping, listRecords pagination).
* feat(registry-cli): scaffold @emdash-cms/registry-cli, build registry-* packages
Adds a standalone CLI for the experimental EmDash plugin registry, distributed
as @emdash-cms/registry-cli with a single emdash-registry binary. Also
switches @emdash-cms/registry-client and @emdash-cms/registry-lexicons from
shipping TypeScript source to building dist/ via tsdown, so consumers
download compiled JS + .d.ts and don't carry a TS toolchain.
Why a separate CLI rather than extending the core emdash CLI: the publishing
flow needs atproto OAuth, a loopback HTTP server, and Node-only deps. Most
EmDash users (site owners, content editors) never publish a plugin. Splitting
keeps these deps out of the core CMS install. Plugin authors run via npx or
install globally; site runtime stays atproto-free.
Subcommands:
- login Interactive atproto OAuth via a loopback HTTP server. Spins up
a server on a random ephemeral 127.0.0.1 port, opens the
user's browser at the AS authorization URL, awaits the callback,
exchanges the code, and persists both the OAuth library's
StoredSession blob (~/.emdash/oauth/) and the publisher's
display info (~/.emdash/credentials.json).
- logout Revoke the active session (or a specific DID) and remove
stored state. Falls back to local-only cleanup if remote
revoke fails, so users always end up logged out locally.
- whoami List the active session and any others stored. No network.
- search Free-text search the aggregator. Read-only; no auth.
- info Show package details. Routes to getPackage (DID + slug) or
resolvePackage (handle + slug) based on input shape.
- publish Stub. Real bundle + atproto write path lands in a follow-up
PR; for now points users at the legacy emdash plugin publish.
OAuth state is held in two FileStores under ~/.emdash/oauth/, both with
mode 0600 and atomic temp-file rename. The OAuth library treats the
contents as opaque; we just round-trip them.
The aggregator URL is configurable per-invocation via --aggregator <url>
or the EMDASH_REGISTRY_URL env var, falling back to the experimental
default. Resolution precedence has unit tests.
Build / packaging changes for the existing registry-* packages:
- registry-lexicons: tsdown bundles src/ + generated/ to dist/ as ESM
+ .d.ts. Codegen still writes to src/generated/ (checked in for
consumers without the lex-cli toolchain). build: copies the JSON
lexicons from the repo root if present, otherwise uses the
in-package copy -- so the package is buildable on any branch.
- registry-client: tsdown bundles all four entry points
(root + credentials + publishing + discovery) to dist/ as ESM + .d.ts.
Tests still run against src/ via vitest's ts pipeline.
- Both add publint + attw to their check scripts.
Discovery client tests fixed: getPackage / resolvePackage / listReleases /
getLatestRelease all take {did|handle, slug|package} pairs, not AT URIs.
Earlier scaffold had the wrong shapes. The new info command and tests
both match the actual lexicon contracts.
Catalogs @atcute/identity-resolver alongside the other @atcute/* deps.
* feat(registry-cli, plugin-types): bundling, publish flow, shared manifest types
Three things in one commit because they're tightly coupled:
1. Adds bundling and publishing to @emdash-cms/registry-cli.
- bundle: copied from packages/core/src/cli/commands/bundle.ts as a
deliberately temporary duplicate. Refactored from a citty handler
full of process.exit and consola calls into a programmatic
bundlePlugin(opts) function that returns a typed BundleResult or
throws BundleError with a structured code (MISSING_PACKAGE_JSON,
MISSING_ENTRYPOINT, MAIN_BUILD_FAILED, INVALID_PLUGIN_FORMAT,
TRUSTED_ONLY_FEATURE, BACKEND_BUILD_FAILED, VALIDATION_FAILED).
The citty wrapper in command.ts is now ~50 lines that delegates to
the API. The legacy core copy stays until phase 1 cutover; both
copies will diverge as we evolve registry-cli, then the legacy one
gets deleted wholesale.
- publish: takes --tarball <path> --url <url>, computes a sha2-256
multibase-multihash, extracts the manifest from the tarball,
verifies the remote URL matches the local checksum, resumes the
active publisher session, bootstraps a com.emdashcms.experimental
.package.profile record on first publish (with --license and
--security-email/--security-url required) or reuses the existing
one, and puts the package.release record at <slug>:<version> with
the artifact URL + checksum.
- Programmatic API exported from the package root: bundlePlugin,
BundleError, BundleResult, BundleLogger, sha256Multihash, plus
re-exports of the manifest contract types. CLI consumers get the
binary; tooling consumers can import from
@emdash-cms/registry-cli directly.
2. Adds @emdash-cms/plugin-types as the shared manifest contract.
Same types were duplicated in core and registry-cli. Now they live
once in a small types-only package, consumed by both. The vocabulary
includes PluginCapability, the legacy-rename map (CAPABILITY_RENAMES,
isDeprecatedCapability, normalizeCapability, normalizeCapabilities),
the manifest shape (PluginManifest, ManifestHookEntry,
ManifestRouteEntry, PluginAdminConfig, PluginStorageConfig,
StorageCollectionConfig).
Core's plugins/types.ts now imports and re-exports these — existing
internal callers keep working because the symbols are still exported
from the same module path. Core keeps its own stricter PluginManifest
interface (uses keyof PluginHooks for hook names, typed
PluginAdminPage[], etc.) with a compile-time assertion that it
remains assignable to the shared version.
After the registry phase 1 cutover removes the legacy bundling code
from core, both sides will continue depending on this single source
of truth — no drift.
3. Test coverage.
- 16 unit tests for bundle/utils.ts pure helpers (extractManifest,
findNodeBuiltinImports across the various import patterns,
findSourceExports for both string and conditional export shapes).
- 8 end-to-end bundle tests against a fixture plugin in
tests/fixtures/minimal-plugin/. Each test invokes bundlePlugin
against a real source directory, runs tsdown, writes the tarball
to a temp dir, unpacks it, and asserts the manifest body and
entry list.
- 1 multihash vector test against a known sha2-256("hello world")
value, captured from the running encoder. The previous suite of 4
tests was tautological ("is deterministic", "differs between
distinct inputs") — replaced with the single contract-level
assertion.
- 10 plugin-types tests covering the rename map's terminal
property, the prototype-key safety of the type guard, the
dedup-on-normalize behaviour for manifests declaring both legacy
and canonical names.
Total across the registry family + core: 3188 tests passing.
Library hygiene:
- Found and dropped publishing.uploadBlob from registry-client. The
RFC's artifact model puts checksums on author-hosted URLs, so the
atproto blob upload path is dead code.
- Replaced hand-rolled isDid regex / DiscoveryError-PublishingError /
custom blob ref types with their atcute-provided equivalents
(isDid from @atcute/lexicons/syntax, ClientResponseError from
@atcute/client, Blob from @atcute/lexicons).
- sha256Multihash uses @atcute/multibase toBase32 for the encoding
(consistent with the rest of the codebase's @atcute/* surface)
and @oslojs/crypto/sha2 for the digest. atcute has no multihash
helper because @atcute/cid would emit a CIDv1, which is a
different shape from the multibase-multihash the FAIR / registry
RFC specifies.
- Catalogued @atcute/multibase, @oslojs/crypto, @atcute/client.
oxlint exemption: packages/registry-cli/src/**/*.ts now matches core's
**/cli/**/*.ts pattern for the no-unsafe-type-assertion rule, since the
copied bundling code uses the same as-cast patterns and registry-cli
is itself a CLI package.
* feat(registry-cli): extract publishRelease() API, refuse version overwrites, mock PDS tests
Three changes that go together:
1. Refactor publish into a programmatic API + thin CLI wrapper.
commands/publish.ts was a 400-line citty handler that mixed flag
parsing, filesystem credentials, OAuth resume, HTTP fetching, manifest
extraction, FAIR/atproto record building, and consola output. Pulled
the core flow into src/publish/api.ts as publishRelease(opts) that
takes pre-built inputs (PublishingClient, manifest, checksum, url,
ProfileBootstrap) and returns a typed PublishResult or throws
PublishError with a structured code. Mirrors the bundle/api.ts
bundlePlugin shape.
PublishError codes:
- DEPRECATED_CAPABILITY: manifest declares one of the legacy
capability names. Bundle warns; publish refuses.
- PROFILE_BOOTSTRAP_MISSING_FIELD: first publish without --license
or --security-email/--security-url. Lexicon enforces both, but
surfacing the failure here gives an actionable error before any
network round-trip.
- RELEASE_ALREADY_PUBLISHED: a release record at <slug>:<version>
already exists in the publisher's repo.
2. Refuse to overwrite an existing release by default.
FAIR specifies version-record immutability; aggregators and
labellers may treat any change to <slug>:<version> as a takedown
event. Previous publishRelease silently overwrote (because the PDS
accepts putRecord on existing rkeys). Now it checks for an existing
record and refuses unless allowOverwrite: true.
Two side effects:
- Subsequent publishes that pass first-publish-only flags
(--license, --author-*, --security-*) get a warning naming each
ignored flag. The existing profile wins; flags are silently
dropped on the wire, and previously the user got no signal.
- The CLI surface adds --allow-overwrite for the rare case where
overwriting is intentional (consumers haven't installed yet, etc).
The error message points at it.
3. Mock PDS test fixture and 14 new publish tests.
tests/mock-pds.ts implements the FetchHandlerObject contract that
PublishingClient.fromHandler accepts, with an in-memory record map
keyed by AT URI. Tests use it to drive the publish flow without OAuth,
filesystem credentials, or a live PDS. Returns realistic atproto error
payloads (RecordNotFound, InvalidRequest) so the publish flow's
ClientResponseError-keyed error handling exercises the same paths a
real PDS would trigger. Reusable for any future test that drives
PublishingClient.
New tests cover:
- First publish: profile + release records, populated from
ProfileBootstrap fields, hard-failing on missing license or
security contact, accepting securityUrl as an alternative to
securityEmail.
- Subsequent release: existing profile preserved (CID and bytes
unchanged), ignoredProfileFields names every overlap, undefined
profile reports empty.
- Version collision: refused by default with detail { slug, version },
overwritten + signalled when allowOverwrite is true, original bytes
preserved on the refused path.
- Deprecated-capability hard-fail runs before any XRPC call (asserted
via pds.calls).
- Slug derivation strips leading @ and replaces / for scoped npm names.
Each test asserts what's in the mock PDS after the call, so we catch
regressions in both happy and error paths.
Other tweaks:
- README rewritten honestly: search/info/publish work in code, but the
aggregator side isn't deployed yet. Lead with bundle as the
introductory example.
- bundle command's "next steps" hint updated to match the new
--url-only publish shape.
- publishRelease re-exported from the package's programmatic API so
tooling can call it directly without spawning a subprocess.
* fix(registry): adversarial-review pass — atomic publish, lexicon validation, hardening
Addresses the findings from the adversarial review of the registry PR. Five
critical bugs and a long tail of high/medium/low items.
CRITICAL
- Profile + release writes now happen in a single `com.atproto.repo.applyWrites`
commit. Previous flow issued separate `putRecord` calls so a network blip
between them could leave a profile with no release (or vice versa). The
atomic batch also lets us update the existing profile's `lastUpdated` on
every release without a second round-trip.
- `PublishingClient.putRecord` defaults to `validate: true` (was `false`).
The PDS now validates every registry record against its lexicon at write
time. The `unsafePutRecord` escape hatch exists for callers writing
records the PDS doesn't yet know how to validate. Default-off validation
silently bypassed every constraint we'd spent the lexicon files defining.
- Slug and version validated against the lexicon constraints upstream of
the network round-trip. `deriveSlugFromId`/`isPluginSlug`/`isPluginVersion`
live in `@emdash-cms/plugin-types` so both the bundler and the publisher
use the same regex (^[a-z][a-z0-9_-]*$ / ^[a-zA-Z0-9.-]+$). New
`PublishError` codes `INVALID_SLUG` and `INVALID_VERSION` produce
actionable errors instead of opaque PDS rejections like `InvalidRequest`.
- OAuth callback server holds the response open until the CLI tells it
what to render, so the user's browser shows "Login complete" only AFTER
atcute has validated the callback params. Previously, ANY GET to /callback
resolved the promise and rendered success. A stray browser tab firing at
the loopback could trick users into thinking they were logged in when
they weren't.
- Tarball URL validation: rejects `file:`, non-http(s) schemes, IPv4
RFC-1918 ranges, IPv6 ULA / link-local. Streams the body with a 5MB cap
so a malicious URL can't OOM the CLI. Manifest extraction wraps the
modern-tar gunzip in a try/catch that produces a clean error if the URL
served HTML instead of a tarball. Manifest extraction now runs BEFORE
any "tarball looks fine" output so a malformed file fails loudly.
HIGH
- The "type-level guard" in core's `PluginManifest` actually enforces
drift now: `const _check: _AssertManifestCompat = true` errors if the
conditional resolves to `never`. Previous `type _CompatCheck = ...`
was decorative because `type X = never` is legal at the type level.
- Bundler descriptor extraction tightened. We only call `createPlugin()`
or the default export -- no more speculative-call-every-named-export
loop that would mis-resolve a plugin with helper functions returning
{id, version}-shaped objects. Dynamic import results validated via
`isResolvedPluginShape` / `isPluginDescriptorShape` runtime guards
before being treated as a plugin.
- The bundler's `emdash` shim is now a Proxy that throws on any access
other than `definePlugin`. Plugins that import other things from
`emdash` (e.g. `defineCronTask`) used to silently get `undefined`
values that tree-shaking eliminated, masking real bugs. The fixture
plugin now uses `import { definePlugin } from "emdash"` so the shim
resolution path is actually exercised by the bundle tests.
- `PublishingClient.putRecord` is generic over `RegistryRecords[C]`
(the lexicon-derived type map). Compile-time check that you can't put a
profile-shaped record into a release collection. New `applyWrites`
method takes a typed `PublishOperation[]` for the same reason.
- Bundler tmpDir uses `mkdtemp(tmpdir())` instead of a fixed
`.emdash-bundle-tmp` under the plugin source. Concurrent bundle runs
no longer trample each other; the tmpdir doesn't show up in `git
status`. Misplaced `.endsWith` cleanup guard removed.
- File writes (`FileCredentialStore`, `FileStore`) now pass
`flush: true` to writeFile for durability. Atomic rename was already
torn-write safe; `flush: true` (Node 21.1+) fsyncs the contents
before rename so a power loss can't surface an empty inode pointing at
unwritten data.
- `EnvCredentialStore` stamps `updatedAt` once at construction, not on
every read. Successive `current()` / `get()` / `list()` now agree
on the timestamp.
- `getRecordOrNull` returns `{ uri, cid, value } | null` sentinel
instead of the value alone. `if (existingProfile !== null)` instead
of truthiness, so a legitimately-falsy stored value can't be mistaken
for "no record".
- Profile-bootstrap field validation runs before any network round-trip:
if `license` or security contact is missing on first publish, the
CLI fails fast with no `getRecord` calls issued. Was previously
caught after the existence check.
- Hard-fails when a standard-format descriptor declares hooks/routes but
no sandbox entry exists. The bundler can't probe for the hook/route
names; emitting a manifest that promises functionality the bundle
can't deliver is worse than refusing to bundle.
- Discovery client always *overwrites* the `atproto-accept-labelers`
request header rather than only setting it if absent. Caller-supplied
values can no longer override the aggregator's policy.
MEDIUM
- New mock PDS faithfully models the rejections a real PDS would issue:
rejects writes whose `repo` field doesn't match the mock's DID,
rejects rkeys outside atproto's record-key alphabet, supports
`applyWrites` with all-or-nothing atomic-commit semantics, derives
CIDs from record content (so identical bytes round-trip to identical
CIDs, matching real-PDS behaviour). Tests now assert XRPC call counts
via `pds.callsTo(nsid)` rather than counting on mock implementation
details.
- Empty-string `--license=""` etc. flags rejected up front with
"--license cannot be empty" instead of bubbling up as a confusing
missing-field error.
- `emdash-registry switch <did>` implemented (whoami previously
printed "TODO: not yet implemented" to end users).
- Search command takes `--cursor`. The advice on a paginated result
now points users at the cursor flag instead of suggesting they bump
`--limit` past the aggregator's 100-result cap.
- `info` parses the lexicon-typed profile via `safeParse(PackageProfile.mainSchema, ...)`
instead of casting to a hand-rolled `ProfileFields` interface. Falls
back to best-effort string extraction with a warning if the record
doesn't validate.
LOW
- escapeHtml also escapes single-quote and forward-slash for defence in
depth.
- `isErrnoException` checks `typeof code === "string"` so a non-fs
Error with a non-string `code` property doesn't pass the guard.
- Proxy-shim writing hoisted into a single `writeEmdashShim` helper
used by both the main bundle and the sandbox probe.
- Module-scope regexes for IP-literal detection so they aren't recompiled
per call (caught by lint).
- `@emdash-cms/plugin-types` added to `test:unit`.
- oxlint `no-unsafe-type-assertion` carve-out narrowed from a blanket
`packages/registry-cli/src/**/*.ts` to the four files that legitimately
use casts at trust boundaries (bundle/api, oauth, publish/api, etc.).
- `extractManifestFromTarball` accepts both `manifest.json` and
`./manifest.json` since modern-tar's exact naming isn't pinned.
- index.ts doc comment updated -- publish is no longer a stub.
NEW TESTS
- 14 plugin-types tests for slug/version validation.
- 21 publish tests up from 14: cover atomic batches, parallel reads,
refusal preserves bytes, overwrite semantics, deprecated capability /
invalid slug / invalid version all hard-fail before any network call,
scoped npm names, malformed-existing-profile fallback path.
- Bundle tests for "hooks declared but no sandbox entry" hard-fail and
for concurrent bundle runs not colliding on tmpdir.
- registry-client gets an applyWrites batch test plus an
unsafePutRecord/skipValidation test.
3227 tests passing across plugin-types, registry-lexicons,
registry-client, registry-cli, and core. Workspace typecheck clean.
Lint clean across all touched files.
* registry-cli: address round-2 review findings
C1 Lexicon validation: validateLocally now safeParses every record against
PackageProfile/PackageRelease/PackageReleaseExtension before applyWrites.
applyWrites is sent with skipValidation: true since the PDS doesn't know
our experimental NSIDs. New PublishError code: LEXICON_VALIDATION_FAILED.
C2 Release extension: publishRelease now embeds a packageReleaseExtension
record inside release.extensions, built from manifest.capabilities and
manifest.allowedHosts via buildDeclaredAccess. Without it, sandbox runtimes
have no contract to enforce.
H1 Semver: PLUGIN_VERSION_RE tightened to real semver-2.0 BNF (no build
metadata, no leading zeros). Tests cover the boundary cases.
H2 Redirect handling: fetchTarball follows redirects manually and
re-validates each hop against validatePublishUrl. Defeats the trick of a
public URL that 302s to 169.254.169.254 or localhost.
H3 MockPds: create rejects when key exists, update rejects when key
absent. Matches real PDS semantics so tests don't pass on broken paths.
H4 MockPds atomicity: existence checks moved to up-front validation pass.
H5 swapCommit: documented why we don't pass it (single-publisher repos
don't need optimistic CAS).
H6 --json purity: redirectConsolaToStderr swaps the global reporter so all
human messages go to stderr; only the final JSON object hits stdout.
H7 _AssertManifestCompat: added comment explaining the one-direction
check is intentional (shared is wider; bidirectional would fail because
shared uses string for hook names while core narrows to HookName).
M1 Manifest validation: assertManifestShape runs after JSON.parse so a
malicious tarball with garbage manifest.json fails fast with a clear
error.
M2 Descriptor guards: now check element types of capabilities and
allowedHosts arrays.
M3/M4 Sandbox probe: hooks/routes without function handlers now hard-fail
with INVALID_PLUGIN_FORMAT instead of silently ending up with undefined
handlers.
M5 tmpDir leak: import("tsdown") moved inside the try block so a
missing/broken tsdown install doesn't orphan the tmpdir.
M6 Directory fsync: after rename, fsync the directory so the rename is
durable across power loss. Best-effort -- some filesystems reject opening
a directory.
M7 stampLastUpdated: documented that lexicon validation in step 5 catches
invalid round-tripped fields.
L1 Shim: documented why named-import errors are caught at build time and
don't need shim-level handling.
L2 --local help: clarified it doesn't skip the download.
L3 Plain HTTP: validatePublishUrl now requires https. The cost is zero in
2026 and it shuts the door on novel checksum-bypass attacks.
* registry-cli: address round-3 review findings
H1 SSRF — IPv4-mapped IPv6: validatePublishUrl now rejects ::ffff:1.2.3.4
and ::1.2.3.4 forms. v4 deny list expanded to include 0.0.0.0/8 and CGNAT
100.64.0.0/10.
H2 Redirect DNS resolution: fetchTarball now DNS-resolves the initial URL
and every redirect hop's hostname against the same private-IP allow-list,
defending against a public hostname pointed at 10.x or 169.254.169.254.
H3 declaredAccess vs bundler warning: publishRelease now hard-fails
network:request with no allowedHosts (lexicon treats {} as unrestricted,
contradicting the bundler warning). Authors must list hosts or upgrade to
network:request:unrestricted. The bundler warning text now matches the
publish-time refusal.
H4 write implies read: buildDeclaredAccess now always emits content.read
and media.read when content.write or media.write is present, matching the
documented lexicon semantics.
H5 stampLastUpdated: always normalizes $type to the current
NSID.packageProfile, so an existing record from an earlier shape doesn't
break every subsequent publish via lexicon validation.
H6 --json error path: every failure path now emits a structured
{ error: { code, message } } JSON object on stdout in --json mode, so
piped consumers see the same JSON contract for success and failure.
Internal CliError class carries stable error codes for non-PublishError
failures.
H7 assertManifestShape: rejects arrays as storage/admin (typeof [] is
'object'), validates that hooks/routes entries are strings or
non-array/non-null objects, with a describeJsonValue helper for clearer
error messages.
M1 MockPds: documented that pre-batch existence checks diverge from a
real PDS's post-batch MST snapshot semantics. Doesn't affect coverage
today.
M2 redirectConsolaToStderr: returns a restore function captured by the
outer try/finally so an in-process wrapper that runs publish then
continues with another command gets its consola back.
M3 fsyncDir: docstring now honestly describes platform reality (Linux
durable, macOS already covered by file fsync, Windows benign no-op).
M4 _AssertManifestCompat: clarified that the one-direction check is
intentional; runtime narrowing of the wider wire shape happens in core's
manifest-schema.ts via zod.
M5 declaredAccess capability gap: warn at publish about users:* and
hooks.*:register capabilities that have no declaredAccess mapping today
(lexicon limitation).
M6 validateLocally: documented that atcute's v.object accepts unknown
keys silently; aggregators MUST do their own strict validation.
L1 INVALID_MANIFEST: now actually thrown (in the network:request hard-
fail from H3).
L2 multihash: docstring corrected (output is 56 chars total, not 34).
* registry-cli: address round-4 review findings
CRITICAL-1 IPv6 bracket bug: Node URL parser keeps brackets and converts
embedded IPv4 to hex pairs. validatePublishUrl now strips brackets and
detects:
- IPv4-mapped dotted form (::ffff:1.2.3.4)
- IPv4-mapped hex form (::ffff:hhhh:hhhh) which decodes to v4 then re-runs
the v4 private check
- IPv4-compatible (::1.2.3.4)
- ULA (fc00::/7), link-local (fe80::/10), loopback (::1), unspecified (::)
- NAT64 prefix (64:ff9b::a.b.c.d) caught by trailing-hex-pair fallback
CRITICAL-2 ULA/link-local IPv6 bracket bug: same root cause; same fix.
The pre-existing IPv6_ULA_FC_RE patterns now run on bracket-stripped
input so they actually match.
26 new test cases in tests/url-validation.test.ts covering all the
SSRF-shaped IPv6 inputs that previously slipped through.
H1 process.exit bypass: capture exitCode in catch, run finally, then
exit. Reporters are restored on both success and failure paths.
H2 CliError.exitCode wired up: catch reads error.exitCode (defaults to 1)
so user-error (2) vs publish-failure (1) is preserved in scripts.
H3 stampLastUpdated whitelist: re-emit only schema-known fields rather
than spreading the existing record. Prevents leftover fields from earlier
experimental shapes from surviving a republish.
H4 validateResolvedHost handles bracketed v6: strips brackets first; the
short-circuit-on-colon path is now safe because validatePublishUrl is
guaranteed to have caught any v6 literal first.
H5 TOCTOU DNS rebinding: documented the residual window (validation
lookup vs fetch lookup) explicitly. Full mitigation requires resolving
once and binding the connection to a literal; we accept the residual
risk for the publish CLI and document it.
H6 unmapped capability detection: derived from what buildDeclaredAccess
actually emitted, via capabilityIsRepresented(). A future capability
added to plugin-types but not to buildDeclaredAccess now surfaces in the
warning automatically.
M1 IPV6_V4_MAPPED regex: replaced with strict ::ffff: dotted/hex variants
plus a separate ::compat-dotted variant, eliminating false positives.
M2 dns lookup: kept lookup() for now; documented residual /etc/hosts
trust in the comment.
M3 hoisted dns import: top-level import { lookup as dnsLookup }; no more
microtask hop per redirect hop, no more import-resolution failure mode.
M4 --json schema doc: flag description now lists success and failure
shapes inline.
M5 assertManifestShape doc: renamed the responsibility honestly to
'best-effort structural sanity check' and pointed callers needing full
validation at packages/core/src/plugins/manifest-schema.ts.
M6 mock-pds claim softened: removed the unverified 'post-batch MST'
claim, replaced with 'behaviour may vary; validate before depending'.
* registry-cli: address round-5 review findings (M-1, M-2)
M-1 trailing-dot bypass: stripTrailingDot canonicalises FQDN form before
the .local / localhost equality checks. mDNS resolvers respond to both
'foo.local' and 'foo.local.', so the syntactic guard had to too.
M-2 NAT64 catch-all false positives: replaced the generic 'last two hex
groups encode v4' fallback with explicit prefix patterns: NAT64
(64:ff9b::/96) and 6to4 (2002::/16). Public v6 addresses whose suffix
coincidentally encodes a private v4 (e.g. 2001:db8::a00:1) no longer
false-positive reject.
Also fixed an IPv4-compat hex normalisation gap: '::169.254.169.254'
gets normalised by Node's URL parser to '::a9fe:a9fe' (no 'ffff:'
prefix). The IPV6_V4_COMPAT_HEX_RE branch catches that form;
IPV6_V4_MAPPED_HEX_RE only catches the '::ffff:' variant.
3 new test cases for the trailing-dot variants, 6to4 with embedded
private v4, and the negative case (public v6 with private-looking
suffix). Total 82 tests passing.
* registry: address copilot review + CI build fix
CI: build registry packages (not just emdash deps) so the unit-test job
can resolve workspace links to dist/. The registry packages aren't
direct deps of emdash, so 'emdash...' filter left them unbuilt and
their tests failed at module resolution.
credentials/file.ts:
- Preserve on-disk version (no silent downgrade); reject forward-version
files explicitly so an older CLI doesn't blindly overwrite a newer
format.
- Validate every session entry structurally (did/handle/pds/updatedAt),
cross-check the map key equals session.did, verify currentDid points
at an existing session.
- Update header comment to match actual behaviour: extra top-level
fields are NOT preserved on round-trip.
PublisherSession.handle: now 'string | null' rather than the branded
Handle template literal. login.ts persists null when handle resolution
fails; whoami/switch/publish/publish-success-line all render
session.handle ?? session.did. No more 'unknown.invalid' placeholder
that misleads users.
discovery/listReleases: docstring clarifies descending semver order
(not 'reverse-chronological').
Changeset: 'publish' is no longer described as a stub; the actual
behaviour (fetch tarball, checksum, manifest extraction, atomic
applyWrites with declaredAccess extension) is documented.
tsdown.config.ts comment: matches the actual '.mjs'/'.d.mts' output.
registry-client docs (src/index.ts + README): reference 'emdash-registry'
(the actual binary name) rather than the imagined 'emdash plugin' path.
registry-cli README: EXPERIMENTAL note clarifies what works today
(publish writes to PDS) vs what needs a deployed aggregator (search,
info). Command list now includes 'switch'.
* registry: address PR review comments
profile.ts: read PDS URL from session.getTokenInfo().aud instead of the
nonexistent getSession.pdsUrl field. The Bluesky lexicon's getSession
output schema does not include pdsUrl, so the previous code persisted
pds: '' on every successful login, locking the user out of subsequent
commands once the new credentials validator rejected the empty pds.
FileCredentialStore.put(): refuse to persist a session that doesn't
pass isPublisherSession. Catches upstream regressions at write time
rather than at next-read.
Credential validator hardening:
- isDid runtime check on session.did and currentDid (was: typeof
string), so hand-edited corruptions surface here rather than in the
OAuth library.
- Object.hasOwn instead of `in` for currentDid -> sessions check, so
prototype-chain names (toString, constructor) can't slip through.
- Sessions map is null-prototype, so bracket access on unknown keys
can't resolve through Object.prototype.
- Version range check requires Number.isInteger and a positive value;
rejects NaN, negative, fractional.
login.ts: --json output and success line now use handleForStorage
(null when handle resolution fails), so we don't render the DID twice
in adjacent lines or emit DID-as-handle in JSON.
URL validation: added RFC 8215 NAT64 local-use prefix (64:ff9b:1::/48)
to the SSRF deny list.
lex.config.ts: codegen reads from the in-package lexicons/ directory
(was: nonexistent repo-root path).
Doc fixes:
- credentials/types.ts: emdash plugin -> emdash-registry
- credentials/env.ts: removed reference to unused EMDASH_PUBLISHER_SESSION
- registry-cli README: switch <did> (was: switch <handle-or-did>)
* registry-client: fix typecheck failure in put() validator
The isPublisherSession type guard narrows the negative branch to never
when the input is already typed PublisherSession, so reading fields
off the value for the error message produced TS2339. Use safeStringify
on the whole value instead.
|
||
|
|
333acee0e5 |
chore(ci): pin node 22 floor, fix bot bypasses on CLA and PR Compliance (#879)
- Add `engines.node: ">=22"` so workflows using `node-version-file: package.json`
(review, bonk) stop falling back to Node 20 when no version is declared.
- CLA Assistant: add `opencode` to the allowlist. ask-bonk PRs commit with git
author `opencode`, which has no GitHub user mapping, so the action's
committer-identity check never matched the existing `ask-bonk[bot]` entry.
- PR Compliance:
- Switch from `pull_request` to `pull_request_target` so the comment step
works on PRs from forks (was hitting 403 Resource not accessible by
integration).
- Filter on `pull_request.user.login` instead of `github.actor`. Actor
becomes a maintainer on synchronize/edited events triggered by pushing
or merging into a bot branch, which let bot PRs slip past the gate.
|
||
|
|
f97d6ab0f1 |
Add query-count perf harness + instrumentation (#653)
* feat: add query-count perf harness + instrumentation
Opt-in Kysely log hook gated behind EMDASH_QUERY_LOG=1 emits per-request
NDJSON on stdout so a harness can count DB queries per route. Zero
overhead when disabled. Exposed at emdash/database/instrumentation so
@emdash-cms/cloudflare can wire the same hook into its per-request D1
session Kysely.
Adds fixtures/perf-site (minimal blog-style fixture, dual sqlite/d1
config), scripts/query-counts.mjs (pnpm query-counts), committed
snapshot files for both targets, and a CI job that runs both.
* fix(perf): invoke emdash CLI directly in query-counts harness
pnpm exec emdash fails in CI because bin symlinks aren't linked for
workspace-local packages (see scripts/relink-bins-if-needed.mjs, which
early-exits under CI). Invoke the built CLI entry by absolute path
instead so the harness works in both CI and local dev.
* ci(perf): build all packages for query-counts job
The fixture config imports from @emdash-cms/cloudflare for the d1 path,
so `pnpm run --filter emdash... build` (which only walks emdash's
deps, not its dependents) leaves cloudflare unbuilt and astro fails
to resolve the import when loading the config.
* fix(perf): wait for TCP port instead of parsing stdout for ready
The ready-regex approach was fragile — in CI, the cloudflare adapter's
dev mode wraps output in [vite] prefixes and the "ready in" line
sometimes never matches (observed on the D1 seed step: typegen POST
succeeded but ready timeout still fired).
TCP-connect is the real question anyway ("is the server accepting
connections?"). It also doesn't warm a fresh workerd isolate —
workerd defers isolate creation to the first HTTP request — so the
per-route cold-isolate measurement stays honest.
* fix(perf): seed D1 before building for preview
`astro dev` (the seed step) leaves .wrangler/deploy/ without the
build-time config.json that cloudflare adapter's preview requires, so
running `astro build` after the seed is what makes the subsequent
`astro preview` spins work.
|
||
|
|
d4bfddba70 |
fix(ci): use script for changeset version command
The changesets action passes the version string as arguments to the binary, not to a shell. "pnpm changeset version && pnpm install" was parsed as extra args to changeset, causing "Too many arguments" error. Use a package.json script instead. |
||
|
|
a378912697 |
fix: relink CLI bins after build only when needed (#482)
* fix: relink CLI bins after build only when needed pnpm only creates bin symlinks for workspace packages when the target file exists at install time. Since the CLI lives in dist/, it doesn't exist until after the first build, so `emdash seed` fails for new contributors. Add a postbuild script that detects missing or stale bins and relinks only when necessary — zero overhead on normal builds. * fix: rewrite relink script as Node for cross-platform support Replace the shell script with a Node script so it works on Windows. Also drop the mtime check — the bundler rewrites the CLI on every build so it would trigger a spurious relink every time. Now only relinks when the built CLI exists but the bin symlink is missing. |
||
|
|
cde3834ddc |
Add Lunaria translation tracking and i18n dashboard (#461)
* Add Lunaria translation tracking with PO dictionary support Configure Lunaria to track PO files directly using dictionary mode (via lunariajs/lunaria#178). Add Spanish as first translation locale. - Add lunaria.config.json with PO dictionary tracking - Add Spanish locale to Lingui config and extract empty catalog - Add locale:extract and locale:compile scripts to root * Switch Lunaria config to TypeScript with defineConfig * Fix Lunaria config: include only source file, not all PO files * Add translation status dashboard deployable to i18n.emdashcms.com Static HTML dashboard generated from Lunaria, deployed as Cloudflare Workers static assets. Shows per-locale completion with progress bars, missing keys, and GitHub edit links. * Move Lunaria build/deploy scripts into i18n/ package * Add Lunaria GitHub Action for PR translation impact comments * Add i18n workspace package, update lockfile * style: format * Replace Spanish with German as first translation locale * fix ts * style: format * Add wrangler --------- Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com> |
||
|
|
e868a60f06 | Fix globs in package.json scripts | ||
|
|
2e863566b3 | Fix scope | ||
|
|
43fcb9a131 | first commit |