Vitest <4.1.0 allows arbitrary file read/execution when the UI server is
listening (GHSA-5xrq-8626-4rwp, severity: critical). Bumps vitest from
3.2.4 to 4.1.x, which also flows through to the bundled @vitest/* packages
in pnpm-lock.yaml.
Adjusts two tests for the stricter v4 mock contract: `new`-callable mocks
must be backed by a `function`/`class` implementation rather than an
arrow function (web/src/shared/lib/date-time.test.ts,
web/src/app/providers.test.ts).
Signed-off-by: dongmucat <1127093059@qq.com>
Use `namespace === 'global'` (without @ prefix) to match the actual
route parameter value. The previous check used '@global' which never
matched, causing anonymous users to be redirected to login even for
global PUBLIC skills.
Co-authored-by: dongmucat <1127093059qq.com>
* fix(runtime): pass auth environment variables to containers
The web container's envsubst in 30-runtime-config.sh only substituted
SKILLHUB_WEB_API_BASE_URL and SKILLHUB_PUBLIC_BASE_URL, leaving auth-related
variables (authDirectEnabled, authSessionBootstrapEnabled, etc.) as literal
${...} strings in runtime-config.js. Additionally, compose.release.yml did not
pass SKILLHUB_WEB_AUTH_DIRECT_ENABLED or SKILLHUB_WEB_AUTH_DIRECT_PROVIDER to
the web container, nor SKILLHUB_AUTH_DIRECT_ENABLED to the server container.
This made it impossible to enable direct (username/password) authentication
for intranet deployments without OAuth2, even though the frontend template and
backend already supported it.
Changes:
- compose.release.yml: add SKILLHUB_AUTH_DIRECT_ENABLED to server env
- compose.release.yml: add auth direct and session bootstrap vars to web env
- 30-runtime-config.sh: expand envsubst to cover all runtime-config.js template variables
- .env.release.example: document the new auth configuration variables
All new variables default to false/empty, preserving existing GitHub OAuth behavior.
* fix: remove session bootstrap frontend config from compose
Per reviewer feedback: exposing SKILLHUB_WEB_AUTH_SESSION_BOOTSTRAP_* in the
compose without matching SKILLHUB_AUTH_SESSION_BOOTSTRAP_ENABLED on the server
would cause 403 errors when frontend attempts bootstrap.
Keep this PR focused on direct auth only. Bootstrap variables are still handled
in 30-runtime-config.sh with false defaults, so runtime-config.js will have
authSessionBootstrapEnabled: "false" and frontend will not trigger bootstrap.
---------
Co-authored-by: wowo <zhenggui5228@126.com>
Co-authored-by: PR Review Helper <review-helper@local>
- Add ariaLabel prop to CopyButton for screen reader differentiation
- Pass per-user aria-label: "Copy user ID for {username}"
- Add truncation for long userIds (max-w-[14rem] + title tooltip)
- Scope E2E copy-button assertions to userId cell to avoid false positives
- Assert on span.font-mono for userId text to exclude button text
- Use toHaveText instead of getByRole name for "Copied" feedback check
- Fix race condition: use Promise.all for goto + waitForResponse
- Remove all waitForTimeout calls, use explicit assertions/waitForResponse
- Assert clipboard content equals the actual userId (not just non-empty)
- Fix unused variable (userIdText) that would fail lint --max-warnings 0
- Trigger real search via button click instead of just filling input
- Add status filter test to cover the filter path
- Add comment explaining mock-profile approach for admin session
Add a userId column with one-click copy functionality to the admin
user management table to help administrators easily access user IDs
for batch operations like namespace member management.
Changes:
- Add userId column after username in admin users table
- Implement one-click copy button for each userId
- Add i18n translations for column header (en/zh)
- Add comprehensive E2E tests (6 test cases)
Closes#426
Fix three blockers and one contract drift issue surfaced in code review:
1. API token policy: add skill:publish scope policy and authentication
policy for /api/cli/v1/skills/*/publish/validate. Without these the
AntPathMatcher pattern /publish would not cover /publish/validate,
so Bearer-token requests would be rejected by the scope filter.
2. Warnings semantics: dry-run now treats warnings as making valid=false.
The CLI publish flow uses confirmWarnings=false, so the real publish
rejects any warnings; dry-run must mirror that to avoid false positives.
3. Visibility parameter: validate endpoint now accepts the same
visibility multipart field as publish. The CLI forwards --visibility
so invalid values are caught at dry-run time rather than at publish.
4. Schema drift: resolvedSlug and resolvedVersion are nullable in
practice (returned as null when validation fails before resolution).
Updated schema.d.ts to reflect string | null instead of optional string.
Tests added:
- RouteSecurityPolicyRegistryTest: validate endpoint scope check
- CliDryRunValidateTest: custom + invalid visibility cases
- publish-dry-run.test.ts: --visibility forwarded to server
Add a validate-only endpoint (POST /api/cli/v1/skills/{namespace}/publish/validate)
that runs the full pre-publish validation chain without persisting anything.
This allows developers to check their package locally before actual publishing.
The validation covers:
- SKILL.md existence and frontmatter parsing (name, description required)
- File extension whitelist and size limits
- Credential leak scanning with line-number precision
- Slug generation and name conflict detection
CLI usage: `skillhub publish <path> --dry-run`
Closes#429
Add a third peer tab 'CLI' to LandingQuickStartSection that surfaces the
official install command 'npm i -g @astron-team/skillhub'. Layout uses
grid-cols-1 md:grid-cols-3 so mobile shows tabs stacked and desktop
shows three equal-width columns.
Addresses iflytek/skillhub#419 (homepage Quick Start part only).
Resolved conflicts by keeping both sides:
- web/src/api/client.ts: preserve paginated listMembers(slug, {page,size})
and add delete(slug) from main.
- web/src/shared/hooks/use-namespace-queries.ts: keep useUpdateNamespace
and useTransferNamespaceOwnership from this branch, plus useDeleteNamespace
from main.
appendNamespaceMember was being called via setQueriesData across all cached
pages, causing the new member to appear at the end of every page. The
invalidation will refresh the list correctly.
Add namespace edit dialog, transfer ownership dialog, and member list pagination. Update API layer to support pagination (PagedResponse), add useUpdateNamespace and useTransferNamespaceOwnership hooks with pagination-aware optimistic updates. Integrate edit button in NamespaceHeader and transfer button on members page. Add i18n keys for all new features (en + zh).
The top-level esbuild.target also applied to dev/test transforms, which
broke vitest suites that use top-level await (Chromium 83 / ES2020 does
not support it). Only build.target and optimizeDeps.esbuildOptions.target
need the legacy target; remove the global esbuild.target override.
Publish page dropdowns (namespace/visibility) failed to open on older
Chromium because Vite 6 defaults build target to chrome87 and some
bundled deps call runtime APIs absent in Chrome 83 (replaceAll, .at,
hasOwn). Lower esbuild/vite target to chrome83, add browserslist, drop
??= in bootstrap, and inject runtime polyfills before main loads.
Addresses review feedback on #413: for a single-package project,
pnpm-workspace.yaml is unnecessary and its 'packages: [.]' declaration
turns the web/ directory into a pnpm workspace root, which is a
semantic side effect we don't want.
Move onlyBuiltDependencies under the 'pnpm' field in package.json
(pnpm 10 still reads it there) and drop the workspace file from the
Dockerfile COPY list. Verified locally with docker buildx: pnpm 10.33
runs esbuild postinstall and the build succeeds.
Corepack was resolving pnpm to latest (11.0.9) on each CI run, and
pnpm 11 refuses unapproved postinstall scripts in --frozen-lockfile
mode. That caused ERR_PNPM_IGNORED_BUILDS: esbuild@0.25.12 and failed
the web image build in publish-images.
Changes:
- web/package.json: pin packageManager to pnpm@10.33.0
- web/pnpm-workspace.yaml: approve esbuild via onlyBuiltDependencies
(pnpm 10 syntax; matches the pinned major)
- web/Dockerfile: copy pnpm-workspace.yaml before pnpm install so the
approval list is visible inside the build stage
Introduce a dedicated `/space/$namespace/$slug/compare` page that compares
two published skill versions GitHub-style: left file list + right unified
diff. Backend exposes `GET /versions/compare` returning structured diff
(computed via java-diff-utils) with per-file hunks, binary placeholder,
and truncation flags. Frontend uses two version selectors scoped to
PUBLISHED versions, a file search box, active-file highlighting, and
whitespace-preserving unified view. E2E covers the publish + rerelease
+ approve round trip; controller/domain tests cover happy path and
same-version rejection.
- Add visual separator between StarButton and SubscribeButton
- Use optimistic updates in useToggleSubscription for instant feedback
- Remove isLoading guard that caused button to unmount during refetch
Published skills start in PENDING_REVIEW status with canInteract=false,
so the SubscribeButton is not rendered. Use admin user to approve the
review first, following the same pattern as search-seed and review-seed.
Use .first() for h1 heading locator since skill detail page
renders two h1 elements (page title + README heading).
Add page-ready wait in second test before locating Subscribe button.
Root cause: two issues caused CI failure:
1. publishSkill hit 429 rate limit from other tests in the suite
2. glob pattern '?' was ambiguous for matching literal '?' in URLs
Fix: remove publishSkill dependency, use regex route matching, and
return fully mocked API responses with fake skill data. This tests
the frontend pagination UI behavior without needing real published
skills.