Reference 를 공개했는데 Studio 에서는 다 보이고 공개 화면만 비어 있었다. 게이트웨이가 읽던 이름이 계약에 없는 것들이었다 — `purposeSummary`, `applyWhenMarkdown`, `exceptionsMarkdown`, `examplesMarkdown`. 계약이 주는 이름은 `scopeSummary`, `appliesTo`, `excludedScope` 다. 전부 undefined 로 떨어졌고, `as string` 단언 때문에 타입 검사는 아무 말도 하지 않았다. 규칙은 `content` 마크다운을 잘라 만들고 있었다. Reference 의 본문은 마크다운 한 덩어리가 아니라 제목이 붙은 규칙의 목록이고, Studio 의 편집기가 그렇게 받아 `body_markdown` 은 비워 둔다 — 자를 것이 없으니 언제나 빈 목록이었다. 계약이 구조로 주는 것을 그대로 쓴다. 값이 아니라 이름을 지키는 테스트를 둔다. 계약에서 그 칸이 사라지면 `satisfies` 가 먼저 깨진다 — 이번 결함은 값을 검사해서는 잡히지 않았다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XEHXspz4rv5pB5wiiSsVDu
69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
import { strict as assert } from "node:assert";
|
|
import { test } from "vitest";
|
|
|
|
import type { components } from "../../../src/features/tech-log/contracts/public/generated.ts";
|
|
|
|
type ReferenceBody =
|
|
components["schemas"]["ReferenceDetailResponse"]["reference"];
|
|
|
|
/*
|
|
이 파일은 사고 하나에서 나왔다.
|
|
|
|
공개 Reference 화면이 통째로 비어 있었다. Studio 에서는 같은 글이 다 보였으므로 "공개 쪽만 안
|
|
나온다" 로 드러났다. 원인은 게이트웨이가 읽던 이름이 계약에 없는 것들이었다는 것이다 —
|
|
`purposeSummary`, `applyWhenMarkdown`, `exceptionsMarkdown`, `examplesMarkdown`. 전부 undefined 로
|
|
떨어졌고 타입 검사는 `as string` 단언 때문에 아무 말도 하지 않았다.
|
|
|
|
그래서 여기서 확인하는 것은 값이 아니라 **이름**이다. 계약이 그 칸을 갖고 있는가, 그리고 화면이
|
|
기대하는 모양인가.
|
|
*/
|
|
test("the public Reference contract keeps the fields the screen reads", () => {
|
|
const reference = {
|
|
title: "",
|
|
scopeSummary: "",
|
|
appliesTo: [],
|
|
excludedScope: [],
|
|
rules: [{ title: "", body: "" }],
|
|
examples: [],
|
|
freshnessStatus: "CURRENT",
|
|
content: "",
|
|
contentFormat: "MARKDOWN",
|
|
contentFormatVersion: 1,
|
|
tags: [],
|
|
publishedAt: "",
|
|
updatedAt: "",
|
|
} satisfies ReferenceBody;
|
|
|
|
// 화면이 읽는 이름 그대로. 하나라도 계약에서 사라지면 위의 `satisfies` 가 먼저 깨진다.
|
|
assert.deepEqual(Object.keys(reference).sort(), [
|
|
"appliesTo",
|
|
"content",
|
|
"contentFormat",
|
|
"contentFormatVersion",
|
|
"examples",
|
|
"excludedScope",
|
|
"freshnessStatus",
|
|
"publishedAt",
|
|
"rules",
|
|
"scopeSummary",
|
|
"tags",
|
|
"title",
|
|
"updatedAt",
|
|
]);
|
|
});
|
|
|
|
/*
|
|
Reference 의 본문은 `content` 마크다운이 아니라 규칙과 예시에 있다. Studio 의 편집기가 제목과
|
|
본문을 따로 받고 `body_markdown` 은 비워 두기 때문이다 — 그래서 `content` 를 잘라 규칙을 만들려
|
|
하면 언제나 빈 목록이 된다.
|
|
*/
|
|
test("a rule carries its own title and body, not a slice of markdown", () => {
|
|
const rule: NonNullable<ReferenceBody["rules"]>[number] = {
|
|
title: "Authorization Endpoint에는 client_secret을 보내지 않는다",
|
|
body: "이 요청은 브라우저의 full-page navigation으로 나간다.",
|
|
};
|
|
|
|
assert.equal(typeof rule.title, "string");
|
|
assert.equal(typeof rule.body, "string");
|
|
});
|