@bstage-sdk/core 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -174,7 +174,7 @@ var HttpTimeoutError = class extends Error {
174
174
  };
175
175
 
176
176
  // src/version.ts
177
- var VERSION = "0.8.4";
177
+ var VERSION = "0.8.6";
178
178
 
179
179
  // src/client/BstageClient.ts
180
180
  function resolveBaseUrl() {
package/dist/index.js CHANGED
@@ -119,7 +119,7 @@ var HttpTimeoutError = class extends Error {
119
119
  };
120
120
 
121
121
  // src/version.ts
122
- var VERSION = "0.8.4";
122
+ var VERSION = "0.8.6";
123
123
 
124
124
  // src/client/BstageClient.ts
125
125
  function resolveBaseUrl() {
@@ -59,10 +59,12 @@ liquid, liquid 파일이 없고 `src/pages|slots/**/template.tsx`가 있거나 S
59
59
  실패할 때의 보조 수단이며, 판정 결과와 어긋나면 덮어쓰지 않고 멈춥니다.
60
60
  - `bstage skills install`은 `bstage ai install`의 **deprecated 별칭**입니다. 경고를 출력하고 같은 일을
61
61
  하며 다음 릴리즈에서 제거됩니다.
62
- - `bstage doctor`는 진단에 더해 **SDK 소유 스킬만** 자동 동기화합니다. `package.json`과 `.husky`는
63
- 건드리지 않으므로, pre-commit 시크릿 가드는 `bstage ai install`로 설치하세요.
62
+ - `bstage doctor`는 진단에 더해 **스킬이 어긋났을 때만** `bstage ai install`과 같은 동기화를 자동으로
63
+ 합니다 — 스킬뿐 아니라 `AGENTS.md` 관리 영역 갱신과 없는 `AGENTS.md`·`CLAUDE.md` 생성까지 포함됩니다.
64
+ `--json`으로 실행하면 아무것도 쓰지 않습니다. `package.json`과 `.husky`는 건드리지 않으므로,
65
+ pre-commit 시크릿 가드는 `bstage ai install`로 설치하세요.
64
66
 
65
- `doctor`의 종료 코드는 전부 최신이면 0, 하나라도 어긋나면 2입니다. 상태 값은 `ok` · `stale` · `missing` ·
67
+ `bstage ai doctor`의 종료 코드는 전부 최신이면 0, 하나라도 어긋나면 2입니다(`bstage doctor`의 종료 코드 0·1과는 별개입니다). 상태 값은 `ok` · `stale` · `missing` ·
66
68
  `extra`이며, **`extra`(지금 kind에 속하지 않는 SDK 스킬이 남아 있음)는 경고일 뿐 종료 코드에 영향을 주지
67
69
  않습니다.** 혼합 레포에서는 어느 SDK 스킬도 `extra`가 아닙니다(두 세트가 모두 대상). 설치가 남의 파일을 지우지 않는 것이 설계라, 실패로 치면 사람이 손으로 지울 때까지 CI가 계속
68
70
  빨간불이 되기 때문입니다.
@@ -57,7 +57,7 @@ Vite 빌드라서 `import.meta.env.VITE_BSTAGE_*`는 **빌드 시점에 문자
57
57
 
58
58
  - **대상 판정** — 두 조건을 모두 만족할 때만 점검합니다.
59
59
  1. 번들에 BstageClient의 앱 ID 헤더(`X-BSTAGE-APP-ID`)가 있을 것. API를 쓰지 않는 UI 전용 템플릿은 `client.ts`를 스캐폴드만 하고 import하지 않으면 트리셰이킹으로 사라지므로 대상이 아닙니다.
60
- 2. 소스가 `import.meta.env.VITE_BSTAGE_*`를 참조할 것. cli 0.40.1 이전 스캐폴드처럼 `client.ts`에 키를 리터럴로 박은 프로젝트는 `.env`가 없는 게 정상이므로(그 전환은 마이그레이션에서 `선택`) 대상이 아닙니다. 참조한 변수만 검사합니다.
60
+ 2. 소스가 `import.meta.env.VITE_BSTAGE_*`를 참조할 것. 옛 스캐폴드처럼 `client.ts`에 키를 리터럴로 박은 프로젝트는 `.env`가 없는 게 정상이므로(그 전환은 마이그레이션에서 `선택`) 대상이 아닙니다. 참조한 변수만 검사합니다.
61
61
  - **검사 항목** — 값 누락, 자리표시자(`YOUR_APP_ID` 등) 잔존, appId·appKey 뒤바뀜, 접두사(`bsa_`/`bsp_`) 불일치. 앱 키는 `VITE_BSTAGE_APP_KEY`(정본)와 옛 이름 `VITE_BSTAGE_APP_SECRET`을 한 값으로 보며, 한쪽만 있으면 빌드가 다른 이름으로도 읽히게 이어 붙인다
62
62
  - **env 해석** — Vite의 `loadEnv`를 그대로 씁니다. `.env` 파일뿐 아니라 CI가 `process.env`로 주입한 값도 번들에 인라인되므로 파일만 읽으면 오탐이 납니다.
63
63
  - **빌드를 실패시키지 않습니다** — 값이 비어도 번들 자체는 정상적으로 나오고, 여기서 실패시키면 기존 소비자 CI가 깨집니다. 경고는 빌드 로그 맨 끝에 출력됩니다.
@@ -583,9 +583,10 @@ npx @bstage-sdk/cli@latest init --target admin
583
583
  | 허가된 앱인가 | `X-BSTAGE-APP-ID`·`X-BSTAGE-APP-KEY` 헤더 — **관리자 콘솔용(MANAGEMENT) 키**(`bsm_`)만 통과합니다 | `.env`와 포털 빌드 환경변수에 MANAGEMENT 키를 넣습니다 |
584
584
 
585
585
  - **키 발급**: 포털 `조직 › API 키`에서 키 타입 **MANAGEMENT**, 스테이지는 이 화면이 들어갈 **하나**, 허용 Origin은 **어드민 콘솔 도메인**(예: sandbox는 `https://{스테이지ID}.mysandstage.in`)으로 발급합니다. 허용 Origin에 자동으로 채워지는 값은 유저 도메인이라 그대로 두면 어드민에서 온 호출이 거부됩니다. 변수 이름은 유저 템플릿과 같고 값만 다릅니다 — `VITE_BSTAGE_APP_KEY=bsm_…`.
586
- - **Surface와 키 타입은 짝입니다** — USER ↔ PUBLIC(`bsp_`), ADMIN ↔ MANAGEMENT(`bsm_`). PUBLIC 키로 어드민 게이트웨이를 부르면 `401 KEY_TYPE_NOT_ALLOWED`, 어드민에 로그인하지 않았거나 어드민 도메인 밖에서 부르면 `401 MISSING_ADMIN_ACCESS_TOKEN`, 허용 Origin이 유저 도메인으로 남아 있으면 `403`입니다. 반대로 MANAGEMENT 키를 유저 템플릿에 넣으면 유저 게이트웨이가 거부하고 키만 노출됩니다.
587
- - **MANAGEMENT 키도 빌드 결과물에 평문으로 실립니다.** 어드민 화면을 열 수 있는 사람은 개발자 도구로 볼 수 있으므로, 허용 Origin과 스테이지 범위를 좁히는 발급 조건이 곧 방어선입니다. 의심되면 포털에서 회전(새 키 발급 + 옛 키 폐기)한 뒤 빌드 환경변수를 바꾸고 다시 빌드합니다. 서버용(SIGNING) 키는 어떤 템플릿에도 넣지 않습니다.
586
+ - **Surface와 키 타입은 짝입니다** — USER ↔ PUBLIC(`bsp_`), ADMIN ↔ MANAGEMENT(`bsm_`). PUBLIC 키로 어드민 게이트웨이를 부르면 `401 KEY_TYPE_NOT_ALLOWED`, 어드민에 로그인하지 않았거나 어드민 도메인 밖에서 부르면 `401 MISSING_ADMIN_ACCESS_TOKEN`, 허용 Origin이 유저 도메인으로 남아 있으면 `403`입니다. 반대로 MANAGEMENT 키를 유저 템플릿에 넣으면 유저 게이트웨이가 거부하고 키만 노출됩니다 — 그래서 포털은 사용자(USER) 레포의 빌드 환경변수에 `bsm_` 값을 저장하지 않습니다(400). 게시한 뒤에는 `bstage doctor`가 키 타입 불일치(`appkey.type_surface`)를 짚어 줍니다.
587
+ - **MANAGEMENT 키도 빌드 결과물에 평문으로 실립니다.** 어드민 화면을 열 수 있는 사람은 개발자 도구로 볼 수 있으므로, 허용 Origin과 스테이지 범위를 좁히는 발급 조건이 곧 방어선입니다. 의심되면 포털에서 회전(새 키 발급 + 옛 키 즉시 만료)한 뒤 빌드 환경변수를 바꾸고 다시 빌드합니다 — 회전하면 APP KEY뿐 아니라 **APP ID도 새 값**이므로 둘 다 바꿉니다. 서버용(SIGNING) 키는 어떤 템플릿에도 넣지 않습니다.
588
588
  - **호출할 수 있는 API**는 포털 개발자 문서의 **API 레퍼런스 › 운영자 탭**에 있는 것뿐입니다. 거기 없는 경로를 추측해 만들지 말고, 필요한 API가 목록에 없으면 b.stage에 요청하세요.
589
+ - **포털은 빌드 환경변수 저장 시점에 거부합니다**(400): 키 이름이 `^VITE_[A-Z0-9_]+$`가 아니거나 32개 초과·이름 128자 초과·값 2048자 초과, 앞뒤 공백을 뺀 값이 `bss_`로 시작(모든 레포)하거나 `bsm_`로 시작(사용자 레포), APP ID·APP KEY가 그 스테이지 키와 맞지 않음(공백 포함·없는 키·만료/폐기·스테이지 범위 밖·짝이 아닌 KEY — 파트너 조회가 실패하면 이 검사는 건너뜁니다).
589
590
  - **로컬·미리보기에서는 응답이 오지 않습니다.** `bstage dev`는 어드민 게이트웨이를 프록시하지 않고(어드민 모드에서 어드민 호스트로 가는 것은 로그인뿐), 포털 미리보기는 템플릿의 직접 게이트웨이 호출을 막습니다. 어드민 API 응답은 게시한 뒤 실제 어드민 화면에서 확인하세요.
590
591
 
591
592
  ---
@@ -631,7 +632,7 @@ CI에서는 `BSTAGE_TOKEN`·`BSTAGE_PORTAL_URL`(또는 `VITE_BSTAGE_PHASE`)·`BS
631
632
  | `rollback [buildId]` | 이전 성공 빌드 재적용 |
632
633
  | `publish on\|off` | 게시 토글 (라이브 버전은 유지) |
633
634
 
634
- 확인 프롬프트가 있는 명령(`deploy`·`rollback`·`publish`·`link`)에서 `--json`은 프롬프트와 섞일 수 없어 **`--yes`와 함께**만 쓸 수 있습니다(`list`·`logs`·`whoami`는 `--json`만으로 됩니다). 출력은 stdout에 객체 **하나**뿐입니다. `deploy`·`rollback`·`publish`는 같은 모양을 씁니다 — 명령마다 다르게 파싱하지 않아도 됩니다.
635
+ 확인 프롬프트가 있는 명령(`deploy`·`rollback`·`publish`·`link`·`placement create`)에서 `--json`은 프롬프트와 섞일 수 없어 **`--yes`와 함께**만 쓸 수 있습니다(`list`·`logs`·`whoami`는 `--json`만으로 됩니다). 출력은 stdout에 객체 **하나**뿐입니다. `deploy`·`rollback`·`publish`는 같은 모양을 씁니다 — 명령마다 다르게 파싱하지 않아도 됩니다.
635
636
 
636
637
  | 키 | 내용 |
637
638
  | ------------- | ----------------------------------------------------- |
@@ -647,7 +648,7 @@ CI에서는 `BSTAGE_TOKEN`·`BSTAGE_PORTAL_URL`(또는 `VITE_BSTAGE_PHASE`)·`BS
647
648
 
648
649
  위젯(슬롯) 배치를 만드는 일과 배치를 지우는 일은 포털 화면에서만 합니다.
649
650
 
650
- **배포했는데 페이지가 기대와 다르면 `bstage doctor`부터 실행하세요.** 로그인·링크된 디렉터리에서는 로컬 진단 뒤에 "포털 진단" 절이 붙어, 이 레포의 배치마다 포털이 판정한 문제(게시 꺼짐, 게시된 빌드 없음, 만료·불일치한 앱 키, 다시 빌드하지 않은 환경변수, 반영 안 된 새 빌드 등)를 조치와 함께 보여 줍니다. 배치가 많으면 30개까지만 보고, `--placement <id|경로|슬롯 id>`로 하나만 볼 수 있습니다. `--json`은 `portal.placements[].findings[]`에 `{ id, severity, title, detail?, fix?, evidence? }`를 담고 `id`(예: `appkey.expired`)는 바뀌지 않는 식별자입니다. 진단에 `error` 항목이 있으면 종료 코드 1입니다. 로그인·링크가 없거나 포털이 아직 진단을 지원하지 않으면 그 절만 건너뜁니다(단 `--placement`를 줬으면 위 표대로 2·3으로 끝납니다).
651
+ **배포했는데 페이지가 기대와 다르면 `bstage doctor`부터 실행하세요.** 로그인·링크된 디렉터리에서는 로컬 진단 뒤에 "포털 진단" 절이 붙어, 이 레포의 배치마다 포털이 판정한 문제(게시 꺼짐, 게시된 빌드 없음, 만료·불일치한 앱 키, 화면과 맞지 않는 키 타입, 다시 빌드하지 않은 환경변수, 반영 안 된 새 빌드 등)를 조치와 함께 보여 줍니다. 14일 안에 만료되는 키는 경고(`appkey.expiring_soon`)로 미리 알려 줍니다. 배치가 많으면 30개까지만 보고, `--placement <id|경로|슬롯 id>`로 하나만 볼 수 있습니다. `--json`은 `portal.placements[].findings[]`에 `{ id, severity, title, detail?, fix?, evidence? }`를 담고 `id`(예: `appkey.expired`)는 바뀌지 않는 식별자입니다. 진단에 `error` 항목이 있거나 **포털 진단 자체가 실패하면**(`portal.status`가 `error` — 이유는 `portal.reason`·`portal.placements[].error`) 종료 코드 1입니다(`warn`·`info`는 종료 코드를 바꾸지 않습니다). 로그인·링크가 없거나 포털이 아직 진단을 지원하지 않으면 그 절만 건너뜁니다(단 `--placement`를 줬으면 위 표대로 링크 없음은 2, 토큰 없음은 3이고, 이 레포에 맞는 배치가 없어도 2로 끝납니다).
651
652
 
652
653
  로컬에서 산출물을 확인하고 싶으면 `npx bstage build`를 실행합니다. 페이지는 `dist/{경로}/template.js`, 위젯은 `dist/{슬롯 id}/template.js`로 나옵니다.
653
654
 
@@ -668,13 +669,13 @@ CI에서는 `BSTAGE_TOKEN`·`BSTAGE_PORTAL_URL`(또는 `VITE_BSTAGE_PHASE`)·`BS
668
669
 
669
670
  ### 9.2 배포 전 점검 — 증상으로 원인 되짚기
670
671
 
671
- 아래 항목은 **SDK가 감지할 수 없습니다.** 키 형식(`bsa_`/`bsp_`)은 ID·시크릿 구분일 뿐 어느 환경에서 발급했는지를 담지 않습니다. 나머지는 BE·콘솔 설정이라 코드에 흔적이 없습니다. 리얼 배포 후 아래 에러를 만나면 이 표로 되짚으세요.
672
+ 아래 항목은 **빌드 시점에는 감지할 수 없습니다.** 키 형식(`bsa_`/`bsp_`)은 ID·시크릿 구분일 뿐 어느 환경에서 발급했는지를 담지 않고, 나머지는 BE·콘솔 설정이라 코드에 흔적이 없습니다. 게시한 뒤에는 `bstage doctor`의 포털 진단이 일부(키 문제, 커스텀 템플릿 토글)를 짚어 줍니다. 리얼 배포 후 아래 에러를 만나면 이 표로 되짚으세요.
672
673
 
673
674
  | 증상 | 원인 | 조치 | 소관 |
674
675
  | ----------------------- | ---------------------------------------- | -------------------------------------------- | ------------ |
675
- | `401 Unauthorized` | 다른 환경(QA 등)의 키로 배포 / 키 미발급 | 배포할 환경에서 발급한 appId·appKey인지 확인 | 파트너 콘솔 |
676
+ | `401 Unauthorized` | 다른 환경(QA 등)의 키로 배포 / 키 미발급 / 재발급 전 옛 APP ID | 배포할 환경에서 발급한 사용 중인 appId·appKey인지 확인(`bstage doctor`가 알려 줌) | 파트너 콘솔 |
676
677
  | `403 Forbidden` | Space ID가 프로젝트에 미등록 | BE에 Space ID 등록 요청 | BE |
677
- | `400 MISSING_ORIGIN` | 키의 Allowed Origins에 배포 도메인 없음 | 배포 도메인을 키 설정에 추가 요청 | BE (키 설정) |
678
+ | `403 ORIGIN_NOT_ALLOWED` | 키의 허용 Origin에 배포 도메인 없음(끝의 `/`·대문자도 다른 값) | 키 상세에서 허용 Origin에 `https://{도메인}` 그대로 추가, 재빌드 불필요 | 포털 (키 설정) |
678
679
  | 템플릿이 화면에 안 뜸 | 콘솔 "커스텀 템플릿 사용" 토글이 꺼짐 | 콘솔에서 토글 확인 | 콘솔 |
679
680
  | 배포 자체가 안 됨 | 데브포털 접근·리얼 배포 권한 없음 | 권한 요청 | DevOps |
680
681
  | 임베드(iframe)가 차단됨 | CSP `frame-ancestors`에 도메인 없음 | 도메인 추가 요청 | BE·보안 |
package/docs/MIGRATION.md CHANGED
@@ -7,7 +7,7 @@
7
7
  - **누가 쓰나**: SDK 작성자. 소비자 영향이 있는 변경을 릴리즈하는 **그 시점에** 항목을 추가한다. 마이그레이션할 때 만드는 게 아니라 미리 쌓아둔다.
8
8
  - **누가 읽나**: 소비자 프로젝트의 마이그레이션 도구(아래)와 사람.
9
9
  - **어디에 실리나**: `docs/`는 core 패키지 배포물에 포함되므로, 소비자는 `node_modules/@bstage-sdk/core/docs/MIGRATION.md`로 이 파일을 본다. cli도 빌드 시 `dist/MIGRATION.md`로 같은 파일을 복사해 `bstage doctor`가 동일 가이드를 읽는다.
10
- - **파일 배포 버전 ≠ 항목 헤더 버전**: 이 파일이 **실려 나가는** 버전(core)과 각 항목 헤더의 버전은 별개다. 패키지는 완전 독립 버전(cli·core·react·host·design이 서로 다른 버전 라인)이라, 항목 헤더는 그 변경을 **실제로 낸 패키지**의 버전을 가리킨다(대개 cli·react이며 core가 아닐 수 있다). 즉 core를 설치한 소비자도 헤더가 `cli 0.43.0`인 항목을 적용하려면 **cli**를 0.43.0 이상으로 올려야 한다.
10
+ - **버전 라인과 항목 헤더**: 공개 패키지(cli·core·react·host·design·ai-toolkit)는 **한 버전 라인을 함께 쓴다** — 릴리즈마다 모든 패키지가 같은 번호로 나간다. 항목 헤더는 그중 그 변경을 **실제로 낸 패키지**를 가리키므로(대개 cli·react·ai-toolkit이며 이 파일이 실려 나가는 core가 아닐 수 있다), 헤더가 `cli 0.8.5`인 항목을 적용하려면 **cli**를 0.8.5 이상으로 올려야 한다.
11
11
 
12
12
  ## 마이그레이션이 동작하는 방식
13
13
 
@@ -20,13 +20,13 @@
20
20
 
21
21
  ### 도구
22
22
 
23
- - **감지**: `bstage doctor` (`npx @bstage-sdk/cli@latest doctor`). 버전 드리프트·보일러플레이트 누락·적용 가능한 마이그레이션 항목을 read-only로 보고한다. `--json`으로 구조화 출력.
23
+ - **감지**: `bstage doctor` (`npx @bstage-sdk/cli@latest doctor`). 버전 드리프트·보일러플레이트 누락·적용 가능한 마이그레이션 항목을 보고한다. 진단 자체는 프로젝트 코드를 고치지 않지만, `--json` 없이 실행하면 SDK가 관리하는 스킬이 뒤처졌을 때 `ai install`과 같은 동기화(스킬·`AGENTS.md` 관리 영역, 없는 `AGENTS.md`·`CLAUDE.md` 생성)를 자동으로 한다. `--json`은 구조화 출력이며 아무것도 쓰지 않는다.
24
24
  - **변환**: `bstage-migrate` 스킬 (`.claude/skills/bstage-migrate/SKILL.md`). doctor 출력과 이 문서를 읽고 프로젝트에 맞춰 적용한다.
25
25
 
26
26
  ### 마이그레이션 스킬 부트스트랩
27
27
 
28
28
  - **새 프로젝트** (이 기능 도입 이후 `bstage init`): `.claude/skills/`에 스킬이 이미 들어 있다. 별도 작업 없음.
29
- - **옛 프로젝트**: `npx @bstage-sdk/cli@latest skills install`로 스킬을 설치한다(`.claude/skills/`에 기록). SDK 버전업 후 다시 실행하면 최신으로 동기화된다. 스킬이 없어도 `bstage doctor` 출력 + 이 문서만으로 AI가 마이그레이션을 진행할 수 있다.
29
+ - **옛 프로젝트**: `npx @bstage-sdk/cli@latest ai install`로 스킬을 설치한다(`.claude/skills/`에 기록). SDK 버전업 후 다시 실행하면 최신으로 동기화된다. 스킬이 없어도 `bstage doctor` 출력 + 이 문서만으로 AI가 마이그레이션을 진행할 수 있다.
30
30
 
31
31
  ## 항목 작성 규칙
32
32
 
@@ -43,14 +43,67 @@
43
43
  - **변경 내용** — 무엇이 왜 바뀌었는지 (배경은 한 줄, 상세는 관련 docs 링크)
44
44
  - **적용** — 단계. 자동 단계와 판단 단계를 구분해서 적는다.
45
45
 
46
- > **`적용` 단계는 옛 프로젝트에서 실제로 따라가 본 뒤 적는다.** 새 `bstage init` 프로젝트에서 되는 것과, 기존 프로젝트가 이 절차만 보고 도달하는 것은 다르다. 따라 했을 때 깨지는 선행 조건이 있으면 **그 조건까지 적는다** — `core 0.44.0` 항목이 그 사례다(스크립트만 넣으면 `@types/node` 부재로 `TS2688`이 난다. 스캐폴드 템플릿을 고쳐 새 프로젝트는 해결됐지만, 먼저 써둔 적용 절차를 되짚지 않아 기존 프로젝트용 지침이 깨진 채 남았다).
46
+ > **`적용` 단계는 옛 프로젝트에서 실제로 따라가 본 뒤 적는다.** 새 `bstage init` 프로젝트에서 되는 것과, 기존 프로젝트가 이 절차만 보고 도달하는 것은 다르다. 따라 했을 때 깨지는 선행 조건이 있으면 **그 조건까지 적는다** — 스크립트를 추가하던 항목이 그 사례다(스크립트만 넣으면 `@types/node` 부재로 `TS2688`이 난다. 스캐폴드 템플릿을 고쳐 새 프로젝트는 해결됐지만, 먼저 써둔 적용 절차를 되짚지 않아 기존 프로젝트용 지침이 깨진 채 남았다).
47
47
 
48
- > **헤더 규칙**: `## → {패키지} {버전}` 형식으로, 그 변경을 실제로 낸 패키지와 버전을 명시한다(예: `→ cli 0.3.0`, `→ core 0.3.0`). 한 변경이 여러 패키지를 함께 범프시켰으면 소비자가 올려야 할 패키지를 `·`로 나열한다(예: `→ core 0.3.0 · cli 0.3.0`). 소비자는 이 헤더의 패키지를 해당 버전 **이상**으로 올려야 한다. 단순 의존성 재핀(dependency bump)만 된 패키지는 헤더에 적지 않는다.
48
+ > **헤더 규칙**: `## → {패키지} {버전}` 형식으로, 그 변경을 실제로 낸 패키지와 버전을 명시한다(예: `→ cli 0.8.5`, `→ core 0.3.0`). 한 변경이 여러 패키지를 함께 범프시켰으면 소비자가 올려야 할 패키지를 `·`로 나열한다(예: `→ cli 0.8.5 · ai-toolkit 0.8.5`). 소비자는 이 헤더의 패키지를 해당 버전 **이상**으로 올려야 한다. 단순 의존성 재핀(dependency bump)만 된 패키지는 헤더에 적지 않는다.
49
49
  >
50
- > **정렬**: 릴리즈 **시점 최신이 위**. 패키지가 독립 버전이라 헤더 숫자만으로는 시간순 정렬이 되지 않으므로 릴리즈 순서를 기준으로 한다.
50
+ > **정렬**: 릴리즈 **시점 최신이 위**. 공개 패키지는 한 버전 라인을 쓰므로 헤더 숫자 순서가 곧 릴리즈 순서다.
51
51
 
52
52
  ---
53
53
 
54
+ ## → ai-toolkit 0.8.6
55
+
56
+ ### `bstage doctor` 종료 코드·동작 안내 정정(에이전트 스킬) — `자동`
57
+
58
+ **영향**
59
+
60
+ - 코드·빌드 동작은 바뀌지 않는다. 에이전트 스킬 본문만 바로잡았다.
61
+ - `bstage-deploy`·`bstage-migrate`·`bstage-onboarding` 스킬이 `bstage doctor`의 종료 코드 1을 "진단에 error 항목이 있을 때"로만 안내했고, doctor를 "파일을 고치지 않는다"고 적었다.
62
+
63
+ **변경 내용**
64
+
65
+ - `bstage-deploy`: 포털 진단 자체가 실패해도(`portal.status`가 `error`) 종료 코드 1이다. 이때 `reason`·`placements[].error`를 읽고, 권한 부족이면 계정 권한·CLI 토큰 등급부터 확인하도록 안내한다.
66
+ - `bstage-migrate`: `doctor --json`이 종료 코드 1이어도 JSON은 정상이며, 포털 진단 결과는 마이그레이션과 무관하다는 점을 적었다. "세 가지"로 적혀 있던 출력 항목 수를 네 가지로 바로잡았다.
67
+ - `bstage-onboarding`: doctor가 포털 진단을 함께 보고, `--json` 없이 실행하면 SDK 소유 스킬을 자동 동기화한다는 점을 적었다.
68
+
69
+ **적용**
70
+
71
+ 1. (자동) `npx @bstage-sdk/cli@latest ai update` — 스킬을 갱신한다.
72
+
73
+ ## → cli 0.8.5 · ai-toolkit 0.8.5
74
+
75
+ ### `bstage doctor`: 포털 진단이 실패해도 종료 코드 1 — `자동` · `선택`
76
+
77
+ **영향**
78
+
79
+ - CI·스크립트·에이전트가 `bstage doctor`의 종료 코드를 보는 프로젝트. 로그인·링크가 없는 환경(포털 진단 `skipped`)은 영향이 없다.
80
+
81
+ **변경 내용**
82
+
83
+ - 포털 진단 자체가 실패하면 — 배치 목록 조회 실패, 일부 배치 진단의 권한 부족(403)·서버 오류(5xx) 등으로 `portal.status`가 `"error"`면 — 종료 코드 **1**로 끝난다. 전에는 `error` 심각도 항목이 없으면 0이라, 진단을 못 끝낸 것을 "문제 없음"으로 읽을 수 있었다.
84
+ - 그대로인 것: `error` 항목이 있으면 1, 건너뜀(`skipped`)·서버 미지원(`unsupported`)·`warn`/`info`만 있으면 0, 로컬 진단 결과는 종료 코드에 영향 없음.
85
+
86
+ **적용**
87
+
88
+ 1. (자동) CLI를 올린다. 종료 코드 1을 실패로 처리하던 CI는 그대로 동작한다. 1이 나오면 `--json`의 `portal.status`·`portal.reason`·`portal.placements[].error`로 원인을 본다(권한 부족이면 스테이지 관리 권한이 있는 계정·토큰인지 확인).
89
+
90
+ ### 어드민 템플릿도 `BstageClient`로 어드민 API를 부른다(에이전트 안내 정정) — `자동`
91
+
92
+ **영향**
93
+
94
+ - 코드·빌드 동작은 바뀌지 않는다. 에이전트 안내 문서만 바로잡았다.
95
+ - `AGENTS.md` 관리 영역과 `bstage-template` 스킬이 "BstageClient는 유저단 API만 지원하고 어드민용 API는 미지원"이라고 안내했다. 어드민 게이트웨이가 열린 지금 이 문구를 따르면 에이전트가 어드민 템플릿의 데이터 호출을 거부하거나 사용자 확인을 되풀이한다.
96
+
97
+ **변경 내용**
98
+
99
+ - 어드민 템플릿도 같은 `BstageClient`를 쓴다. 어드민 도메인에 임베드되면 `baseUrl` 기본값이 어드민 게이트웨이(`/gw`)가 되고, 게이트웨이가 어드민 로그인 쿠키와 MANAGEMENT 키(`bsm_`)를 함께 확인한다. PUBLIC 키로는 `KEY_TYPE_NOT_ALLOWED`다.
100
+ - 호출 가능한 경로는 포털 API 레퍼런스(유저/운영자 탭)에 있는 것뿐이며, 목록에 없는 API는 경로를 추측하지 말고 사용자에게 먼저 확인한다는 안내는 그대로다.
101
+ - **AGENTS.md 관리 영역 v17**: 파일 트리의 `client.ts` 설명과 API 금지 사항 절을 위 내용으로 고쳤다. `bstage-template` 스킬도 같은 내용으로 고쳤다. 상세는 [GETTING_STARTED.md](./GETTING_STARTED.md) "8. 어드민 템플릿 › API 호출".
102
+
103
+ **적용**
104
+
105
+ 1. (자동) `npx @bstage-sdk/cli@latest ai update` — 스킬·`AGENTS.md` 관리 영역을 v17로 갱신한다.
106
+
54
107
  ## → cli 0.8.4 · ai-toolkit 0.8.4
55
108
 
56
109
  ### `bstage doctor`가 포털 배치 진단을 함께 본다 — `자동` · `선택`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bstage-sdk/core",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "bstage SDK core — HTTP client for b.stage API",
5
5
  "type": "module",
6
6
  "publishConfig": {