Commit graph

230 commits

Author SHA1 Message Date
dongmucat
351dddc912 feat(cli): add SkillHub CLI v1 with full command suite
Implement complete CLI tool for SkillHub with 12 commands, 7 backend API endpoints, and comprehensive documentation.

CLI Commands:
- help, version: Basic information
- login, logout, whoami: Authentication management
- search: Discover published skills
- install: Install skills to agent directories (14 Tier 1 agents supported)
- list, remove, doctor: Local skill management
- publish: Publish skill packages
- update: Self-update mechanism

Backend API:
- Add /api/cli/v1 endpoints for auth, search, resolve, download, delete, publish
- Implement CliAuthController and CliSkillController
- Add security policies for CLI routes
- Full test coverage (19 backend tests)

CLI Implementation:
- TypeScript with strict mode, Bun runtime
- Pure JS zip handling (fflate) for cross-platform compatibility
- 15 agent profiles (14 Tier 1 + generic fallback)
- Secure token storage (0600 permissions)
- Path safety validation for remove operations
- Comprehensive error handling (404/403/network distinction)
- 41 unit and integration tests

Documentation:
- CLI user guide (Chinese and English)
- README updates with quick start
- GitHub Actions workflow for cross-platform CI

Quality:
- lint: 0 errors
- typecheck: pass
- test: 41/41 pass
- build: 0.30 MB (target=node for npm/npx compatibility)
2026-04-29 15:37:04 +08:00
dongmucat
0cc3c46831
Merge pull request #340 from iflytek/feature/web-update-skill
feat(dashboard): add Update button to My Skills with publish prefill
2026-04-24 15:25:04 +08:00
dongmucat
3739c7879b
Merge pull request #305 from iflytek/fix/bootstrap-admin-role-backfill
fix(auth): backfill bootstrap admin role binding
2026-04-23 10:11:43 +08:00
dongmucat
230b915194 feat(dashboard): add Update button to My Skills with publish prefill
Add an "Update" button to each skill card on the My Skills dashboard
page. Clicking it navigates to the Publish page with the skill's
namespace and visibility pre-selected, reducing manual steps when
re-publishing a skill package.

- Add visibility field to SkillSummaryResponse so the list API exposes
  each skill's current visibility setting
- Add publish-prefill module to normalize and validate URL search params
- Wire TanStack Router validateSearch on the publish route
- Add E2E tests covering the prefill flow and invalid-param fallback
2026-04-22 14:59:01 +08:00
dongmucat
f902c6f59b fix(search): restore clawhub namespace-only access 2026-04-21 17:28:05 +08:00
dongmucat
e01c987a82 fix(search): restore clawhub namespace-only access 2026-04-21 09:45:39 +08:00
dongmucat
2c519c8efd fix(search): harden portal search query parsing 2026-04-20 16:57:47 +08:00
wrj97
7be6a36960
feat(auth): add GitLab OAuth2 provider support (#264)
* feat(auth): add GitLab OAuth2 provider support

Add GitLab as an additional OAuth2 authentication provider alongside
GitHub. This includes:

- GitLab OAuth2 client configuration with customizable base URL
- GitLabClaimsExtractor for handling GitLab-specific user claims
- Multi-provider login UI with provider-specific icons
- Updated localization to use OAuth-agnostic terminology
- JSON type annotation for IdentityBinding entity

* fix(auth): restore oauth redirect and gitlab email checks

* test(auth): align oauth login handler expectation

---------

Co-authored-by: wowo-zZ <zhenggui5228@126.com>
2026-04-17 19:56:32 +08:00
XiaoSeS
080be28eef
fix(search): align portal visibility for private skills (#323)
* feat(ci): add AI-powered release notes generation

- Add GitHub Models integration for automated release notes
- Support bilingual (EN) release notes with highlights extraction
- Fallback to conventional commit grouping when LLM unavailable
- Trigger on tag push or manual workflow dispatch
- Zero configuration: uses GitHub Models (gpt-4o-mini) by default

* chore: pin action versions and update gitignore

- Pin checkout and setup-deno to commit hashes matching project convention
- Add .playwright-mcp/ and .mcp.json to gitignore

* fix(search): keep private skills out of portal discovery

- remove super admin expanded visibility from portal search
- exclude all private skills from portal search results
- keep namespace-only skills visible only to namespace members
- reserve private skill access for my-skills and future admin surfaces

* test(search): update test to reflect portal visibility policy

- rename test from platformWideAccessShouldBypass... to platformWideAccessShouldNotBypass...
- verify that platformWideAccess flag does not grant extra visibility in portal search
- verify PRIVATE skills are excluded from search SQL
- aligns test with new requirement: portal search uses standard visibility rules

* test(search): update app service test for portal visibility policy

- rename test from search_shouldGrantPlatformWideAccessToSuperAdmin to search_shouldNotGrantPlatformWideAccessToSuperAdminInPortal
- verify super admin does not get platformWideAccess in portal search
- aligns with requirement: portal uses standard visibility, admin features reserved for dedicated interface
2026-04-17 17:46:05 +08:00
dongmucat
a6f8956549 fix(auth): preserve bootstrap admin profile on backfill 2026-04-15 15:49:42 +08:00
dongmucat
2cfd4a730b
Merge pull request #302 from iflytek/fix/rerelease-precheck-warnings
fix(rerelease): support precheck warning confirmation flow
2026-04-14 20:28:00 +08:00
dongmucat
5d87a0ccd3
Merge pull request #304 from iflytek/feat/oss-02-super-admin-visibility
feat(access): add SUPER_ADMIN platform role support
2026-04-14 20:27:39 +08:00
dongmucat
2334aa6a5a fix(review): avoid stale promotion approval save 2026-04-14 20:02:41 +08:00
xiose
7c2f06d1b6 test(rerelease): add confirmWarnings coverage and sync generated schema
- Add domain tests for rerelease with precheck warnings (reject + confirm)
- Add controller test verifying confirmWarnings passthrough
- Sync SkillVersionRereleaseRequest generated type with backend DTO
2026-04-14 17:55:56 +08:00
dongmucat
1246cca930
Merge pull request #279 from iflytek/fix/issue-276-review-own-namespace
fix(review): allow namespace admins to review own submissions
2026-04-14 17:22:08 +08:00
xiose
edcc248244 fix(portal): keep skill detail on viewer permissions 2026-04-14 16:42:22 +08:00
dongmucat
082d97a69d fix(review): handle promotion target skill conflicts 2026-04-14 16:23:31 +08:00
xiose
a1e4904d97 fix(i18n): update version delete error message to include UPLOADED and SCAN_FAILED
The error message for unsupported version deletion still referenced only
DRAFT/REJECTED. Updated both EN and ZH messages to reflect the actual
deletable statuses: DRAFT, UPLOADED, REJECTED, SCAN_FAILED.

Also updated OSS-02 design doc to mark all blocking items as completed.
2026-04-14 15:49:25 +08:00
dongmucat
e35e99ae59 fix(auth): backfill bootstrap admin role binding 2026-04-14 14:44:08 +08:00
xiose
9801b549fc feat(access): add SUPER_ADMIN platform role support
- Add platformRoles parameter to VisibilityChecker.canAccess() for platform-level access control
- SUPER_ADMIN can access all skills regardless of visibility or publication status
- Add archived namespace check to SkillQueryService.getSkillDetail()
- Extract platformRoles from AuthContext in SkillController
- Replace VisibilityChecker mock with real instance in SkillQueryServiceTest
- Add 5 new tests for SUPER_ADMIN access scenarios
- Add version-status-badge.tsx component for frontend status display

Tests: 347 domain tests + 16 app tests passing
2026-04-14 14:18:43 +08:00
xiose
b597a6f511 merge: resolve conflicts after merging origin/main
- Remove duplicate useSubmitForReview/useConfirmPublish in hooks and client
- Restore resolveVersionStatusLabel (version-status-badge not in this branch)
- Fix missing Card closing tag in versions tab
2026-04-14 13:44:30 +08:00
xiose
b26fe6a364 fix(rerelease): support precheck warning confirmation flow
- Backend: Add confirmWarnings parameter to rerelease DTO, domain service, and app service
- Frontend: Add warning dialog with retry logic when precheck warnings are detected
- i18n: Add rerelease warning dialog translations (en/zh)

Fixes the issue where rereleasing a published version with secret detection warnings
always fails with 400 error. Now follows the same confirm-and-retry pattern as initial publish.
2026-04-14 11:58:15 +08:00
dongmucat
c419a119f1 merge: sync origin/main into fix/security-hardening-unauth 2026-04-14 10:28:25 +08:00
dongmucat
38ebb13133
feat(auth): 邮箱验证码重置密码与 SMTP 配置支持 (#273)
* feat(auth): add email-based password reset with SMTP config docs

* test(e2e): stabilize password reset flow

* test(e2e): isolate password reset rate limits

* test(ci): stabilize backend and register e2e

* docs(auth): sanitize smtp setup examples
2026-04-13 20:27:00 +08:00
dongmucat
1184e00a00
fix(compat): support namespace-aware clawhub publish (#291) 2026-04-13 20:26:42 +08:00
dongmucat
38757084ba fix(review): restore namespace admin review access 2026-04-13 17:03:41 +08:00
XiaoSeS
532d0450aa
feat(skill): add UPLOADED status for PRIVATE skill lifecycle (#290)
* feat(skill): add UPLOADED status for PRIVATE skill lifecycle

## Summary
- Add UPLOADED status for PRIVATE skills after security scan passes
- PRIVATE skill owners can test before confirming publish or submitting for review
- Rerelease now follows visibility rules (PRIVATE→UPLOADED, PUBLIC→PENDING_REVIEW)
- Auto-withdraw changes status to UPLOADED (not DRAFT) to keep versions visible

## Changes
- SkillVersionStatus: Add UPLOADED enum value
- SkillPublishService: PRIVATE skills go to UPLOADED after scan
- SecurityScanService: Visibility-based status transition after scan
- SkillGovernanceService: Withdraw→UPLOADED, delete allows UPLOADED
- SkillQueryService: Include UPLOADED in version list filters
- SkillReviewSubmitService: New service for submit-review and confirm-publish
- SkillLifecycleController: Add submit-review and confirm-publish endpoints
- Frontend: Add buttons, dialogs, and hooks for new operations

## Workflow
- PRIVATE: Publish → SCANNING → UPLOADED → confirm-publish → PUBLISHED
- PUBLIC: Publish → SCANNING → PENDING_REVIEW → PUBLISHED

* feat(review): add backward compatibility for DRAFT status

Support both DRAFT (legacy) and UPLOADED (new flow) status in:
- SkillReviewSubmitService.submitForReview
- SkillReviewSubmitService.confirmPublish
- ReviewService.submitReview (both overloads)

This ensures existing data with DRAFT status continues to work
with the new visibility-based workflow introduced in OSS-02.
2026-04-13 11:39:45 +08:00
xiose
f55c520ebe feat(skill): add UPLOADED status for PRIVATE skill lifecycle
## Summary
- Add UPLOADED status for PRIVATE skills after security scan passes
- PRIVATE skill owners can test before confirming publish or submitting for review
- Rerelease now follows visibility rules (PRIVATE→UPLOADED, PUBLIC→PENDING_REVIEW)
- Auto-withdraw changes status to UPLOADED (not DRAFT) to keep versions visible

## Changes
- SkillVersionStatus: Add UPLOADED enum value
- SkillPublishService: PRIVATE skills go to UPLOADED after scan
- SecurityScanService: Visibility-based status transition after scan
- SkillGovernanceService: Withdraw→UPLOADED, delete allows UPLOADED
- SkillQueryService: Include UPLOADED in version list filters
- SkillReviewSubmitService: New service for submit-review and confirm-publish
- SkillLifecycleController: Add submit-review and confirm-publish endpoints
- Frontend: Add buttons, dialogs, and hooks for new operations

## Workflow
- PRIVATE: Publish → SCANNING → UPLOADED → confirm-publish → PUBLISHED
- PUBLIC: Publish → SCANNING → PENDING_REVIEW → PUBLISHED
2026-04-13 09:26:01 +08:00
wowo
2def67b037
feat(publish): relax pre-publish checks into warning + confirm flow (#288)
* feat(publish): allow warning-confirmed pre-publish checks\n\nFixes #287

* fix(i18n): add missing register validation translation keys

The registration form uses i18n keys like register.usernameInvalid,
register.passwordTooShort etc. but they were never defined in the
locale files, causing E2E tests to fail because the raw key strings
were displayed instead of human-readable messages.
2026-04-12 19:15:57 +08:00
wowo
348eb4e717
fix(storage): defer S3 bucket verification until first access (#289)
* fix(storage): defer S3 bucket verification until first access

* test(storage): cover deferred S3 bucket verification

* fix(runtime): widen backend container healthcheck window

* fix(runtime): widen backend container healthcheck window

* fix(test): use ddl-auto=create to prevent cross-context table drops

Multiple @SpringBootTest classes with different @MockBean configs
cause separate Spring contexts sharing the same H2 in-memory database.
With create-drop, one context's shutdown drops tables needed by another,
causing "Table not found (this database is empty)" errors.

* fix(test): widen awaitIndexedDocument timeout to 15s

CI runners are resource-constrained and async search indexing may not
complete within the previous 5-second window, causing flaky failures.
2026-04-12 15:24:09 +08:00
Uğur Tafralı
02b3ac5b62
fix: add support for .cjs and .mjs JavaScript extensions (#285) 2026-04-11 11:15:36 +08:00
dongmucat
40807e7fa0 test(app): isolate H2 db per Spring test context 2026-04-10 10:12:27 +08:00
dongmucat
27b631a5d6 merge: sync origin/main into fix/security-hardening-unauth 2026-04-10 09:26:19 +08:00
dongmucat
cd7c1ba384
fix(review): correct review queue totals (#265) 2026-04-09 18:12:02 +08:00
dongmucat
b24cc58338
fix(search): include permitted skills in clawhub explore (#258) 2026-04-09 18:11:47 +08:00
dongmucat
44f556037b merge: sync origin/main into fix/security-hardening-unauth 2026-04-09 18:11:35 +08:00
tenten-shih
77e271f24c
Merge pull request #269 from iflytek/pr/exclude-playwright-report
fix register validation, review visibility, and search e2e coverage
2026-04-09 14:37:46 +05:30
wowo
8f694ddc7c
[codex] add issue triage automation mvp (#268)
* add issue triage automation mvp

* Document issue automation design in Chinese

* Fix legacy compat slug tests
2026-04-09 15:04:33 +08:00
huishi3
2167981392 fix(review): sync approval state before returning tasks 2026-04-09 09:56:58 +05:30
Seasoning
739e21e0fd
Feat/namespace member display username (#236)
* 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
2026-04-08 20:02:20 +08:00
dongmucat
441dc9e0e7 fix(security): close unauthorized metrics and compat access paths 2026-04-07 16:24:15 +08:00
dongmucat
0b84e4eff3
fix(compat): support canonical query slug for resolve/download (#227)
Co-authored-by: huihan3 <huihan3@iflytek.com>
2026-04-03 17:27:02 +08:00
eryuan
5d7bee2c58 Pr/fix sse timeout global exception handler (#178)
* 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>
2026-03-31 11:20:42 +08:00
wowo
34de5bb53e feat(upload): allow xsd, xsl, dtd file types in skill packages (#185)
* 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
2026-03-30 18:13:37 +08:00
XiaoSeS
1237d42119 Webclient fix (#173)
* fix(scanner): wire timeout config and create dedicated scanner HttpClient

- Create scanner-specific HttpClient bean with proper timeout configuration
- Wire SkillScannerProperties.connectTimeoutMs (5s) and readTimeoutMs (5min) into WebClient
- Add logging for timeout configuration verification
- Fix cloud environment 5-second timeout issue by ensuring responseTimeout is properly applied

The previous global WebClient.Builder configuration was not being used correctly,
causing scanner requests to timeout after 5 seconds in cloud environment.
This fix creates a dedicated HttpClient for scanner with explicit timeout settings.

* refactor(webclient): use WebClientCustomizer and add scanner connection pool

- Replace singleton WebClient.Builder bean with WebClientCustomizer
  (follows Spring Boot best practice for prototype-scoped builder)
- Add connection pool config to scanner HttpClient (maxConn=10,
  maxIdleTime=20s, evictInBackground=30s) to prevent stale connections
- Add connectTimeout to global WebClient config

* fix(skill): use system default timezone for auto-generated version numbers

- Change AUTO_VERSION_FORMATTER from UTC to ZoneId.systemDefault()
- Version format yyyyMMdd.HHmmss now uses server's local timezone
- Update test to validate format instead of exact value (timezone-independent)

This allows the service to adapt to deployment location:
- Deployed in China → uses Asia/Shanghai timezone
- Deployed in US → uses US timezone
- Follows server's system timezone configuration
2026-03-27 15:41:58 +08:00
XiaoSeS
90c1f3c805 fix(scanner): wire timeout config and create dedicated scanner HttpClient (#166)
- Create scanner-specific HttpClient bean with proper timeout configuration
- Wire SkillScannerProperties.connectTimeoutMs (5s) and readTimeoutMs (5min) into WebClient
- Add logging for timeout configuration verification
- Fix cloud environment 5-second timeout issue by ensuring responseTimeout is properly applied

The previous global WebClient.Builder configuration was not being used correctly,
causing scanner requests to timeout after 5 seconds in cloud environment.
This fix creates a dedicated HttpClient for scanner with explicit timeout settings.
2026-03-27 11:16:07 +08:00
XiaoSeS
175eb8e1ae fix(scanner): stage upload bundles from object storage (#164)
* fix(scanner): stage upload bundles from object storage

* fix(web): wrap long skill detail values
2026-03-26 17:08:23 +08:00
XiaoSeS
86b4d0508b fix(skill): defer version storage deletion until commit (#162)
* fix(skill): resolve duplicate result error when deleting skill with shared namespace+slug

V13 migration changed the unique constraint from (namespace_id, slug) to
(namespace_id, slug, owner_id), allowing multiple skills with the same
namespace+slug but different owners. The findByNamespaceSlugAndSlug query
returned Optional<Skill> which threw IncorrectResultSizeDataAccessException
when 2 rows matched.

Changed the query to return List<Skill> and added ownerId query param to
DELETE endpoints so the frontend can specify exactly which skill to delete.

* fix(review): keep failed scans reviewable and expose feedback

* fix(skill-delete): delete skills by id

* fix(skill): defer version storage deletion until commit
2026-03-26 13:54:30 +08:00
XiaoSeS
a78684ce44 Fix/skill delete duplicate result (#159)
* fix(skill): resolve duplicate result error when deleting skill with shared namespace+slug

V13 migration changed the unique constraint from (namespace_id, slug) to
(namespace_id, slug, owner_id), allowing multiple skills with the same
namespace+slug but different owners. The findByNamespaceSlugAndSlug query
returned Optional<Skill> which threw IncorrectResultSizeDataAccessException
when 2 rows matched.

Changed the query to return List<Skill> and added ownerId query param to
DELETE endpoints so the frontend can specify exactly which skill to delete.

* fix(review): keep failed scans reviewable and expose feedback
2026-03-25 16:15:50 +08:00
XiaoSeS
6020006a25 fix: scanner redis sentinel, publish flush, version delete, clipboard fallback (#157)
* fix(scanner): migrate scan stream to redisson

* fix(web): update security audit pending labels

* fix(scanner): support redis sentinel in redisson config

* fix(db): allow deleting skill versions with audit history

* fix(publish): flush replaced versions before recreation

* fix(i18n): localize agent setup command in Chinese locale

Translate the agent quick-start prompt from English to Chinese and add
a test to verify both locale strings.

* fix(clipboard): add fallback for insecure contexts

navigator.clipboard is undefined in HTTP/iframe/WebView contexts,
causing TypeError on copy. Extract copyToClipboard() utility with
execCommand fallback and apply across all 6 call sites.
2026-03-24 20:26:50 +08:00