docs: scope the TechLog contract packageId to satisfy PACKAGE_ID
The platform models contract contributions as published npm packages and rejects an unscoped packageId at composition time. Use @tech-log/studio-contract, the name a real publish would carry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6c40c291d9
commit
a6fc536d8a
@@ -25,6 +25,7 @@
|
||||
- **인증·CSRF·Idempotency는 플랫폼 seam을 쓴다. 직접 헤더를 만들지 않는다.** 계약의 `projectRequest`는 `pathValues`/`queryEntries`/`body`만 만들 수 있고 헤더 채널이 없다(`external-contract-runtime.ts`의 `HttpRequestProjection`). 헤더는 두 경로로만 들어간다.
|
||||
- `Idempotency-Key`: 실행 context의 `intent.idempotencyKey`에서 온다(`http-execution-v3.ts:689-690`). 계약 소유 헤더이므로 credential 쪽에서 공급하면 거절된다(`:657-661`). 명령 gateway는 `intent`를 넘기고 **입력 본문에 `idempotencyKey`를 넣지 않는다**.
|
||||
- `x-csrf-token`: `attachCredentials` collaborator가 공급하고 `admitCredentialHeaders`가 auth profile의 허용 목록으로 검사한다(`http-execution-v3.ts:435, :672`). gateway 입력에 `csrfToken`을 넣지 않는다.
|
||||
- 계약 기여의 `packageId`는 **npm scope 형식**이어야 한다: `PACKAGE_ID = /^@[a-z0-9][a-z0-9._-]{0,62}\/[a-z0-9][a-z0-9._-]{0,62}$/`(`external-contract-runtime.ts:218-219`). scope 없는 이름은 composition 시점에 거절된다. 이 계약의 값은 `@tech-log/studio-contract`다 — 플랫폼이 기여를 게시된 패키지로 모델링하기 때문이며, 실제 배포로 승격할 때 같은 이름을 쓴다.
|
||||
- `frontend.authProfileId`는 `INSTALLED_REST_AUTH_PROFILES`에 등록된 값이어야 한다. 없는 값이면 **composition이 실패한다**(`external-contract-runtime.ts:325-326`). 등록은 Task 3 Step 1이 한다.
|
||||
- `frontend.responseByteLimit`은 **1 이상**이어야 하고(`external-contract-runtime.ts:336-337`) `hardResponseBytes: 8_388_608`을 넘을 수 없다. `requestByteLimit`은 0 이상 `hardRequestBytes: 1_048_576` 이하다.
|
||||
- 매 Task는 red → green → 게이트 → commit 순서를 지킨다.
|
||||
@@ -68,7 +69,7 @@ test("vendored contract matches the recorded canonical digest", () => {
|
||||
});
|
||||
|
||||
test("canonical source records the pinned revision and version", () => {
|
||||
assert.equal(canonicalSource.packageId, "tech-log-studio-contract");
|
||||
assert.equal(canonicalSource.packageId, "@tech-log/studio-contract");
|
||||
assert.equal(canonicalSource.version, "2.0.0");
|
||||
// revision은 생성 시점에 기록된다. canonical 저장소는 활발히 편집 중이므로
|
||||
// 특정 값을 박아두면 계약이 그대로인데도 테스트가 깨진다. 형식만 고정한다.
|
||||
@@ -188,7 +189,7 @@ const canonicalBytes = readFileSync(CANONICAL_YAML);
|
||||
const canonicalText = canonicalBytes.toString("utf8");
|
||||
|
||||
const record: CanonicalRecord = {
|
||||
packageId: "tech-log-studio-contract",
|
||||
packageId: "@tech-log/studio-contract",
|
||||
version: specVersionOf(canonicalText),
|
||||
digest: digestOf(canonicalBytes),
|
||||
sourceRevision: execFileSync(
|
||||
@@ -238,7 +239,7 @@ console.log(
|
||||
- [ ] **Step 5: 생성 실행**
|
||||
|
||||
Run: `corepack pnpm generate:tech-log-contract`
|
||||
Expected: `Generated from tech-log-studio-contract@2.0.0 (<7자리 revision>), 19 operations.`
|
||||
Expected: `Generated from @tech-log/studio-contract@2.0.0 (<7자리 revision>), 19 operations.`
|
||||
|
||||
`generated.ts`의 diff가 크다. `paths`에 `/api/v1/studio/session`, `/api/v1/studio/assets`, `/api/v1/studio/assets/{assetId}`가 생기고 `components.schemas`에 `StudioSession`, `Asset`, `AssetDetail`, `AssetPage`, `AssetUploadForm`, `UpdateAssetCommand`, `AssetUsage`, `AssetKind`, `AssetManagementStatus`가 생기는지 육안 확인한다.
|
||||
|
||||
@@ -998,7 +999,7 @@ Expected: 5 tests PASS
|
||||
- [ ] **Step 7: 계약 집합과 아키텍처 게이트 확인**
|
||||
|
||||
Run: `corepack pnpm check:types:app && corepack pnpm generate:contract-set && corepack pnpm check:architecture`
|
||||
Expected: PASS. `contractSet`에 `tech-log-studio-contract@2.0.0`이 나타난다. `EXTERNAL_PACKAGE`이므로 `TEMPLATE_FIXTURE`와 달리 release digest에 반영된다.
|
||||
Expected: PASS. `contractSet`에 `@tech-log/studio-contract@2.0.0`이 나타난다. `EXTERNAL_PACKAGE`이므로 `TEMPLATE_FIXTURE`와 달리 release digest에 반영된다.
|
||||
|
||||
- [ ] **Step 8: 커밋**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user