Commit graph

66 commits

Author SHA1 Message Date
XiaoSeS
021cefb311 test(cli): synchronize target lock contenders
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
181e0ba076 fix(cli): use proven cross-process target locks
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
73806c5e6e fix(cli): make stale target lock recovery ownership-safe
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
90260c6019 test(cli): prove shared target lock cleanup
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
b1c6f2c6b4 fix(cli): serialize remove with target upgrades
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
cbb3c009ec fix(cli): reject upgrade targets removed after planning
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
343ab0b6f3 fix(cli): close upgrade commit races
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
35e15f4493 test(cli): keep upgrade assertions registry-scoped
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
397ac78751 test(cli): bind ownership sentinels to each fixture
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
12e04331be test(cli): prove manual ownership remains untouched
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
007a693b9b test(cli): prove upgrade safety invariants
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
229b0dc66f test(cli): use a dead pid for stale lock recovery
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
9adc49212a test(cli): cover upgrade selection and fallback boundaries
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
dea1b4395c fix(cli): make multi-target upgrades failure-safe
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
4ceae76443 fix(cli): harden skill upgrade lifecycle
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
77bd82c302 feat(cli): add source-safe skill upgrades
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-02 09:10:21 +08:00
XiaoSeS
9443731dc4 fix(cli): stabilize namespace sync fingerprints
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-08-29 16:39:27 +08:00
mrLi
84feb38931 feat(cli): add namespace workspace sync
Signed-off-by: mrLi <50289372+15258725278@users.noreply.github.com>
2026-08-18 18:24:11 +08:00
XiaoSeS
13b3f2da92 chore(cli): integrate contributor merge update (#606)
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-29 10:37:03 +08:00
XiaoSeS
a9007a4e8c fix(cli): preserve download error contract (#606)
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-29 10:31:49 +08:00
dongmucat
c1835fc9e9 merge(main): resolve CLI error mapping conflicts (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-29 10:24:23 +08:00
XiaoSeS
ad4a2dbc2f chore(cli): merge main into PR #608
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-29 10:19:03 +08:00
gale-popai
d977ea9dc4
fix(api): tell callers why a request was forbidden (#610)
* fix(api): tell callers why a request was forbidden

The scope filter already computes an exact reason ("Missing API token
scope: skill:delete", "API token cannot access endpoint: /x") and the
access-denied handler discarded it, returning a bare "Forbidden" for
every case: missing scope, endpoint closed to API tokens, and paths
that simply don't exist. Clients cannot tell those apart, so they
guess — the published CLI reports every 403 as "token may lack
required scope", which sent us debugging token scopes for an hour when
the real causes were a revoked token and a mistyped namespace path.

The reason now rides in the response via a new error.forbidden.detail
message (en + zh), and is logged alongside the exception type.

Signed-off-by: Gal Eyal <gal.e@popai.health>

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(api): safely expose API token denial reasons

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

---------

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-28 17:42:20 +08:00
dongmucat
d4d1f65705 fix(cli): scope local remove by namespace (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
6e6cce0588 test(cli): cover all namespace request paths (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
bd83d2d95f fix(cli): reject ambiguous namespace paths (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
b702f0f9f6 test(cli): align namespace error contracts (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
27efaa1b61 docs(cli): document namespace and error behavior (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
3e66c80f94 fix(cli): preserve structured registry errors (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:32 +08:00
dongmucat
95da3cd5e8 fix(cli): normalize namespace coordinates (#606)
Signed-off-by: dongmucat <1127093059@qq.com>
2026-07-28 16:58:31 +08:00
betterlmy
f519b08a73 fix(cli): preflight canonical install targets
Signed-off-by: betterlmy <betterlmy@icloud.com>
2026-07-17 17:20:22 +08:00
betterlmy
8b84201516 feat: add generic user-level agent install target
Signed-off-by: betterlmy <betterlmy@icloud.com>
2026-07-17 11:39:29 +08:00
dongmucat
f8ea4e67e4
feat(cli): support anonymous public search and install
feat(cli): support anonymous public search and install
2026-06-18 14:29:45 +08:00
dongmucat
ea73c305b8
Merge pull request #534 from SenLinLeo/fix/install-target-enter-selection
fix(cli): treat highlighted install target as selected
2026-06-18 09:43:48 +08:00
dongmucat
9520cf63e0 fix(cli): add token auth to search
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-17 11:35:16 +08:00
dongmucat
e50140272b fix(security): close review hardening gaps
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-16 17:48:15 +08:00
SenLinLeo
b44c65443d fix(cli): treat highlighted install target as selected
Signed-off-by: SenLinLeo <1664761477@qq.com>
2026-06-16 16:30:30 +08:00
dongmucat
7d0402e937 fix(security): address review blockers
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-16 14:19:39 +08:00
dongmucat
40d7de8462 fix(security): harden review findings
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-12 14:40:30 +08:00
XiaoSeS
2bb7dedaf4
feat(cli,domain): support non-global namespace skill download (#497)
* feat(cli,domain): support non-global namespace skill download

Parse namespace from skill name using -- separator (e.g.,
astroclaw--api-gateway) so users don't need --namespace flag.
Allow anonymous download for any PUBLIC skill regardless of namespace.

CLI changes:
- Add cli/src/shared/skill-name-parser.ts utility
- Update install and remove commands to parse skill name argument
- 10 unit tests covering edge cases

Domain changes:
- SkillDownloadService.isAnonymousDownloadAllowed: drop namespace
  type check, only require PUBLIC visibility
- Update test to expect success for team-namespace public skill

Synced from SAAS commit 26c67e31b1221249cf9b73321d1b726d8ba6e6df

* fix(cli): use bun:test instead of vitest in skill-name-parser test
2026-06-05 16:20:34 +08:00
dongmucat
c6fa37bb78 Merge branch 'main' into feat/cli-install-scope 2026-05-19 09:48:49 +08:00
dongmucat
60eaf11d3f
Merge pull request #427 from iflytek/worktree-cli-test-migration
test(cli): migrate comprehensive test suite from test/cli-integration-coverage
2026-05-19 09:40:50 +08:00
dongmucat
655adcbcbd test(cli): add 403 scope-denied test for dry-run
Covers the new "access denied — token may lack required scope" error
path with a fake-registry 'forbidden' failure mode. Prevents the
improved 403 message from regressing silently.
2026-05-18 17:36:59 +08:00
dongmucat
a0def9463b chore(cli): improve dry-run test fixture and 403 error message
- Fix test fixture: warnings-only response now uses valid=false to
  match real backend behavior (warnings make dry-run invalid)
- Distinguish 403 from 401 in CLI error messages: 403 now says
  "access denied — token may lack required scope" with a hint to
  regenerate the token, rather than the generic "authentication failed"
2026-05-18 16:42:06 +08:00
dongmucat
943294b558 fix(publish): address Codex review findings for dry-run
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
2026-05-18 14:50:14 +08:00
dongmucat
bdc94ad19c fix(publish): address code review findings for dry-run
- Exit non-zero (code 6) when --dry-run validation fails, enabling
  CI/CD pipeline integration
- Add archived skill check: dry-run now detects when the publisher's
  own skill is archived
- Add version-exists check: dry-run now detects when the resolved
  version is already published
- Use StandardCharsets.UTF_8 for SKILL.md content parsing
2026-05-18 10:57:14 +08:00
dongmucat
1067d0ff6e feat(publish): add --dry-run validation endpoint and CLI option
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
2026-05-18 10:36:58 +08:00
dongmucat
96681b021a fix(cli): label scope by userRoots membership instead of cwd prefix
When --agent is provided without --scope, scope was inferred via
root.startsWith(cwd), which mislabels user roots as project when
cwd === home. Use profile.userRoots(home) membership instead, so the
candidate scope reflects the profile's intent rather than path prefix
overlap. The chosen root path itself is unchanged.
2026-05-15 14:43:25 +08:00
dongmucat
f7ab8f4db7 feat(cli): add --scope option to install command
- Distinguish user vs project install scope via explicit --scope flag
- Interactive mode prompts for scope when --scope/--agent/--dir not provided
- Non-interactive bare install preserves existing behavior (backward compatible)
- Mutual exclusion: --dir cannot be combined with --scope or --agent
- Symmetric fallback: --scope user falls back to ~/.agents/skills,
  --scope project falls back to <cwd>/.agents/skills
- Strict TTY check requires both stdin and stdout TTY plus no --json
- Scope-aware candidate generation avoids root.startsWith(cwd) misjudgement
  when cwd === home or paths overlap
- Correct gemini-cli (.gemini/skills) and kiro-cli (.kiro/skills) paths
  in install path tables across README and guide docs
- Note CLI fallback uses .agents/skills (with s) in skill protocol doc
2026-05-15 14:43:25 +08:00
dongmucat
cf6f6e5680 test(cli): restore NpmRegistryClient unit tests and fix publish test name
Restore 9 deleted unit tests covering registry URL resolution priority,
case-insensitive env lookup, empty env fallback, default registry, non-2xx
responses, invalid JSON, missing version, and invalid registry URL.

Fix misleading test name in publish-command: 503 maps to EXIT.network
(not EXIT.generic) per the 502/503 special-case in skillhub-client.ts.
2026-05-14 16:24:49 +08:00