* feat(publish): increase max file count from 100 to 500
Configurable via SKILLHUB_PUBLISH_MAX_FILE_COUNT env var.
* feat(publish): support SKILL.md in subdirectory with warning for ignored files
When SKILL.md is found in a single subdirectory (e.g. my-skill/SKILL.md),
promote that directory's contents to root and discard files outside it.
Discarded files are reported as warnings through the existing confirm flow.
* feat(publish): pass extraction warnings through confirm flow
When files are ignored during SKILL.md subdirectory promotion,
warnings are surfaced to the user via the existing precheck confirm dialog.
* fix(security): add invalidSessionStrategy to return 401 on expired session
Handles the case where Spring Security detects an invalid session cookie,
returning a clean 401 JSON response instead of triggering cascading exceptions.
Closes#360 (part 1/2)
* fix(security): handle session invalidation IllegalStateException as 401
Catches IllegalStateException with "Session was invalidated" message and
returns 401 instead of letting it fall through to the generic 500 handler.
Non-session IllegalStateExceptions are re-thrown to the catch-all handler.
Closes#360 (part 2/2)
* feat(publish): filter macOS metadata and add integration tests
Skip __MACOSX/, .DS_Store, and ._ resource fork entries during zip
extraction. Add integration tests for nested SKILL.md warning flow,
session invalidation 401 response, and macOS metadata filtering.
* test(publish): add real-world macOS zip and edge case integration tests
Covers: macOS zip with nested SKILL.md + __MACOSX + .DS_Store + stray files,
simple macOS single-folder case, and missing SKILL.md fallback behavior.
When access-key / secret-key are left blank, fall back to the AWS
DefaultCredentialsProvider chain so that deployments on EC2, ECS,
and EKS can authenticate via instance profile, task role, or IRSA
without static credentials.
- Extract buildCredentialsProvider() in S3StorageService
- Add sts dependency for Web Identity Token (EKS) support
- Add unit tests for credential provider selection
- Update storage-spi docs (zh + en) and env example
Include subscriptionCount in SkillDetailDTO and SkillDetailResponse
so the frontend SubscribeButton receives the updated count after
subscribe/unsubscribe mutations.
Revert emailVerified check in EmailDomainAccessPolicy to preserve
backward compatibility with GitHub/GitLab OAuth users. Instead, null
unverified emails in CustomOidcUserService.toOAuthClaims() so
EmailDomainAccessPolicy naturally denies them via null email.
Add SLF4J logging to CustomOidcUserService for OIDC authentication
flow tracing and failure diagnostics.
Add registration ID collision warning to deployment docs.
- Add null/blank validation for OIDC sub claim in CustomOidcUserService
- Throw OAuth2AuthenticationException when sub is missing or blank
- Complete .env.release.example with all required OIDC environment variables
- Add test cases for sub validation and providerLogin fallback scenarios
- All 5 tests passing
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
* 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