* feat: display username and email in namespace member management
MemberResponse DTO now includes displayName and email fields.
NamespacePortalQueryAppService batch-loads UserAccount data via
findByIdIn to avoid N+1 queries. Frontend member table shows
username (with userId as fallback subtitle) and email columns
instead of raw user IDs.
* test(namespace): add displayName/email assertions and new test coverage
- Controller: add displayName and email assertions to addMember and updateMemberRole tests
- QueryAppService: add listMembers tests for batch user enrichment and null degradation
- CommandAppService: add addMember/updateMemberRole tests for displayName/email population and graceful degradation
Addresses PR #236 review feedback comments:
- Issue 2: Controller tests now assert displayName and email from mocked UserAccount
- Issue 3: Service layer tests now cover batch query and null user degradation
* docs: add Maven mirror config and troubleshooting guide for China developers
- Add Aliyun mirror config in server/.mvn/settings.xml
- Update maven-wrapper.properties to use Aliyun mirror for Maven distribution
- Add detailed error messages in Makefile when backend startup fails
- Add troubleshooting section in quickstart.md for China developers
- Add FAQ entry for local development startup issues
- Update README with link to local development guide
* perf: optimize file tree and preview rendering performance
- Add useMemo to cache tree structure and syntax highlighting results
- Add React.memo to FileTreeNodeComponent to prevent unnecessary re-renders
- Add useCallback for stable callback references
- Simplify CSS styles (remove gradients, blur, shadows) to reduce GPU load
Fixes performance issues with file preview lag reported by users.
* test: update test for React.memo wrapped component
- Add Aliyun mirror config in server/.mvn/settings.xml
- Update maven-wrapper.properties to use Aliyun mirror for Maven distribution
- Add detailed error messages in Makefile when backend startup fails
- Add troubleshooting section in quickstart.md for China developers
- Add FAQ entry for local development startup issues
- Update README with link to local development guide
* docs: simplify runtime script usage
Unify to use runtime.sh for all deployment commands, removing the
distinction between "official images" and "Aliyun mirror". The --aliyun
parameter is preserved for users in China to specify the mirror.
Changes:
- Remove runtime-github.sh references, use runtime.sh uniformly
- Default command uses GHCR images
- Add --aliyun parameter for China users
- Update README.md, README_zh.md, and docs/skillhub/ quickstart files
* docs: consolidate documentation links with clear descriptions
Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment
This makes it easier for users to find the right documentation.
* docs: consolidate documentation links with clear descriptions
Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment
This makes it easier for users to find the right documentation.
* fix: include --home parameter in shutdown command
When starting with a custom --home directory, the generated shutdown
command now includes the same --home parameter to ensure it can find
the correct compose files.
* docs: add Kubernetes deployment guide with overlays structure
- Restructure k8s configs with base/overlays pattern for flexibility
- Add overlays/with-infra for full deployment (PostgreSQL + Redis)
- Add overlays/external for external database scenarios
- Add comprehensive ConfigMap with bootstrap admin settings
- Fix health check path to /actuator/health (auth issue)
- Add SKILLHUB_API_UPSTREAM env for frontend
- Set SESSION_COOKIE_SECURE=false for HTTP environments
- Add Chinese and English documentation in docs/skillhub/
* docs: update k8s README with complete config reference
* docs: simplify runtime script usage
Unify to use runtime.sh for all deployment commands, removing the
distinction between "official images" and "Aliyun mirror". The --aliyun
parameter is preserved for users in China to specify the mirror.
Changes:
- Remove runtime-github.sh references, use runtime.sh uniformly
- Default command uses GHCR images
- Add --aliyun parameter for China users
- Update README.md, README_zh.md, and docs/skillhub/ quickstart files
* docs: consolidate documentation links with clear descriptions
Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment
This makes it easier for users to find the right documentation.
* docs: consolidate documentation links with clear descriptions
Merge the two documentation links into a single "Documentation" section
with clear descriptions of each:
- User Guide: skill publishing, search, CLI usage
- Developer Docs: architecture, API reference, deployment
This makes it easier for users to find the right documentation.
* fix: include --home parameter in shutdown command
When starting with a custom --home directory, the generated shutdown
command now includes the same --home parameter to ensure it can find
the correct compose files.
* docs: add VitePress bilingual documentation site
- Add VitePress-based documentation with Chinese (root) and English (/en/) locales
- Include 6 feature guides: skill-publish, skill-discovery, namespace, review, scanner, social
- Add quickstart, introduction, and FAQ pages
- Include AI-generated diagrams and screenshots
- Add GitHub Pages deployment workflow
- Add Makefile targets: docs-dev, docs-build, docs-preview
* docs: rename docs/claude to docs/skillhub
- Rename documentation directory from docs/claude to docs/skillhub
- Update Makefile paths for docs-dev, docs-build, docs-preview
- Update GitHub workflow paths for deploy-docs.yml
* fix: add enablement parameter to auto-enable GitHub Pages
* Revert "fix: add enablement parameter to auto-enable GitHub Pages"
This reverts commit 11096b1a9b.
* docs: add documentation link to README
Add link to GitHub Pages documentation (https://iflytek.github.io/skillhub/)
under Quick Start section in both English and Chinese README files.
* fix: add --public-url parameter for docker deployment
- Add --public-url parameter to runtime.sh for configuring public access URL
- Create skill.md.template for dynamic URL substitution at container startup
- Update getBaseUrl() to fallback to window.location.host when appBaseUrl is localhost
- Update landing-quick-start.tsx to dynamically generate agent command URL
- Add commandTemplate to i18n files for URL placeholder support
- Update README.md and README_zh.md with deployment parameter documentation
Fixes: Docker deployment shows localhost in install commands and skill.md
* chore(workflow): align local hooks and e2e guidance
* test(e2e): expand reusable api mock helpers
* test(skill): stabilize share button e2e assertions
* chore(test): add e2e make target and tune playwright workers
* test(web): expand e2e coverage and smoke suite
* test(e2e): migrate to real API flows and add request-based data builder
* ci(e2e): add PR workflow for real-service frontend e2e
* ci(e2e): install playwright chromium in PR workflow
* test(e2e): relax timeout and force single worker in CI
* test(e2e): stabilize not-found assertions and harden CI session bootstrap
* chore(agents): align tester role with web/e2e workflow
* feat : 调整本地开发环境
* feat : 调整sse 超时 GlobalExceptionHandler 拦截异常
See :
rg.springframework.web.context.request.async.AsyncRequestTimeoutException: null
at org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor.handleTimeout(TimeoutDeferredResultProcessingInterceptor.java:42) ~[spring-web-6.1.4.jar:6.1.4]
at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterTimeout(DeferredResultInterceptorChain.java:81) ~[spring-web-6.1.4.jar:6.1.4]
at org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$5(WebAsyncManager.java:430) ~[spring-web-6.1.4.jar:6.1.4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) ~[na:na]
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:149) ~[spring-web-6.1.4.jar:6.1.4]
at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:136) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:135) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
* Revert "feat : 调整sse 超时 GlobalExceptionHandler 拦截异常"
This reverts commit 6f0cea85b5daac47025767efe1bd90565b5da469.
* Revert "feat : 调整本地开发环境"
This reverts commit 0695a3d7c823491ce5c83aabe3660ba9997f28c5.
* feat : 调整sse 超时 GlobalExceptionHandler 拦截异常
See :
rg.springframework.web.context.request.async.AsyncRequestTimeoutException: null
at org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor.handleTimeout(TimeoutDeferredResultProcessingInterceptor.java:42) ~[spring-web-6.1.4.jar:6.1.4]
at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterTimeout(DeferredResultInterceptorChain.java:81) ~[spring-web-6.1.4.jar:6.1.4]
at org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$5(WebAsyncManager.java:430) ~[spring-web-6.1.4.jar:6.1.4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) ~[na:na]
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:149) ~[spring-web-6.1.4.jar:6.1.4]
at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:136) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:135) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
* fix(app): stabilize async timeout handling
---------
Co-authored-by: zhaieryuan <zhaieryuan@enn.cn>
Co-authored-by: wowo-zZ <zhenggui5228@126.com>
* fix: increase nginx upload limit and filter Chrome DevTools logs
- Add client_max_body_size 100M to nginx config to allow large skill package uploads
- Silently handle Chrome DevTools .well-known requests to reduce log noise
Fixes#193
* feat(domain): add Unicode slug support with emoji validation
- Update SLUG_PATTERN to support Unicode letters (\p{L}), numbers (\p{N}), and symbols (\p{So})
- Add UPPERCASE_PATTERN to maintain lowercase-only validation
- Modify slugify() to preserve Unicode characters instead of replacing with hyphens
- Add 8 new test cases covering Chinese, Japanese, Korean, emoji, and mixed Unicode slugs
- Maintain backward compatibility with existing ASCII slug validation
- All 16 tests passing
Implements Phase 1 of unicode-slug-support-v1.0-prd.md
* feat(web): add URL encoding for Unicode slugs and improve monospace font support
- Encode skill slugs in all navigation URLs using encodeURIComponent
- Encode slugs in API client methods for proper HTTP request handling
- Update share button to generate properly encoded URLs
- Extend monospace font stack with system fonts for better Unicode support
- All frontend tests pass (506 tests)
Related to Unicode slug support PRD phase 2 and 3
* feat(web): regenerate API types for Unicode slug support
- Update OpenAPI schema types after backend slug validator changes
- Reflects new Unicode-aware slug pattern validation
* remove
* feat(deploy): add scanner service to release deployment
- Add skill-scanner service to compose.release.yml (enabled by default)
- Add scanner image to CI publish-images workflow matrix
- Add --scanner-image and --no-scanner flags to runtime.sh
- Add scanner config to .env.release.example
* fix(docker): add skillhub-notification module to server Dockerfile
* fix(deploy): set scanner mode to upload for container deployment
* fix(deploy): use env override instead of persisting scanner disabled state
* feat(upload): allow xsd, xsl, dtd file types in skill packages
Add XML schema-related file extensions (.xsd, .xsl, .dtd) to the
upload allowlist and text content validation. Users uploading skills
with XML Schema files (e.g., Anthropic's docx skill) were getting
rejected because .xsd was not in the allowed extensions list.
Closes#165
* feat(upload): expand office file allowlist
* test(app): verify publish extension env override
* docs(readme): document upload allowlist override
* test(web): add Playwright e2e testing framework
Add Playwright for end-to-end testing with initial test suites for search flow and network error handling. Also enhance unit tests for network error scenarios.
- Add @playwright/test dependency and npm scripts
- Configure Playwright with chromium browser and HTML reporter
- Add e2e tests for search flow and network error handling
- Update .gitignore to exclude Playwright generated files
- Add network error test cases to api-error unit tests
* feat(web): add skill share button to detail page
Add share button to skill detail page that copies skill info to clipboard. Share text includes skill name, short description (max 30 chars), and detail page URL.
Closes#168
* test(web): add e2e tests for skill share button
Add Playwright e2e tests to verify share button functionality including clipboard copy, text formatting, and state transitions.
* fix(web): fix share button e2e tests and document Playwright workflow
Fix 3 issues in share-button e2e tests:
- Use authenticated mock (skill detail page requires login)
- Add publishedVersion to skill factory (ShareButton render condition)
- Mock versions/files sub-resource APIs to prevent server errors
- Adjust description assertion for 30-char truncation logic
Add Playwright E2E section to CLAUDE.md documenting commands,
screenshot behavior, and test-results directory conventions.
E2E test results: 10/10 passed (Chromium, Playwright 1.58.2)
- network-error.spec.ts: 3/3 passed
- search-flow.spec.ts: 3/3 passed
- share-button.spec.ts: 4/4 passed
* refactor(web): improve share button layout and text format
- Remove description truncation, display full text
- Change share text format from 2 lines to 3 lines (name, description, URL)
- Replace Button component with custom styled native button
- Move ShareButton from card to below download button
- Update tests to match new 3-line format
* fix(web): handle clipboard copy failure in fallback path
- Check document.execCommand('copy') return value
- Throw error when copy fails in fallback path
- Ensure error is properly caught and displayed to user
Fixes issue where "复制 Token 失败,请重试" was shown but the
underlying failure was not properly detected in the fallback code path.
* refactor(web): modernize clipboard with useCopyToClipboard hook
- Add useCopyToClipboard React hook for cleaner state management
- Migrate all copy buttons to use the new hook
- Remove repetitive useState + setTimeout patterns across 7 files
- Simplify clipboard.ts by removing excessive diagnostic logging
- Keep copyToClipboard utility for special cases (file-preview-dialog)
Benefits:
- More idiomatic React code with custom hook
- Consistent 2-second auto-reset behavior
- Reduced code duplication
- Better separation of concerns
* test(web): fix api-error tests and exclude e2e from vitest
- Set i18n language to 'zh' in api-error.test.ts beforeEach
- Add vitest config to exclude e2e directory from unit tests
- All 506 tests now pass
---------
Co-authored-by: xiose <huyanlin@nuaa.edu.cn>