chore(cli): integrate contributor merge update (#606)

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-07-29 10:37:03 +08:00
commit 13b3f2da92
3 changed files with 26 additions and 4 deletions

View file

@ -23,11 +23,12 @@ export function createFakeRegistry(handlers: Record<string, FakeHandler>) {
* Controls how a specific endpoint behaves when a failure is injected:
* 'auth' => 401 { code: 401, message: 'unauthorized' }
* 'forbidden' => 403 with a standard SkillHub error envelope
* 'forbidden_unstructured' => 403 with a non-JSON response body
* 'not_found' => 404 { code: 404, message: 'not found' }
* 'server_error' => 500 { code: 500, message: 'internal error' }
* 'network' => handler throws, causing fetch() to reject with a TypeError
*/
export type FailureMode = 'auth' | 'forbidden' | 'not_found' | 'server_error' | 'network'
export type FailureMode = 'auth' | 'forbidden' | 'forbidden_unstructured' | 'not_found' | 'server_error' | 'network'
function failureResponse(mode: FailureMode): Response {
switch (mode) {
@ -39,6 +40,11 @@ function failureResponse(mode: FailureMode): Response {
msg: 'API token is missing required scope: skill:publish',
requestId: 'req-test-forbidden'
}, { status: 403 })
case 'forbidden_unstructured':
return new Response('<html>sensitive proxy denial</html>', {
status: 403,
headers: { 'Content-Type': 'text/html' }
})
case 'not_found':
return Response.json({ code: 404, message: 'not found' }, { status: 404 })
case 'server_error':

View file

@ -159,7 +159,7 @@ describe('publish --dry-run', () => {
expect(result.stderr).toContain('authentication')
})
test('--dry-run preserves a structured 403 reason and request ID', async () => {
test('--dry-run surfaces the public message and request ID on a structured 403', async () => {
const env = await createTempHome()
registry = await startFakeRegistry({ token: 'sk_ok', failures: { validate: 'forbidden' } })
await login(env, registry.url)
@ -174,4 +174,20 @@ describe('publish --dry-run', () => {
expect(result.stderr).toContain('scope')
expect(result.stderr).toContain('Request ID: req-test-forbidden')
})
test('--dry-run uses a neutral fallback without leaking an unstructured 403 body', async () => {
const env = await createTempHome()
registry = await startFakeRegistry({ token: 'sk_ok', failures: { validate: 'forbidden_unstructured' } })
await login(env, registry.url)
const dir = await makeTempDir(['SKILL.md', '---\nname: test\ndescription: test\n---\n'])
const result = await runCli(['publish', dir, '--dry-run', '--registry', registry.url], {
HOME: env.home,
USERPROFILE: env.home
})
expect(result.exitCode).toBe(2)
expect(result.stderr).toContain('access denied')
expect(result.stderr).not.toContain('sensitive proxy denial')
})
})

View file

@ -16,8 +16,8 @@ revalidation did not recreate historical RED states; it reran the current
GREEN gates with the repository-pinned Bun 1.3.13:
- Focused namespace/error/help regression: 142 tests passed.
- Complete CLI regression: 378 tests passed with
`bun test --max-concurrency=1` (peak RSS 152128 KiB).
- Complete CLI regression: 379 tests passed with
`bun test --max-concurrency=1` (peak RSS 180452 KiB).
- Typecheck, lint, and build passed.
- The packed `@astron-team/skillhub@0.1.9` artifact contained `dist/index.js`,
`README.md`, `CHANGELOG.md`, `LICENSE`, and `package.json`.